3 * ./sparse-llvm hello.c | llc | as -o hello.o
6 #include <llvm-c/Core.h>
7 #include <llvm-c/BitWriter.h>
14 #include "expression.h"
15 #include "linearize.h"
19 LLVMBuilderRef builder
;
24 static LLVMTypeRef
symbol_type(struct symbol
*sym
)
26 LLVMTypeRef ret
= NULL
;
28 switch (sym
->bit_size
) {
36 ret
= LLVMInt16Type();
39 ret
= LLVMInt32Type();
42 ret
= LLVMInt64Type();
45 die("invalid bit size %d for type %d", sym
->bit_size
, sym
->type
);
52 static LLVMLinkage
data_linkage(struct symbol
*sym
)
54 if (sym
->ctype
.modifiers
& MOD_STATIC
)
55 return LLVMPrivateLinkage
;
57 return LLVMExternalLinkage
;
60 static LLVMLinkage
function_linkage(struct symbol
*sym
)
62 if (sym
->ctype
.modifiers
& MOD_STATIC
)
63 return LLVMInternalLinkage
;
65 return LLVMExternalLinkage
;
68 static void output_op_binary(struct function
*fn
, struct instruction
*insn
)
70 switch (insn
->opcode
) {
121 /* Binary comparison */
158 static void output_op_ret(struct function
*fn
, struct instruction
*insn
)
160 pseudo_t pseudo
= insn
->src
;
162 if (pseudo
&& pseudo
!= VOID
) {
163 switch (pseudo
->type
) {
171 LLVMBuildRet(fn
->builder
, LLVMConstInt(LLVMGetReturnType(fn
->type
), pseudo
->value
, 1));
174 LLVMValueRef param
= LLVMGetParam(fn
->fn
, pseudo
->nr
- 1);
175 LLVMBuildRet(fn
->builder
, param
);
185 LLVMBuildRetVoid(fn
->builder
);
188 static void output_insn(struct function
*fn
, struct instruction
*insn
)
190 switch (insn
->opcode
) {
192 output_op_ret(fn
, insn
);
202 case OP_COMPUTEDGOTO
:
208 case OP_LOAD
: case OP_LNOP
:
210 case OP_STORE
: case OP_SNOP
:
212 case OP_INLINED_CALL
:
220 case OP_BINARY
... OP_BINARY_END
:
221 case OP_BINCMP
... OP_BINCMP_END
:
222 output_op_binary(fn
, insn
);
228 case OP_NOT
: case OP_NEG
:
247 static void output_bb(struct function
*fn
, struct basic_block
*bb
, unsigned long generation
)
249 struct instruction
*insn
;
251 bb
->generation
= generation
;
253 FOR_EACH_PTR(bb
->insns
, insn
) {
257 output_insn(fn
, insn
);
259 END_FOR_EACH_PTR(insn
);
264 static void output_fn(LLVMModuleRef module
, struct entrypoint
*ep
)
266 unsigned long generation
= ++bb_generation
;
267 struct symbol
*sym
= ep
->name
;
268 struct symbol
*base_type
= sym
->ctype
.base_type
;
269 struct symbol
*ret_type
= sym
->ctype
.base_type
->ctype
.base_type
;
270 LLVMTypeRef arg_types
[MAX_ARGS
];
271 LLVMTypeRef return_type
;
272 struct function function
;
273 struct basic_block
*bb
;
278 FOR_EACH_PTR(base_type
->arguments
, arg
) {
279 struct symbol
*arg_base_type
= arg
->ctype
.base_type
;
281 arg_types
[nr_args
++] = symbol_type(arg_base_type
);
282 } END_FOR_EACH_PTR(arg
);
284 name
= show_ident(sym
->ident
);
286 return_type
= symbol_type(ret_type
);
288 function
.type
= LLVMFunctionType(return_type
, arg_types
, nr_args
, 0);
290 function
.fn
= LLVMAddFunction(module
, name
, function
.type
);
292 LLVMSetLinkage(function
.fn
, function_linkage(sym
));
296 function
.builder
= LLVMCreateBuilder();
298 LLVMBasicBlockRef entry
= LLVMAppendBasicBlock(function
.fn
, "entry");
300 LLVMPositionBuilderAtEnd(function
.builder
, entry
);
302 FOR_EACH_PTR(ep
->bbs
, bb
) {
303 if (bb
->generation
== generation
)
306 output_bb(&function
, bb
, generation
);
308 END_FOR_EACH_PTR(bb
);
311 static int output_data(LLVMModuleRef module
, struct symbol
*sym
)
313 struct expression
*initializer
= sym
->initializer
;
314 unsigned long long initial_value
= 0;
319 if (initializer
->type
== EXPR_VALUE
)
320 initial_value
= initializer
->value
;
325 name
= show_ident(sym
->ident
);
327 data
= LLVMAddGlobal(module
, symbol_type(sym
->ctype
.base_type
), name
);
329 LLVMSetLinkage(data
, data_linkage(sym
));
331 LLVMSetInitializer(data
, LLVMConstInt(symbol_type(sym
), initial_value
, 1));
336 static int compile(LLVMModuleRef module
, struct symbol_list
*list
)
340 FOR_EACH_PTR(list
, sym
) {
341 struct entrypoint
*ep
;
343 ep
= linearize_symbol(sym
);
345 output_fn(module
, ep
);
347 output_data(module
, sym
);
349 END_FOR_EACH_PTR(sym
);
354 int main(int argc
, char **argv
)
356 struct string_list
* filelist
= NULL
;
359 LLVMModuleRef module
= LLVMModuleCreateWithName("sparse");
361 compile(module
, sparse_initialize(argc
, argv
, &filelist
));
363 FOR_EACH_PTR_NOTAG(filelist
, file
) {
364 compile(module
, sparse(file
));
365 } END_FOR_EACH_PTR_NOTAG(file
);
368 LLVMWriteBitcodeToFD(module
, STDOUT_FILENO
, 0, 0);
370 LLVMDumpModule(module
);
373 LLVMDisposeModule(module
);