aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-04-25 11:59:22 -0300
committerBad Diode <bd@badd10de.dev>2022-04-25 11:59:22 -0300
commitada3f3a2eac5b3828c3a55970d5640fef922d3d0 (patch)
tree6e1ce0a6cb41b21f3fd58eade27d3f219cb05c46
parent38fd557a61e7366140b6fbdacfebc3ad28f55369 (diff)
downloadbdl-ada3f3a2eac5b3828c3a55970d5640fef922d3d0.tar.gz
bdl-ada3f3a2eac5b3828c3a55970d5640fef922d3d0.zip
Add BASM generation for `if` expressions
-rw-r--r--src/ir.c45
-rw-r--r--src/ir.h2
-rw-r--r--src/viz.c75
3 files changed, 85 insertions, 37 deletions
diff --git a/src/ir.c b/src/ir.c
index f1b7eb9..86a1a9a 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -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 93Operand
94emit_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
102Operand 138Operand
103emit_basm(ProgramBASM *program, Node *node) { 139emit_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};
diff --git a/src/ir.h b/src/ir.h
index d5b167e..c0ce22a 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -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,
diff --git a/src/viz.c b/src/viz.c
index 3d6a0f7..8e31387 100644
--- a/src/viz.c
+++ b/src/viz.c
@@ -237,39 +237,41 @@ viz_symtables(Scope **scopes) {
237} 237}
238 238
239static const char* basm_op_str[] = { 239static 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
275void 277void
@@ -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);