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 #define MAX_PSEUDO_NAME 64
70 static void pseudo_name(pseudo_t pseudo
, char *buf
)
72 switch (pseudo
->type
) {
74 snprintf(buf
, MAX_PSEUDO_NAME
, "R%d", pseudo
->nr
);
87 snprintf(buf
, MAX_PSEUDO_NAME
, "PHI%d", pseudo
->nr
);
94 static LLVMValueRef
pseudo_to_value(struct function
*fn
, pseudo_t pseudo
)
98 switch (pseudo
->type
) {
100 result
= pseudo
->priv
;
106 result
= LLVMConstInt(LLVMGetReturnType(fn
->type
), pseudo
->value
, 1);
109 result
= LLVMGetParam(fn
->fn
, pseudo
->nr
- 1);
113 result
= pseudo
->priv
;
125 static void output_op_binary(struct function
*fn
, struct instruction
*insn
)
127 LLVMValueRef lhs
, rhs
, target
;
128 char target_name
[64];
130 lhs
= pseudo_to_value(fn
, insn
->src1
);
132 rhs
= pseudo_to_value(fn
, insn
->src2
);
134 pseudo_name(insn
->target
, target_name
);
136 switch (insn
->opcode
) {
139 target
= LLVMBuildAdd(fn
->builder
, lhs
, rhs
, target_name
);
142 target
= LLVMBuildSub(fn
->builder
, lhs
, rhs
, target_name
);
145 target
= LLVMBuildMul(fn
->builder
, lhs
, rhs
, target_name
);
148 target
= LLVMBuildMul(fn
->builder
, lhs
, rhs
, target_name
);
151 target
= LLVMBuildUDiv(fn
->builder
, lhs
, rhs
, target_name
);
154 target
= LLVMBuildSDiv(fn
->builder
, lhs
, rhs
, target_name
);
157 target
= LLVMBuildURem(fn
->builder
, lhs
, rhs
, target_name
);
160 target
= LLVMBuildSRem(fn
->builder
, lhs
, rhs
, target_name
);
163 target
= LLVMBuildShl(fn
->builder
, lhs
, rhs
, target_name
);
166 target
= LLVMBuildLShr(fn
->builder
, lhs
, rhs
, target_name
);
169 target
= LLVMBuildAShr(fn
->builder
, lhs
, rhs
, target_name
);
174 target
= LLVMBuildAnd(fn
->builder
, lhs
, rhs
, target_name
);
177 target
= LLVMBuildOr(fn
->builder
, lhs
, rhs
, target_name
);
180 target
= LLVMBuildXor(fn
->builder
, lhs
, rhs
, target_name
);
189 /* Binary comparison */
191 target
= LLVMBuildICmp(fn
->builder
, LLVMIntEQ
, lhs
, rhs
, target_name
);
194 target
= LLVMBuildICmp(fn
->builder
, LLVMIntNE
, lhs
, rhs
, target_name
);
203 target
= LLVMBuildICmp(fn
->builder
, LLVMIntSLT
, lhs
, rhs
, target_name
);
206 target
= LLVMBuildICmp(fn
->builder
, LLVMIntSGT
, lhs
, rhs
, target_name
);
225 insn
->target
->priv
= target
;
228 static void output_op_ret(struct function
*fn
, struct instruction
*insn
)
230 pseudo_t pseudo
= insn
->src
;
232 if (pseudo
&& pseudo
!= VOID
) {
233 LLVMValueRef result
= pseudo_to_value(fn
, pseudo
);
235 LLVMBuildRet(fn
->builder
, result
);
237 LLVMBuildRetVoid(fn
->builder
);
240 static void output_op_br(struct function
*fn
, struct instruction
*br
)
243 LLVMValueRef cond
= pseudo_to_value(fn
, br
->cond
);
245 LLVMBuildCondBr(fn
->builder
, cond
,
249 LLVMBuildBr(fn
->builder
,
250 br
->bb_true
? br
->bb_true
->priv
:
254 static void output_op_sel(struct function
*fn
, struct instruction
*insn
)
256 LLVMValueRef target
, src1
, src2
, src3
;
258 src1
= pseudo_to_value(fn
, insn
->src1
);
259 src2
= pseudo_to_value(fn
, insn
->src2
);
260 src3
= pseudo_to_value(fn
, insn
->src3
);
262 target
= LLVMBuildSelect(fn
->builder
, src1
, src2
, src3
, "select");
264 insn
->target
->priv
= target
;
267 static void output_op_switch(struct function
*fn
, struct instruction
*insn
)
269 LLVMValueRef sw_val
, target
;
270 struct basic_block
*def
= NULL
;
271 struct multijmp
*jmp
;
274 FOR_EACH_PTR(insn
->multijmp_list
, jmp
) {
275 if (jmp
->begin
== jmp
->end
) { /* case N */
277 } else if (jmp
->begin
< jmp
->end
) { /* case M..N */
279 } else /* default case */
281 } END_FOR_EACH_PTR(jmp
);
283 sw_val
= pseudo_to_value(fn
, insn
->target
);
284 target
= LLVMBuildSwitch(fn
->builder
, sw_val
,
285 def
? def
->priv
: NULL
, n_jmp
);
287 FOR_EACH_PTR(insn
->multijmp_list
, jmp
) {
288 if (jmp
->begin
== jmp
->end
) { /* case N */
290 LLVMConstInt(LLVMInt32Type(), jmp
->begin
, 0),
292 } else if (jmp
->begin
< jmp
->end
) { /* case M..N */
295 } END_FOR_EACH_PTR(jmp
);
297 insn
->target
->priv
= target
;
300 static void output_insn(struct function
*fn
, struct instruction
*insn
)
302 switch (insn
->opcode
) {
304 output_op_ret(fn
, insn
);
307 output_op_br(fn
, insn
);
316 output_op_switch(fn
, insn
);
318 case OP_COMPUTEDGOTO
:
322 LLVMValueRef src
, target
;
323 char target_name
[64];
325 pseudo_name(insn
->target
, target_name
);
326 src
= pseudo_to_value(fn
, insn
->phi_src
);
328 target
= LLVMBuildAdd(fn
->builder
, src
,
329 LLVMConstInt(LLVMInt32Type(), 0, 0), target_name
);
331 insn
->target
->priv
= target
;
338 target
= LLVMBuildPhi(fn
->builder
, symbol_type(insn
->type
),
341 FOR_EACH_PTR(insn
->phi_list
, phi
) {
342 if (pseudo_to_value(fn
, phi
)) /* skip VOID */
344 } END_FOR_EACH_PTR(phi
);
346 LLVMValueRef
*phi_vals
= calloc(pll
, sizeof(LLVMValueRef
));
347 LLVMBasicBlockRef
*phi_blks
= calloc(pll
, sizeof(LLVMBasicBlockRef
));
350 FOR_EACH_PTR(insn
->phi_list
, phi
) {
353 v
= pseudo_to_value(fn
, phi
);
354 if (v
) { /* skip VOID */
356 phi_blks
[idx
] = phi
->def
->bb
->priv
;
359 } END_FOR_EACH_PTR(phi
);
361 LLVMAddIncoming(target
, phi_vals
, phi_blks
, pll
);
363 insn
->target
->priv
= target
;
366 case OP_LOAD
: case OP_LNOP
:
369 case OP_STORE
: case OP_SNOP
:
372 case OP_INLINED_CALL
:
377 LLVMValueRef src
, target
;
378 char target_name
[64];
380 src
= insn
->src
->priv
;
382 pseudo_name(insn
->target
, target_name
);
384 target
= LLVMBuildIntCast(fn
->builder
, src
, symbol_type(insn
->type
), target_name
);
386 insn
->target
->priv
= target
;
397 case OP_BINARY
... OP_BINARY_END
:
398 case OP_BINCMP
... OP_BINCMP_END
:
399 output_op_binary(fn
, insn
);
402 output_op_sel(fn
, insn
);
407 case OP_NOT
: case OP_NEG
:
426 LLVMValueRef src
, target
;
427 char target_name
[64];
429 pseudo_name(insn
->target
, target_name
);
430 src
= pseudo_to_value(fn
, insn
->src
);
432 target
= LLVMBuildAdd(fn
->builder
, src
,
433 LLVMConstInt(LLVMInt32Type(), 0, 0), target_name
);
435 insn
->target
->priv
= target
;
443 static void output_bb(struct function
*fn
, struct basic_block
*bb
, unsigned long generation
)
445 struct instruction
*insn
;
447 bb
->generation
= generation
;
449 FOR_EACH_PTR(bb
->insns
, insn
) {
453 output_insn(fn
, insn
);
455 END_FOR_EACH_PTR(insn
);
460 static void output_fn(LLVMModuleRef module
, struct entrypoint
*ep
)
462 unsigned long generation
= ++bb_generation
;
463 struct symbol
*sym
= ep
->name
;
464 struct symbol
*base_type
= sym
->ctype
.base_type
;
465 struct symbol
*ret_type
= sym
->ctype
.base_type
->ctype
.base_type
;
466 LLVMTypeRef arg_types
[MAX_ARGS
];
467 LLVMTypeRef return_type
;
468 struct function function
;
469 struct basic_block
*bb
;
474 FOR_EACH_PTR(base_type
->arguments
, arg
) {
475 struct symbol
*arg_base_type
= arg
->ctype
.base_type
;
477 arg_types
[nr_args
++] = symbol_type(arg_base_type
);
478 } END_FOR_EACH_PTR(arg
);
480 name
= show_ident(sym
->ident
);
482 return_type
= symbol_type(ret_type
);
484 function
.type
= LLVMFunctionType(return_type
, arg_types
, nr_args
, 0);
486 function
.fn
= LLVMAddFunction(module
, name
, function
.type
);
487 LLVMSetFunctionCallConv(function
.fn
, LLVMCCallConv
);
489 LLVMSetLinkage(function
.fn
, function_linkage(sym
));
495 function
.builder
= LLVMCreateBuilder();
499 FOR_EACH_PTR(ep
->bbs
, bb
) {
500 if (bb
->generation
== generation
)
503 LLVMBasicBlockRef bbr
;
506 sprintf(bbname
, "L%d", nr_bb
++);
507 bbr
= LLVMAppendBasicBlock(function
.fn
, bbname
);
511 END_FOR_EACH_PTR(bb
);
513 FOR_EACH_PTR(ep
->bbs
, bb
) {
514 if (bb
->generation
== generation
)
517 LLVMPositionBuilderAtEnd(function
.builder
, bb
->priv
);
519 output_bb(&function
, bb
, generation
);
521 END_FOR_EACH_PTR(bb
);
524 static int output_data(LLVMModuleRef module
, struct symbol
*sym
)
526 struct expression
*initializer
= sym
->initializer
;
527 unsigned long long initial_value
= 0;
532 if (initializer
->type
== EXPR_VALUE
)
533 initial_value
= initializer
->value
;
538 name
= show_ident(sym
->ident
);
540 data
= LLVMAddGlobal(module
, symbol_type(sym
->ctype
.base_type
), name
);
542 LLVMSetLinkage(data
, data_linkage(sym
));
544 LLVMSetInitializer(data
, LLVMConstInt(symbol_type(sym
), initial_value
, 1));
549 static int compile(LLVMModuleRef module
, struct symbol_list
*list
)
553 FOR_EACH_PTR(list
, sym
) {
554 struct entrypoint
*ep
;
556 ep
= linearize_symbol(sym
);
558 output_fn(module
, ep
);
560 output_data(module
, sym
);
562 END_FOR_EACH_PTR(sym
);
567 int main(int argc
, char **argv
)
569 struct string_list
* filelist
= NULL
;
572 LLVMModuleRef module
= LLVMModuleCreateWithName("sparse");
574 compile(module
, sparse_initialize(argc
, argv
, &filelist
));
576 FOR_EACH_PTR_NOTAG(filelist
, file
) {
577 compile(module
, sparse(file
));
578 } END_FOR_EACH_PTR_NOTAG(file
);
581 LLVMWriteBitcodeToFD(module
, STDOUT_FILENO
, 0, 0);
583 LLVMDumpModule(module
);
586 LLVMDisposeModule(module
);