From e7a0f6760377c6a4ad7f37ade8eabf2fdf150e0a Mon Sep 17 00:00:00 2001 From: Russ Cox <rsc@golang.org> Date: Mon, 13 Dec 2010 11:57:41 -0500 Subject: [PATCH] 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 --- src/cmd/5g/galign.c | 1 - src/cmd/5g/ggen.c | 4 +-- src/cmd/6g/galign.c | 1 - src/cmd/6g/ggen.c | 4 +-- src/cmd/8g/galign.c | 1 - src/cmd/8g/ggen.c | 4 +-- src/cmd/gc/align.c | 66 +++++++++++++++++++++++--------------------- src/cmd/gc/gen.c | 4 +-- src/cmd/gc/go.h | 2 +- src/cmd/gc/lex.c | 2 +- src/cmd/gc/reflect.c | 11 ++------ src/cmd/gc/subr.c | 3 +- 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 @@ -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); 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; } -- 2.30.9