diff options
-rw-r--r-- | src/ir.c | 45 | ||||
-rw-r--r-- | src/ir.h | 2 | ||||
-rw-r--r-- | src/viz.c | 75 |
3 files changed, 85 insertions, 37 deletions
@@ -13,8 +13,8 @@ emit_arith(ProgramBASM *program, Node *node, Operator op) { | |||
13 | Operand reg_b; | 13 | Operand reg_b; |
14 | for (size_t i = 1; i < array_size(node->builtin.args); ++i) { | 14 | for (size_t i = 1; i < array_size(node->builtin.args); ++i) { |
15 | Node *arg = node->builtin.args[i]; | 15 | Node *arg = node->builtin.args[i]; |
16 | Operand reg_dst = NEW_REG(); | ||
17 | reg_b = emit_basm(program, arg); | 16 | reg_b = emit_basm(program, arg); |
17 | Operand reg_dst = NEW_REG(); | ||
18 | EMIT_2(program, line, op, reg_dst, reg_a, reg_b); | 18 | EMIT_2(program, line, op, reg_dst, reg_a, reg_b); |
19 | reg_a = reg_dst; | 19 | reg_a = reg_dst; |
20 | } | 20 | } |
@@ -90,14 +90,50 @@ emit_bool(ProgramBASM *program, Node *node) { | |||
90 | return reg_dst; | 90 | return reg_dst; |
91 | } | 91 | } |
92 | 92 | ||
93 | // TODO: emit_if | 93 | Operand |
94 | emit_if(ProgramBASM *program, Node *node) { | ||
95 | LineInfo line = (LineInfo){.line = node->line, .col = node->col}; | ||
96 | Operand label_false = NEW_LAB(); | ||
97 | Operand label_end = NEW_LAB(); | ||
98 | |||
99 | // If type of expression is `void`, there is nothing to return. Don't | ||
100 | // generate a new register or copy output. | ||
101 | Operand reg_out = (Operand){0}; | ||
102 | if (node->expr_type != &default_types[TYPE_VOID]) { | ||
103 | reg_out = NEW_REG(); | ||
104 | } | ||
105 | |||
106 | Operand cond = emit_basm(program, node->ifexpr.cond); | ||
107 | EMIT_1(program, line, OP_JMP_FALSE, label_false, cond); | ||
108 | |||
109 | Operand ret_true = emit_basm(program, node->ifexpr.expr_true); | ||
110 | if (node->ifexpr.expr_false != NULL) { | ||
111 | if (node->expr_type != &default_types[TYPE_VOID]) { | ||
112 | EMIT_1(program, line, OP_CP64, reg_out, ret_true); // TODO: depends on the type of output | ||
113 | } | ||
114 | EMIT_0(program, line, OP_JMP, label_end); | ||
115 | EMIT_0(program, line, OP_LABEL, label_false); | ||
116 | Operand ret_false = emit_basm(program, node->ifexpr.expr_false); | ||
117 | if (node->expr_type != &default_types[TYPE_VOID]) { | ||
118 | EMIT_1(program, line, OP_CP64, reg_out, ret_false); // TODO: depends on the type of output | ||
119 | } | ||
120 | EMIT_0(program, line, OP_LABEL, label_end); | ||
121 | } else { | ||
122 | EMIT_0(program, line, OP_LABEL, label_false); | ||
123 | } | ||
124 | |||
125 | return reg_out; | ||
126 | } | ||
127 | |||
94 | // TODO: emit_and | 128 | // TODO: emit_and |
95 | // TODO: emit_or | 129 | // TODO: emit_or |
96 | // TODO: emit_not | 130 | // TODO: emit_not |
97 | // TODO: emit_global | 131 | // TODO: emit_block |
98 | // TODO: emit_local | ||
99 | // TODO: emit_procedure | 132 | // TODO: emit_procedure |
133 | // TODO: emit_local_vars | ||
134 | // TODO: emit_param_vars | ||
100 | // TODO: emit_proc_call | 135 | // TODO: emit_proc_call |
136 | // TODO: emit_global_vars | ||
101 | 137 | ||
102 | Operand | 138 | Operand |
103 | emit_basm(ProgramBASM *program, Node *node) { | 139 | emit_basm(ProgramBASM *program, Node *node) { |
@@ -105,6 +141,7 @@ emit_basm(ProgramBASM *program, Node *node) { | |||
105 | case NODE_BOOL: { return emit_bool(program, node); } break; | 141 | case NODE_BOOL: { return emit_bool(program, node); } break; |
106 | case NODE_NUMBER: { return emit_number(program, node); } break; | 142 | case NODE_NUMBER: { return emit_number(program, node); } break; |
107 | case NODE_BUILTIN: { return emit_builtin(program, node); } break; | 143 | case NODE_BUILTIN: { return emit_builtin(program, node); } break; |
144 | case NODE_IF: { return emit_if(program, node); } break; | ||
108 | default: { | 145 | default: { |
109 | push_error(ERR_TYPE_BASM, ERR_UNIMPLEMENTED, node->line, node->col); | 146 | push_error(ERR_TYPE_BASM, ERR_UNIMPLEMENTED, node->line, node->col); |
110 | return (Operand){0}; | 147 | return (Operand){0}; |
@@ -36,6 +36,8 @@ typedef enum Operator { | |||
36 | // (Un)conditional jump operations. | 36 | // (Un)conditional jump operations. |
37 | OP_LABEL, | 37 | OP_LABEL, |
38 | OP_JMP, | 38 | OP_JMP, |
39 | OP_JMP_TRUE, | ||
40 | OP_JMP_FALSE, | ||
39 | OP_JMP_EQ, | 41 | OP_JMP_EQ, |
40 | OP_JMP_NEQ, | 42 | OP_JMP_NEQ, |
41 | OP_JMP_GT, | 43 | OP_JMP_GT, |
@@ -237,39 +237,41 @@ viz_symtables(Scope **scopes) { | |||
237 | } | 237 | } |
238 | 238 | ||
239 | static const char* basm_op_str[] = { | 239 | static const char* basm_op_str[] = { |
240 | [OP_ADD] = "add ", | 240 | [OP_ADD] = "add ", |
241 | [OP_SUB] = "sub ", | 241 | [OP_SUB] = "sub ", |
242 | [OP_MUL] = "mul ", | 242 | [OP_MUL] = "mul ", |
243 | [OP_DIV] = "div ", | 243 | [OP_DIV] = "div ", |
244 | [OP_MOD] = "mod ", | 244 | [OP_MOD] = "mod ", |
245 | [OP_LD8] = "ld8 ", | 245 | [OP_LD8] = "ld8 ", |
246 | [OP_LD16] = "ld16 ", | 246 | [OP_LD16] = "ld16 ", |
247 | [OP_LD32] = "ld32 ", | 247 | [OP_LD32] = "ld32 ", |
248 | [OP_LD64] = "ld64 ", | 248 | [OP_LD64] = "ld64 ", |
249 | [OP_ST8] = "st8 ", | 249 | [OP_ST8] = "st8 ", |
250 | [OP_ST16] = "st16 ", | 250 | [OP_ST16] = "st16 ", |
251 | [OP_ST32] = "st32 ", | 251 | [OP_ST32] = "st32 ", |
252 | [OP_ST64] = "st64 ", | 252 | [OP_ST64] = "st64 ", |
253 | [OP_CP8] = "cp8 ", | 253 | [OP_CP8] = "cp8 ", |
254 | [OP_CP16] = "cp16 ", | 254 | [OP_CP16] = "cp16 ", |
255 | [OP_CP32] = "cp32 ", | 255 | [OP_CP32] = "cp32 ", |
256 | [OP_CP64] = "cp64 ", | 256 | [OP_CP64] = "cp64 ", |
257 | [OP_NOT] = "not ", | 257 | [OP_NOT] = "not ", |
258 | [OP_AND] = "and ", | 258 | [OP_AND] = "and ", |
259 | [OP_OR] = "or ", | 259 | [OP_OR] = "or ", |
260 | [OP_XOR] = "xor ", | 260 | [OP_XOR] = "xor ", |
261 | [OP_LSHIFT] = "lshift", | 261 | [OP_LSHIFT] = "lshift", |
262 | [OP_RSHIFT] = "rshift", | 262 | [OP_RSHIFT] = "rshift", |
263 | [OP_LROT] = "lrot ", | 263 | [OP_LROT] = "lrot ", |
264 | [OP_RROT] = "rrot ", | 264 | [OP_RROT] = "rrot ", |
265 | [OP_LABEL] = "lab ", | 265 | [OP_LABEL] = "lab ", |
266 | [OP_JMP] = "jmp ", | 266 | [OP_JMP] = "jmp ", |
267 | [OP_JMP_EQ] = "jeq ", | 267 | [OP_JMP_TRUE] = "jt ", |
268 | [OP_JMP_NEQ] = "jne ", | 268 | [OP_JMP_FALSE] = "jf ", |
269 | [OP_JMP_GT] = "jgt ", | 269 | [OP_JMP_EQ] = "jeq ", |
270 | [OP_JMP_LT] = "jlt ", | 270 | [OP_JMP_NEQ] = "jne ", |
271 | [OP_JMP_GE] = "jge ", | 271 | [OP_JMP_GT] = "jgt ", |
272 | [OP_JMP_LE] = "jle ", | 272 | [OP_JMP_LT] = "jlt ", |
273 | [OP_JMP_GE] = "jge ", | ||
274 | [OP_JMP_LE] = "jle ", | ||
273 | }; | 275 | }; |
274 | 276 | ||
275 | void | 277 | void |
@@ -314,6 +316,13 @@ viz_instruction(Instruction *inst, LineInfo *line) { | |||
314 | printf(" "); | 316 | printf(" "); |
315 | viz_operand(inst->dst); | 317 | viz_operand(inst->dst); |
316 | } break; | 318 | } break; |
319 | case OP_JMP_TRUE: | ||
320 | case OP_JMP_FALSE: { | ||
321 | printf(" "); | ||
322 | viz_operand(inst->dst); | ||
323 | printf(", "); | ||
324 | viz_operand(inst->src_a); | ||
325 | } break; | ||
317 | default: { | 326 | default: { |
318 | printf(" "); | 327 | printf(" "); |
319 | viz_operand(inst->dst); | 328 | viz_operand(inst->dst); |