1
0
mirror of https://github.com/golang/go synced 2024-11-24 04:20:03 -07:00

gc: introduce explicit alignments

No semantic changes here, but working
toward being able to align structs based
on the maximum alignment of the fields
inside instead of having a fixed alignment
for all structs (issue 482).

R=ken2
CC=golang-dev
https://golang.org/cl/3617041
This commit is contained in:
Russ Cox 2010-12-13 11:57:41 -05:00
parent 96db724cfc
commit e7a0f67603
12 changed files with 49 additions and 54 deletions

View File

@ -25,7 +25,6 @@ Typedef typedefs[] =
void
betypeinit(void)
{
maxround = 4;
widthptr = 4;
zprog.link = P;

View File

@ -111,12 +111,12 @@ compile(Node *fn)
// fill in argument size
ptxt->to.type = D_CONST2;
ptxt->reg = 0; // flags
ptxt->to.offset2 = rnd(curfn->type->argwid, maxround);
ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
// fill in final stack size
if(stksize > maxstksize)
maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, maxround);
ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0;
if(debug['f'])

View File

@ -25,7 +25,6 @@ Typedef typedefs[] =
void
betypeinit(void)
{
maxround = 8;
widthptr = 8;
zprog.link = P;

View File

@ -109,11 +109,11 @@ compile(Node *fn)
}
// fill in argument size
ptxt->to.offset = rnd(curfn->type->argwid, maxround);
ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
// fill in final stack size
ptxt->to.offset <<= 32;
ptxt->to.offset |= rnd(stksize+maxarg, maxround);
ptxt->to.offset |= rnd(stksize+maxarg, widthptr);
if(debug['f'])
frame(0);

View File

@ -25,7 +25,6 @@ Typedef typedefs[] =
void
betypeinit(void)
{
maxround = 4;
widthptr = 4;
zprog.link = P;

View File

@ -118,12 +118,12 @@ compile(Node *fn)
regopt(ptxt);
}
// fill in argument size
ptxt->to.offset2 = rnd(curfn->type->argwid, maxround);
ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
// fill in final stack size
if(stksize > maxstksize)
maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, maxround);
ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0;
if(debug['f'])

View File

@ -16,15 +16,9 @@ static int defercalc;
uint32
rnd(uint32 o, uint32 r)
{
if(maxround == 0)
if(r < 1 || r > 8 || (r&(r-1)) != 0)
fatal("rnd");
if(r > maxround)
r = maxround;
if(r != 0)
while(o%r != 0)
o++;
return o;
return (o+r-1)&~(r-1);
}
static void
@ -42,30 +36,25 @@ offmod(Type *t)
}
}
static uint32
arrayelemwidth(Type *t)
{
while(t->etype == TARRAY && t->bound >= 0)
t = t->type;
return t->width;
}
static uint32
widstruct(Type *t, uint32 o, int flag)
{
Type *f;
int32 w, m;
int32 w, maxalign;
maxalign = flag;
if(maxalign < 1)
maxalign = 1;
for(f=t->type; f!=T; f=f->down) {
if(f->etype != TFIELD)
fatal("widstruct: not TFIELD: %lT", f);
dowidth(f->type);
if(f->align > maxalign)
maxalign = f->align;
if(f->type->width < 0)
fatal("invalid width %lld", f->type->width);
w = f->type->width;
m = arrayelemwidth(f->type);
o = rnd(o, m);
o = rnd(o, f->type->align);
f->width = o; // really offset for TFIELD
if(f->nname != N) {
// this same stackparam logic is in addrescapes
@ -82,7 +71,8 @@ widstruct(Type *t, uint32 o, int flag)
}
// final width is rounded
if(flag)
o = rnd(o, maxround);
o = rnd(o, maxalign);
t->align = maxalign;
// type width only includes back to first field's offset
if(t->type == T)
@ -100,7 +90,7 @@ dowidth(Type *t)
int lno;
Type *t1;
if(maxround == 0 || widthptr == 0)
if(widthptr == 0)
fatal("dowidth without betypeinit");
if(t == T)
@ -124,6 +114,7 @@ dowidth(Type *t)
lno = lineno;
lineno = t->lineno;
t->width = -2;
t->align = 0;
et = t->etype;
switch(et) {
@ -166,9 +157,11 @@ dowidth(Type *t)
case TFLOAT64:
case TCOMPLEX64:
w = 8;
t->align = widthptr;
break;
case TCOMPLEX128:
w = 16;
t->align = widthptr;
break;
case TPTR32:
w = 4;
@ -180,6 +173,7 @@ dowidth(Type *t)
break;
case TINTER: // implemented as 2 pointers
w = 2*widthptr;
t->align = widthptr;
offmod(t);
break;
case TCHAN: // implemented as pointer
@ -197,6 +191,7 @@ dowidth(Type *t)
dowidth(t->type); // just in case
if(t1->type->width >= (1<<16))
yyerror("channel element type too large (>64kB)");
t->width = 1;
break;
case TMAP: // implemented as pointer
w = widthptr;
@ -217,6 +212,7 @@ dowidth(Type *t)
if(sizeof_String == 0)
fatal("early dowidth string");
w = sizeof_String;
t->align = widthptr;
break;
case TARRAY:
if(t->type == T)
@ -235,11 +231,13 @@ dowidth(Type *t)
yyerror("type %lT larger than address space", t);
w = t->bound * t->type->width;
if(w == 0)
w = maxround;
w = 1;
t->align = t->type->align;
}
else if(t->bound == -1) {
w = sizeof_Array;
checkwidth(t->type);
t->align = widthptr;
}
else if(t->bound == -100)
yyerror("use of [...] array outside of array literal");
@ -250,9 +248,9 @@ dowidth(Type *t)
case TSTRUCT:
if(t->funarg)
fatal("dowidth fn struct %T", t);
w = widstruct(t, 0, 1);
w = widstruct(t, 0, widthptr);
if(w == 0)
w = maxround;
w = 1;
break;
case TFUNC:
@ -271,16 +269,22 @@ dowidth(Type *t)
// compute their widths as side-effect.
t1 = t->type;
w = widstruct(*getthis(t1), 0, 0);
w = widstruct(*getinarg(t1), w, 1);
w = widstruct(*getoutarg(t1), w, 1);
w = widstruct(*getinarg(t1), w, widthptr);
w = widstruct(*getoutarg(t1), w, widthptr);
t1->argwid = w;
t->align = 1;
break;
}
// catch all for error cases; avoid divide by zero later
if(w == 0)
w = maxround;
w = 1;
t->width = w;
if(t->align == 0) {
if(w > 8 || (w&(w-1)) != 0)
fatal("invalid alignment for %T", t);
t->align = w;
}
lineno = lno;
if(defercalc == 1)
@ -596,10 +600,10 @@ typeinit(void)
Array_array = rnd(0, widthptr);
Array_nel = rnd(Array_array+widthptr, types[TUINT32]->width);
Array_cap = rnd(Array_nel+types[TUINT32]->width, types[TUINT32]->width);
sizeof_Array = rnd(Array_cap+types[TUINT32]->width, maxround);
sizeof_Array = rnd(Array_cap+types[TUINT32]->width, widthptr);
// string is same as slice wo the cap
sizeof_String = rnd(Array_nel+types[TUINT32]->width, maxround);
sizeof_String = rnd(Array_nel+types[TUINT32]->width, widthptr);
dowidth(types[TSTRING]);
dowidth(idealstring);

View File

@ -58,7 +58,7 @@ allocparams(void)
if(w >= MAXWIDTH)
fatal("bad width");
stksize += w;
stksize = rnd(stksize, w);
stksize = rnd(stksize, n->type->align);
n->xoffset = -stksize;
}
lineno = lno;
@ -664,7 +664,7 @@ tempname(Node *n, Type *t)
dowidth(t);
w = t->width;
stksize += w;
stksize = rnd(stksize, w);
stksize = rnd(stksize, t->align);
n->xoffset = -stksize;
n->pun = anyregalloc();
}

View File

@ -154,6 +154,7 @@ struct Type
uchar deferwidth;
uchar broke;
uchar isddd; // TFIELD is ... argument
uchar align;
Node* nod; // canonical OTYPE node
Type* orig; // original type (type literal or predefined type)
@ -751,7 +752,6 @@ EXTERN int hasdefer; // flag that curfn has defer statetment
EXTERN Node* curfn;
EXTERN int maxround;
EXTERN int widthptr;
EXTERN Node* typesw;

View File

@ -194,7 +194,7 @@ main(int argc, char *argv[])
fmtinstall('F', Fconv); // big float numbers
betypeinit();
if(maxround == 0 || widthptr == 0)
if(widthptr == 0)
fatal("betypeinit failed");
lexinit();

View File

@ -577,7 +577,6 @@ dcommontype(Sym *s, int ot, Type *t)
{
int i;
Sym *s1;
Type *elem;
char *p;
dowidth(t);
@ -605,14 +604,8 @@ dcommontype(Sym *s, int ot, Type *t)
ot = duintptr(s, ot, t->width);
ot = duint32(s, ot, typehash(t));
ot = duint8(s, ot, algtype(t));
elem = t;
while(elem->etype == TARRAY && elem->bound >= 0)
elem = elem->type;
i = elem->width;
if(i > maxround)
i = maxround;
ot = duint8(s, ot, i); // align
ot = duint8(s, ot, i); // fieldAlign
ot = duint8(s, ot, t->align); // align
ot = duint8(s, ot, t->align); // fieldAlign
i = kinds[t->etype];
if(t->etype == TARRAY && t->bound < 0)
i = KindSlice;

View File

@ -2309,7 +2309,8 @@ ptrto(Type *t)
fatal("ptrto: nil");
t1 = typ(tptr);
t1->type = t;
t1->width = types[tptr]->width;
t1->width = widthptr;
t1->align = widthptr;
return t1;
}