// 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 "go.h" /* * machine size and rounding * alignment is dictated around * the size of a pointer, set in belexinit * (see ../6g/align.c). */ uint32 rnd(uint32 o, uint32 r) { if(maxround == 0) fatal("rnd"); if(r > maxround) r = maxround; if(r != 0) while(o%r != 0) o++; return o; } 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("widstruct: not TFIELD: %lT", f); if(f->type->etype != TFUNC) continue; f->width = o; o += widthptr; } } 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; for(f=t->type; f!=T; f=f->down) { if(f->etype != TFIELD) fatal("widstruct: not TFIELD: %lT", f); dowidth(f->type); w = f->type->width; m = arrayelemwidth(f->type); o = rnd(o, m); f->width = o; // really offset for TFIELD o += w; } // final width is rounded if(flag) o = rnd(o, maxround); // type width only includes back to first field's offset if(t->type == T) t->width = 0; else t->width = o - t->type->width; return o; } void dowidth(Type *t) { int32 et; uint32 w; if(maxround == 0 || widthptr == 0) fatal("dowidth without betypeinit"); if(t == T) return; if(t->width == -2) { yyerror("invalid recursive type %T", t); t->width = 0; return; } t->width = -2; 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: %E", t->etype); 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: case TPTR32: // note lack of recursion w = 4; break; case TINT64: case TUINT64: case TFLOAT64: case TPTR64: // note lack of recursion w = 8; break; case TFLOAT80: w = 10; break; case TDDD: w = 2*widthptr; break; case TINTER: // implemented as 2 pointers case TFORWINTER: offmod(t); w = 2*widthptr; break; case TCHAN: // implemented as pointer dowidth(t->type); dowidth(t->down); w = widthptr; break; case TMAP: // implemented as pointer dowidth(t->type); w = widthptr; break; case TFORW: // should have been filled in case TFORWSTRUCT: yyerror("incomplete type %T", t); w = widthptr; break; case TANY: // implemented as pointer w = widthptr; break; case TSTRING: w = sizeof_String; break; case TARRAY: if(t->type == T) break; dowidth(t->type); w = sizeof_Array; if(t->bound >= 0) w = t->bound * t->type->width; break; case TSTRUCT: if(t->funarg) fatal("dowidth fn struct %T", t); w = widstruct(t, 0, 1); if(w == 0) w = maxround; break; case TFUNC: // function is 3 cated structures; // compute their widths as side-effect. w = widstruct(*getthis(t), 0, 0); w = widstruct(*getinarg(t), w, 1); w = widstruct(*getoutarg(t), w, 1); t->argwid = w; // but width of func type is pointer w = widthptr; break; } t->width = w; } void typeinit(void) { int i, etype, sameas; Type *t; Sym *s; if(widthptr == 0) fatal("typeinit before betypeinit"); for(i=0; i= 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 = s; dowidth(t); types[etype] = t; s->def = typenod(t); } 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); // string is same as slice wo the cap sizeof_String = rnd(Array_nel+types[TUINT32]->width, maxround); } /* * compute total size of f's in/out arguments. */ int argsize(Type *t) { Iter save; Type *fp; int 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+7) & ~7; return w; }