aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2014-05-04 21:02:19 +0800
committerTeddy <ted.sybil@gmail.com>2014-05-04 21:02:19 +0800
commit732fc2c154c45f596bf2ffa0b9dd98c1d28e9c33 (patch)
tree78841e7108edd2c04592e9d03eb213e63668033c
parent2c9342037673e5d979cb42cfea6b82436e0cc912 (diff)
can now pass ALL official testcases
-rw-r--r--lib.s18
-rw-r--r--mips.c183
-rw-r--r--ssa.c11
-rw-r--r--ssa.h1
4 files changed, 170 insertions, 43 deletions
diff --git a/lib.s b/lib.s
index c8c4b2e..32e5a77 100644
--- a/lib.s
+++ b/lib.s
@@ -154,16 +154,16 @@ _func_malloc:
syscall
jr $31
_func_memcpy: # the copied mem must be 4-aligned
- lw $8, 0($sp) # dest addr
- lw $9, 4($sp) # src addr
- lw $10, 8($sp) # size
+ lw $4, 0($sp) # dest addr
+ lw $5, 4($sp) # src addr
+ lw $6, 8($sp) # size
j __COND
__LOOP:
- lw $2, 0($9)
- sw $2, 0($8)
- addiu $8, $8, 4
- addiu $9, $9, 4
- addiu $10, $10, -4
+ lw $2, 0($5)
+ sw $2, 0($4)
+ addiu $4, $4, 4
+ addiu $5, $5, 4
+ addiu $6, $6, -4
__COND:
- bnez $10, __LOOP
+ bnez $6, __LOOP
jr $31
diff --git a/mips.c b/mips.c
index eeada74..2ccbb3d 100644
--- a/mips.c
+++ b/mips.c
@@ -7,6 +7,7 @@
int reg_v0 = 2;
int reg_v1 = 3;
+int memcpy_cnt;
static int save_pos[32];
static int used_reg[32];
@@ -74,7 +75,7 @@ void mips_load(int reg, COpr_t opr) {
if (var->loc > 0)
printf("\tla $%d, _%s\n", reg, var->name);
else
- printf("\taddi $%d, $sp, %d\n", reg, var->start);
+ printf("\taddiu $%d, $sp, %d\n", reg, var->start);
}
else
{
@@ -119,9 +120,24 @@ int mips_to_reg(COpr_t opr, int reg0) {
return reg0;
}
+void mips_memcpy() {
+ printf("\tj _mem_cond%d\n", memcpy_cnt);
+ printf("_mem_loop%d:\n", memcpy_cnt);
+ printf("\tlw $5, 0($%d)\n", reg_v0);
+ printf("\tsw $5, 0($%d)\n", reg_v1);
+ printf("\taddiu $%d, $%d, 4\n", reg_v1, reg_v1);
+ printf("\taddiu $%d, $%d, 4\n", reg_v0, reg_v0);
+ printf("\taddiu $a0, $a0, -4\n");
+ printf("_mem_cond%d:\n", memcpy_cnt);
+ printf("\tbnez $a0, _mem_loop%d\n", memcpy_cnt);
+ memcpy_cnt++;
+}
+
+/* memcpy requires three arguments */
+#define RESERVED_CALL_SIZE 12
void mips_space_alloc() {
int local_size = func->rec.func.local_size;
- int arg_size = 0;
+ int arg_size = RESERVED_CALL_SIZE;
int bret_size = 0;
int tmp_size = 0;
int offset = 0;
@@ -184,6 +200,7 @@ void mips_space_alloc() {
i->bret = bret_size;
bret_size += calc_size(rt);
}
+ else i->bret = -1;
}
}
}
@@ -198,6 +215,8 @@ void mips_space_alloc() {
int i;
for (i = 0; i < MAX_AVAIL_REGS; i++)
save_pos[avail_regs[i]] = prev + i * INT_SIZE;
+ save_pos[30] = save_size;
+ save_size += INT_SIZE;
}
prev += save_size;
/* adjust offset for spilled temporaries */
@@ -214,7 +233,7 @@ void mips_space_alloc() {
{
CInst_t i, ih = p->insts;
for (i = ih->next; i != ih; i = i->next)
- if (i->op == CALL)
+ if (i->op == CALL && i->bret != -1)
i->bret += prev;
}
prev += bret_size;
@@ -255,6 +274,7 @@ void mips_func_end() {
void mips_generate() {
CBlock_t p;
+ CType_t rt = func->rec.func.ret;
/* int arg_cnt = 0; */
mips_space_alloc();
if (strcmp(func->name, "main"))
@@ -287,12 +307,31 @@ void mips_generate() {
/* TODO: struct */
int rs = mips_to_reg(i->src1, reg_v0);
int rd = i->dest->reg;
- if (rd > 0)
- printf("\tmove $%d $%d\n", rd, rs);
+ CType_t type = i->dest->type;
+ if (type->type == CSTRUCT || type->type == CUNION)
+ {
+ assert(i->dest->kind == VAR);
+ printf("\tsw $%d, 4($sp)\n", rs);
+ if (rd < 0) rd = reg_v0;
+ mips_load(rd, i->dest);
+ printf("\tsw $%d, 0($sp)\n", rd);
+ printf("\tli $%d, %d\n", reg_v0, calc_size(type));
+ printf("\tsw $%d, 8($sp)\n", reg_v0);
+ /* don't need to save current registers because
+ * memcpy doesn't interfere with them */
+ printf("\tjal _func_memcpy\n");
+ }
else
- rd = rs;
- if (i->dest->reg == -1 || i->dest->kind == VAR)
- mips_store(rd, i->dest);
+ {
+ if (rd > 0)
+ {
+ if (rd != rs) printf("\tmove $%d $%d\n", rd, rs);
+ }
+ else
+ rd = rs;
+ if (i->dest->reg == -1 || i->dest->kind == VAR)
+ mips_store(rd, i->dest);
+ }
}
break;
case BEQZ:
@@ -325,7 +364,7 @@ void mips_generate() {
{
int index = i->src2->info.imm;
rd = i->dest->reg;
- if (rd == -1) rd = reg_v1;
+ if (rd < 0) rd = reg_v1;
printf("\t%s $%d, %d($%d)\n", l, rd, index, arr);
}
else
@@ -342,26 +381,54 @@ void mips_generate() {
break;
case WARR:
{
- CType_t type = i->dest->type;
- int arr = mips_to_reg(i->dest, reg_v0);
+ CType_t type = i->wtype;
+ int arr = mips_to_reg(i->dest, reg_v1);
const char *s;
int rs;
+ /*
if (type->type == CARR)
type = type->rec.arr.elem;
else
type = type->rec.ref;
+ */
s = type->type == CCHAR ? "sb" : "sw";
- if (i->src2->kind == IMM)
+
+ if (type->type == CSTRUCT || type->type == CUNION)
{
- rs = mips_to_reg(i->src1, reg_v1);
- printf("\t%s $%d, %d($%d)\n", s, rs, i->src2->info.imm, arr);
+ if (i->src2->kind == IMM)
+ printf("\taddiu $%d, $%d, %d\n", reg_v1, arr, i->src2->info.imm);
+ else
+ {
+ int index = mips_to_reg(i->src2, reg_v0);
+ printf("\taddu $%d, $%d, $%d\n", reg_v1, arr, index);
+ }
+ rs = mips_to_reg(i->src1, reg_v0);
+ printf("\tmove $%d, $%d\n", reg_v0, rs);
+ printf("\tli $a0, %d\n", calc_size(type));
+ mips_memcpy();
}
else
{
- int index = mips_to_reg(i->src2, reg_v1);
- printf("\taddu $%d, $%d, $%d\n", reg_v1, arr, index);
- rs = mips_to_reg(i->src1, reg_v0);
- printf("\t%s $%d, 0($%d)\n", s, rs, reg_v1);
+ if (i->src2->kind == IMM)
+ {
+ rs = mips_to_reg(i->src1, reg_v0);
+ if (type->type == CSTRUCT || type->type == CUNION)
+ {
+ printf("\tmove $%d, $%d\n", reg_v0, rs);
+ printf("\taddiu $%d, $%d, $%d\n", reg_v1, arr, i->src2->info.imm);
+ printf("\tli $a0, %d\n", calc_size(type));
+ mips_memcpy();
+ }
+ else
+ printf("\t%s $%d, %d($%d)\n", s, rs, i->src2->info.imm, arr);
+ }
+ else
+ {
+ int index = mips_to_reg(i->src2, reg_v0);
+ printf("\taddu $%d, $%d, $%d\n", reg_v0, arr, index);
+ rs = mips_to_reg(i->src1, reg_v1);
+ printf("\t%s $%d, 0($%d)\n", s, rs, reg_v0);
+ }
}
}
break;
@@ -376,8 +443,24 @@ void mips_generate() {
else
{
*/
- /* TODO: push struct */
- printf("\tsw $%d, %d($sp) # push\n", rs, i->offset);
+ CType_t type = i->src1->type;
+ if (type && (type->type == CSTRUCT || type->type == CUNION))
+ {
+ /*
+ printf("\tsw $%d, 4($sp)\n", rs);
+ printf("\taddiu $%d, $sp, %d\n", reg_v0, i->offset);
+ printf("\tsw $%d, 0($sp)\n", reg_v0);
+ printf("\tli $%d, %d\n", reg_v0, calc_size(type));
+ printf("\tsw $%d, 8($sp)\n", reg_v0);
+ printf("\tjal _func_memcpy\n");
+ */
+ printf("\taddiu $%d, $sp, %d\n", reg_v1, i->offset);
+ printf("\tmove $%d, $%d\n", reg_v0, rs);
+ printf("\tli $a0, %d\n", calc_size(type));
+ mips_memcpy();
+ }
+ else
+ printf("\tsw $%d, %d($sp) # push\n", rs, i->offset);
/* }
arg_cnt++; */
}
@@ -388,6 +471,8 @@ void mips_generate() {
int rd = i->dest->reg;
int j;
memset(used_reg, 0, sizeof used_reg);
+ if (rt->type == CSTRUCT || rt->type == CUNION)
+ used_reg[30] = 1; /* save $fp */
for (p = defs; p; p = p->next)
{
COpr_t opr = p->opr;
@@ -399,6 +484,13 @@ void mips_generate() {
for (j = 0; j < 32; j++)
if (used_reg[j])
printf("\tsw $%d, %d($sp) # save reg\n", j, save_pos[j]);
+ if (i->bret != -1)
+ {
+ if (i->dest->kind == TMP)
+ printf("\taddiu $fp, $sp, %d\n", i->bret);
+ else
+ mips_load(30, i->dest);
+ }
if (i->src1->kind == IMMF)
printf("\tjal %s%s\n",
strcmp(i->src1->info.str, "main") ? "_func_" : "",
@@ -419,12 +511,25 @@ void mips_generate() {
}
if (rd != -2)
{
- if (rd != -1)
- printf("\tmove $%d, $%d\n", rd, reg_v0);
+ if (i->bret != -1 && i->dest->kind == VAR)
+ {
+ if (rd == -1)
+ rd = mips_to_reg(i->dest, reg_v1);
+ printf("\tmove $%d, $%d\n", reg_v1, rd);
+ printf("\tli $a0, %d\n", calc_size(i->dest->type));
+ mips_memcpy();
+ }
else
- rd = reg_v0;
- if (i->dest->reg == -1 || i->dest->kind == VAR)
- mips_store(reg_v0, i->dest);
+ {
+ if (rd != -1)
+ printf("\tmove $%d, $%d\n", rd, reg_v0);
+ /*
+ else
+ rd = reg_v0;
+ */
+ if (i->dest->reg == -1 || i->dest->kind == VAR)
+ mips_store(reg_v0, i->dest);
+ }
}
}
break;
@@ -432,15 +537,31 @@ void mips_generate() {
{
if (i->src1)
{
- if (i->src1->reg != -1)
+ if (rt->type == CSTRUCT || rt->type == CUNION)
{
- if (i->src1->kind == IMM)
- printf("\tli $%d, %d\n", reg_v0, i->src1->info.imm);
- else
- printf("\tmove $%d, $%d\n", reg_v0, mips_to_reg(i->src1, reg_v1));
+ int rs = mips_to_reg(i->src1, reg_v0);
+ assert(i->src1->kind == VAR || i->src1->kind == TMP);
+ printf("\tsw $%d, 4($sp)\n", rs);
+ printf("\tsw $fp, 0($sp)\n");
+ printf("\tli $%d, %d\n", reg_v0, calc_size(rt));
+ printf("\tsw $%d, 8($sp)\n", reg_v0);
+ printf("\tjal _func_memcpy\n");
+ printf("\tmove $%d, $fp\n", reg_v0);
}
else
- mips_to_reg(i->src1, reg_v0);
+ {
+ if (i->src1->reg != -1)
+ {
+ if (i->src1->kind == IMM)
+ printf("\tli $%d, %d\n", reg_v0, i->src1->info.imm);
+ else
+ printf("\tmove $%d, $%d\n", reg_v0, mips_to_reg(i->src1, reg_v1));
+ }
+ else
+ {
+ mips_to_reg(i->src1, reg_v0);
+ }
+ }
}
printf("\tj _ret_%s\n", func->name);
}
diff --git a/ssa.c b/ssa.c
index 6fcc653..81f3f2b 100644
--- a/ssa.c
+++ b/ssa.c
@@ -337,14 +337,17 @@ void ssa_generate() {
#define POINTER_CONV(inst) \
do { \
- if (rt->type == CARR || rt->type == CSTRUCT || rt->type == CUNION) \
+ if (rt->type == CARR) \
{ \
/* convert to pointer type */ \
- CType_t a = ctype_create("", CPTR, p); \
+ CType_t a; \
+ a = ctype_create("", CPTR, p); \
a->rec.ref = rt->rec.arr.elem; \
(inst)->op = ADD; \
- (inst)->dest->type = a; \
+ (inst)->dest->type = a; \
} \
+ else if (rt->type == CSTRUCT || rt->type == CUNION) \
+ (inst)->op = ADD; \
else (inst)->op = ARR; \
} while (0)
@@ -477,6 +480,7 @@ COpr_t ssa_postfix(CNode *p, CBlock_t *cur, CInst_t lval, CBlock_t succ) {
lval->op = WARR;
lval->dest = base->src1;
lval->src2 = base->src2;
+ lval->wtype = p->ext.type;
free(base);
return lval->dest;
}
@@ -585,6 +589,7 @@ COpr_t ssa_exp_(CNode *p, CBlock_t *cur, CInst_t lval, CBlock_t succ) {/*{{{*/
lval->src2 = copr_create();
lval->src2->kind = IMM;
lval->src2->info.imm = 0;
+ lval->wtype = p->ext.type;
return lval->dest;
}
else
diff --git a/ssa.h b/ssa.h
index 77010a4..aeef029 100644
--- a/ssa.h
+++ b/ssa.h
@@ -73,6 +73,7 @@ struct CInst {
} op;
COpr_t dest, src1, src2;
CInst_t next, prev;
+ CType_t wtype; /* for WARR */
int id;
int is_def;
int bret; /* for CALL */