Skip to content

Commit

Permalink
Assign offsets to local variables in gen_x86 instead of in gen_ir.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rui314 committed Sep 1, 2018
1 parent 443b0b5 commit 04df768
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 23 deletions.
3 changes: 1 addition & 2 deletions 9cc.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ typedef struct {
Node *node;
Vector *lvars;
Vector *bbs;
int stacksize;
} Function;

// Represents toplevel constructs.
Expand Down Expand Up @@ -358,8 +357,8 @@ typedef struct {
Reg *r2;

int imm;
int imm2;
int label;
Var *var;

BB *bb1;
BB *bb2;
Expand Down
20 changes: 4 additions & 16 deletions gen_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -438,26 +438,14 @@ 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++)
gen_param(params->data[i], i);

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 changes: 13 additions & 3 deletions gen_x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -173,14 +173,24 @@ 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");
p(".global %s", fn->name);
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");
Expand Down
5 changes: 3 additions & 2 deletions irdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static Var *add_lvar(Type *ty, char *name) {
Var *var = calloc(1, sizeof(Var));
var->ty = ty;
var->is_local = true;
var->name = name;
map_put(env->vars, name, var);
vec_push(lvars, var);
return var;
Expand Down

0 comments on commit 04df768

Please sign in to comment.