Rework the way stack frames are laid out to be simpler and, hopefully, more

correct. Saved registers are now placed in what may be the right place.
This commit is contained in:
David Given 2016-11-11 21:17:45 +01:00
parent 84ee75ec07
commit b5c1d622f5
3 changed files with 50 additions and 20 deletions

View file

@ -6,13 +6,13 @@
* | --------------- <- ab * | --------------- <- ab
* | old FR * | old FR
* | old FP * | old FP
* | --------------- <- st, fp (a.k.a. lb) * | --------------- <- fp (a.k.a. lb)
* | locals * | locals
* | ---------------
* | spills
* | --------------- * | ---------------
* | spills
* | --------------- <- sb
* | saved regs * | saved regs
* | --------------- <- sp * | --------------- <- sp, rb
* V ...user area... * V ...user area...
* *
* st indexes up; lb indexes down. * st indexes up; lb indexes down.
@ -31,17 +31,31 @@ void platform_calculate_offsets(void)
{ {
struct hreg* hreg = current_proc->usedregs.item[i]; struct hreg* hreg = current_proc->usedregs.item[i];
if (!(hreg->attrs & burm_volatile_ATTR) &&
((hreg->attrs & burm_long_ATTR) || (hreg->attrs & burm_double_ATTR)))
{
hreg->offset = current_proc->saved_size;
current_proc->saved_size += 8;
array_append(&saved_regs, hreg);
}
}
for (i=0; i<current_proc->usedregs.count; i++)
{
struct hreg* hreg = current_proc->usedregs.item[i];
if (!(hreg->attrs & burm_volatile_ATTR) && if (!(hreg->attrs & burm_volatile_ATTR) &&
((hreg->attrs & burm_int_ATTR) || (hreg->attrs & burm_float_ATTR))) ((hreg->attrs & burm_int_ATTR) || (hreg->attrs & burm_float_ATTR)))
{ {
hreg->offset = current_proc->saved_size;
current_proc->saved_size += 4; current_proc->saved_size += 4;
array_append(&saved_regs, hreg); array_append(&saved_regs, hreg);
} }
} }
current_proc->fp_to_st = -current_proc->locals_size;
current_proc->fp_to_ab = 8; current_proc->fp_to_ab = 8;
current_proc->fp_to_lb = 0; current_proc->fp_to_lb = 0;
current_proc->fp_to_sb = -(current_proc->locals_size + current_proc->spills_size);
current_proc->fp_to_rb = current_proc->fp_to_sb - current_proc->saved_size;
} }
struct hop* platform_prologue(void) struct hop* platform_prologue(void)
@ -52,9 +66,20 @@ struct hop* platform_prologue(void)
current_proc->locals_size; current_proc->locals_size;
struct hop* hop = new_hop(current_proc->entry, NULL); struct hop* hop = new_hop(current_proc->entry, NULL);
hop_add_insel(hop, "! saved_size = %d bytes", current_proc->saved_size); hop_add_insel(hop, "! params @ fp+%d", current_proc->fp_to_ab);
hop_add_insel(hop, "! spills_size = %d bytes", current_proc->spills_size); hop_add_insel(hop, "! lr @ fp+4");
hop_add_insel(hop, "! locals_size = %d bytes", current_proc->locals_size); hop_add_insel(hop, "! fp @ fp+0");
hop_add_insel(hop, "! locals @ fp-%d to fp+0",
current_proc->locals_size);
hop_add_insel(hop, "! spills @ fp-%d to fp-%d",
-current_proc->fp_to_sb, current_proc->locals_size);
for (i=0; i<saved_regs.count; i++)
{
struct hreg* hreg = saved_regs.item[i];
hop_add_insel(hop, "! %s @ fp-%d",
hreg->id, -(current_proc->fp_to_rb + hreg->offset));
}
hop_add_insel(hop, "addi sp, sp, %d", -(spoffset + 8)); hop_add_insel(hop, "addi sp, sp, %d", -(spoffset + 8));
hop_add_insel(hop, "mfspr r0, lr"); hop_add_insel(hop, "mfspr r0, lr");
hop_add_insel(hop, "stw fp, %d(sp)", spoffset + 0); hop_add_insel(hop, "stw fp, %d(sp)", spoffset + 0);
@ -67,10 +92,11 @@ struct hop* platform_prologue(void)
{ {
struct hreg* hreg = saved_regs.item[i]; struct hreg* hreg = saved_regs.item[i];
if (hreg->attrs & burm_int_ATTR) if (hreg->attrs & burm_int_ATTR)
hop_add_insel(hop, "stw %H, %d(fp)", hreg, saved_offset); hop_add_insel(hop, "stw %H, %d(fp)",
hreg, current_proc->fp_to_rb + saved_offset);
else if (hreg->attrs & burm_float_ATTR) else if (hreg->attrs & burm_float_ATTR)
hop_add_insel(hop, "stfs %H, %d(fp)", hreg, saved_offset); hop_add_insel(hop, "stfs %H, %d(fp)",
saved_offset += 4; hreg, current_proc->fp_to_rb + saved_offset);
} }
return hop; return hop;
} }
@ -81,16 +107,15 @@ struct hop* platform_epilogue(void)
int i; int i;
int saved_offset; int saved_offset;
/* Saved reg offsets are negative. */
saved_offset = -(current_proc->locals_size + current_proc->spills_size);
for (i=0; i<saved_regs.count; i++) for (i=0; i<saved_regs.count; i++)
{ {
struct hreg* hreg = saved_regs.item[i]; struct hreg* hreg = saved_regs.item[i];
if (hreg->attrs & burm_int_ATTR) if (hreg->attrs & burm_int_ATTR)
hop_add_insel(hop, "lwz %H, %d(fp)", hreg, saved_offset); hop_add_insel(hop, "lwz %H, %d(fp)",
hreg, current_proc->fp_to_rb + saved_offset);
else if (hreg->attrs & burm_float_ATTR) else if (hreg->attrs & burm_float_ATTR)
hop_add_insel(hop, "lfs %H, %d(fp)", hreg, saved_offset); hop_add_insel(hop, "lfs %H, %d(fp)",
saved_offset += 4; hreg, current_proc->fp_to_rb + saved_offset);
} }
hop_add_insel(hop, "lwz r0, 4(fp)"); hop_add_insel(hop, "lwz r0, 4(fp)");

View file

@ -113,6 +113,10 @@ void hop_add_insel(struct hop* hop, const char* fmt, ...)
hop_add_string_insel(hop, aprintf("%d", va_arg(ap, int))); hop_add_string_insel(hop, aprintf("%d", va_arg(ap, int)));
break; break;
case 's':
hop_add_string_insel(hop, va_arg(ap, const char*));
break;
case 'S': case 'S':
hop_add_st_offset_insel(hop, va_arg(ap, struct hreg*)); hop_add_st_offset_insel(hop, va_arg(ap, struct hreg*));
break; break;
@ -248,7 +252,7 @@ char* hop_render(struct hop* hop)
break; break;
case INSEL_ST_OFFSET: case INSEL_ST_OFFSET:
appendf("%d", current_proc->fp_to_st + insel->u.hreg->offset); appendf("%d", current_proc->fp_to_sb + insel->u.hreg->offset);
break; break;
case INSEL_AB_OFFSET: case INSEL_AB_OFFSET:

View file

@ -16,9 +16,10 @@ struct procedure
int locals_size; int locals_size;
int spills_size; int spills_size;
int saved_size; int saved_size;
int fp_to_st; int fp_to_ab; /* argument base (indexes up) */
int fp_to_ab; int fp_to_lb; /* locals base (indexes down) */
int fp_to_lb; int fp_to_sb; /* spill base (indexes up) */
int fp_to_rb; /* saved registers base (indexes up) */
ARRAYOF(struct basicblock) blocks; ARRAYOF(struct basicblock) blocks;
IMAPOF(struct local) locals; IMAPOF(struct local) locals;
ARRAYOF(struct hreg) usedregs; ARRAYOF(struct hreg) usedregs;