diff options
Diffstat (limited to 'src/ir.c')
-rw-r--r-- | src/ir.c | 45 |
1 files changed, 41 insertions, 4 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}; |