#include <stdio.h>
#include <assert.h>
#include "ssa.h"
#include "mips.h"
int reg_v0 = 2;
int reg_v1 = 3;
void mips_prologue() {
CVList_t v;
CSList_t s;
printf(".data 0x10000000\n");
for (v = gvars; v; v = v->next)
{
CVar_t var = v->var;
printf("\t.align 2\n");
printf("_%s:\n", var->name);
var->start = -1;
printf("\t.space %d\n", calc_size(var->type));
}
for (s = cstrs; s; s = s->next)
{
printf("_str_%d:\n", s->id);
printf("\t.asciiz \"%s\"\n", s->str);
}
/* pre-calc done */
printf(".text\n");
}
void mips_load(int reg, COpr_t opr) {
CVar_t var = cinterv_repr(opr)->info.var;
CType_t type = var->type;
if (type->type == CSTRUCT ||
type->type == CUNION ||
type->type == CARR)
{
if (var->global)
printf("\tla $%d, _%s\n", reg, var->name);
else
printf("\taddi $%d, $sp, %d\n", reg, var->start);
}
else
{
const char *l = type->type == CCHAR ? "lb" : "lw";
if (var->global)
printf("\t%s $%d, _%s\n", l, reg, var->name);
else
printf("\t%s $%d, %d($sp)\t#%s\n", l, reg, var->start, var->name);
}
}
void mips_store(int reg, COpr_t opr) {
CVar_t var = cinterv_repr(opr)->info.var;
CType_t type = var->type;
const char *l = type->type == CCHAR ? "sb" : "sw";
/* TODO: struct */
if (var->global)
printf("\t%s $%d, _%s\n", l, reg, var->name);
else
printf("\t%s $%d, %d($sp)\t#%s\n", l, reg, var->start, var->name);
}
int mips_to_reg(COpr_t opr, int reg0) {
if (opr->kind == IMM)
{
printf("\tli $%d, %d\n", reg0, opr->info.imm);
return reg0;
}
else if (opr->kind == IMMS)
{
printf("\tla $%d, _str_%d\n", reg0, opr->info.cstr->id);
return reg0;
}
else if (opr->kind == IMMF)
{
printf("\tla $%d, %s\n", reg0, opr->info.str);
return reg0;
}
if (opr->reg != -1) return opr->reg;
mips_load(reg0, opr);
return reg0;
}
void mips_space_alloc() {
int local_size = func->rec.func.local_size;
int arg_size = 0;
int bret_size = 0;
int tmp_size = 0;
int offset = 0;
int prev = 0;
CBlock_t p;
COList_t d;
CVar_t v;
for (d = defs; d; d = d->next)
{
COpr_t opr = d->opr;
if (opr->kind == TMP && opr->par == opr)
{
int t = opr->info.var->type->type;
tmp_size += align_shift(tmp_size);
opr->info.var->start = tmp_size;
if (t == CSTRUCT || t == CUNION || t == CARR)
tmp_size += PTR_SIZE;
else if (t == CVOID)
tmp_size += INT_SIZE;
else
tmp_size += calc_size(opr->info.var->type);
}
}
for (p = entry; p; p = p->next)
{
CInst_t i, ih = p->insts;
for (i = ih->next; i != ih; i = i->next)
{
if (i->op == PUSH)
{
COpr_t arg = i->src1;
offset += align_shift(offset);
i->offset = offset;
if (arg->kind == IMM)
offset += INT_SIZE;
else if (arg->kind == IMMS)
offset += PTR_SIZE;
else if (arg->kind == IMMF)
offset += PTR_SIZE;
else
{
CType_t t = arg->info.var->type;
if (t->type == CARR)
offset += PTR_SIZE;
else
offset += calc_size(t);
}
}
else if (i->op == CALL)
{
CType_t rt = i->dest->info.var->type;
if (offset > arg_size)
arg_size = offset;
offset = 0;
if (rt->type == CSTRUCT || rt->type == CUNION)
{
bret_size += align_shift(bret_size);
i->bret = bret_size;
bret_size += calc_size(rt);
}
}
}
}
prev += arg_size;
prev += align_shift(prev);
/* adjust offset for local variables */
for (v = func->rec.func.local; v; v = v->next)
v->start += prev;
prev += local_size;
prev += align_shift(prev);
/* adjust offset for spilled temporaries */
for (d = defs; d; d = d->next)
{
COpr_t opr = d->opr;
if (opr->kind == TMP && opr->par == opr)
opr->info.var->start += prev;
}
prev += tmp_size;
prev += align_shift(prev);
for (p = entry; p; p = p->next)
{
CInst_t i, ih = p->insts;
for (i = ih->next; i != ih; i = i->next)
if (i->op == CALL)
i->bret += prev;
}
prev += bret_size;
prev += align_shift(prev);
prev += 4; /* return address */
for (v = func->rec.func.params; v; v = v->next)
v->start += prev; /* skip the whole frame to reach args */
func->rec.func.frame_size = prev;
}
void mips_func_begin() {
int fsize = func->rec.func.frame_size;
printf("\taddiu $sp, $sp, -%d\n", fsize);
printf("\tsw $31, %d($sp)\n", fsize - 4);
}
void mips_func_end() {
int fsize = func