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:
Rui Ueyama 2018-09-01 00:40:21 +00:00
parent 443b0b554c
commit 04df768a1f
5 changed files with 22 additions and 23 deletions

3
9cc.h
View File

@ -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;

View File

@ -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;
}
}

View File

@ -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");

View File

@ -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:

View File

@ -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;