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
* | old FR
* | old FP
* | --------------- <- st, fp (a.k.a. lb)
* | --------------- <- fp (a.k.a. lb)
* | locals
* | ---------------
* | spills
* | ---------------
* | --------------- <- sb
* | saved regs
* | --------------- <- sp
* | --------------- <- sp, rb
* V ...user area...
*
* st indexes up; lb indexes down.
@ -31,17 +31,31 @@ void platform_calculate_offsets(void)
{
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) &&
((hreg->attrs & burm_int_ATTR) || (hreg->attrs & burm_float_ATTR)))
{
hreg->offset = current_proc->saved_size;
current_proc->saved_size += 4;
array_append(&saved_regs, hreg);
}
}
current_proc->fp_to_st = -current_proc->locals_size;
current_proc->fp_to_ab = 8;
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)
@ -52,9 +66,20 @@ struct hop* platform_prologue(void)
current_proc->locals_size;
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, "! spills_size = %d bytes", current_proc->spills_size);
hop_add_insel(hop, "! locals_size = %d bytes", current_proc->locals_size);
hop_add_insel(hop, "! params @ fp+%d", current_proc->fp_to_ab);
hop_add_insel(hop, "! lr @ fp+4");
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, "mfspr r0, lr");
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];
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)
hop_add_insel(hop, "stfs %H, %d(fp)", hreg, saved_offset);
saved_offset += 4;
hop_add_insel(hop, "stfs %H, %d(fp)",
hreg, current_proc->fp_to_rb + saved_offset);
}
return hop;
}
@ -81,16 +107,15 @@ struct hop* platform_epilogue(void)
int i;
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++)
{
struct hreg* hreg = saved_regs.item[i];
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)
hop_add_insel(hop, "lfs %H, %d(fp)", hreg, saved_offset);
saved_offset += 4;
hop_add_insel(hop, "lfs %H, %d(fp)",
hreg, current_proc->fp_to_rb + saved_offset);
}
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)));
break;
case 's':
hop_add_string_insel(hop, va_arg(ap, const char*));
break;
case 'S':
hop_add_st_offset_insel(hop, va_arg(ap, struct hreg*));
break;
@ -248,7 +252,7 @@ char* hop_render(struct hop* hop)
break;
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;
case INSEL_AB_OFFSET:

View file

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