aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-04-22 22:49:59 -0300
committerBad Diode <bd@badd10de.dev>2022-04-22 22:49:59 -0300
commitd30601a02fe1af1eb43f15eabf6a427baedfce14 (patch)
tree5a992b606332c923942b55b476343eb4381baa96
parent268ad7e0db894c8fbc445a0ec64bb50d0d0b7c48 (diff)
downloadbdl-d30601a02fe1af1eb43f15eabf6a427baedfce14.tar.gz
bdl-d30601a02fe1af1eb43f15eabf6a427baedfce14.zip
Add initial BASM generation for arithmetic ops
-rw-r--r--src/ir.c82
-rw-r--r--src/main.c4
-rw-r--r--src/viz.c93
3 files changed, 171 insertions, 8 deletions
diff --git a/src/ir.c b/src/ir.c
index 4c85792..4eeb07b 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -47,23 +47,24 @@ typedef enum OperandType {
47 OP_TYPE_LABEL, 47 OP_TYPE_LABEL,
48} OperandType; 48} OperandType;
49 49
50static 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
50typedef struct Operand { 55typedef 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
88Operand
89emit_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
141ProgramBASM *
142generate_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}
diff --git a/src/main.c b/src/main.c
index 0fbabdb..72aac77 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
67void 71void
diff --git a/src/viz.c b/src/viz.c
index ea8a817..eb5631b 100644
--- a/src/viz.c
+++ b/src/viz.c
@@ -235,3 +235,96 @@ viz_symtables(Scope **scopes) {
235 } 235 }
236 printf("}\n"); 236 printf("}\n");
237} 237}
238
239static 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
275void
276viz_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
290void
291viz_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
324void
325viz_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}