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