Commit e7a0f676 authored by Russ Cox's avatar Russ Cox

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
parent 96db724c
...@@ -25,7 +25,6 @@ Typedef typedefs[] = ...@@ -25,7 +25,6 @@ Typedef typedefs[] =
void void
betypeinit(void) betypeinit(void)
{ {
maxround = 4;
widthptr = 4; widthptr = 4;
zprog.link = P; zprog.link = P;
......
...@@ -111,12 +111,12 @@ compile(Node *fn) ...@@ -111,12 +111,12 @@ compile(Node *fn)
// fill in argument size // fill in argument size
ptxt->to.type = D_CONST2; ptxt->to.type = D_CONST2;
ptxt->reg = 0; // flags 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 // fill in final stack size
if(stksize > maxstksize) if(stksize > maxstksize)
maxstksize = stksize; maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, maxround); ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0; maxstksize = 0;
if(debug['f']) if(debug['f'])
......
...@@ -25,7 +25,6 @@ Typedef typedefs[] = ...@@ -25,7 +25,6 @@ Typedef typedefs[] =
void void
betypeinit(void) betypeinit(void)
{ {
maxround = 8;
widthptr = 8; widthptr = 8;
zprog.link = P; zprog.link = P;
......
...@@ -109,11 +109,11 @@ compile(Node *fn) ...@@ -109,11 +109,11 @@ compile(Node *fn)
} }
// fill in argument size // 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 // fill in final stack size
ptxt->to.offset <<= 32; ptxt->to.offset <<= 32;
ptxt->to.offset |= rnd(stksize+maxarg, maxround); ptxt->to.offset |= rnd(stksize+maxarg, widthptr);
if(debug['f']) if(debug['f'])
frame(0); frame(0);
......
...@@ -25,7 +25,6 @@ Typedef typedefs[] = ...@@ -25,7 +25,6 @@ Typedef typedefs[] =
void void
betypeinit(void) betypeinit(void)
{ {
maxround = 4;
widthptr = 4; widthptr = 4;
zprog.link = P; zprog.link = P;
......
...@@ -118,12 +118,12 @@ compile(Node *fn) ...@@ -118,12 +118,12 @@ compile(Node *fn)
regopt(ptxt); regopt(ptxt);
} }
// fill in argument size // 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 // fill in final stack size
if(stksize > maxstksize) if(stksize > maxstksize)
maxstksize = stksize; maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, maxround); ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0; maxstksize = 0;
if(debug['f']) if(debug['f'])
......
...@@ -16,15 +16,9 @@ static int defercalc; ...@@ -16,15 +16,9 @@ static int defercalc;
uint32 uint32
rnd(uint32 o, uint32 r) rnd(uint32 o, uint32 r)
{ {
if(maxround == 0) if(r < 1 || r > 8 || (r&(r-1)) != 0)
fatal("rnd"); fatal("rnd");
return (o+r-1)&~(r-1);
if(r > maxround)
r = maxround;
if(r != 0)
while(o%r != 0)
o++;
return o;
} }
static void static void
...@@ -42,30 +36,25 @@ offmod(Type *t) ...@@ -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 static uint32
widstruct(Type *t, uint32 o, int flag) widstruct(Type *t, uint32 o, int flag)
{ {
Type *f; Type *f;
int32 w, m; int32 w, maxalign;
maxalign = flag;
if(maxalign < 1)
maxalign = 1;
for(f=t->type; f!=T; f=f->down) { for(f=t->type; f!=T; f=f->down) {
if(f->etype != TFIELD) if(f->etype != TFIELD)
fatal("widstruct: not TFIELD: %lT", f); fatal("widstruct: not TFIELD: %lT", f);
dowidth(f->type); dowidth(f->type);
if(f->align > maxalign)
maxalign = f->align;
if(f->type->width < 0) if(f->type->width < 0)
fatal("invalid width %lld", f->type->width); fatal("invalid width %lld", f->type->width);
w = f->type->width; w = f->type->width;
m = arrayelemwidth(f->type); o = rnd(o, f->type->align);
o = rnd(o, m);
f->width = o; // really offset for TFIELD f->width = o; // really offset for TFIELD
if(f->nname != N) { if(f->nname != N) {
// this same stackparam logic is in addrescapes // this same stackparam logic is in addrescapes
...@@ -82,7 +71,8 @@ widstruct(Type *t, uint32 o, int flag) ...@@ -82,7 +71,8 @@ widstruct(Type *t, uint32 o, int flag)
} }
// final width is rounded // final width is rounded
if(flag) if(flag)
o = rnd(o, maxround); o = rnd(o, maxalign);
t->align = maxalign;
// type width only includes back to first field's offset // type width only includes back to first field's offset
if(t->type == T) if(t->type == T)
...@@ -100,7 +90,7 @@ dowidth(Type *t) ...@@ -100,7 +90,7 @@ dowidth(Type *t)
int lno; int lno;
Type *t1; Type *t1;
if(maxround == 0 || widthptr == 0) if(widthptr == 0)
fatal("dowidth without betypeinit"); fatal("dowidth without betypeinit");
if(t == T) if(t == T)
...@@ -124,6 +114,7 @@ dowidth(Type *t) ...@@ -124,6 +114,7 @@ dowidth(Type *t)
lno = lineno; lno = lineno;
lineno = t->lineno; lineno = t->lineno;
t->width = -2; t->width = -2;
t->align = 0;
et = t->etype; et = t->etype;
switch(et) { switch(et) {
...@@ -166,9 +157,11 @@ dowidth(Type *t) ...@@ -166,9 +157,11 @@ dowidth(Type *t)
case TFLOAT64: case TFLOAT64:
case TCOMPLEX64: case TCOMPLEX64:
w = 8; w = 8;
t->align = widthptr;
break; break;
case TCOMPLEX128: case TCOMPLEX128:
w = 16; w = 16;
t->align = widthptr;
break; break;
case TPTR32: case TPTR32:
w = 4; w = 4;
...@@ -180,6 +173,7 @@ dowidth(Type *t) ...@@ -180,6 +173,7 @@ dowidth(Type *t)
break; break;
case TINTER: // implemented as 2 pointers case TINTER: // implemented as 2 pointers
w = 2*widthptr; w = 2*widthptr;
t->align = widthptr;
offmod(t); offmod(t);
break; break;
case TCHAN: // implemented as pointer case TCHAN: // implemented as pointer
...@@ -197,6 +191,7 @@ dowidth(Type *t) ...@@ -197,6 +191,7 @@ dowidth(Type *t)
dowidth(t->type); // just in case dowidth(t->type); // just in case
if(t1->type->width >= (1<<16)) if(t1->type->width >= (1<<16))
yyerror("channel element type too large (>64kB)"); yyerror("channel element type too large (>64kB)");
t->width = 1;
break; break;
case TMAP: // implemented as pointer case TMAP: // implemented as pointer
w = widthptr; w = widthptr;
...@@ -217,6 +212,7 @@ dowidth(Type *t) ...@@ -217,6 +212,7 @@ dowidth(Type *t)
if(sizeof_String == 0) if(sizeof_String == 0)
fatal("early dowidth string"); fatal("early dowidth string");
w = sizeof_String; w = sizeof_String;
t->align = widthptr;
break; break;
case TARRAY: case TARRAY:
if(t->type == T) if(t->type == T)
...@@ -235,11 +231,13 @@ dowidth(Type *t) ...@@ -235,11 +231,13 @@ dowidth(Type *t)
yyerror("type %lT larger than address space", t); yyerror("type %lT larger than address space", t);
w = t->bound * t->type->width; w = t->bound * t->type->width;
if(w == 0) if(w == 0)
w = maxround; w = 1;
t->align = t->type->align;
} }
else if(t->bound == -1) { else if(t->bound == -1) {
w = sizeof_Array; w = sizeof_Array;
checkwidth(t->type); checkwidth(t->type);
t->align = widthptr;
} }
else if(t->bound == -100) else if(t->bound == -100)
yyerror("use of [...] array outside of array literal"); yyerror("use of [...] array outside of array literal");
...@@ -250,9 +248,9 @@ dowidth(Type *t) ...@@ -250,9 +248,9 @@ dowidth(Type *t)
case TSTRUCT: case TSTRUCT:
if(t->funarg) if(t->funarg)
fatal("dowidth fn struct %T", t); fatal("dowidth fn struct %T", t);
w = widstruct(t, 0, 1); w = widstruct(t, 0, widthptr);
if(w == 0) if(w == 0)
w = maxround; w = 1;
break; break;
case TFUNC: case TFUNC:
...@@ -271,16 +269,22 @@ dowidth(Type *t) ...@@ -271,16 +269,22 @@ dowidth(Type *t)
// compute their widths as side-effect. // compute their widths as side-effect.
t1 = t->type; t1 = t->type;
w = widstruct(*getthis(t1), 0, 0); w = widstruct(*getthis(t1), 0, 0);
w = widstruct(*getinarg(t1), w, 1); w = widstruct(*getinarg(t1), w, widthptr);
w = widstruct(*getoutarg(t1), w, 1); w = widstruct(*getoutarg(t1), w, widthptr);
t1->argwid = w; t1->argwid = w;
t->align = 1;
break; break;
} }
// catch all for error cases; avoid divide by zero later // catch all for error cases; avoid divide by zero later
if(w == 0) if(w == 0)
w = maxround; w = 1;
t->width = w; 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; lineno = lno;
if(defercalc == 1) if(defercalc == 1)
...@@ -596,10 +600,10 @@ typeinit(void) ...@@ -596,10 +600,10 @@ typeinit(void)
Array_array = rnd(0, widthptr); Array_array = rnd(0, widthptr);
Array_nel = rnd(Array_array+widthptr, types[TUINT32]->width); Array_nel = rnd(Array_array+widthptr, types[TUINT32]->width);
Array_cap = rnd(Array_nel+types[TUINT32]->width, 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 // 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(types[TSTRING]);
dowidth(idealstring); dowidth(idealstring);
......
...@@ -58,7 +58,7 @@ allocparams(void) ...@@ -58,7 +58,7 @@ allocparams(void)
if(w >= MAXWIDTH) if(w >= MAXWIDTH)
fatal("bad width"); fatal("bad width");
stksize += w; stksize += w;
stksize = rnd(stksize, w); stksize = rnd(stksize, n->type->align);
n->xoffset = -stksize; n->xoffset = -stksize;
} }
lineno = lno; lineno = lno;
...@@ -664,7 +664,7 @@ tempname(Node *n, Type *t) ...@@ -664,7 +664,7 @@ tempname(Node *n, Type *t)
dowidth(t); dowidth(t);
w = t->width; w = t->width;
stksize += w; stksize += w;
stksize = rnd(stksize, w); stksize = rnd(stksize, t->align);
n->xoffset = -stksize; n->xoffset = -stksize;
n->pun = anyregalloc(); n->pun = anyregalloc();
} }
...@@ -154,6 +154,7 @@ struct Type ...@@ -154,6 +154,7 @@ struct Type
uchar deferwidth; uchar deferwidth;
uchar broke; uchar broke;
uchar isddd; // TFIELD is ... argument uchar isddd; // TFIELD is ... argument
uchar align;
Node* nod; // canonical OTYPE node Node* nod; // canonical OTYPE node
Type* orig; // original type (type literal or predefined type) Type* orig; // original type (type literal or predefined type)
...@@ -751,7 +752,6 @@ EXTERN int hasdefer; // flag that curfn has defer statetment ...@@ -751,7 +752,6 @@ EXTERN int hasdefer; // flag that curfn has defer statetment
EXTERN Node* curfn; EXTERN Node* curfn;
EXTERN int maxround;
EXTERN int widthptr; EXTERN int widthptr;
EXTERN Node* typesw; EXTERN Node* typesw;
......
...@@ -194,7 +194,7 @@ main(int argc, char *argv[]) ...@@ -194,7 +194,7 @@ main(int argc, char *argv[])
fmtinstall('F', Fconv); // big float numbers fmtinstall('F', Fconv); // big float numbers
betypeinit(); betypeinit();
if(maxround == 0 || widthptr == 0) if(widthptr == 0)
fatal("betypeinit failed"); fatal("betypeinit failed");
lexinit(); lexinit();
......
...@@ -577,7 +577,6 @@ dcommontype(Sym *s, int ot, Type *t) ...@@ -577,7 +577,6 @@ dcommontype(Sym *s, int ot, Type *t)
{ {
int i; int i;
Sym *s1; Sym *s1;
Type *elem;
char *p; char *p;
dowidth(t); dowidth(t);
...@@ -605,14 +604,8 @@ dcommontype(Sym *s, int ot, Type *t) ...@@ -605,14 +604,8 @@ dcommontype(Sym *s, int ot, Type *t)
ot = duintptr(s, ot, t->width); ot = duintptr(s, ot, t->width);
ot = duint32(s, ot, typehash(t)); ot = duint32(s, ot, typehash(t));
ot = duint8(s, ot, algtype(t)); ot = duint8(s, ot, algtype(t));
elem = t; ot = duint8(s, ot, t->align); // align
while(elem->etype == TARRAY && elem->bound >= 0) ot = duint8(s, ot, t->align); // fieldAlign
elem = elem->type;
i = elem->width;
if(i > maxround)
i = maxround;
ot = duint8(s, ot, i); // align
ot = duint8(s, ot, i); // fieldAlign
i = kinds[t->etype]; i = kinds[t->etype];
if(t->etype == TARRAY && t->bound < 0) if(t->etype == TARRAY && t->bound < 0)
i = KindSlice; i = KindSlice;
......
...@@ -2309,7 +2309,8 @@ ptrto(Type *t) ...@@ -2309,7 +2309,8 @@ ptrto(Type *t)
fatal("ptrto: nil"); fatal("ptrto: nil");
t1 = typ(tptr); t1 = typ(tptr);
t1->type = t; t1->type = t;
t1->width = types[tptr]->width; t1->width = widthptr;
t1->align = widthptr;
return t1; return t1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment