Skip to content

Commit 072bd82

Browse files
committed
lvalue is memory; expression parsing improvements; stack_alloc
1 parent d21681f commit 072bd82

4 files changed

Lines changed: 95 additions & 40 deletions

File tree

src/core.h

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "stdio.h"
77
#include "stdlib.h"
88
#include "string.h"
9+
#include "sys/param.h"
910

1011
typedef struct {
1112
size_t start;
@@ -101,7 +102,7 @@ typedef struct {
101102
} OperandImmediate;
102103

103104
typedef enum {
104-
REL_RIP,
105+
REL_RIP = 1,
105106
REL_RBP,
106107
SYMBOL_LOCAL,
107108
SYMBOL_GLOBAL,
@@ -115,7 +116,7 @@ typedef struct {
115116
typedef struct {
116117
OperandTag tag;
117118
// in case operand is used in lvalue context, use this instead of `o`
118-
OperandRegister lvalue;
119+
OperandMemory lvalue;
119120
union {
120121
OperandRegister reg;
121122
OperandImmediate immediate;
@@ -163,23 +164,54 @@ typedef struct {
163164
Operand operand;
164165
} Operator;
165166

166-
uint8_t operator_precedence[] = {4, 4, 7, 7, 6, 6, 6, 6, 1, 2, 14, 3, 11, 12, 2};
167+
uint8_t operator_precedence[] = {
168+
0,
169+
4, // OP_ADD
170+
4, // OP_SUB
171+
7, // OP_EQ
172+
7, // OP_NEQ
173+
6, // OP_GT
174+
6, // OP_GE
175+
6, // OP_LT
176+
6, // OP_LE
177+
1, // OP_INDEX
178+
2, // OP_INCREMENT
179+
14, // OP_ASSIGN
180+
3, // OP_REMAINDER
181+
11, // OP_AND
182+
12, // OP_OR
183+
2, // OP_ADDRESS_OF
184+
};
167185

168186
typedef enum {
169187
ASSOC_LEFT,
170188
ASSOC_RIGHT,
171189
} Associativity;
172190

173191
uint8_t operator_associativity[] = {
174-
ASSOC_LEFT, ASSOC_LEFT, ASSOC_LEFT, ASSOC_LEFT, ASSOC_LEFT,
175-
ASSOC_LEFT, ASSOC_LEFT, ASSOC_LEFT, ASSOC_LEFT, ASSOC_RIGHT,
176-
ASSOC_RIGHT, ASSOC_LEFT, ASSOC_LEFT, ASSOC_LEFT, ASSOC_RIGHT,
192+
0,
193+
ASSOC_LEFT, // OP_ADD
194+
ASSOC_LEFT, // OP_SUB
195+
ASSOC_LEFT, // OP_EQ
196+
ASSOC_LEFT, // OP_NEQ
197+
ASSOC_LEFT, // OP_GT
198+
ASSOC_LEFT, // OP_GE
199+
ASSOC_LEFT, // OP_LT
200+
ASSOC_LEFT, // OP_LE
201+
ASSOC_LEFT, // OP_INDEX
202+
ASSOC_RIGHT, // OP_INCREMENT
203+
ASSOC_RIGHT, // OP_ASSIGN
204+
ASSOC_LEFT, // OP_REMAINDER
205+
ASSOC_LEFT, // OP_AND
206+
ASSOC_LEFT, // OP_OR
207+
ASSOC_RIGHT, // OP_ADDRESS_OF
177208
};
178209

179210
typedef struct {
180211
Span span;
181212
Operand operand;
182213
size_t size;
214+
size_t count;
183215
size_t item_size;
184216
size_t index;
185217
ElfSymbolEntry entry;
@@ -203,14 +235,14 @@ size_t stack_size = 0;
203235

204236
/**
205237
* RSP offset in a current function
206-
* push increments to keep it unsigned
207238
*/
208-
size_t stack_offset = 0;
239+
int32_t stack_offset = 0;
209240

210241
void stack_push() {
242+
Scope last = stack[stack_size];
211243
stack[stack_size++] = (Scope){
212244
.symbols_start = symbols_size,
213-
.bp_offset = 0,
245+
.bp_offset = last.bp_offset,
214246
};
215247
}
216248

src/emit.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ void asm_mov(Operand a, Operand b) {
194194
text_buf[text_size++] = (uint8_t)b.memory.offset;
195195
return;
196196
}
197+
if (a.tag == MEMORY && b.tag == MEMORY) {
198+
Operand tmp = expr_registers[expr_registers_busy];
199+
asm_mov(tmp, b);
200+
asm_mov(a, tmp);
201+
return;
202+
}
197203
fprintf(stderr, "TODO asm_mov %d %d\n", a.tag, b.tag);
198204
asm_nop();
199205
}
@@ -291,7 +297,7 @@ void asm_push(Operand a) {
291297
text_buf[text_size++] = rex(false, false, false, true);
292298
}
293299
text_buf[text_size++] = 0x50 + (a.reg.i & 0b111);
294-
stack_offset += 8;
300+
stack_offset -= 8;
295301
return;
296302
}
297303
fprintf(stderr, "TODO asm_push\n");
@@ -304,7 +310,7 @@ void asm_pop(Operand a) {
304310
text_buf[text_size++] = rex(false, false, false, true);
305311
}
306312
text_buf[text_size++] = 0x58 + (a.reg.i & 0b111);
307-
stack_offset -= 8;
313+
stack_offset += 8;
308314
return;
309315
}
310316
fprintf(stderr, "TODO asm_pop\n");
@@ -377,7 +383,7 @@ void asm_sete(Operand a) {
377383
if (a.tag == REGISTER) {
378384
text_buf[text_size++] = 0x0F;
379385
text_buf[text_size++] = 0x94;
380-
text_buf[text_size++] = modrm(MOD_REGISTER, a.reg.i, 0);
386+
text_buf[text_size++] = modrm(MOD_REGISTER, 0, a.reg.i);
381387
return;
382388
}
383389
if (a.tag == MEMORY && a.memory.mode == REL_RBP) {

src/expr.h

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "core.h"
22
#include "emit.h"
33

4+
Operand stack_alloc(size_t size);
45
Expr visit_operand();
56
Operator visit_op_infix();
67
Operator visit_op_prefix();
@@ -23,7 +24,7 @@ typedef struct {
2324
*
2425
* @see https://en.wikipedia.org/wiki/Shunting_yard_algorithm
2526
*/
26-
bool shunting_yard(ExprToken expr_stack[], size_t* expr_stack_size) {
27+
bool shunting_yard(ExprToken out_queue[], size_t* out_queue_size) {
2728
Operator op_stack[1 << 10];
2829
size_t op_stack_size = 0;
2930

@@ -49,7 +50,7 @@ bool shunting_yard(ExprToken expr_stack[], size_t* expr_stack_size) {
4950
Expr operand = visit_operand();
5051
if (!operand.ok) return false;
5152
expr_token.operand = operand.operand;
52-
expr_stack[(*expr_stack_size)++] = expr_token;
53+
out_queue[(*out_queue_size)++] = expr_token;
5354
infix_postfix_time = true;
5455
}
5556
}
@@ -58,19 +59,20 @@ bool shunting_yard(ExprToken expr_stack[], size_t* expr_stack_size) {
5859
Operator op = expr_token.op;
5960
while (op_stack_size > 0 && (operator_precedence[op_stack[op_stack_size - 1].tag] <
6061
operator_precedence[op.tag] ||
61-
(operator_associativity[op.tag] == ASSOC_LEFT &&
62-
operator_precedence[op_stack[op_stack_size - 1].tag] ==
63-
operator_precedence[op.tag]))) {
64-
expr_stack[(*expr_stack_size)++] = (ExprToken){
62+
(operator_precedence[op_stack[op_stack_size - 1].tag] ==
63+
operator_precedence[op.tag] &&
64+
operator_associativity[op.tag] == ASSOC_LEFT))) {
65+
out_queue[(*out_queue_size)++] = (ExprToken){
6566
.is_operator = true,
6667
.op = op_stack[--op_stack_size],
6768
};
6869
}
6970
op_stack[op_stack_size++] = op;
7071
}
7172
}
73+
7274
while (op_stack_size > 0) {
73-
expr_stack[(*expr_stack_size)++] = (ExprToken){
75+
out_queue[(*out_queue_size)++] = (ExprToken){
7476
.is_operator = true,
7577
.op = op_stack[--op_stack_size],
7678
};
@@ -139,13 +141,15 @@ Expr visit_expr() {
139141
asm_push(RDX);
140142

141143
asm_mov(RAX, *o1);
144+
asm_mov(RDX, immediate(0));
142145
asm_idiv(o2);
143-
asm_mov(tmp, RDX);
146+
Operand tmp_stack = stack_alloc(8);
147+
asm_mov(tmp_stack, RDX);
144148

145149
asm_pop(RDX);
146150
asm_pop(RAX);
147151

148-
*o1 = tmp;
152+
*o1 = tmp_stack;
149153
break;
150154
}
151155
case OP_AND: {
@@ -175,7 +179,7 @@ Expr visit_expr() {
175179
case OP_EQ: {
176180
asm_cmp(*o1, o2);
177181
asm_mov(tmp, immediate(0));
178-
asm_setne(tmp);
182+
asm_sete(tmp);
179183
*o1 = tmp;
180184
break;
181185
}
@@ -184,11 +188,12 @@ Expr visit_expr() {
184188
break;
185189
}
186190
case OP_ASSIGN: {
187-
if (o1->lvalue.size == 0) {
191+
if (o1->lvalue.mode == 0) {
188192
fprintf(stderr, "not an lvalue\n");
193+
assert(false);
189194
return (Expr){};
190195
}
191-
asm_mov((Operand){.tag = REGISTER, .reg = o1->lvalue}, o2);
196+
asm_mov((Operand){.tag = MEMORY, .memory = o1->lvalue}, o2);
192197
break;
193198
}
194199
default: {
@@ -205,16 +210,15 @@ Expr visit_expr() {
205210
case OP_INDEX: {
206211
Operand idx = op.operand;
207212
{
208-
Operand ptr = expr_registers[expr_registers_busy++];
213+
Operand ptr = stack_alloc(8);
209214
asm_mov(ptr, idx);
210215
asm_add(ptr, *o);
211216

212217
Operand res = expr_registers[expr_registers_busy++];
213-
ptr.reg.indirect = true;
218+
res.lvalue = ptr.lvalue;
214219
asm_mov(res, ptr);
215220

216221
*o = res;
217-
o->lvalue = ptr.reg;
218222
}
219223
goto c;
220224
}

src/parse.h

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
#include "emit.h"
44
#include "expr.h"
55

6+
Operand stack_alloc(size_t size) {
7+
Scope* scope = &stack[stack_size];
8+
Operand operand = {
9+
.tag = MEMORY,
10+
.memory = {.mode = REL_RBP, .offset = scope->bp_offset},
11+
};
12+
operand.lvalue = operand.memory;
13+
scope->bp_offset -= size;
14+
return operand;
15+
}
16+
617
Symbol* symbol_find(Span span) {
718
if (stack_size == 0) return NULL;
819
for (int64_t scope = stack_size - 1; scope >= 0; scope--) {
@@ -36,16 +47,14 @@ Symbol* symbol_add_global(Span name, size_t pos, bool impl) {
3647
}
3748

3849
Symbol* symbol_add_stack(Span name_span, size_t size, size_t count) {
39-
Scope* scope = &stack[stack_size];
40-
scope->bp_offset -= size;
41-
Operand operand = {
42-
.tag = MEMORY,
43-
.memory = {.mode = REL_RBP, .offset = scope->bp_offset},
44-
};
50+
size_t s = size * MAX(count, 1);
51+
Operand operand = stack_alloc(s);
52+
operand.lvalue = operand.memory;
4553
symbols_buf[symbols_size++] = (Symbol){
4654
.span = name_span,
47-
.operand = operand,
48-
.size = size * count,
55+
.operand = stack_alloc(s),
56+
.size = s,
57+
.count = count,
4958
.item_size = size,
5059
};
5160
return &symbols_buf[symbols_size - 1];
@@ -295,8 +304,9 @@ Expr visit_operand() {
295304
if (!ident.ok) return expr;
296305
Symbol* symbol = symbol_find(ident.span);
297306
if (symbol == NULL) return expr;
298-
if (symbol->size > 0) {
307+
if (symbol->count > 0) {
299308
Operand tmp = expr_registers[expr_registers_busy++];
309+
tmp.lvalue = symbol->operand.lvalue;
300310
asm_lea(tmp, symbol->operand);
301311
expr.operand = tmp;
302312
} else {
@@ -318,8 +328,11 @@ Expr visit_operand() {
318328
fprintf(stderr, "TODO %s\n", token_name[t.type]);
319329
return expr;
320330
} else if (t.type == O_PAREN) {
321-
fprintf(stderr, "TODO %s\n", token_name[t.type]);
322-
return expr;
331+
token_pos++;
332+
Expr sub_expr = visit_expr();
333+
if (!sub_expr.ok) return expr;
334+
token_pos++;
335+
expr.operand = sub_expr.operand;
323336
} else {
324337
fprintf(stderr, "TODO %s\n", token_name[t.type]);
325338
return expr;
@@ -423,7 +436,7 @@ Expr visit_call() {
423436
}
424437

425438
size_t misalign = stack_offset % 16;
426-
if (misalign > 0) asm_sub(RSP, immediate(misalign));
439+
if (misalign != 0) asm_sub(RSP, immediate(misalign));
427440

428441
if (symbol->entry.name != 0) {
429442
asm_call_global(symbol);
@@ -561,7 +574,7 @@ bool visit_func_def() {
561574
symbol_add_global(name.span, symbol_pos, true);
562575
stack_push();
563576

564-
stack_offset = stack_prealloc;
577+
stack_offset = -stack_prealloc;
565578

566579
// TODO: only preserve used registers
567580
for (size_t i = 0; i < non_volatile_registers_size; i++) {

0 commit comments

Comments
 (0)