mirror of https://github.com/rui314/9cc.git
Assign offsets to local variables in gen_x86 instead of in gen_ir.
In SSA, we will promote local variables in memory to register values, so that they are allocated to physical registers rather than the stack if there are enough number of registers available. Therefore, computing function's stack size in gen_ir is too early.
This commit is contained in:
parent
443b0b554c
commit
04df768a1f
3
9cc.h
3
9cc.h
|
@ -285,7 +285,6 @@ typedef struct {
|
|||
Node *node;
|
||||
Vector *lvars;
|
||||
Vector *bbs;
|
||||
int stacksize;
|
||||
} Function;
|
||||
|
||||
// Represents toplevel constructs.
|
||||
|
@ -358,8 +357,8 @@ typedef struct {
|
|||
Reg *r2;
|
||||
|
||||
int imm;
|
||||
int imm2;
|
||||
int label;
|
||||
Var *var;
|
||||
|
||||
BB *bb1;
|
||||
BB *bb2;
|
||||
|
|
20
gen_ir.c
20
gen_ir.c
|
@ -123,7 +123,7 @@ static Reg *gen_lval(Node *node) {
|
|||
if (var->is_local) {
|
||||
IR *ir = new_ir(IR_BPREL);
|
||||
ir->r0 = r;
|
||||
ir->imm = var->offset;
|
||||
ir->var = var;
|
||||
} else {
|
||||
IR *ir = emit1(IR_LABEL_ADDR, r);
|
||||
ir->name = var->name;
|
||||
|
@ -426,8 +426,8 @@ static void gen_stmt(Node *node) {
|
|||
|
||||
static void gen_param(Var *var, int i) {
|
||||
IR *ir = new_ir(IR_STORE_ARG);
|
||||
ir->imm = var->offset;
|
||||
ir->imm2 = i;
|
||||
ir->var = var;
|
||||
ir->imm = i;
|
||||
ir->size = var->ty->size;
|
||||
}
|
||||
|
||||
|
@ -438,16 +438,6 @@ void gen_ir(Program *prog) {
|
|||
|
||||
assert(fn->node->op == ND_FUNC);
|
||||
|
||||
// Assign an offset from RBP to each local variable.
|
||||
int off = 0;
|
||||
for (int i = 0; i < fn->lvars->len; i++) {
|
||||
Var *var = fn->lvars->data[i];
|
||||
off += var->ty->size;
|
||||
off = roundup(off, var->ty->align);
|
||||
var->offset = -off;
|
||||
}
|
||||
fn->stacksize = off;
|
||||
|
||||
// Emit IR.
|
||||
Vector *params = fn->node->params;
|
||||
for (int i = 0; i < params->len; i++)
|
||||
|
@ -455,9 +445,7 @@ void gen_ir(Program *prog) {
|
|||
|
||||
gen_stmt(fn->node->body);
|
||||
|
||||
// Later passes shouldn't need the following members,
|
||||
// so make it explicit.
|
||||
fn->lvars = NULL;
|
||||
// Later passes shouldn't need the AST, so make it explicit.
|
||||
fn->node = NULL;
|
||||
}
|
||||
}
|
||||
|
|
16
gen_x86.c
16
gen_x86.c
|
@ -68,7 +68,7 @@ static void emit_ir(IR *ir, char *ret) {
|
|||
emit("mov %s, %d", regs[r0], ir->imm);
|
||||
break;
|
||||
case IR_BPREL:
|
||||
emit("lea %s, [rbp%d]", regs[r0], ir->imm);
|
||||
emit("lea %s, [rbp%d]", regs[r0], ir->var->offset);
|
||||
break;
|
||||
case IR_MOV:
|
||||
emit("mov %s, %s", regs[r0], regs[r2]);
|
||||
|
@ -140,7 +140,7 @@ static void emit_ir(IR *ir, char *ret) {
|
|||
emit("mov [%s], %s", regs[r1], reg(r2, ir->size));
|
||||
break;
|
||||
case IR_STORE_ARG:
|
||||
emit("mov [rbp%d], %s", ir->imm, argreg(ir->imm2, ir->size));
|
||||
emit("mov [rbp%d], %s", ir->var->offset, argreg(ir->imm, ir->size));
|
||||
break;
|
||||
case IR_ADD:
|
||||
emit("add %s, %s", regs[r0], regs[r2]);
|
||||
|
@ -173,6 +173,16 @@ static void emit_ir(IR *ir, char *ret) {
|
|||
}
|
||||
|
||||
void emit_code(Function *fn) {
|
||||
// Assign an offset from RBP to each local variable.
|
||||
int off = 0;
|
||||
for (int i = 0; i < fn->lvars->len; i++) {
|
||||
Var *var = fn->lvars->data[i];
|
||||
off += var->ty->size;
|
||||
off = roundup(off, var->ty->align);
|
||||
var->offset = -off;
|
||||
}
|
||||
|
||||
// Emit assembly
|
||||
char *ret = format(".Lend%d", nlabel++);
|
||||
|
||||
p(".text");
|
||||
|
@ -180,7 +190,7 @@ void emit_code(Function *fn) {
|
|||
p("%s:", fn->name);
|
||||
emit("push rbp");
|
||||
emit("mov rbp, rsp");
|
||||
emit("sub rsp, %d", roundup(fn->stacksize, 16));
|
||||
emit("sub rsp, %d", roundup(off, 16));
|
||||
emit("push r12");
|
||||
emit("push r13");
|
||||
emit("push r14");
|
||||
|
|
5
irdump.c
5
irdump.c
|
@ -73,11 +73,12 @@ static char *tostr(IR *ir) {
|
|||
case IR_STORE:
|
||||
return format("STORE%d r%d, r%d", ir->size, r1, r2);
|
||||
case IR_STORE_ARG:
|
||||
return format("STORE_ARG%d %d, %d", ir->size, ir->imm, ir->imm2);
|
||||
return format("STORE_ARG%d %d %s (%d)", ir->size, ir->imm, ir->var->name,
|
||||
ir->var->offset);
|
||||
case IR_SUB:
|
||||
return format("r%d = r%d - r%d", r0, r1, r2);
|
||||
case IR_BPREL:
|
||||
return format("BPREL r%d %d", r0, ir->imm);
|
||||
return format("BPREL r%d %s (%d)", r0, ir->var->name, ir->var->offset);
|
||||
case IR_BR:
|
||||
return format("BR r%d .L%d .L%d", r2, ir->bb1->label, ir->bb2->label);
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue