sparse, llvm: Add output_op_binary() stub
[smatch.git] / sparse-llvm.c
blobbd76c7654a586901e6c5548b944b8b7bbf20201f
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 struct function {
19 LLVMBuilderRef builder;
20 LLVMTypeRef type;
21 LLVMValueRef fn;
24 static LLVMTypeRef symbol_type(struct symbol *sym)
26 LLVMTypeRef ret = NULL;
28 switch (sym->bit_size) {
29 case -1:
30 ret = LLVMVoidType();
31 break;
32 case 8:
33 ret = LLVMInt8Type();
34 break;
35 case 16:
36 ret = LLVMInt16Type();
37 break;
38 case 32:
39 ret = LLVMInt32Type();
40 break;
41 case 64:
42 ret = LLVMInt64Type();
43 break;
44 default:
45 die("invalid bit size %d for type %d", sym->bit_size, sym->type);
46 break;
49 return ret;
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) {
71 /* Binary */
72 case OP_ADD:
73 assert(0);
74 break;
75 case OP_SUB:
76 assert(0);
77 break;
78 case OP_MULU:
79 assert(0);
80 break;
81 case OP_MULS:
82 assert(0);
83 break;
84 case OP_DIVU:
85 assert(0);
86 break;
87 case OP_DIVS:
88 assert(0);
89 break;
90 case OP_MODU:
91 assert(0);
92 break;
93 case OP_MODS:
94 assert(0);
95 break;
96 case OP_SHL:
97 assert(0);
98 break;
99 case OP_LSR:
100 assert(0);
101 break;
102 case OP_ASR:
103 assert(0);
104 break;
106 /* Logical */
107 case OP_AND:
108 assert(0);
109 break;
110 case OP_OR:
111 assert(0);
112 break;
113 case OP_XOR:
114 assert(0);
115 break;
116 case OP_AND_BOOL:
117 assert(0);
118 break;
119 case OP_OR_BOOL:
121 /* Binary comparison */
122 case OP_SET_EQ:
123 assert(0);
124 break;
125 case OP_SET_NE:
126 assert(0);
127 break;
128 case OP_SET_LE:
129 assert(0);
130 break;
131 case OP_SET_GE:
132 assert(0);
133 break;
134 case OP_SET_LT:
135 assert(0);
136 break;
137 case OP_SET_GT:
138 assert(0);
139 break;
140 case OP_SET_B:
141 assert(0);
142 break;
143 case OP_SET_A:
144 assert(0);
145 break;
146 case OP_SET_BE:
147 assert(0);
148 break;
149 case OP_SET_AE:
150 assert(0);
151 break;
152 default:
153 assert(0);
154 break;
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) {
164 case PSEUDO_REG:
165 assert(0);
166 break;
167 case PSEUDO_SYM:
168 assert(0);
169 break;
170 case PSEUDO_VAL:
171 LLVMBuildRet(fn->builder, LLVMConstInt(LLVMGetReturnType(fn->type), pseudo->value, 1));
172 break;
173 case PSEUDO_ARG: {
174 LLVMValueRef param = LLVMGetParam(fn->fn, pseudo->nr - 1);
175 LLVMBuildRet(fn->builder, param);
176 break;
178 case PSEUDO_PHI:
179 assert(0);
180 break;
181 default:
182 assert(0);
184 } else
185 LLVMBuildRetVoid(fn->builder);
188 static void output_insn(struct function *fn, struct instruction *insn)
190 switch (insn->opcode) {
191 case OP_RET:
192 output_op_ret(fn, insn);
193 break;
194 case OP_BR:
195 break;
196 case OP_SYMADDR:
197 break;
198 case OP_SETVAL:
199 break;
200 case OP_SWITCH:
201 break;
202 case OP_COMPUTEDGOTO:
203 break;
204 case OP_PHISOURCE:
205 break;
206 case OP_PHI:
207 break;
208 case OP_LOAD: case OP_LNOP:
209 break;
210 case OP_STORE: case OP_SNOP:
211 break;
212 case OP_INLINED_CALL:
213 case OP_CALL:
214 break;
215 case OP_CAST:
216 case OP_SCAST:
217 case OP_FPCAST:
218 case OP_PTRCAST:
219 break;
220 case OP_BINARY ... OP_BINARY_END:
221 case OP_BINCMP ... OP_BINCMP_END:
222 output_op_binary(fn, insn);
223 break;
224 case OP_SEL:
225 break;
226 case OP_SLICE:
227 break;
228 case OP_NOT: case OP_NEG:
229 break;
230 case OP_CONTEXT:
231 break;
232 case OP_RANGE:
233 break;
234 case OP_NOP:
235 break;
236 case OP_DEATHNOTE:
237 break;
238 case OP_ASM:
239 break;
240 case OP_COPY:
241 break;
242 default:
243 break;
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) {
254 if (!insn->bb)
255 continue;
257 output_insn(fn, insn);
259 END_FOR_EACH_PTR(insn);
262 #define MAX_ARGS 64
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;
274 struct symbol *arg;
275 const char *name;
276 int nr_args = 0;
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));
294 unssa(ep);
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)
304 continue;
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;
315 LLVMValueRef data;
316 const char *name;
318 if (initializer) {
319 if (initializer->type == EXPR_VALUE)
320 initial_value = initializer->value;
321 else
322 assert(0);
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));
333 return 0;
336 static int compile(LLVMModuleRef module, struct symbol_list *list)
338 struct symbol *sym;
340 FOR_EACH_PTR(list, sym) {
341 struct entrypoint *ep;
342 expand_symbol(sym);
343 ep = linearize_symbol(sym);
344 if (ep)
345 output_fn(module, ep);
346 else
347 output_data(module, sym);
349 END_FOR_EACH_PTR(sym);
351 return 0;
354 int main(int argc, char **argv)
356 struct string_list * filelist = NULL;
357 char *file;
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);
367 #if 1
368 LLVMWriteBitcodeToFD(module, STDOUT_FILENO, 0, 0);
369 #else
370 LLVMDumpModule(module);
371 #endif
373 LLVMDisposeModule(module);
375 return 0;