Trabalhando na atribuicao, fui jantar.
[toypasc.git] / llvm_codegen_visitor.c
bloba2d25bdc0cf07e2f45f2042aa82ac676b707fc6b
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include "llvm_codegen_visitor.h"
6 static char *pf_name;
7 static int tmp_var = 0;
9 static void _tab(struct AstNode *node);
10 static int _get_type_size(Type type);
11 static char *_create_temporary();
12 static void _print_op_symbol(struct AstNode *node);
14 Visitor *
15 llvm_codegen_new()
17 Visitor *visitor = (Visitor *) malloc (sizeof(Visitor));
19 visitor->visit_program = &llvm_codegen_visit_program;
20 visitor->visit_programdecl = &llvm_codegen_visit_programdecl;
21 visitor->visit_vardecl_list = &llvm_codegen_visit_vardecl_list;
22 visitor->visit_vardecl = &llvm_codegen_visit_vardecl;
23 visitor->visit_identifier_list = &llvm_codegen_visit_identifier_list;
24 visitor->visit_procfunc_list = &llvm_codegen_visit_procfunc_list;
25 visitor->visit_procedure = &llvm_codegen_visit_procfunc;
26 visitor->visit_function = &llvm_codegen_visit_procfunc;
27 visitor->visit_param_list = &llvm_codegen_visit_param_list;
28 visitor->visit_parameter = &llvm_codegen_visit_parameter;
29 visitor->visit_statement_list = &llvm_codegen_visit_statement_list;
30 visitor->visit_printint_stmt = &llvm_codegen_visit_printint_stmt;
31 visitor->visit_printchar_stmt = &llvm_codegen_visit_printchar_stmt;
32 visitor->visit_printbool_stmt = &llvm_codegen_visit_printbool_stmt;
33 visitor->visit_printline_stmt = &llvm_codegen_visit_printline_stmt;
34 visitor->visit_assignment_stmt = &llvm_codegen_visit_assignment_stmt;
35 visitor->visit_if_stmt = &llvm_codegen_visit_if_stmt;
36 visitor->visit_while_stmt = &llvm_codegen_visit_while_stmt;
37 visitor->visit_for_stmt = &llvm_codegen_visit_for_stmt;
38 visitor->visit_rel_expr = &llvm_codegen_visit_binary_expr;
39 visitor->visit_add_expr = &llvm_codegen_visit_binary_expr;
40 visitor->visit_mul_expr = &llvm_codegen_visit_binary_expr;
41 visitor->visit_notfactor = &llvm_codegen_visit_notfactor;
42 visitor->visit_call = &llvm_codegen_visit_call;
43 visitor->visit_callparam_list = &llvm_codegen_visit_callparam_list;
44 visitor->visit_identifier = &llvm_codegen_visit_identifier;
45 visitor->visit_literal = &llvm_codegen_visit_literal;
46 visitor->visit_add_op = &llvm_codegen_visit_binary_op;
47 visitor->visit_mul_op = &llvm_codegen_visit_binary_op;
48 visitor->visit_rel_op = &llvm_codegen_visit_binary_op;
49 visitor->visit_not_op = &llvm_codegen_visit_not_op;
51 return visitor;
54 void
55 llvm_codegen_visit_program(struct _Visitor *visitor, struct AstNode *node)
57 struct AstNode *child;
59 printf("; Generated with toypasc\n");
60 for (child = node->children;
61 child != NULL && child->kind != STATEMENT_LIST;
62 child = child->sibling) {
63 ast_node_accept(child, visitor);
66 if (child != NULL) {
67 printf("; Definition of main function\n");
68 printf("define i32 @main () {\n");
69 ast_node_accept(child, visitor);
70 printf(TAB"ret i32 0\n}\n\n");
74 void
75 llvm_codegen_visit_programdecl(struct _Visitor *visitor, struct AstNode *node)
77 printf("; program ");
78 ast_node_accept(node->children, visitor);
79 printf("\n\n");
80 printf("; Declare the string constants as a global constants...\n");
81 printf("@.true_str = internal constant [5 x i8] c\"true\\00\"\n");
82 printf("@.false_str = internal constant [6 x i8] c\"false\\00\"\n");
83 printf("@.int_fmt = internal constant [3 x i8] c\"%%d\\00\"\n");
85 printf("\n; External declaration of functions\n");
86 printf("declare i32 @puts(i8 *)\n");
87 printf("declare i32 @putchar(i32)\n");
88 printf("declare i32 @printf(i8*, ...)\n\n");
91 void
92 llvm_codegen_visit_vardecl_list (struct _Visitor *visitor, struct AstNode *node)
94 ast_node_accept_children(node->children, visitor);
95 printf("\n");
98 void
99 llvm_codegen_visit_identifier_list (struct _Visitor *visitor, struct AstNode *node)
101 struct AstNode *child;
103 for (child = node->children; child != NULL; child = child->sibling) {
104 ast_node_accept(child, visitor);
105 if (child->sibling != NULL)
106 printf(", ");
110 void
111 llvm_codegen_visit_procfunc_list (struct _Visitor *visitor, struct AstNode *node)
113 ast_node_accept_children(node->children, visitor);
116 void
117 llvm_codegen_visit_procfunc (struct _Visitor *visitor, struct AstNode *node)
119 struct AstNode *child;
121 pf_name = _create_temporary();
123 printf("define ");
124 PRINT_TYPE(node->type);
125 printf(" ");
127 child = node->children; // Identifier
128 ast_node_accept(child, visitor);
130 printf(" ( ");
132 child = child->sibling;
133 if (child->kind == PARAM_LIST) {
134 ast_node_accept(child, visitor);
135 child = child->sibling;
138 printf(" ) {\n");
139 printf("entry:\n");
141 if (node->kind == FUNCTION) {
142 printf(TAB);
143 PRINT_TYPE(node->type);
144 printf(" %%%s\n", pf_name);
147 if (child->kind == VARDECL_LIST) {
148 ast_node_accept(child, visitor);
149 child = child->sibling;
152 printf("\n");
154 ast_node_accept(child, visitor);
156 printf(TAB"ret ");
157 PRINT_TYPE(node->type);
159 if (node->kind == FUNCTION)
160 printf(" %s", pf_name);
162 printf("\n}\n\n");
164 free(pf_name);
167 void
168 llvm_codegen_visit_param_list (struct _Visitor *visitor, struct AstNode *node)
170 struct AstNode *child;
172 for (child = node->children; child != NULL; child = child->sibling) {
173 //printf("%s ", _get_type_string(child->type));
174 ast_node_accept(child, visitor);
175 if (child->sibling != NULL)
176 printf(", ");
180 void
181 llvm_codegen_visit_statement_list (struct _Visitor *visitor, struct AstNode *node)
183 struct AstNode *child;
185 for (child = node->children; child != NULL; child = child->sibling) {
186 _tab(child);
187 ast_node_accept(child, visitor);
188 printf("\n");
192 void
193 llvm_codegen_visit_binary_expr (struct _Visitor *visitor, struct AstNode *node)
195 struct AstNode *left = node->children;
196 struct AstNode *op = left->sibling;
197 struct AstNode *right = op->sibling;
199 fprintf(stderr, "[%s]\n", node->name);
200 fprintf(stderr, "left : %s\n", left->name);
201 fprintf(stderr, "op : %s\n", op->name);
202 fprintf(stderr, "right: %s\n\n", right->name);
204 if (IS_LITERAL(left->kind) && IS_LITERAL(right->kind)) {
205 _print_op_symbol(op);
206 printf(" ");
207 ast_node_accept(left, visitor);
208 printf(", ");
209 ast_node_accept(right, visitor);
212 // %tmp = mul i32 %x, %y
213 // %tmp2 = add i32 %tmp, %z
214 //ast_node_accept_children(node->children, visitor);
217 void
218 llvm_codegen_visit_callparam_list (struct _Visitor *visitor, struct AstNode *node)
220 ast_node_accept(node->children, visitor);
223 void
224 llvm_codegen_visit_identifier (struct _Visitor *visitor, struct AstNode *node)
226 printf("%s%s", node->symbol->is_global ? "@" : TAB"%",
227 node->symbol->name);
230 void
231 llvm_codegen_visit_literal (struct _Visitor *visitor, struct AstNode *node)
233 if (node->type == BOOLEAN) {
234 printf("%bool_str = getelementptr [");
235 if (node->value.boolean)
236 printf("5 x i8]* @.true");
237 else
238 printf("6 x i8]* @.false");
239 printf("_str, i32 0, i32 0\n");
241 } else
242 printf("%d", node->value.integer);
245 void
246 llvm_codegen_visit_vardecl (struct _Visitor *visitor, struct AstNode *node)
248 struct AstNode *child;
249 const char *type;// = _get_type_string(node->type);
251 child = node->children;
252 child->visited = TRUE;
254 for (child = child->children; child != NULL; child = child->sibling) {
255 ast_node_accept(child, visitor);
256 if (node->parent->parent->kind == PROGRAM)
257 printf(" = global i%d 0\n", _get_type_size(child->type));
258 else
259 printf(" = add i%d 0, 0\n", _get_type_size(child->type));
263 void
264 llvm_codegen_visit_parameter (struct _Visitor *visitor, struct AstNode *node)
266 PRINT_TYPE(node->type);
267 printf(" ");
268 ast_node_accept(node->children, visitor);
271 void
272 llvm_codegen_visit_printint_stmt (struct _Visitor *visitor, struct AstNode *node)
274 printf("call i32 (i8* noalias , ...)* bitcast (i32 (i8*, ...)* ");
275 printf("@printf to i32 (i8* noalias , ...)*)( i8* getelementptr ");
276 printf("([3 x i8]* @.int_fmt, i32 0, i32 0) noalias , i32 ");
277 ast_node_accept(node->children, visitor);
278 printf(" )\n");
281 void
282 llvm_codegen_visit_printchar_stmt (struct _Visitor *visitor, struct AstNode *node)
284 printf("call i32 @putchar( i32 ");
285 ast_node_accept(node->children, visitor);
286 printf(" )\n");
289 void
290 llvm_codegen_visit_printbool_stmt (struct _Visitor *visitor, struct AstNode *node)
292 ast_node_accept(node->children, visitor);
293 printf(TAB"call i32 @puts( i8 * %bool_str )\n");
296 void
297 llvm_codegen_visit_printline_stmt (struct _Visitor *visitor, struct AstNode *node)
299 printf("call i32 @putchar( i32 10 )\n");
302 void
303 llvm_codegen_visit_assignment_stmt (struct _Visitor *visitor, struct AstNode *node)
305 Symbol *lsym;
306 int tsize = _get_type_size(node->children->type);
307 printf("; [Template] store i32 50, i32* @x, align 4\n");
309 lsym = node->children->symbol;
311 fprintf(stderr, "%s - ", node->children->symbol->name);
312 fprintf(stderr, "is_global? %d\n", node->children->symbol->is_global);
314 //printf(TAB"store i%d ", tsize);
315 //ast_node_accept(node->children->sibling, visitor);
316 //printf(", i%d* ", tsize);
317 ast_node_accept(node->children, visitor);
318 printf("\n");
321 void
322 llvm_codegen_visit_if_stmt (struct _Visitor *visitor, struct AstNode *node)
324 struct AstNode *child;
325 const char *var;
327 printf("if (");
328 child = node->children; // Expression
329 ast_node_accept(child, visitor);
330 printf(") {\n");
332 child = child->sibling; // If Statements
333 ast_node_accept(child, visitor);
335 printf("\n");
336 _tab(node);
337 printf("}");
339 child = child->sibling; // Else Statements
341 if (child != NULL) {
342 printf(" else {\n");
343 ast_node_accept(child, visitor);
344 printf("\n");
345 _tab(node);
346 printf("}");
348 printf("\n");
351 void
352 llvm_codegen_visit_while_stmt (struct _Visitor *visitor, struct AstNode *node)
354 struct AstNode *child;
355 const char *var;
357 printf("while (");
358 child = node->children; // Expression
359 ast_node_accept(child, visitor);
360 printf(") {\n");
362 child = child->sibling; // Statements
363 ast_node_accept(child, visitor);
365 _tab(node);
366 printf("}\n");
369 void
370 llvm_codegen_visit_for_stmt (struct _Visitor *visitor, struct AstNode *node)
372 struct AstNode *child;
373 const char *var;
375 printf("for (");
376 child = node->children; // Assignment
377 ast_node_accept(child, visitor);
379 var = child->children->symbol->name;
380 printf(" %s < ", var);
382 child = child->sibling; // Stop condition
383 ast_node_accept(child, visitor);
385 printf("; %s++) {\n", var);
387 child = child->sibling; // Statements
388 ast_node_accept_children(child, visitor);
390 printf("\n");
391 _tab(node);
392 printf("}\n");
395 void
396 llvm_codegen_visit_notfactor (struct _Visitor *visitor, struct AstNode *node)
398 ast_node_accept_children(node->children, visitor);
401 void
402 llvm_codegen_visit_call (struct _Visitor *visitor, struct AstNode *node)
404 struct AstNode *child = node->children;
406 printf("call ");
407 PRINT_TYPE(child->symbol->type);
408 printf(" ");
409 ast_node_accept(child, visitor);
410 printf("( ");
411 for (child = child->sibling->children; child != NULL;
412 child = child->sibling) {
413 PRINT_TYPE(child->type);
414 printf(" ");
415 ast_node_accept(child, visitor);
416 if (child->sibling != NULL)
417 printf(", ");
419 printf(" )\n");
422 void
423 llvm_codegen_visit_simplenode (struct _Visitor *visitor, struct AstNode *node)
425 ast_node_accept_children(node->children, visitor);
428 void
429 llvm_codegen_visit_binary_op (struct _Visitor *visitor, struct AstNode *node)
431 _print_op_symbol(node);
434 void
435 llvm_codegen_visit_not_op (struct _Visitor *visitor, struct AstNode *node)
437 printf(" !", node->name);
440 static void
441 _tab(struct AstNode *node) {
442 struct AstNode *parent;
443 for (parent = node->parent; parent->parent != NULL; parent = parent->parent)
444 printf(TAB);
447 static int
448 _get_type_size(Type type)
450 switch (type) {
451 case INTEGER:
452 return 32;
453 case BOOLEAN:
454 return 1;
455 case CHAR:
456 return 8;
457 default:
458 return 0;
462 static char
463 *_create_temporary()
465 char *temp;
467 if (asprintf (&temp, "tmp%d", tmp_var) < 0)
468 return NULL;
470 tmp_var++;
471 return temp;
474 static void
475 _print_op_symbol(struct AstNode *node)
477 switch (node->kind) {
478 /*case T_OR:
479 printf(" || ");
480 break;
481 case T_AND:
482 printf(" && ");
483 break;
484 case T_EQUAL:
485 printf(" == ");
486 break;
487 case T_NOTEQUAL:
488 printf(" != ");
489 break;
490 case T_LESSER:
491 printf(" < ");
492 break;
493 case T_GREATER:
494 printf(" > ");
495 break;
496 case T_LESSEREQUAL:
497 printf(" <= ");
498 break;
499 case T_GREATEREQUAL:
500 printf(" >= ");
501 break;*/
502 case T_PLUS:
503 printf("add");
504 break;
505 case T_MINUS:
506 printf("sub");
507 break;
508 case T_STAR:
509 printf("mul");
510 break;
511 /*case T_SLASH:
512 printf(" %s ", node->name);*/