Commit dc9a3b27 authored by Russ Cox's avatar Russ Cox

gc: align structs according to max alignment of fields

cc: same
runtime: test cc alignment (required moving #define of offsetof to runtime.h)
fix bug260

Fixes #482.
Fixes #609.

R=ken2, r
CC=golang-dev
https://golang.org/cl/3563042
parent 287e45e2
...@@ -606,7 +606,7 @@ zaddr(char *bp, Adr *a, int s) ...@@ -606,7 +606,7 @@ zaddr(char *bp, Adr *a, int s)
} }
int32 int32
align(int32 i, Type *t, int op) align(int32 i, Type *t, int op, int32 *maxalign)
{ {
int32 o; int32 o;
Type *v; Type *v;
...@@ -620,7 +620,9 @@ align(int32 i, Type *t, int op) ...@@ -620,7 +620,9 @@ align(int32 i, Type *t, int op)
break; break;
case Asu2: /* padding at end of a struct */ case Asu2: /* padding at end of a struct */
w = SZ_LONG; w = *maxalign;
if(w < 1)
w = 1;
if(packflg) if(packflg)
w = packflg; w = packflg;
break; break;
...@@ -628,10 +630,16 @@ align(int32 i, Type *t, int op) ...@@ -628,10 +630,16 @@ align(int32 i, Type *t, int op)
case Ael1: /* initial align of struct element */ case Ael1: /* initial align of struct element */
for(v=t; v->etype==TARRAY; v=v->link) for(v=t; v->etype==TARRAY; v=v->link)
; ;
w = ewidth[v->etype]; if(v->etype == TSTRUCT || v->etype == TUNION)
if(w <= 0 || w >= SZ_LONG) w = v->align;
w = SZ_LONG; else {
if(packflg) w = ewidth[v->etype];
if(w == 8)
w = 4;
}
if(w < 1 || w > SZ_LONG)
fatal(Z, "align");
if(packflg)
w = packflg; w = packflg;
break; break;
...@@ -641,8 +649,8 @@ align(int32 i, Type *t, int op) ...@@ -641,8 +649,8 @@ align(int32 i, Type *t, int op)
case Aarg0: /* initial passbyptr argument in arg list */ case Aarg0: /* initial passbyptr argument in arg list */
if(typesuv[t->etype]) { if(typesuv[t->etype]) {
o = align(o, types[TIND], Aarg1); o = align(o, types[TIND], Aarg1, nil);
o = align(o, types[TIND], Aarg2); o = align(o, types[TIND], Aarg2, nil);
} }
break; break;
...@@ -661,12 +669,14 @@ align(int32 i, Type *t, int op) ...@@ -661,12 +669,14 @@ align(int32 i, Type *t, int op)
break; break;
case Aaut3: /* total align of automatic */ case Aaut3: /* total align of automatic */
o = align(o, t, Ael2); o = align(o, t, Ael2, nil);
o = align(o, t, Ael1); o = align(o, t, Ael1, nil);
w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */ w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
break; break;
} }
o = xround(o, w); o = xround(o, w);
if(maxalign != nil && *maxalign < w)
*maxalign = w;
if(debug['A']) if(debug['A'])
print("align %s %d %T = %d\n", bnames[op], i, t, o); print("align %s %d %T = %d\n", bnames[op], i, t, o);
return o; return o;
......
...@@ -388,7 +388,7 @@ err: ...@@ -388,7 +388,7 @@ err:
void void
regsalloc(Node *n, Node *nn) regsalloc(Node *n, Node *nn)
{ {
cursafe = align(cursafe, nn->type, Aaut3); cursafe = align(cursafe, nn->type, Aaut3, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
*n = *nodsafe; *n = *nodsafe;
n->xoffset = -(stkoff + cursafe); n->xoffset = -(stkoff + cursafe);
...@@ -402,22 +402,22 @@ regaalloc1(Node *n, Node *nn) ...@@ -402,22 +402,22 @@ regaalloc1(Node *n, Node *nn)
{ {
nodreg(n, nn, REGARG); nodreg(n, nn, REGARG);
reg[REGARG]++; reg[REGARG]++;
curarg = align(curarg, nn->type, Aarg1); curarg = align(curarg, nn->type, Aarg1, nil);
curarg = align(curarg, nn->type, Aarg2); curarg = align(curarg, nn->type, Aarg2, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
} }
void void
regaalloc(Node *n, Node *nn) regaalloc(Node *n, Node *nn)
{ {
curarg = align(curarg, nn->type, Aarg1); curarg = align(curarg, nn->type, Aarg1, nil);
*n = *nn; *n = *nn;
n->op = OINDREG; n->op = OINDREG;
n->reg = REGSP; n->reg = REGSP;
n->xoffset = curarg + SZ_LONG; n->xoffset = curarg + SZ_LONG;
n->complex = 0; n->complex = 0;
n->addable = 20; n->addable = 20;
curarg = align(curarg, nn->type, Aarg2); curarg = align(curarg, nn->type, Aarg2, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
} }
......
...@@ -1928,7 +1928,7 @@ vaddr(Node *n, int a) ...@@ -1928,7 +1928,7 @@ vaddr(Node *n, int a)
int32 int32
hi64v(Node *n) hi64v(Node *n)
{ {
if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
return (int32)(n->vconst) & ~0L; return (int32)(n->vconst) & ~0L;
else else
return (int32)((uvlong)n->vconst>>32) & ~0L; return (int32)((uvlong)n->vconst>>32) & ~0L;
...@@ -1937,7 +1937,7 @@ hi64v(Node *n) ...@@ -1937,7 +1937,7 @@ hi64v(Node *n)
int32 int32
lo64v(Node *n) lo64v(Node *n)
{ {
if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
return (int32)((uvlong)n->vconst>>32) & ~0L; return (int32)((uvlong)n->vconst>>32) & ~0L;
else else
return (int32)(n->vconst) & ~0L; return (int32)(n->vconst) & ~0L;
......
...@@ -503,7 +503,7 @@ zaddr(Biobuf *b, Adr *a, int s) ...@@ -503,7 +503,7 @@ zaddr(Biobuf *b, Adr *a, int s)
} }
int32 int32
align(int32 i, Type *t, int op) align(int32 i, Type *t, int op, int32 *maxalign)
{ {
int32 o; int32 o;
Type *v; Type *v;
...@@ -517,7 +517,9 @@ align(int32 i, Type *t, int op) ...@@ -517,7 +517,9 @@ align(int32 i, Type *t, int op)
break; break;
case Asu2: /* padding at end of a struct */ case Asu2: /* padding at end of a struct */
w = SZ_VLONG; w = *maxalign;
if(w < 1)
w = 1;
if(packflg) if(packflg)
w = packflg; w = packflg;
break; break;
...@@ -525,10 +527,13 @@ align(int32 i, Type *t, int op) ...@@ -525,10 +527,13 @@ align(int32 i, Type *t, int op)
case Ael1: /* initial align of struct element */ case Ael1: /* initial align of struct element */
for(v=t; v->etype==TARRAY; v=v->link) for(v=t; v->etype==TARRAY; v=v->link)
; ;
w = ewidth[v->etype]; if(v->etype == TSTRUCT || v->etype == TUNION)
if(w <= 0 || w >= SZ_VLONG) w = v->align;
w = SZ_VLONG; else
if(packflg) w = ewidth[v->etype];
if(w < 1 || w > SZ_VLONG)
fatal(Z, "align");
if(packflg)
w = packflg; w = packflg;
break; break;
...@@ -538,8 +543,8 @@ align(int32 i, Type *t, int op) ...@@ -538,8 +543,8 @@ align(int32 i, Type *t, int op)
case Aarg0: /* initial passbyptr argument in arg list */ case Aarg0: /* initial passbyptr argument in arg list */
if(typesu[t->etype]) { if(typesu[t->etype]) {
o = align(o, types[TIND], Aarg1); o = align(o, types[TIND], Aarg1, nil);
o = align(o, types[TIND], Aarg2); o = align(o, types[TIND], Aarg2, nil);
} }
break; break;
...@@ -560,11 +565,13 @@ align(int32 i, Type *t, int op) ...@@ -560,11 +565,13 @@ align(int32 i, Type *t, int op)
break; break;
case Aaut3: /* total align of automatic */ case Aaut3: /* total align of automatic */
o = align(o, t, Ael1); o = align(o, t, Ael1, nil);
o = align(o, t, Ael2); o = align(o, t, Ael2, nil);
break; break;
} }
o = xround(o, w); o = xround(o, w);
if(maxalign && *maxalign < w)
*maxalign = w;
if(debug['A']) if(debug['A'])
print("align %s %d %T = %d\n", bnames[op], i, t, o); print("align %s %d %T = %d\n", bnames[op], i, t, o);
return o; return o;
......
...@@ -424,7 +424,7 @@ err: ...@@ -424,7 +424,7 @@ err:
void void
regsalloc(Node *n, Node *nn) regsalloc(Node *n, Node *nn)
{ {
cursafe = align(cursafe, nn->type, Aaut3); cursafe = align(cursafe, nn->type, Aaut3, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
*n = *nodsafe; *n = *nodsafe;
n->xoffset = -(stkoff + cursafe); n->xoffset = -(stkoff + cursafe);
...@@ -440,22 +440,22 @@ regaalloc1(Node *n, Node *nn) ...@@ -440,22 +440,22 @@ regaalloc1(Node *n, Node *nn)
diag(n, "regaalloc1 and REGARG<0"); diag(n, "regaalloc1 and REGARG<0");
nodreg(n, nn, REGARG); nodreg(n, nn, REGARG);
reg[REGARG]++; reg[REGARG]++;
curarg = align(curarg, nn->type, Aarg1); curarg = align(curarg, nn->type, Aarg1, nil);
curarg = align(curarg, nn->type, Aarg2); curarg = align(curarg, nn->type, Aarg2, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
} }
void void
regaalloc(Node *n, Node *nn) regaalloc(Node *n, Node *nn)
{ {
curarg = align(curarg, nn->type, Aarg1); curarg = align(curarg, nn->type, Aarg1, nil);
*n = *nn; *n = *nn;
n->op = OINDREG; n->op = OINDREG;
n->reg = REGSP; n->reg = REGSP;
n->xoffset = curarg; n->xoffset = curarg;
n->complex = 0; n->complex = 0;
n->addable = 20; n->addable = 20;
curarg = align(curarg, nn->type, Aarg2); curarg = align(curarg, nn->type, Aarg2, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
} }
......
...@@ -57,7 +57,7 @@ vaddr(Node *n, int a) ...@@ -57,7 +57,7 @@ vaddr(Node *n, int a)
int32 int32
hi64v(Node *n) hi64v(Node *n)
{ {
if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
return (int32)(n->vconst) & ~0L; return (int32)(n->vconst) & ~0L;
else else
return (int32)((uvlong)n->vconst>>32) & ~0L; return (int32)((uvlong)n->vconst>>32) & ~0L;
...@@ -66,7 +66,7 @@ hi64v(Node *n) ...@@ -66,7 +66,7 @@ hi64v(Node *n)
int32 int32
lo64v(Node *n) lo64v(Node *n)
{ {
if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
return (int32)((uvlong)n->vconst>>32) & ~0L; return (int32)((uvlong)n->vconst>>32) & ~0L;
else else
return (int32)(n->vconst) & ~0L; return (int32)(n->vconst) & ~0L;
......
...@@ -501,7 +501,7 @@ zaddr(Biobuf *b, Adr *a, int s) ...@@ -501,7 +501,7 @@ zaddr(Biobuf *b, Adr *a, int s)
} }
int32 int32
align(int32 i, Type *t, int op) align(int32 i, Type *t, int op, int32 *maxalign)
{ {
int32 o; int32 o;
Type *v; Type *v;
...@@ -515,7 +515,9 @@ align(int32 i, Type *t, int op) ...@@ -515,7 +515,9 @@ align(int32 i, Type *t, int op)
break; break;
case Asu2: /* padding at end of a struct */ case Asu2: /* padding at end of a struct */
w = SZ_LONG; w = *maxalign;
if(w < 1)
w = 1;
if(packflg) if(packflg)
w = packflg; w = packflg;
break; break;
...@@ -523,10 +525,16 @@ align(int32 i, Type *t, int op) ...@@ -523,10 +525,16 @@ align(int32 i, Type *t, int op)
case Ael1: /* initial align of struct element */ case Ael1: /* initial align of struct element */
for(v=t; v->etype==TARRAY; v=v->link) for(v=t; v->etype==TARRAY; v=v->link)
; ;
w = ewidth[v->etype]; if(v->etype == TSTRUCT || v->etype == TUNION)
if(w <= 0 || w >= SZ_LONG) w = v->align;
w = SZ_LONG; else {
if(packflg) w = ewidth[v->etype];
if(w == 8)
w = 4;
}
if(w < 1 || w > SZ_LONG)
fatal(Z, "align");
if(packflg)
w = packflg; w = packflg;
break; break;
...@@ -536,8 +544,8 @@ align(int32 i, Type *t, int op) ...@@ -536,8 +544,8 @@ align(int32 i, Type *t, int op)
case Aarg0: /* initial passbyptr argument in arg list */ case Aarg0: /* initial passbyptr argument in arg list */
if(typesuv[t->etype]) { if(typesuv[t->etype]) {
o = align(o, types[TIND], Aarg1); o = align(o, types[TIND], Aarg1, nil);
o = align(o, types[TIND], Aarg2); o = align(o, types[TIND], Aarg2, nil);
} }
break; break;
...@@ -558,11 +566,13 @@ align(int32 i, Type *t, int op) ...@@ -558,11 +566,13 @@ align(int32 i, Type *t, int op)
break; break;
case Aaut3: /* total align of automatic */ case Aaut3: /* total align of automatic */
o = align(o, t, Ael1); o = align(o, t, Ael1, nil);
o = align(o, t, Ael2); o = align(o, t, Ael2, nil);
break; break;
} }
o = xround(o, w); o = xround(o, w);
if(maxalign && *maxalign < w)
*maxalign = w;
if(debug['A']) if(debug['A'])
print("align %s %d %T = %d\n", bnames[op], i, t, o); print("align %s %d %T = %d\n", bnames[op], i, t, o);
return o; return o;
......
...@@ -385,7 +385,7 @@ err: ...@@ -385,7 +385,7 @@ err:
void void
regsalloc(Node *n, Node *nn) regsalloc(Node *n, Node *nn)
{ {
cursafe = align(cursafe, nn->type, Aaut3); cursafe = align(cursafe, nn->type, Aaut3, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
*n = *nodsafe; *n = *nodsafe;
n->xoffset = -(stkoff + cursafe); n->xoffset = -(stkoff + cursafe);
...@@ -399,22 +399,22 @@ regaalloc1(Node *n, Node *nn) ...@@ -399,22 +399,22 @@ regaalloc1(Node *n, Node *nn)
{ {
nodreg(n, nn, REGARG); nodreg(n, nn, REGARG);
reg[REGARG]++; reg[REGARG]++;
curarg = align(curarg, nn->type, Aarg1); curarg = align(curarg, nn->type, Aarg1, nil);
curarg = align(curarg, nn->type, Aarg2); curarg = align(curarg, nn->type, Aarg2, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
} }
void void
regaalloc(Node *n, Node *nn) regaalloc(Node *n, Node *nn)
{ {
curarg = align(curarg, nn->type, Aarg1); curarg = align(curarg, nn->type, Aarg1, nil);
*n = *nn; *n = *nn;
n->op = OINDREG; n->op = OINDREG;
n->reg = REGSP; n->reg = REGSP;
n->xoffset = curarg; n->xoffset = curarg;
n->complex = 0; n->complex = 0;
n->addable = 20; n->addable = 20;
curarg = align(curarg, nn->type, Aarg2); curarg = align(curarg, nn->type, Aarg2, nil);
maxargsafe = maxround(maxargsafe, cursafe+curarg); maxargsafe = maxround(maxargsafe, cursafe+curarg);
} }
......
...@@ -166,6 +166,7 @@ struct Type ...@@ -166,6 +166,7 @@ struct Type
uchar nbits; uchar nbits;
uchar etype; uchar etype;
uchar garb; uchar garb;
uchar align;
}; };
#define T ((Type*)0) #define T ((Type*)0)
...@@ -785,7 +786,7 @@ int32 outlstring(ushort*, int32); ...@@ -785,7 +786,7 @@ int32 outlstring(ushort*, int32);
void sextern(Sym*, Node*, int32, int32); void sextern(Sym*, Node*, int32, int32);
void xcom(Node*); void xcom(Node*);
int32 exreg(Type*); int32 exreg(Type*);
int32 align(int32, Type*, int); int32 align(int32, Type*, int, int32*);
int32 maxround(int32, int32); int32 maxround(int32, int32);
extern schar ewidth[]; extern schar ewidth[];
......
...@@ -552,9 +552,10 @@ void ...@@ -552,9 +552,10 @@ void
sualign(Type *t) sualign(Type *t)
{ {
Type *l; Type *l;
int32 o, w; int32 o, w, maxal;
o = 0; o = 0;
maxal = 0;
switch(t->etype) { switch(t->etype) {
case TSTRUCT: case TSTRUCT:
...@@ -577,13 +578,14 @@ sualign(Type *t) ...@@ -577,13 +578,14 @@ sualign(Type *t)
l->sym->name); l->sym->name);
else else
diag(Z, "incomplete structure element"); diag(Z, "incomplete structure element");
w = align(w, l, Ael1); w = align(w, l, Ael1, &maxal);
l->offset = w; l->offset = w;
w = align(w, l, Ael2); w = align(w, l, Ael2, &maxal);
} }
} }
w = align(w, t, Asu2); w = align(w, t, Asu2, &maxal);
t->width = w; t->width = w;
t->align = maxal;
acidtype(t); acidtype(t);
pickletype(t); pickletype(t);
return; return;
...@@ -600,12 +602,13 @@ sualign(Type *t) ...@@ -600,12 +602,13 @@ sualign(Type *t)
diag(Z, "incomplete union element"); diag(Z, "incomplete union element");
l->offset = 0; l->offset = 0;
l->shift = 0; l->shift = 0;
o = align(align(0, l, Ael1), l, Ael2); o = align(align(0, l, Ael1, &maxal), l, Ael2, &maxal);
if(o > w) if(o > w)
w = o; w = o;
} }
w = align(w, t, Asu2); w = align(w, t, Asu2, &maxal);
t->width = w; t->width = w;
t->align = maxal;
acidtype(t); acidtype(t);
pickletype(t); pickletype(t);
return; return;
...@@ -663,7 +666,7 @@ argmark(Node *n, int pass) ...@@ -663,7 +666,7 @@ argmark(Node *n, int pass)
{ {
Type *t; Type *t;
autoffset = align(0, thisfn->link, Aarg0); autoffset = align(0, thisfn->link, Aarg0, nil);
stkoff = 0; stkoff = 0;
for(; n->left != Z; n = n->left) { for(; n->left != Z; n = n->left) {
if(n->op != OFUNC || n->left->op != ONAME) if(n->op != OFUNC || n->left->op != ONAME)
...@@ -745,9 +748,9 @@ loop: ...@@ -745,9 +748,9 @@ loop:
firstarg = s; firstarg = s;
firstargtype = s->type; firstargtype = s->type;
} }
autoffset = align(autoffset, s->type, Aarg1); autoffset = align(autoffset, s->type, Aarg1, nil);
s->offset = autoffset; s->offset = autoffset;
autoffset = align(autoffset, s->type, Aarg2); autoffset = align(autoffset, s->type, Aarg2, nil);
} else } else
dodecl(pdecl, CXXX, types[TINT], n); dodecl(pdecl, CXXX, types[TINT], n);
break; break;
...@@ -1275,7 +1278,7 @@ adecl(int c, Type *t, Sym *s) ...@@ -1275,7 +1278,7 @@ adecl(int c, Type *t, Sym *s)
} }
switch(c) { switch(c) {
case CAUTO: case CAUTO:
autoffset = align(autoffset, t, Aaut3); autoffset = align(autoffset, t, Aaut3, nil);
stkoff = maxround(stkoff, autoffset); stkoff = maxround(stkoff, autoffset);
s->offset = -autoffset; s->offset = -autoffset;
break; break;
...@@ -1285,10 +1288,10 @@ adecl(int c, Type *t, Sym *s) ...@@ -1285,10 +1288,10 @@ adecl(int c, Type *t, Sym *s)
firstarg = s; firstarg = s;
firstargtype = t; firstargtype = t;
} }
autoffset = align(autoffset, t, Aarg1); autoffset = align(autoffset, t, Aarg1, nil);
if(s) if(s)
s->offset = autoffset; s->offset = autoffset;
autoffset = align(autoffset, t, Aarg2); autoffset = align(autoffset, t, Aarg2, nil);
break; break;
} }
} }
...@@ -1587,7 +1590,7 @@ contig(Sym *s, Node *n, int32 v) ...@@ -1587,7 +1590,7 @@ contig(Sym *s, Node *n, int32 v)
if(v != 0) if(v != 0)
diag(n, "automatic adjustable array: %s", s->name); diag(n, "automatic adjustable array: %s", s->name);
v = s->offset; v = s->offset;
autoffset = align(autoffset, s->type, Aaut3); autoffset = align(autoffset, s->type, Aaut3, nil);
s->offset = -autoffset; s->offset = -autoffset;
stkoff = maxround(stkoff, autoffset); stkoff = maxround(stkoff, autoffset);
symadjust(s, n, v - s->offset); symadjust(s, n, v - s->offset);
......
...@@ -37,7 +37,7 @@ argsize(void) ...@@ -37,7 +37,7 @@ argsize(void)
int32 s; int32 s;
//print("t=%T\n", thisfn); //print("t=%T\n", thisfn);
s = align(0, thisfn->link, Aarg0); s = align(0, thisfn->link, Aarg0, nil);
for(t=thisfn->down; t!=T; t=t->down) { for(t=thisfn->down; t!=T; t=t->down) {
switch(t->etype) { switch(t->etype) {
case TVOID: case TVOID:
...@@ -47,8 +47,8 @@ argsize(void) ...@@ -47,8 +47,8 @@ argsize(void)
s += 64; s += 64;
break; break;
default: default:
s = align(s, t, Aarg1); s = align(s, t, Aarg1, nil);
s = align(s, t, Aarg2); s = align(s, t, Aarg2, nil);
break; break;
} }
//print(" %d %T\n", s, t); //print(" %d %T\n", s, t);
...@@ -99,7 +99,7 @@ codgen(Node *n, Node *nn) ...@@ -99,7 +99,7 @@ codgen(Node *n, Node *nn)
nod1 = *nodret->left; nod1 = *nodret->left;
nod1.sym = firstarg; nod1.sym = firstarg;
nod1.type = firstargtype; nod1.type = firstargtype;
nod1.xoffset = align(0, firstargtype, Aarg1); nod1.xoffset = align(0, firstargtype, Aarg1, nil);
nod1.etype = firstargtype->etype; nod1.etype = firstargtype->etype;
nodreg(&nod, &nod1, REGARG); nodreg(&nod, &nod1, REGARG);
gmove(&nod, &nod1); gmove(&nod, &nod1);
......
...@@ -115,7 +115,7 @@ outlstring(ushort *s, int32 n) ...@@ -115,7 +115,7 @@ outlstring(ushort *s, int32 n)
r = nstring; r = nstring;
while(n > 0) { while(n > 0) {
c = *s++; c = *s++;
if(align(0, types[TCHAR], Aarg1)) { if(align(0, types[TCHAR], Aarg1, nil)) {
buf[0] = c>>8; buf[0] = c>>8;
buf[1] = c; buf[1] = c;
} else { } else {
......
...@@ -49,8 +49,8 @@ widstruct(Type *t, uint32 o, int flag) ...@@ -49,8 +49,8 @@ widstruct(Type *t, uint32 o, int flag)
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) if(f->type->align > maxalign)
maxalign = f->align; maxalign = f->type->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;
...@@ -248,9 +248,11 @@ dowidth(Type *t) ...@@ -248,9 +248,11 @@ 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, widthptr); w = widstruct(t, 0, 1);
if(w == 0) if(w == 0)
w = 1; w = 1;
//if(t->align < widthptr)
// warn("align %d: %T\n", t->align, t);
break; break;
case TFUNC: case TFUNC:
...@@ -272,6 +274,8 @@ dowidth(Type *t) ...@@ -272,6 +274,8 @@ dowidth(Type *t)
w = widstruct(*getinarg(t1), w, widthptr); w = widstruct(*getinarg(t1), w, widthptr);
w = widstruct(*getoutarg(t1), w, widthptr); w = widstruct(*getoutarg(t1), w, widthptr);
t1->argwid = w; t1->argwid = w;
if(w%widthptr)
warn("bad type %T %d\n", t1, w);
t->align = 1; t->align = 1;
break; break;
} }
......
...@@ -1124,7 +1124,7 @@ reswitch: ...@@ -1124,7 +1124,7 @@ reswitch:
case OPRINT: case OPRINT:
case OPRINTN: case OPRINTN:
ok |= Etop; ok |= Etop;
typechecklist(n->list, Erv); typechecklist(n->list, Erv | Eindir); // Eindir: address does not escape
goto ret; goto ret;
case OPANIC: case OPANIC:
......
...@@ -730,8 +730,6 @@ type tiny struct { ...@@ -730,8 +730,6 @@ type tiny struct {
// Call calls the function fv with input parameters in. // Call calls the function fv with input parameters in.
// It returns the function's output parameters as Values. // It returns the function's output parameters as Values.
func (fv *FuncValue) Call(in []Value) []Value { func (fv *FuncValue) Call(in []Value) []Value {
var structAlign = Typeof((*tiny)(nil)).(*PtrType).Elem().Size()
t := fv.Type().(*FuncType) t := fv.Type().(*FuncType)
nin := len(in) nin := len(in)
if fv.first != nil && !fv.isInterface { if fv.first != nil && !fv.isInterface {
...@@ -757,7 +755,7 @@ func (fv *FuncValue) Call(in []Value) []Value { ...@@ -757,7 +755,7 @@ func (fv *FuncValue) Call(in []Value) []Value {
size = (size + a - 1) &^ (a - 1) size = (size + a - 1) &^ (a - 1)
size += tv.Size() size += tv.Size()
} }
size = (size + structAlign - 1) &^ (structAlign - 1) size = (size + ptrSize - 1) &^ (ptrSize - 1)
for i := 0; i < nout; i++ { for i := 0; i < nout; i++ {
tv := t.Out(i) tv := t.Out(i)
a := uintptr(tv.Align()) a := uintptr(tv.Align())
...@@ -767,9 +765,9 @@ func (fv *FuncValue) Call(in []Value) []Value { ...@@ -767,9 +765,9 @@ func (fv *FuncValue) Call(in []Value) []Value {
// size must be > 0 in order for &args[0] to be valid. // size must be > 0 in order for &args[0] to be valid.
// the argument copying is going to round it up to // the argument copying is going to round it up to
// a multiple of 8 anyway, so make it 8 to begin with. // a multiple of ptrSize anyway, so make it ptrSize to begin with.
if size < 8 { if size < ptrSize {
size = 8 size = ptrSize
} }
// round to pointer size // round to pointer size
...@@ -811,7 +809,7 @@ func (fv *FuncValue) Call(in []Value) []Value { ...@@ -811,7 +809,7 @@ func (fv *FuncValue) Call(in []Value) []Value {
memmove(addr(ptr+off), v.getAddr(), n) memmove(addr(ptr+off), v.getAddr(), n)
off += n off += n
} }
off = (off + structAlign - 1) &^ (structAlign - 1) off = (off + ptrSize - 1) &^ (ptrSize - 1)
// Call // Call
call(*(**byte)(fv.addr), (*byte)(addr(ptr)), uint32(size)) call(*(**byte)(fv.addr), (*byte)(addr(ptr)), uint32(size))
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
package runtime package runtime
import "unsafe"
// Breakpoint() executes a breakpoint trap. // Breakpoint() executes a breakpoint trap.
func Breakpoint() func Breakpoint()
...@@ -73,6 +75,15 @@ type MemStatsType struct { ...@@ -73,6 +75,15 @@ type MemStatsType struct {
} }
} }
var sizeof_C_MStats int // filled in by malloc.goc
func init() {
if sizeof_C_MStats != unsafe.Sizeof(MemStats) {
println(sizeof_C_MStats, unsafe.Sizeof(MemStats))
panic("MStats vs MemStatsType size mismatch")
}
}
// MemStats holds statistics about the memory system. // MemStats holds statistics about the memory system.
// The statistics are only approximate, as they are not interlocked on update. // The statistics are only approximate, as they are not interlocked on update.
var MemStats MemStatsType var MemStats MemStatsType
......
...@@ -64,7 +64,6 @@ ...@@ -64,7 +64,6 @@
*/ */
#define malloc runtime·mal #define malloc runtime·mal
#define offsetof(s,m) (uint32)(&(((s*)0)->m))
#define memset(a,b,c) runtime·memclr((byte*)(a), (uint32)(c)) #define memset(a,b,c) runtime·memclr((byte*)(a), (uint32)(c))
#define memcpy(a,b,c) runtime·mcpy((byte*)(a),(byte*)(b),(uint32)(c)) #define memcpy(a,b,c) runtime·mcpy((byte*)(a),(byte*)(b),(uint32)(c))
#define assert(a) if(!(a)) runtime·throw("assert") #define assert(a) if(!(a)) runtime·throw("assert")
......
...@@ -244,6 +244,8 @@ runtime·allocmcache(void) ...@@ -244,6 +244,8 @@ runtime·allocmcache(void)
return c; return c;
} }
int32 runtime·sizeof_C_MStats = sizeof(MStats);
void void
runtime·mallocinit(void) runtime·mallocinit(void)
{ {
......
...@@ -258,6 +258,13 @@ runtime·check(void) ...@@ -258,6 +258,13 @@ runtime·check(void)
float64 j; float64 j;
void* k; void* k;
uint16* l; uint16* l;
struct x1 {
byte x;
};
struct y1 {
struct x1 x1;
byte y;
};
if(sizeof(a) != 1) runtime·throw("bad a"); if(sizeof(a) != 1) runtime·throw("bad a");
if(sizeof(b) != 1) runtime·throw("bad b"); if(sizeof(b) != 1) runtime·throw("bad b");
...@@ -271,7 +278,9 @@ runtime·check(void) ...@@ -271,7 +278,9 @@ runtime·check(void)
if(sizeof(j) != 8) runtime·throw("bad j"); if(sizeof(j) != 8) runtime·throw("bad j");
if(sizeof(k) != sizeof(uintptr)) runtime·throw("bad k"); if(sizeof(k) != sizeof(uintptr)) runtime·throw("bad k");
if(sizeof(l) != sizeof(uintptr)) runtime·throw("bad l"); if(sizeof(l) != sizeof(uintptr)) runtime·throw("bad l");
// prints(1"check ok\n"); if(sizeof(struct x1) != 1) runtime·throw("bad sizeof x1");
if(offsetof(struct y1, y) != 1) runtime·throw("bad offsetof y1.y");
if(sizeof(struct y1) != 2) runtime·throw("bad sizeof y1");
uint32 z; uint32 z;
z = 1; z = 1;
......
...@@ -306,6 +306,7 @@ enum { ...@@ -306,6 +306,7 @@ enum {
*/ */
#define nelem(x) (sizeof(x)/sizeof((x)[0])) #define nelem(x) (sizeof(x)/sizeof((x)[0]))
#define nil ((void*)0) #define nil ((void*)0)
#define offsetof(s,m) (uint32)(&(((s*)0)->m))
/* /*
* known to compiler * known to compiler
......
...@@ -10,9 +10,15 @@ import ( ...@@ -10,9 +10,15 @@ import (
"strconv" "strconv"
) )
type T1 struct { x uint8 } type T1 struct {
type T2 struct { x uint16 } x uint8
type T4 struct { x uint32 } }
type T2 struct {
x uint16
}
type T4 struct {
x uint32
}
func main() { func main() {
report := len(os.Args) > 1 report := len(os.Args) > 1
...@@ -20,7 +26,7 @@ func main() { ...@@ -20,7 +26,7 @@ func main() {
var b1 [10]T1 var b1 [10]T1
a0, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[0])[2:], 16) a0, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[0])[2:], 16)
a1, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[1])[2:], 16) a1, _ := strconv.Btoui64(fmt.Sprintf("%p", &b1[1])[2:], 16)
if a1 != a0 + 1 { if a1 != a0+1 {
fmt.Println("FAIL") fmt.Println("FAIL")
if report { if report {
fmt.Println("alignment should be 1, is", a1-a0) fmt.Println("alignment should be 1, is", a1-a0)
...@@ -30,7 +36,7 @@ func main() { ...@@ -30,7 +36,7 @@ func main() {
var b2 [10]T2 var b2 [10]T2
a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[0])[2:], 16) a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[0])[2:], 16)
a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[1])[2:], 16) a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b2[1])[2:], 16)
if a1 != a0 + 2 { if a1 != a0+2 {
if status == 0 { if status == 0 {
fmt.Println("FAIL") fmt.Println("FAIL")
status = 1 status = 1
...@@ -42,7 +48,7 @@ func main() { ...@@ -42,7 +48,7 @@ func main() {
var b4 [10]T4 var b4 [10]T4
a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[0])[2:], 16) a0, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[0])[2:], 16)
a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[1])[2:], 16) a1, _ = strconv.Btoui64(fmt.Sprintf("%p", &b4[1])[2:], 16)
if a1 != a0 + 4 { if a1 != a0+4 {
if status == 0 { if status == 0 {
fmt.Println("FAIL") fmt.Println("FAIL")
status = 1 status = 1
......
...@@ -173,7 +173,3 @@ panic: interface conversion: interface is main.T, not main.T ...@@ -173,7 +173,3 @@ panic: interface conversion: interface is main.T, not main.T
panic PC=xxx panic PC=xxx
== bugs/ == bugs/
=========== bugs/bug260.go
FAIL
BUG: bug260 failed
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