aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/gc/align.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/align.c')
-rw-r--r--src/cmd/gc/align.c689
1 files changed, 0 insertions, 689 deletions
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
deleted file mode 100644
index 59ff0abf73..0000000000
--- a/src/cmd/gc/align.c
+++ /dev/null
@@ -1,689 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-/*
- * machine size and rounding
- * alignment is dictated around
- * the size of a pointer, set in betypeinit
- * (see ../6g/galign.c).
- */
-
-static int defercalc;
-
-vlong
-rnd(vlong o, vlong r)
-{
- if(r < 1 || r > 8 || (r&(r-1)) != 0)
- fatal("rnd %lld", r);
- 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 >= thearch.MAXWIDTH) {
- yyerror("interface too large");
- o = widthptr;
- }
- }
-}
-
-static vlong
-widstruct(Type *errtype, Type *t, vlong o, int flag)
-{
- Type *f;
- int64 w;
- int32 maxalign;
- vlong starto, lastzero;
-
- starto = o;
- maxalign = flag;
- if(maxalign < 1)
- maxalign = 1;
- lastzero = 0;
- for(f=t->type; f!=T; f=f->down) {
- if(f->etype != TFIELD)
- fatal("widstruct: not TFIELD: %lT", f);
- if(f->type == T) {
- // broken field, just skip it so that other valid fields
- // get a width.
- 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; // really offset for TFIELD
- if(f->nname != N) {
- // this same stackparam logic is in addrescapes
- // in typecheck.c. usually addrescapes runs after
- // widstruct, in which case we could drop this,
- // but function closure functions are the exception.
- if(f->nname->stackparam) {
- f->nname->stackparam->xoffset = o;
- f->nname->xoffset = 0;
- } else
- f->nname->xoffset = o;
- }
- if(w == 0)
- lastzero = o;
- o += w;
- if(o >= thearch.MAXWIDTH) {
- yyerror("type %lT too large", errtype);
- o = 8; // small but nonzero
- }
- }
- // For nonzero-sized structs which end in a zero-sized thing, we add
- // an extra byte of padding to the type. This padding ensures that
- // taking the address of the zero-sized thing can't manufacture a
- // pointer to the next object in the heap. See issue 9401.
- if(flag == 1 && o > starto && o == lastzero)
- o++;
-
- // final width is rounded
- if(flag)
- o = rnd(o, maxalign);
- t->align = maxalign;
-
- // type width only includes back to first field's offset
- t->width = o - starto;
- 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) {
- t->broke = 1;
- yyerror("invalid recursive type %T", t);
- }
- t->width = 0;
- lineno = lno;
- return;
- }
-
- // break infinite recursion if the broken recursive type
- // is referenced again
- if(t->broke && t->width == 0)
- return;
-
- // defer checkwidth calls until after we're done
- 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:
- /* simtype == 0 during bootstrap */
- if(simtype[t->etype] != 0)
- et = simtype[t->etype];
- break;
- }
-
- w = 0;
- switch(et) {
- default:
- fatal("dowidth: unknown type: %T", t);
- break;
-
- /* compiler-specific stuff */
- case TINT8:
- case TUINT8:
- case TBOOL: // bool is int8
- 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: // implemented as 2 pointers
- w = 2*widthptr;
- t->align = widthptr;
- offmod(t);
- break;
- case TCHAN: // implemented as pointer
- w = widthptr;
- checkwidth(t->type);
-
- // make fake type to check later to
- // trigger channel argument check.
- t1 = typ(TCHANARGS);
- t1->type = t;
- checkwidth(t1);
- break;
- case TCHANARGS:
- t1 = t->type;
- 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;
- checkwidth(t->type);
- checkwidth(t->down);
- break;
- case TFORW: // should have been filled in
- if(!t->broke)
- yyerror("invalid recursive type %T", t);
- w = 1; // anything will do
- break;
- case TANY:
- // dummy type; should be replaced before use.
- if(!debug['A'])
- fatal("dowidth any");
- w = 1; // anything will do
- 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 = (thearch.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); // probably [...]T
- break;
-
- case TSTRUCT:
- if(t->funarg)
- fatal("dowidth fn struct %T", t);
- w = widstruct(t, t, 0, 1);
- break;
-
- case TFUNC:
- // make fake type to check later to
- // trigger function argument computation.
- t1 = typ(TFUNCARGS);
- t1->type = t;
- checkwidth(t1);
-
- // width of func type is pointer
- w = widthptr;
- break;
-
- case TFUNCARGS:
- // function is 3 cated structures;
- // compute their widths as side-effect.
- 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;
-}
-
-/*
- * when a type's width should be known, we call checkwidth
- * to compute it. during a declaration like
- *
- * type T *struct { next T }
- *
- * it is necessary to defer the calculation of the struct width
- * until after T has been initialized to be a pointer to that struct.
- * similarly, during import processing structs may be used
- * before their definition. in those situations, calling
- * defercheckwidth() stops width calculations until
- * resumecheckwidth() is called, at which point all the
- * checkwidths that were deferred are executed.
- * dowidth should only be called when the type's size
- * is needed immediately. checkwidth makes sure the
- * size is evaluated eventually.
- */
-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;
-
- // function arg structs should not be checked
- // outside of the enclosing function.
- 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)
-{
- // we get out of sync on syntax errors, so don't be pedantic.
- 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;
-
- /*
- * initialize okfor
- */
- 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; // nil only; refined in typecheck
- okforeq[TFUNC] = 1; // nil only; refined in typecheck
- okforeq[TARRAY] = 1; // nil slice only; refined in typecheck
- okforeq[TSTRUCT] = 1; // it's complicated; refined in typecheck
-
- okforcmp[TSTRING] = 1;
-
- for(i=0; i<nelem(okfor); i++)
- okfor[i] = okfornone;
-
- // binary
- 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;
-
- // unary
- okfor[OCOM] = okforand;
- okfor[OMINUS] = okforarith;
- okfor[ONOT] = okforbool;
- okfor[OPLUS] = okforarith;
-
- // special
- okfor[OCAP] = okforcap;
- okfor[OLEN] = okforlen;
-
- // comparison
- 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");
-
- /* f is valid float if min < f < max. (min and max are not themselves valid.) */
- mpatoflt(maxfltval[TFLOAT32], "33554431p103"); /* 2^24-1 p (127-23) + 1/2 ulp*/
- mpatoflt(minfltval[TFLOAT32], "-33554431p103");
- mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970"); /* 2^53-1 p (1023-52) + 1/2 ulp */
- mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970");
-
- maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32];
- minfltval[TCOMPLEX64] = minfltval[TFLOAT32];
- maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64];
- minfltval[TCOMPLEX128] = minfltval[TFLOAT64];
-
- /* for walk to use in error messages */
- types[TFUNC] = functype(N, nil, nil);
-
- /* types used in front end */
- // types[TNIL] got set early in lexinit
- types[TIDEAL] = typ(TIDEAL);
- types[TINTER] = typ(TINTER);
-
- /* simple aliases */
- simtype[TMAP] = tptr;
- simtype[TCHAN] = tptr;
- simtype[TFUNC] = tptr;
- simtype[TUNSAFEPTR] = tptr;
-
- /* pick up the backend thearch.typedefs */
- for(i=0; thearch.typedefs[i].name; i++) {
- s = lookup(thearch.typedefs[i].name);
- s1 = pkglookup(thearch.typedefs[i].name, builtinpkg);
-
- etype = thearch.typedefs[i].etype;
- if(etype < 0 || etype >= nelem(types))
- fatal("typeinit: %s bad etype", s->name);
- sameas = thearch.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);
-
- // string is same as slice wo the cap
- sizeof_String = rnd(Array_nel+widthint, widthptr);
-
- dowidth(types[TSTRING]);
- dowidth(idealstring);
-}
-
-/*
- * compute total size of f's in/out arguments.
- */
-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;
-}