diff options
author | Bad Diode <bd@badd10de.dev> | 2022-04-22 22:49:59 -0300 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-04-22 22:49:59 -0300 |
commit | d30601a02fe1af1eb43f15eabf6a427baedfce14 (patch) | |
tree | 5a992b606332c923942b55b476343eb4381baa96 | |
parent | 268ad7e0db894c8fbc445a0ec64bb50d0d0b7c48 (diff) | |
download | bdl-d30601a02fe1af1eb43f15eabf6a427baedfce14.tar.gz bdl-d30601a02fe1af1eb43f15eabf6a427baedfce14.zip |
Add initial BASM generation for arithmetic ops
-rw-r--r-- | src/ir.c | 82 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/viz.c | 93 |
3 files changed, 171 insertions, 8 deletions
@@ -47,23 +47,24 @@ typedef enum OperandType { | |||
47 | OP_TYPE_LABEL, | 47 | OP_TYPE_LABEL, |
48 | } OperandType; | 48 | } OperandType; |
49 | 49 | ||
50 | static size_t reg_gen_id = 0; | ||
51 | |||
52 | #define NEW_REG() (Operand){ .type = OP_TYPE_REG, .id = reg_gen_id++ } | ||
53 | #define NEW_S64(C) (Operand){ .type = OP_TYPE_CONST, .constant.sval = (C) } | ||
54 | |||
50 | typedef struct Operand { | 55 | typedef struct Operand { |
51 | OperandType type; | 56 | OperandType type; |
52 | union { | 57 | union { |
53 | struct { | 58 | // REG/LABEL |
54 | size_t num; | 59 | size_t id; |
55 | } reg; | ||
56 | |||
57 | struct { | ||
58 | size_t num; | ||
59 | } label; | ||
60 | 60 | ||
61 | // s64 constant; | ||
61 | struct { | 62 | struct { |
62 | union { | 63 | union { |
63 | u64 uval; | 64 | u64 uval; |
64 | s64 sval; | 65 | s64 sval; |
65 | }; | 66 | }; |
66 | } const; | 67 | } constant; |
67 | }; | 68 | }; |
68 | } Operand; | 69 | } Operand; |
69 | 70 | ||
@@ -83,3 +84,68 @@ typedef struct ProgramBASM { | |||
83 | Instruction *inst; | 84 | Instruction *inst; |
84 | LineInfo *lines; | 85 | LineInfo *lines; |
85 | } ProgramBASM; | 86 | } ProgramBASM; |
87 | |||
88 | Operand | ||
89 | emit_basm(ProgramBASM *program, Node *node) { | ||
90 | switch (node->type) { | ||
91 | case NODE_NUMBER: { | ||
92 | // TODO: ldX depending on type of number. | ||
93 | Instruction inst = (Instruction){ | ||
94 | .op = OP_LD64, | ||
95 | .dst = NEW_REG(), | ||
96 | .src_a = NEW_S64(node->number.integral), | ||
97 | }; | ||
98 | LineInfo line = (LineInfo){.line = node->line, .col = node->col}; | ||
99 | array_push(program->inst, inst); | ||
100 | array_push(program->lines, line); | ||
101 | return inst.dst; | ||
102 | } break; | ||
103 | case NODE_BUILTIN: { | ||
104 | Operator op; | ||
105 | switch (node->builtin.type) { | ||
106 | case TOKEN_ADD: { op = OP_ADD; } break; | ||
107 | case TOKEN_SUB: { op = OP_SUB; } break; | ||
108 | case TOKEN_MUL: { op = OP_MUL; } break; | ||
109 | case TOKEN_DIV: { op = OP_DIV; } break; | ||
110 | case TOKEN_MOD: { op = OP_MOD; } break; | ||
111 | default: break; | ||
112 | } | ||
113 | Operand reg_a = emit_basm(program, node->builtin.args[0]); | ||
114 | Operand reg_b; | ||
115 | for (size_t i = 1; i < array_size(node->builtin.args); ++i) { | ||
116 | Node *arg = node->builtin.args[i]; | ||
117 | reg_b = emit_basm(program, arg); | ||
118 | Instruction inst = (Instruction){ | ||
119 | .op = op, | ||
120 | .dst = NEW_REG(), | ||
121 | .src_a = reg_a, | ||
122 | .src_b = reg_b, | ||
123 | }; | ||
124 | reg_a = inst.dst; | ||
125 | LineInfo line = (LineInfo){ | ||
126 | .line = node->line, | ||
127 | .col = node->col, | ||
128 | }; | ||
129 | array_push(program->inst, inst); | ||
130 | array_push(program->lines, line); | ||
131 | } | ||
132 | return reg_a; | ||
133 | } break; | ||
134 | default: { | ||
135 | printf("UNIMPLEMENTED\n"); | ||
136 | return (Operand){0}; | ||
137 | } break; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | ProgramBASM * | ||
142 | generate_basm(ParseTree *parse_tree) { | ||
143 | ProgramBASM *program = malloc(sizeof(ProgramBASM)); | ||
144 | array_init(program->inst, 0); | ||
145 | array_init(program->lines, 0); | ||
146 | for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { | ||
147 | Node *root = parse_tree->roots[i]; | ||
148 | emit_basm(program, root); | ||
149 | } | ||
150 | return program; | ||
151 | } | ||
@@ -62,6 +62,10 @@ process_source(const StringView *source, const char *file_name) { | |||
62 | viz_symtables(parse_tree->scopes); | 62 | viz_symtables(parse_tree->scopes); |
63 | return; | 63 | return; |
64 | } | 64 | } |
65 | |||
66 | ProgramBASM *program = generate_basm(parse_tree); | ||
67 | check_errors(file_name); | ||
68 | viz_basm(program); | ||
65 | } | 69 | } |
66 | 70 | ||
67 | void | 71 | void |
@@ -235,3 +235,96 @@ viz_symtables(Scope **scopes) { | |||
235 | } | 235 | } |
236 | printf("}\n"); | 236 | printf("}\n"); |
237 | } | 237 | } |
238 | |||
239 | static const char* basm_op_str[] = { | ||
240 | [OP_ADD] = "add ", | ||
241 | [OP_SUB] = "sub ", | ||
242 | [OP_MUL] = "mul ", | ||
243 | [OP_DIV] = "div ", | ||
244 | [OP_MOD] = "mod ", | ||
245 | [OP_LD8] = "ld8 ", | ||
246 | [OP_LD16] = "ld16 ", | ||
247 | [OP_LD32] = "ld32 ", | ||
248 | [OP_LD64] = "ld64 ", | ||
249 | [OP_ST8] = "st8 ", | ||
250 | [OP_ST16] = "st16 ", | ||
251 | [OP_ST32] = "st32 ", | ||
252 | [OP_ST64] = "st64 ", | ||
253 | [OP_CP8] = "cp8 ", | ||
254 | [OP_CP16] = "cp16 ", | ||
255 | [OP_CP32] = "cp32 ", | ||
256 | [OP_CP64] = "cp64 ", | ||
257 | [OP_NOT] = "not ", | ||
258 | [OP_AND] = "and ", | ||
259 | [OP_OR] = "or ", | ||
260 | [OP_XOR] = "xor ", | ||
261 | [OP_LSHIFT] = "lshift", | ||
262 | [OP_RSHIFT] = "rshift", | ||
263 | [OP_LROT] = "lrot ", | ||
264 | [OP_RROT] = "rrot ", | ||
265 | [OP_LABEL] = "lab ", | ||
266 | [OP_JMP] = "jmp ", | ||
267 | [OP_JMP_EQ] = "jeq ", | ||
268 | [OP_JMP_NEQ] = "jne ", | ||
269 | [OP_JMP_GT] = "jgt ", | ||
270 | [OP_JMP_LT] = "jlt ", | ||
271 | [OP_JMP_GE] = "jge ", | ||
272 | [OP_JMP_LE] = "jle ", | ||
273 | }; | ||
274 | |||
275 | void | ||
276 | viz_operand(Operand op) { | ||
277 | switch (op.type) { | ||
278 | case OP_TYPE_LABEL: { | ||
279 | printf("l%zu", op.id); | ||
280 | } break; | ||
281 | case OP_TYPE_REG: { | ||
282 | printf("r%zu", op.id); | ||
283 | } break; | ||
284 | case OP_TYPE_CONST: { | ||
285 | printf("%lld", op.constant.uval); | ||
286 | } break; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | void | ||
291 | viz_instruction(Instruction *inst, LineInfo *line) { | ||
292 | printf("[%6ld:%-6ld] ", line->line, line->col); | ||
293 | printf("%s", basm_op_str[inst->op]); | ||
294 | switch (inst->op) { | ||
295 | case OP_ST8: | ||
296 | case OP_ST16: | ||
297 | case OP_ST32: | ||
298 | case OP_ST64: | ||
299 | case OP_LD8: | ||
300 | case OP_LD16: | ||
301 | case OP_LD32: | ||
302 | case OP_LD64: { | ||
303 | printf(" "); | ||
304 | viz_operand(inst->dst); | ||
305 | printf(", "); | ||
306 | viz_operand(inst->src_a); | ||
307 | if (inst->src_a.type != OP_TYPE_CONST) { | ||
308 | printf(", "); | ||
309 | viz_operand(inst->src_b); | ||
310 | } | ||
311 | } break; | ||
312 | default: { | ||
313 | printf(" "); | ||
314 | viz_operand(inst->dst); | ||
315 | printf(", "); | ||
316 | viz_operand(inst->src_a); | ||
317 | printf(", "); | ||
318 | viz_operand(inst->src_b); | ||
319 | } break; | ||
320 | } | ||
321 | printf("\n"); | ||
322 | } | ||
323 | |||
324 | void | ||
325 | viz_basm(ProgramBASM *program) { | ||
326 | for (size_t i = 0; i < array_size(program->inst); ++i) { | ||
327 | viz_instruction(&program->inst[i], &program->lines[i]); | ||
328 | } | ||
329 | |||
330 | } | ||