Skip to content

Commit

Permalink
finish up alignment refactoring and fixing
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Jan 11, 2013
1 parent 514fa3e commit aa3e657
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 45 deletions.
101 changes: 63 additions & 38 deletions src/backend/cgcod.c
Expand Up @@ -567,6 +567,31 @@ void codgen()
#endif
}

/*********************************************
* Align sections on the stack.
* base negative offset of section from frame pointer
* alignment alignment to use
* bias difference between where frame pointer points and the STACKALIGNed
* part of the stack
* Returns:
* base revised downward so it is aligned
*/
targ_size_t alignsection(targ_size_t base, unsigned alignment, int bias)
{
assert((int)base <= 0);
if (alignment > STACKALIGN)
alignment = STACKALIGN;
if (alignment)
{
int sz = -base + bias;
assert(sz >= 0);
sz &= (alignment - 1);
if (sz)
base -= alignment - sz;
}
return base;
}

/*******************************
* Generate code for a function start.
* Input:
Expand All @@ -583,7 +608,6 @@ code *prolog()
{
SYMIDX si;
bool enter;
unsigned Foffset;
unsigned xlocalsize; // amount to subtract from ESP to make room for locals
char guessneedframe;
regm_t namedargs = 0;
Expand Down Expand Up @@ -652,50 +676,31 @@ code *prolog()
Fast.size -= 5 * 4;
#endif
#endif
Fast.size = -align(Fast.alignment,-Fast.size + Fast.offset);
if (STACKALIGN == 16 && Fast.size & (STACKALIGN - 1))
Fast.size = -((-Fast.size + STACKALIGN - 1) & ~(STACKALIGN - 1));
Auto.size = Fast.size - align(0,Auto.offset);
Fast.size = -align(REGSIZE,-Fast.size + Fast.offset);

int bias = Para.size + (needframe ? 0 : REGSIZE);
if (Auto.alignment < REGSIZE)
Auto.alignment = REGSIZE; // necessary because localsize must be REGSIZE aligned
Auto.size = alignsection(Fast.size - Auto.offset, Auto.alignment, bias);

regsave.off = alignsection(Auto.size - regsave.top, regsave.alignment, bias);

unsigned floatregsize = floatreg ? (config.fpxmmregs || I32 ? 16 : DOUBLESIZE) : 0;
Foff = alignsection(regsave.off - floatregsize, STACKALIGN, bias);

regsave.off = Auto.size - align(0,regsave.top);
Foffset = floatreg ? (config.fpxmmregs || I32 ? 16 : DOUBLESIZE) : 0;
Foff = regsave.off - align(0,Foffset);
assert(usedalloca != 1);
AllocaOff = usedalloca ? (Foff - REGSIZE) : Foff;
CSoff = AllocaOff - align(0,cstop * REGSIZE);
AllocaOff = alignsection(usedalloca ? (Foff - REGSIZE) : Foff, REGSIZE, bias);

CSoff = alignsection(AllocaOff - cstop * REGSIZE, REGSIZE, bias);

#if TX86
NDPoff = CSoff - align(0,NDP::savetop * NDPSAVESIZE);
NDPoff = alignsection(CSoff - NDP::savetop * NDPSAVESIZE, REGSIZE, bias);
#else
NDPoff = CSoff;
#endif

//printf("Fast.size = x%x, Auto.size = x%x\n", (int)Fast.size, (int)Auto.size);

if (Foffset > Auto.alignment)
Auto.alignment = Foffset; // floatreg must be aligned, too
if (Auto.alignment > REGSIZE)
{
// Adjust Auto.size so that it is Auto.alignment byte aligned, assuming that
// before function parameters were pushed the stack was
// Auto.alignment byte aligned
targ_size_t psize = (Para.offset + (REGSIZE - 1)) & ~(REGSIZE - 1);
// if (config.exe == EX_WIN64)
if (STACKALIGN == 16)
// Parameters always consume multiple of 16 bytes
psize = (Para.offset + 15) & ~15;
int sz = psize + -Fast.size + -Auto.size + Para.size + (needframe ? 0 : REGSIZE);
//printf("Auto.alignment = %d, psize = x%llx, Para.size = x%llx, needframe = %d\n", Auto.alignment, psize, Para.size, needframe);
if (sz & (Auto.alignment - 1))
{ int adj = Auto.alignment - (sz & (Auto.alignment - 1));
Auto.size -= adj;
regsave.off -= adj;
Foff -= adj;
AllocaOff -= adj;
CSoff -= adj;
NDPoff -= adj;
}
}

localsize = -NDPoff;

regm_t topush = fregsaved & ~mfuncreg; // mask of registers that need saving
Expand Down Expand Up @@ -918,6 +923,11 @@ if (STACKALIGN == 16)
c = cat(c, prolog_genvarargs(sv, &namedargs));
}

/* Alignment checks
*/
//assert(Auto.alignment <= STACKALIGN);
//assert(((Auto.size + Para.size + BPoff) & (Auto.alignment - 1)) == 0);

return c;
}

Expand Down Expand Up @@ -966,7 +976,8 @@ void stackoffsets(int flags)
sz++; // can't handle 0 length structs

unsigned alignsize = s->Salignsize();
assert(I32 || I64 || alignsize <= REGSIZE);
if (alignsize > STACKALIGN)
alignsize = STACKALIGN; // no point if the stack is less aligned

//printf("symbol '%s', size = x%lx, alignsize = %d, read = %x\n",s->Sident,(long)sz, (int)alignsize, s->Sflags & SFLread);
assert((int)sz >= 0);
Expand Down Expand Up @@ -1000,7 +1011,21 @@ void stackoffsets(int flags)
case SCauto:
if (s->Sfl == FLreg) // if allocated in register
break;
// See if we can share storage with another variable

/* We can go further with this:
* 1. sort by alignsize, biggest first
* 2. move variables nearer the frame pointer that have higher Sweights
* because addressing mode is fewer bytes. Grouping together high Sweight
* variables also may put them in the same cache
* 3. put static arrays nearest the frame pointer, so buffer overflows
* can't change other variable contents
* 4. Do the coloring at the byte level to minimize stack usage
*/

/* See if we can share storage with another variable
* if their live ranges do not overlap.
* An approximation to case 4.
*/
if (config.flags4 & CFG4optimized &&
// Don't share because could stomp on variables
// used in finally blocks
Expand Down
4 changes: 2 additions & 2 deletions src/backend/cod3.c
Expand Up @@ -200,7 +200,7 @@ code *REGSAVE::save(code *c, int reg, unsigned *pidx)
idx += 16;
// MOVD idx[RBP],xmm
unsigned op = STOAPD;
if (1)
if (0)
/* This is because the regsave does not get properly aligned
* to 16 on 32 bit machines.
* Doing so wreaks havoc with the location of vthis, which messes
Expand Down Expand Up @@ -235,7 +235,7 @@ code *REGSAVE::restore(code *c, int reg, unsigned idx)
assert(alignment == 16);
// MOVD xmm,idx[RBP]
unsigned op = LODAPD;
if (1)
if (0)
op = LODUPD;
c = genc1(c,op,modregxrm(2, reg - XMM0, BPRM),FLregsave,(targ_uns) idx);
}
Expand Down
1 change: 0 additions & 1 deletion src/backend/code.h
Expand Up @@ -319,7 +319,6 @@ cd_t cdnullcheck;
cd_t cdclassinit;

/* cod3.c */
extern int BPoff;

int cod3_EA(code *c);
regm_t cod3_useBP();
Expand Down
5 changes: 1 addition & 4 deletions src/backend/symbol.c
Expand Up @@ -193,13 +193,10 @@ int Symbol::Salignsize()
return Salignment;
int alignsize = type_alignsize(Stype);

if (I16 && alignsize > 2)
alignsize = 2; // stack is aligned on 2 anyway

/* Reduce alignment faults when SIMD vectors
* are reinterpreted cast to other types with less alignment.
*/
else if (config.fpxmmregs && alignsize < 16 &&
if (config.fpxmmregs && alignsize < 16 &&
Sclass == SCauto &&
type_size(Stype) == 16)
{
Expand Down

0 comments on commit aa3e657

Please sign in to comment.