aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-12-13 11:57:41 -0500
committerRuss Cox <rsc@golang.org>2010-12-13 11:57:41 -0500
commite7a0f6760377c6a4ad7f37ade8eabf2fdf150e0a (patch)
treeb276e77129321cc2723c79a1bd5b8ca007954656
parent96db724cfc3b2d3e187cc06b9c81175ca225eaa1 (diff)
downloadgo-e7a0f6760377c6a4ad7f37ade8eabf2fdf150e0a.tar.gz
go-e7a0f6760377c6a4ad7f37ade8eabf2fdf150e0a.zip
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
-rw-r--r--src/cmd/5g/galign.c1
-rw-r--r--src/cmd/5g/ggen.c4
-rw-r--r--src/cmd/6g/galign.c1
-rw-r--r--src/cmd/6g/ggen.c4
-rw-r--r--src/cmd/8g/galign.c1
-rw-r--r--src/cmd/8g/ggen.c4
-rw-r--r--src/cmd/gc/align.c66
-rw-r--r--src/cmd/gc/gen.c4
-rw-r--r--src/cmd/gc/go.h2
-rw-r--r--src/cmd/gc/lex.c2
-rw-r--r--src/cmd/gc/reflect.c11
-rw-r--r--src/cmd/gc/subr.c3
12 files changed, 49 insertions, 54 deletions
diff --git a/src/cmd/5g/galign.c b/src/cmd/5g/galign.c
index 76affbf008..9c8760aea7 100644
--- a/src/cmd/5g/galign.c
+++ b/src/cmd/5g/galign.c
@@ -25,7 +25,6 @@ Typedef typedefs[] =
void
betypeinit(void)
{
- maxround = 4;
widthptr = 4;
zprog.link = P;
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index db1837b110..42a89415d3 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -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'])
diff --git a/src/cmd/6g/galign.c b/src/cmd/6g/galign.c
index 68647e21b4..bdfc9947e8 100644
--- a/src/cmd/6g/galign.c
+++ b/src/cmd/6g/galign.c
@@ -25,7 +25,6 @@ Typedef typedefs[] =
void
betypeinit(void)
{
- maxround = 8;
widthptr = 8;
zprog.link = P;
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index ebee6f8103..d9fa1793c6 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -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);
diff --git a/src/cmd/8g/galign.c b/src/cmd/8g/galign.c
index 346647205a..1c14dfe471 100644
--- a/src/cmd/8g/galign.c
+++ b/src/cmd/8g/galign.c
@@ -25,7 +25,6 @@ Typedef typedefs[] =
void
betypeinit(void)
{
- maxround = 4;
widthptr = 4;
zprog.link = P;
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 0c3a8260c2..f1461adbeb 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -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'])
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index 57dd3071be..4b6d92e786 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -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
@@ -43,29 +37,24 @@ 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);
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 65861c7635..8144fabaa8 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -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();
}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 5b7e316fe0..4b48ad55ea 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -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;
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 9dded356d4..0f1acd2fcd 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -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();
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 04ff3f0ec8..b31eb51549 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -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;
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 8acf1cdfec..9b6c79d866 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -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;
}