This source file includes following definitions.
- rnd
- offmod
- widstruct
- dowidth
- checkwidth
- defercheckwidth
- resumecheckwidth
- typeinit
- argsize
#include <u.h>
#include <libc.h>
#include "go.h"
static int defercalc;
vlong
rnd(vlong o, vlong r)
{
if(r < 1 || r > 8 || (r&(r-1)) != 0)
fatal("rnd");
return (o+r-1)&~(r-1);
}
static void
offmod(Type *t)
{
Type *f;
int32 o;
o = 0;
for(f=t->type; f!=T; f=f->down) {
if(f->etype != TFIELD)
fatal("offmod: not TFIELD: %lT", f);
f->width = o;
o += widthptr;
if(o >= MAXWIDTH) {
yyerror("interface too large");
o = widthptr;
}
}
}
static vlong
widstruct(Type *errtype, Type *t, vlong o, int flag)
{
Type *f;
int64 w;
int32 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);
if(f->type == T) {
continue;
}
dowidth(f->type);
if(f->type->align > maxalign)
maxalign = f->type->align;
if(f->type->width < 0)
fatal("invalid width %lld", f->type->width);
w = f->type->width;
if(f->type->align > 0)
o = rnd(o, f->type->align);
f->width = o;
if(f->nname != N) {
if(f->nname->stackparam) {
f->nname->stackparam->xoffset = o;
f->nname->xoffset = 0;
} else
f->nname->xoffset = o;
}
o += w;
if(o >= MAXWIDTH) {
yyerror("type %lT too large", errtype);
o = 8;
}
}
if(flag)
o = rnd(o, maxalign);
t->align = maxalign;
if(t->type == T)
t->width = 0;
else
t->width = o - t->type->width;
return o;
}
void
dowidth(Type *t)
{
int32 et;
int64 w;
int lno;
Type *t1;
if(widthptr == 0)
fatal("dowidth without betypeinit");
if(t == T)
return;
if(t->width > 0)
return;
if(t->width == -2) {
lno = lineno;
lineno = t->lineno;
if(!t->broke)
yyerror("invalid recursive type %T", t);
t->width = 0;
lineno = lno;
return;
}
defercalc++;
lno = lineno;
lineno = t->lineno;
t->width = -2;
t->align = 0;
et = t->etype;
switch(et) {
case TFUNC:
case TCHAN:
case TMAP:
case TSTRING:
break;
default:
if(simtype[t->etype] != 0)
et = simtype[t->etype];
break;
}
w = 0;
switch(et) {
default:
fatal("dowidth: unknown type: %T", t);
break;
case TINT8:
case TUINT8:
case TBOOL:
w = 1;
break;
case TINT16:
case TUINT16:
w = 2;
break;
case TINT32:
case TUINT32:
case TFLOAT32:
w = 4;
break;
case TINT64:
case TUINT64:
case TFLOAT64:
case TCOMPLEX64:
w = 8;
t->align = widthreg;
break;
case TCOMPLEX128:
w = 16;
t->align = widthreg;
break;
case TPTR32:
w = 4;
checkwidth(t->type);
break;
case TPTR64:
w = 8;
checkwidth(t->type);
break;
case TUNSAFEPTR:
w = widthptr;
break;
case TINTER:
w = 2*widthptr;
t->align = widthptr;
offmod(t);
break;
case TCHAN:
w = widthptr;
checkwidth(t->type);
t1 = typ(TCHANARGS);
t1->type = t;
checkwidth(t1);
break;
case TCHANARGS:
t1 = t->type;
dowidth(t->type);
if(t1->type->width >= (1<<16))
yyerror("channel element type too large (>64kB)");
t->width = 1;
break;
case TMAP:
w = widthptr;
checkwidth(t->type);
checkwidth(t->down);
break;
case TFORW:
if(!t->broke)
yyerror("invalid recursive type %T", t);
w = 1;
break;
case TANY:
if(!debug['A'])
fatal("dowidth any");
w = 1;
break;
case TSTRING:
if(sizeof_String == 0)
fatal("early dowidth string");
w = sizeof_String;
t->align = widthptr;
break;
case TARRAY:
if(t->type == T)
break;
if(t->bound >= 0) {
uint64 cap;
dowidth(t->type);
if(t->type->width != 0) {
cap = (MAXWIDTH-1) / t->type->width;
if(t->bound > cap)
yyerror("type %lT larger than address space", t);
}
w = t->bound * t->type->width;
t->align = t->type->align;
}
else if(t->bound == -1) {
w = sizeof_Array;
checkwidth(t->type);
t->align = widthptr;
}
else if(t->bound == -100) {
if(!t->broke) {
yyerror("use of [...] array outside of array literal");
t->broke = 1;
}
}
else
fatal("dowidth %T", t);
break;
case TSTRUCT:
if(t->funarg)
fatal("dowidth fn struct %T", t);
w = widstruct(t, t, 0, 1);
break;
case TFUNC:
t1 = typ(TFUNCARGS);
t1->type = t;
checkwidth(t1);
w = widthptr;
break;
case TFUNCARGS:
t1 = t->type;
w = widstruct(t->type, *getthis(t1), 0, 0);
w = widstruct(t->type, *getinarg(t1), w, widthreg);
w = widstruct(t->type, *getoutarg(t1), w, widthreg);
t1->argwid = w;
if(w%widthreg)
warn("bad type %T %d\n", t1, w);
t->align = 1;
break;
}
if(widthptr == 4 && w != (int32)w)
yyerror("type %T too large", t);
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)
resumecheckwidth();
else
--defercalc;
}
typedef struct TypeList TypeList;
struct TypeList {
Type *t;
TypeList *next;
};
static TypeList *tlfree;
static TypeList *tlq;
void
checkwidth(Type *t)
{
TypeList *l;
if(t == T)
return;
if(t->funarg)
fatal("checkwidth %T", t);
if(!defercalc) {
dowidth(t);
return;
}
if(t->deferwidth)
return;
t->deferwidth = 1;
l = tlfree;
if(l != nil)
tlfree = l->next;
else
l = mal(sizeof *l);
l->t = t;
l->next = tlq;
tlq = l;
}
void
defercheckwidth(void)
{
if(defercalc && nerrors == 0)
fatal("defercheckwidth");
defercalc = 1;
}
void
resumecheckwidth(void)
{
TypeList *l;
if(!defercalc)
fatal("resumecheckwidth");
for(l = tlq; l != nil; l = tlq) {
l->t->deferwidth = 0;
tlq = l->next;
dowidth(l->t);
l->next = tlfree;
tlfree = l;
}
defercalc = 0;
}
void
typeinit(void)
{
int i, etype, sameas;
Type *t;
Sym *s, *s1;
if(widthptr == 0)
fatal("typeinit before betypeinit");
for(i=0; i<NTYPE; i++)
simtype[i] = i;
types[TPTR32] = typ(TPTR32);
dowidth(types[TPTR32]);
types[TPTR64] = typ(TPTR64);
dowidth(types[TPTR64]);
t = typ(TUNSAFEPTR);
types[TUNSAFEPTR] = t;
t->sym = pkglookup("Pointer", unsafepkg);
t->sym->def = typenod(t);
dowidth(types[TUNSAFEPTR]);
tptr = TPTR32;
if(widthptr == 8)
tptr = TPTR64;
for(i=TINT8; i<=TUINT64; i++)
isint[i] = 1;
isint[TINT] = 1;
isint[TUINT] = 1;
isint[TUINTPTR] = 1;
isfloat[TFLOAT32] = 1;
isfloat[TFLOAT64] = 1;
iscomplex[TCOMPLEX64] = 1;
iscomplex[TCOMPLEX128] = 1;
isptr[TPTR32] = 1;
isptr[TPTR64] = 1;
isforw[TFORW] = 1;
issigned[TINT] = 1;
issigned[TINT8] = 1;
issigned[TINT16] = 1;
issigned[TINT32] = 1;
issigned[TINT64] = 1;
for(i=0; i<NTYPE; i++) {
if(isint[i] || i == TIDEAL) {
okforeq[i] = 1;
okforcmp[i] = 1;
okforarith[i] = 1;
okforadd[i] = 1;
okforand[i] = 1;
okforconst[i] = 1;
issimple[i] = 1;
minintval[i] = mal(sizeof(*minintval[i]));
maxintval[i] = mal(sizeof(*maxintval[i]));
}
if(isfloat[i]) {
okforeq[i] = 1;
okforcmp[i] = 1;
okforadd[i] = 1;
okforarith[i] = 1;
okforconst[i] = 1;
issimple[i] = 1;
minfltval[i] = mal(sizeof(*minfltval[i]));
maxfltval[i] = mal(sizeof(*maxfltval[i]));
}
if(iscomplex[i]) {
okforeq[i] = 1;
okforadd[i] = 1;
okforarith[i] = 1;
okforconst[i] = 1;
issimple[i] = 1;
}
}
issimple[TBOOL] = 1;
okforadd[TSTRING] = 1;
okforbool[TBOOL] = 1;
okforcap[TARRAY] = 1;
okforcap[TCHAN] = 1;
okforconst[TBOOL] = 1;
okforconst[TSTRING] = 1;
okforlen[TARRAY] = 1;
okforlen[TCHAN] = 1;
okforlen[TMAP] = 1;
okforlen[TSTRING] = 1;
okforeq[TPTR32] = 1;
okforeq[TPTR64] = 1;
okforeq[TUNSAFEPTR] = 1;
okforeq[TINTER] = 1;
okforeq[TCHAN] = 1;
okforeq[TSTRING] = 1;
okforeq[TBOOL] = 1;
okforeq[TMAP] = 1;
okforeq[TFUNC] = 1;
okforeq[TARRAY] = 1;
okforeq[TSTRUCT] = 1;
okforcmp[TSTRING] = 1;
for(i=0; i<nelem(okfor); i++)
okfor[i] = okfornone;
okfor[OADD] = okforadd;
okfor[OAND] = okforand;
okfor[OANDAND] = okforbool;
okfor[OANDNOT] = okforand;
okfor[ODIV] = okforarith;
okfor[OEQ] = okforeq;
okfor[OGE] = okforcmp;
okfor[OGT] = okforcmp;
okfor[OLE] = okforcmp;
okfor[OLT] = okforcmp;
okfor[OMOD] = okforand;
okfor[OMUL] = okforarith;
okfor[ONE] = okforeq;
okfor[OOR] = okforand;
okfor[OOROR] = okforbool;
okfor[OSUB] = okforarith;
okfor[OXOR] = okforand;
okfor[OLSH] = okforand;
okfor[ORSH] = okforand;
okfor[OCOM] = okforand;
okfor[OMINUS] = okforarith;
okfor[ONOT] = okforbool;
okfor[OPLUS] = okforarith;
okfor[OCAP] = okforcap;
okfor[OLEN] = okforlen;
iscmp[OLT] = 1;
iscmp[OGT] = 1;
iscmp[OGE] = 1;
iscmp[OLE] = 1;
iscmp[OEQ] = 1;
iscmp[ONE] = 1;
mpatofix(maxintval[TINT8], "0x7f");
mpatofix(minintval[TINT8], "-0x80");
mpatofix(maxintval[TINT16], "0x7fff");
mpatofix(minintval[TINT16], "-0x8000");
mpatofix(maxintval[TINT32], "0x7fffffff");
mpatofix(minintval[TINT32], "-0x80000000");
mpatofix(maxintval[TINT64], "0x7fffffffffffffff");
mpatofix(minintval[TINT64], "-0x8000000000000000");
mpatofix(maxintval[TUINT8], "0xff");
mpatofix(maxintval[TUINT16], "0xffff");
mpatofix(maxintval[TUINT32], "0xffffffff");
mpatofix(maxintval[TUINT64], "0xffffffffffffffff");
mpatoflt(maxfltval[TFLOAT32], "33554431p103");
mpatoflt(minfltval[TFLOAT32], "-33554431p103");
mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970");
mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970");
maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32];
minfltval[TCOMPLEX64] = minfltval[TFLOAT32];
maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64];
minfltval[TCOMPLEX128] = minfltval[TFLOAT64];
types[TFUNC] = functype(N, nil, nil);
types[TIDEAL] = typ(TIDEAL);
types[TINTER] = typ(TINTER);
simtype[TMAP] = tptr;
simtype[TCHAN] = tptr;
simtype[TFUNC] = tptr;
simtype[TUNSAFEPTR] = tptr;
for(i=0; typedefs[i].name; i++) {
s = lookup(typedefs[i].name);
s1 = pkglookup(typedefs[i].name, builtinpkg);
etype = typedefs[i].etype;
if(etype < 0 || etype >= nelem(types))
fatal("typeinit: %s bad etype", s->name);
sameas = typedefs[i].sameas;
if(sameas < 0 || sameas >= nelem(types))
fatal("typeinit: %s bad sameas", s->name);
simtype[etype] = sameas;
minfltval[etype] = minfltval[sameas];
maxfltval[etype] = maxfltval[sameas];
minintval[etype] = minintval[sameas];
maxintval[etype] = maxintval[sameas];
t = types[etype];
if(t != T)
fatal("typeinit: %s already defined", s->name);
t = typ(etype);
t->sym = s1;
dowidth(t);
types[etype] = t;
s1->def = typenod(t);
}
Array_array = rnd(0, widthptr);
Array_nel = rnd(Array_array+widthptr, widthint);
Array_cap = rnd(Array_nel+widthint, widthint);
sizeof_Array = rnd(Array_cap+widthint, widthptr);
sizeof_String = rnd(Array_nel+widthint, widthptr);
dowidth(types[TSTRING]);
dowidth(idealstring);
}
int
argsize(Type *t)
{
Iter save;
Type *fp;
int64 w, x;
w = 0;
fp = structfirst(&save, getoutarg(t));
while(fp != T) {
x = fp->width + fp->type->width;
if(x > w)
w = x;
fp = structnext(&save);
}
fp = funcfirst(&save, t);
while(fp != T) {
x = fp->width + fp->type->width;
if(x > w)
w = x;
fp = funcnext(&save);
}
w = (w+widthptr-1) & ~(widthptr-1);
if((int)w != w)
fatal("argsize too big");
return w;
}