sparse, llvm: Fix assert() in sparse code
[smatch.git] / sparse-llvm.c
blob792f8253c7601608271bb018fe06703088b2b1e9
1 /*
2 * Example usage:
3 * ./sparse-llvm hello.c | llc | as -o hello.o
4 */
6 #include <llvm-c/Core.h>
7 #include <llvm-c/BitWriter.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <assert.h>
13 #include "symbol.h"
14 #include "expression.h"
15 #include "linearize.h"
16 #include "flow.h"
18 static LLVMTypeRef symbol_type(struct symbol *sym)
20 LLVMTypeRef ret = NULL;
22 switch (sym->bit_size) {
23 case -1:
24 ret = LLVMVoidType();
25 break;
26 case 8:
27 ret = LLVMInt8Type();
28 break;
29 case 16:
30 ret = LLVMInt16Type();
31 break;
32 case 32:
33 ret = LLVMInt32Type();
34 break;
35 case 64:
36 ret = LLVMInt64Type();
37 break;
38 default:
39 die("invalid bit size %d for type %d", sym->bit_size, sym->type);
40 break;
43 return ret;
46 static LLVMLinkage data_linkage(struct symbol *sym)
48 if (sym->ctype.modifiers & MOD_STATIC)
49 return LLVMPrivateLinkage;
51 return LLVMCommonLinkage;
54 static LLVMLinkage function_linkage(struct symbol *sym)
56 if (sym->ctype.modifiers & MOD_STATIC)
57 return LLVMInternalLinkage;
59 return LLVMExternalLinkage;
62 static void output_insn(struct instruction *insn)
66 static void output_bb(struct basic_block *bb, unsigned long generation)
68 struct instruction *insn;
70 bb->generation = generation;
72 FOR_EACH_PTR(bb->insns, insn) {
73 if (!insn->bb)
74 continue;
76 output_insn(insn);
78 END_FOR_EACH_PTR(insn);
81 #define MAX_ARGS 64
83 static void output_fn(LLVMModuleRef module, struct entrypoint *ep)
85 unsigned long generation = ++bb_generation;
86 struct symbol *sym = ep->name;
87 struct symbol *base_type = sym->ctype.base_type;
88 struct symbol *ret_type = sym->ctype.base_type->ctype.base_type;
89 LLVMTypeRef arg_types[MAX_ARGS];
90 struct basic_block *bb;
91 LLVMValueRef function;
92 struct symbol *arg;
93 const char *name;
94 int nr_args = 0;
96 FOR_EACH_PTR(base_type->arguments, arg) {
97 struct symbol *arg_base_type = arg->ctype.base_type;
99 arg_types[nr_args++] = symbol_type(arg_base_type);
100 } END_FOR_EACH_PTR(arg);
102 name = show_ident(sym->ident);
104 function = LLVMAddFunction(module, name, LLVMFunctionType(symbol_type(ret_type), arg_types, nr_args, 0));
106 LLVMSetLinkage(function, function_linkage(sym));
108 unssa(ep);
110 FOR_EACH_PTR(ep->bbs, bb) {
111 if (bb->generation == generation)
112 continue;
113 output_bb(bb, generation);
115 END_FOR_EACH_PTR(bb);
117 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry");
119 LLVMBuilderRef builder = LLVMCreateBuilder();
121 LLVMPositionBuilderAtEnd(builder, entry);
123 if (ret_type == &void_ctype)
124 LLVMBuildRetVoid(builder);
125 else
126 LLVMBuildRet(builder, LLVMConstInt(symbol_type(ret_type), 0, 1));
129 static int output_data(LLVMModuleRef module, struct symbol *sym)
131 LLVMValueRef data;
132 const char *name;
134 name = show_ident(sym->ident);
136 data = LLVMAddGlobal(module, symbol_type(sym->ctype.base_type), name);
138 LLVMSetLinkage(data, data_linkage(sym));
140 LLVMSetInitializer(data, LLVMConstInt(symbol_type(sym), 0, 1));
142 return 0;
145 static int compile(LLVMModuleRef module, struct symbol_list *list)
147 struct symbol *sym;
149 FOR_EACH_PTR(list, sym) {
150 struct entrypoint *ep;
151 expand_symbol(sym);
152 ep = linearize_symbol(sym);
153 if (ep)
154 output_fn(module, ep);
155 else
156 output_data(module, sym);
158 END_FOR_EACH_PTR(sym);
160 return 0;
163 int main(int argc, char **argv)
165 struct string_list * filelist = NULL;
166 char *file;
168 LLVMModuleRef module = LLVMModuleCreateWithName("sparse");
170 compile(module, sparse_initialize(argc, argv, &filelist));
172 FOR_EACH_PTR_NOTAG(filelist, file) {
173 compile(module, sparse(file));
174 } END_FOR_EACH_PTR_NOTAG(file);
176 #if 1
177 LLVMWriteBitcodeToFD(module, STDOUT_FILENO, 0, 0);
178 #else
179 LLVMDumpModule(module);
180 #endif
182 LLVMDisposeModule(module);
184 return 0;