diff options
Diffstat (limited to 'src/cmd/cc/dcl.c')
-rw-r--r-- | src/cmd/cc/dcl.c | 1707 |
1 files changed, 0 insertions, 1707 deletions
diff --git a/src/cmd/cc/dcl.c b/src/cmd/cc/dcl.c deleted file mode 100644 index 117508fd6..000000000 --- a/src/cmd/cc/dcl.c +++ /dev/null @@ -1,1707 +0,0 @@ -// Inferno utils/cc/dcl.c -// http://code.google.com/p/inferno-os/source/browse/utils/cc/dcl.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include <u.h> -#include "cc.h" -#include "../ld/textflag.h" - -static int haspointers(Type*); - -Node* -dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n) -{ - Sym *s; - Node *n1; - int32 v; - - nearln = lineno; - lastfield = 0; - -loop: - if(n != Z) - switch(n->op) { - default: - diag(n, "unknown declarator: %O", n->op); - break; - - case OARRAY: - t = typ(TARRAY, t); - t->width = 0; - n1 = n->right; - n = n->left; - if(n1 != Z) { - complex(n1); - v = -1; - if(n1->op == OCONST) - v = n1->vconst; - if(v <= 0) { - diag(n, "array size must be a positive constant"); - v = 1; - } - t->width = v * t->link->width; - } - goto loop; - - case OIND: - t = typ(TIND, t); - t->garb = n->garb; - n = n->left; - goto loop; - - case OFUNC: - t = typ(TFUNC, t); - t->down = fnproto(n); - n = n->left; - goto loop; - - case OBIT: - n1 = n->right; - complex(n1); - lastfield = -1; - if(n1->op == OCONST) - lastfield = n1->vconst; - if(lastfield < 0) { - diag(n, "field width must be non-negative constant"); - lastfield = 1; - } - if(lastfield == 0) { - lastbit = 0; - firstbit = 1; - if(n->left != Z) { - diag(n, "zero width named field"); - lastfield = 1; - } - } - if(!typei[t->etype]) { - diag(n, "field type must be int-like"); - t = types[TINT]; - lastfield = 1; - } - if(lastfield > tfield->width*8) { - diag(n, "field width larger than field unit"); - lastfield = 1; - } - lastbit += lastfield; - if(lastbit > tfield->width*8) { - lastbit = lastfield; - firstbit = 1; - } - n = n->left; - goto loop; - - case ONAME: - if(f == NODECL) - break; - s = n->sym; - (*f)(c, t, s); - if(s->class == CLOCAL) - s = mkstatic(s); - if(dataflag) { - s->dataflag = dataflag; - dataflag = 0; - } else if(s->type != T && !haspointers(s->type)) - s->dataflag = NOPTR; - firstbit = 0; - n->sym = s; - n->type = s->type; - n->xoffset = s->offset; - n->class = s->class; - n->etype = TVOID; - if(n->type != T) - n->etype = n->type->etype; - if(debug['d']) - dbgdecl(s); - acidvar(s); - godefvar(s); - s->varlineno = lineno; - break; - } - lastdcl = t; - return n; -} - -Sym* -mkstatic(Sym *s) -{ - Sym *s1; - - if(s->class != CLOCAL) - return s; - snprint(symb, NSYMB, "%s$%d", s->name, s->block); - s1 = lookup(); - if(s1->class != CSTATIC) { - s1->type = s->type; - s1->offset = s->offset; - s1->block = s->block; - s1->class = CSTATIC; - } - return s1; -} - -/* - * make a copy of a typedef - * the problem is to split out incomplete - * arrays so that it is in the variable - * rather than the typedef. - */ -Type* -tcopy(Type *t) -{ - Type *tl, *tx; - int et; - - if(t == T) - return t; - et = t->etype; - if(typesu[et]) - return t; - tl = tcopy(t->link); - if(tl != t->link || - (et == TARRAY && t->width == 0)) { - tx = copytyp(t); - tx->link = tl; - return tx; - } - return t; -} - -Node* -doinit(Sym *s, Type *t, int32 o, Node *a) -{ - Node *n; - - if(t == T) - return Z; - if(s->class == CEXTERN) { - s->class = CGLOBL; - if(debug['d']) - dbgdecl(s); - } - if(debug['i']) { - print("t = %T; o = %d; n = %s\n", t, o, s->name); - prtree(a, "doinit value"); - } - - - n = initlist; - if(a->op == OINIT) - a = a->left; - initlist = a; - - a = init1(s, t, o, 0); - if(initlist != Z) - diag(initlist, "more initializers than structure: %s", - s->name); - initlist = n; - - return a; -} - -/* - * get next major operator, - * dont advance initlist. - */ -Node* -peekinit(void) -{ - Node *a; - - a = initlist; - -loop: - if(a == Z) - return a; - if(a->op == OLIST) { - a = a->left; - goto loop; - } - return a; -} - -/* - * consume and return next element on - * initlist. expand strings. - */ -Node* -nextinit(void) -{ - Node *a, *b, *n; - - a = initlist; - n = Z; - - if(a == Z) - return a; - if(a->op == OLIST) { - n = a->right; - a = a->left; - } - if(a->op == OUSED) { - a = a->left; - b = new(OCONST, Z, Z); - b->type = a->type->link; - if(a->op == OSTRING) { - b->vconst = convvtox(*a->cstring, TCHAR); - a->cstring++; - } - if(a->op == OLSTRING) { - b->vconst = convvtox(*a->rstring, TRUNE); - a->rstring++; - } - a->type->width -= b->type->width; - if(a->type->width <= 0) - initlist = n; - return b; - } - initlist = n; - return a; -} - -int -isstruct(Node *a, Type *t) -{ - Node *n; - - switch(a->op) { - case ODOTDOT: - n = a->left; - if(n && n->type && sametype(n->type, t)) - return 1; - case OSTRING: - case OLSTRING: - case OCONST: - case OINIT: - case OELEM: - return 0; - } - - n = new(ODOTDOT, Z, Z); - *n = *a; - - /* - * ODOTDOT is a flag for tcom - * a second tcom will not be performed - */ - a->op = ODOTDOT; - a->left = n; - a->right = Z; - - if(tcom(n)) - return 0; - - if(sametype(n->type, t)) - return 1; - return 0; -} - -Node* -init1(Sym *s, Type *t, int32 o, int exflag) -{ - Node *a, *l, *r, nod; - Type *t1; - int32 e, w, so, mw; - - a = peekinit(); - if(a == Z) - return Z; - - if(debug['i']) { - print("t = %T; o = %d; n = %s\n", t, o, s->name); - prtree(a, "init1 value"); - } - - if(exflag && a->op == OINIT) - return doinit(s, t, o, nextinit()); - - switch(t->etype) { - default: - diag(Z, "unknown type in initialization: %T to: %s", t, s->name); - return Z; - - case TCHAR: - case TUCHAR: - case TINT: - case TUINT: - case TSHORT: - case TUSHORT: - case TLONG: - case TULONG: - case TVLONG: - case TUVLONG: - case TFLOAT: - case TDOUBLE: - case TIND: - single: - if(a->op == OARRAY || a->op == OELEM) - return Z; - - a = nextinit(); - if(a == Z) - return Z; - - if(t->nbits) - diag(Z, "cannot initialize bitfields"); - if(s->class == CAUTO) { - l = new(ONAME, Z, Z); - l->sym = s; - l->type = t; - l->etype = TVOID; - if(s->type) - l->etype = s->type->etype; - l->xoffset = s->offset + o; - l->class = s->class; - - l = new(OASI, l, a); - return l; - } - - complex(a); - if(a->type == T) - return Z; - - if(a->op == OCONST) { - if(vconst(a) && t->etype == TIND && a->type && a->type->etype != TIND){ - diag(a, "initialize pointer to an integer: %s", s->name); - return Z; - } - if(!sametype(a->type, t)) { - /* hoop jumping to save malloc */ - if(nodcast == Z) - nodcast = new(OCAST, Z, Z); - nod = *nodcast; - nod.left = a; - nod.type = t; - nod.lineno = a->lineno; - complex(&nod); - if(nod.type) - *a = nod; - } - if(a->op != OCONST) { - diag(a, "initializer is not a constant: %s", - s->name); - return Z; - } - if(vconst(a) == 0) - return Z; - goto gext; - } - if(t->etype == TIND) { - while(a->op == OCAST) { - warn(a, "CAST in initialization ignored"); - a = a->left; - } - if(!sametype(t, a->type)) { - diag(a, "initialization of incompatible pointers: %s\n%T and %T", - s->name, t, a->type); - } - if(a->op == OADDR) - a = a->left; - goto gext; - } - - while(a->op == OCAST) - a = a->left; - if(a->op == OADDR) { - warn(a, "initialize pointer to an integer: %s", s->name); - a = a->left; - goto gext; - } - diag(a, "initializer is not a constant: %s", s->name); - return Z; - - gext: - gextern(s, a, o, t->width); - - return Z; - - case TARRAY: - w = t->link->width; - if(a->op == OSTRING || a->op == OLSTRING) - if(typei[t->link->etype]) { - /* - * get rid of null if sizes match exactly - */ - a = nextinit(); - mw = t->width/w; - so = a->type->width/a->type->link->width; - if(mw && so > mw) { - if(so != mw+1) - diag(a, "string initialization larger than array"); - a->type->width -= a->type->link->width; - } - - /* - * arrange strings to be expanded - * inside OINIT braces. - */ - a = new(OUSED, a, Z); - return doinit(s, t, o, a); - } - - mw = -w; - l = Z; - for(e=0;;) { - /* - * peek ahead for element initializer - */ - a = peekinit(); - if(a == Z) - break; - if(a->op == OELEM && t->link->etype != TSTRUCT) - break; - if(a->op == OARRAY) { - if(e && exflag) - break; - a = nextinit(); - r = a->left; - complex(r); - if(r->op != OCONST) { - diag(r, "initializer subscript must be constant"); - return Z; - } - e = r->vconst; - if(t->width != 0) - if(e < 0 || e*w >= t->width) { - diag(a, "initialization index out of range: %d", e); - continue; - } - } - - so = e*w; - if(so > mw) - mw = so; - if(t->width != 0) - if(mw >= t->width) - break; - r = init1(s, t->link, o+so, 1); - l = newlist(l, r); - e++; - } - if(t->width == 0) - t->width = mw+w; - return l; - - case TUNION: - case TSTRUCT: - /* - * peek ahead to find type of rhs. - * if its a structure, then treat - * this element as a variable - * rather than an aggregate. - */ - if(isstruct(a, t)) - goto single; - - if(t->width <= 0) { - diag(Z, "incomplete structure: %s", s->name); - return Z; - } - l = Z; - - again: - for(t1 = t->link; t1 != T; t1 = t1->down) { - if(a->op == OARRAY && t1->etype != TARRAY) - break; - if(a->op == OELEM) { - if(t1->sym != a->sym) - continue; - nextinit(); - } - r = init1(s, t1, o+t1->offset, 1); - l = newlist(l, r); - a = peekinit(); - if(a == Z) - break; - if(a->op == OELEM) - goto again; - } - if(a && a->op == OELEM) - diag(a, "structure element not found %F", a); - return l; - } -} - -Node* -newlist(Node *l, Node *r) -{ - if(r == Z) - return l; - if(l == Z) - return r; - return new(OLIST, l, r); -} - -static int -haspointers(Type *t) -{ - Type *fld; - - switch(t->etype) { - case TSTRUCT: - for(fld = t->link; fld != T; fld = fld->down) { - if(haspointers(fld)) - return 1; - } - return 0; - case TARRAY: - return haspointers(t->link); - case TIND: - return t->link->etype != TFUNC; - default: - return 0; - } -} - -void -sualign(Type *t) -{ - Type *l; - int32 o, w, maxal; - - o = 0; - maxal = 0; - switch(t->etype) { - - case TSTRUCT: - t->offset = 0; - w = 0; - for(l = t->link; l != T; l = l->down) { - if(l->nbits) { - if(l->shift <= 0) { - l->shift = -l->shift; - w = xround(w, tfield->width); - o = w; - w += tfield->width; - } - l->offset = o; - } else { - if(l->width <= 0) - if(l->down != T) - if(l->sym) - diag(Z, "incomplete structure element: %s", - l->sym->name); - else - diag(Z, "incomplete structure element"); - w = align(w, l, Ael1, &maxal); - l->offset = w; - w = align(w, l, Ael2, &maxal); - } - } - w = align(w, t, Asu2, &maxal); - t->width = w; - t->align = maxal; - acidtype(t); - godeftype(t); - return; - - case TUNION: - t->offset = 0; - w = 0; - for(l = t->link; l != T; l = l->down) { - if(l->width <= 0) - if(l->sym) - diag(Z, "incomplete union element: %s", - l->sym->name); - else - diag(Z, "incomplete union element"); - l->offset = 0; - l->shift = 0; - if((debug['q'] || debug['Q']) && haspointers(l)) - diag(Z, "precise garbage collector cannot handle unions with pointers"); - - o = align(align(0, l, Ael1, &maxal), l, Ael2, &maxal); - if(o > w) - w = o; - } - w = align(w, t, Asu2, &maxal); - t->width = w; - t->align = maxal; - acidtype(t); - godeftype(t); - return; - - default: - diag(Z, "unknown type in sualign: %T", t); - break; - } -} - -int32 -xround(int32 v, int w) -{ - int r; - - if(w <= 0 || w > 8) { - diag(Z, "rounding by %d", w); - w = 1; - } - r = v%w; - if(r) - v += w-r; - return v; -} - -Type* -ofnproto(Node *n) -{ - Type *tl, *tr, *t; - - if(n == Z) - return T; - switch(n->op) { - case OLIST: - tl = ofnproto(n->left); - tr = ofnproto(n->right); - if(tl == T) - return tr; - tl->down = tr; - return tl; - - case ONAME: - t = copytyp(n->sym->type); - t->down = T; - return t; - } - return T; -} - -#define ANSIPROTO 1 -#define OLDPROTO 2 - -void -argmark(Node *n, int pass) -{ - Type *t; - - if(hasdotdotdot(thisfn->link)) - autoffset = align(0, thisfn->link, Aarg0, nil); - stkoff = 0; - for(; n->left != Z; n = n->left) { - if(n->op != OFUNC || n->left->op != ONAME) - continue; - walkparam(n->right, pass); - if(pass != 0 && anyproto(n->right) == OLDPROTO) { - t = typ(TFUNC, n->left->sym->type->link); - t->down = typ(TOLD, T); - t->down->down = ofnproto(n->right); - tmerge(t, n->left->sym); - n->left->sym->type = t; - } - break; - } - autoffset = 0; - stkoff = 0; -} - -void -walkparam(Node *n, int pass) -{ - Sym *s; - Node *n1; - - if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID]) - return; - -loop: - if(n == Z) - return; - switch(n->op) { - default: - diag(n, "argument not a name/prototype: %O", n->op); - break; - - case OLIST: - walkparam(n->left, pass); - n = n->right; - goto loop; - - case OPROTO: - for(n1 = n; n1 != Z; n1=n1->left) - if(n1->op == ONAME) { - if(pass == 0) { - s = n1->sym; - push1(s); - s->offset = -1; - break; - } - dodecl(pdecl, CPARAM, n->type, n->left); - break; - } - if(n1) - break; - if(pass == 0) { - /* - * extension: - * allow no name in argument declaration - diag(Z, "no name in argument declaration"); - */ - break; - } - dodecl(NODECL, CPARAM, n->type, n->left); - pdecl(CPARAM, lastdcl, S); - break; - - case ODOTDOT: - break; - - case ONAME: - s = n->sym; - if(pass == 0) { - push1(s); - s->offset = -1; - break; - } - if(s->offset != -1) { - if(autoffset == 0) { - firstarg = s; - firstargtype = s->type; - } - autoffset = align(autoffset, s->type, Aarg1, nil); - s->offset = autoffset; - autoffset = align(autoffset, s->type, Aarg2, nil); - } else - dodecl(pdecl, CXXX, types[TINT], n); - break; - } -} - -void -markdcl(void) -{ - Decl *d; - - blockno++; - d = push(); - d->val = DMARK; - d->offset = autoffset; - d->block = autobn; - autobn = blockno; -} - -Node* -revertdcl(void) -{ - Decl *d; - Sym *s; - Node *n, *n1; - - n = Z; - for(;;) { - d = dclstack; - if(d == D) { - diag(Z, "pop off dcl stack"); - break; - } - dclstack = d->link; - s = d->sym; - switch(d->val) { - case DMARK: - autoffset = d->offset; - autobn = d->block; - return n; - - case DAUTO: - if(debug['d']) - print("revert1 \"%s\"\n", s->name); - if(s->aused == 0) { - nearln = s->varlineno; - if(s->class == CAUTO) - warn(Z, "auto declared and not used: %s", s->name); - if(s->class == CPARAM) - warn(Z, "param declared and not used: %s", s->name); - } - if(s->type && (s->type->garb & GVOLATILE)) { - n1 = new(ONAME, Z, Z); - n1->sym = s; - n1->type = s->type; - n1->etype = TVOID; - if(n1->type != T) - n1->etype = n1->type->etype; - n1->xoffset = s->offset; - n1->class = s->class; - - n1 = new(OADDR, n1, Z); - n1 = new(OUSED, n1, Z); - if(n == Z) - n = n1; - else - n = new(OLIST, n1, n); - } - s->type = d->type; - s->class = d->class; - s->offset = d->offset; - s->block = d->block; - s->varlineno = d->varlineno; - s->aused = d->aused; - break; - - case DSUE: - if(debug['d']) - print("revert2 \"%s\"\n", s->name); - s->suetag = d->type; - s->sueblock = d->block; - break; - - case DLABEL: - if(debug['d']) - print("revert3 \"%s\"\n", s->name); - if(s->label && s->label->addable == 0) - warn(s->label, "label declared and not used \"%s\"", s->name); - s->label = Z; - break; - } - } - return n; -} - -Type* -fnproto(Node *n) -{ - int r; - - r = anyproto(n->right); - if(r == 0 || (r & OLDPROTO)) { - if(r & ANSIPROTO) - diag(n, "mixed ansi/old function declaration: %F", n->left); - return T; - } - return fnproto1(n->right); -} - -int -anyproto(Node *n) -{ - int r; - - r = 0; - -loop: - if(n == Z) - return r; - switch(n->op) { - case OLIST: - r |= anyproto(n->left); - n = n->right; - goto loop; - - case ODOTDOT: - case OPROTO: - return r | ANSIPROTO; - } - return r | OLDPROTO; -} - -Type* -fnproto1(Node *n) -{ - Type *t; - - if(n == Z) - return T; - switch(n->op) { - case OLIST: - t = fnproto1(n->left); - if(t != T) - t->down = fnproto1(n->right); - return t; - - case OPROTO: - lastdcl = T; - dodecl(NODECL, CXXX, n->type, n->left); - t = typ(TXXX, T); - if(lastdcl != T) - *t = *paramconv(lastdcl, 1); - return t; - - case ONAME: - diag(n, "incomplete argument prototype"); - return typ(TINT, T); - - case ODOTDOT: - return typ(TDOT, T); - } - diag(n, "unknown op in fnproto"); - return T; -} - -void -dbgdecl(Sym *s) -{ - print("decl \"%s\": C=%s [B=%d:O=%d] T=%T\n", - s->name, cnames[s->class], s->block, s->offset, s->type); -} - -Decl* -push(void) -{ - Decl *d; - - d = alloc(sizeof(*d)); - d->link = dclstack; - dclstack = d; - return d; -} - -Decl* -push1(Sym *s) -{ - Decl *d; - - d = push(); - d->sym = s; - d->val = DAUTO; - d->type = s->type; - d->class = s->class; - d->offset = s->offset; - d->block = s->block; - d->varlineno = s->varlineno; - d->aused = s->aused; - return d; -} - -int -sametype(Type *t1, Type *t2) -{ - - if(t1 == t2) - return 1; - return rsametype(t1, t2, 5, 1); -} - -int -rsametype(Type *t1, Type *t2, int n, int f) -{ - int et; - - n--; - for(;;) { - if(t1 == t2) - return 1; - if(t1 == T || t2 == T) - return 0; - if(n <= 0) - return 1; - et = t1->etype; - if(et != t2->etype) - return 0; - if(et == TFUNC) { - if(!rsametype(t1->link, t2->link, n, 0)) - return 0; - t1 = t1->down; - t2 = t2->down; - while(t1 != T && t2 != T) { - if(t1->etype == TOLD) { - t1 = t1->down; - continue; - } - if(t2->etype == TOLD) { - t2 = t2->down; - continue; - } - while(t1 != T || t2 != T) { - if(!rsametype(t1, t2, n, 0)) - return 0; - t1 = t1->down; - t2 = t2->down; - } - break; - } - return 1; - } - if(et == TARRAY) - if(t1->width != t2->width && t1->width != 0 && t2->width != 0) - return 0; - if(typesu[et]) { - if(t1->link == T) - snap(t1); - if(t2->link == T) - snap(t2); - t1 = t1->link; - t2 = t2->link; - for(;;) { - if(t1 == t2) - return 1; - if(!rsametype(t1, t2, n, 0)) - return 0; - t1 = t1->down; - t2 = t2->down; - } - } - t1 = t1->link; - t2 = t2->link; - if((f || !debug['V']) && et == TIND) { - if(t1 != T && t1->etype == TVOID) - return 1; - if(t2 != T && t2->etype == TVOID) - return 1; - } - } -} - -typedef struct Typetab Typetab; - -struct Typetab{ - int n; - Type **a; -}; - -static int -sigind(Type *t, Typetab *tt) -{ - int n; - Type **a, **na, **p, **e; - - n = tt->n; - a = tt->a; - e = a+n; - /* linear search seems ok */ - for(p = a ; p < e; p++) - if(sametype(*p, t)) - return p-a; - if((n&15) == 0){ - na = malloc((n+16)*sizeof(Type*)); - if(na == nil) { - print("%s: out of memory", argv0); - errorexit(); - } - memmove(na, a, n*sizeof(Type*)); - free(a); - a = tt->a = na; - } - a[tt->n++] = t; - return -1; -} - -static uint32 -signat(Type *t, Typetab *tt) -{ - int i; - Type *t1; - int32 s; - - s = 0; - for(; t; t=t->link) { - s = s*thash1 + thash[t->etype]; - if(t->garb&GINCOMPLETE) - return s; - switch(t->etype) { - default: - return s; - case TARRAY: - s = s*thash2 + 0; /* was t->width */ - break; - case TFUNC: - for(t1=t->down; t1; t1=t1->down) - s = s*thash3 + signat(t1, tt); - break; - case TSTRUCT: - case TUNION: - if((i = sigind(t, tt)) >= 0){ - s = s*thash2 + i; - return s; - } - for(t1=t->link; t1; t1=t1->down) - s = s*thash3 + signat(t1, tt); - return s; - case TIND: - break; - } - } - return s; -} - -uint32 -signature(Type *t) -{ - uint32 s; - Typetab tt; - - tt.n = 0; - tt.a = nil; - s = signat(t, &tt); - free(tt.a); - return s; -} - -uint32 -sign(Sym *s) -{ - uint32 v; - Type *t; - - if(s->sig == SIGINTERN) - return SIGNINTERN; - if((t = s->type) == T) - return 0; - v = signature(t); - if(v == 0) - v = SIGNINTERN; - return v; -} - -void -snap(Type *t) -{ - if(typesu[t->etype]) - if(t->link == T && t->tag && t->tag->suetag) { - t->link = t->tag->suetag->link; - t->width = t->tag->suetag->width; - } -} - -Type* -dotag(Sym *s, int et, int bn) -{ - Decl *d; - - if(bn != 0 && bn != s->sueblock) { - d = push(); - d->sym = s; - d->val = DSUE; - d->type = s->suetag; - d->block = s->sueblock; - s->suetag = T; - } - if(s->suetag == T) { - s->suetag = typ(et, T); - s->sueblock = autobn; - } - if(s->suetag->etype != et) - diag(Z, "tag used for more than one type: %s", - s->name); - if(s->suetag->tag == S) - s->suetag->tag = s; - return s->suetag; -} - -Node* -dcllabel(Sym *s, int f) -{ - Decl *d, d1; - Node *n; - - n = s->label; - if(n != Z) { - if(f) { - if(n->complex) - diag(Z, "label reused: %s", s->name); - n->complex = 1; // declared - } else - n->addable = 1; // used - return n; - } - - d = push(); - d->sym = s; - d->val = DLABEL; - dclstack = d->link; - - d1 = *firstdcl; - *firstdcl = *d; - *d = d1; - - firstdcl->link = d; - firstdcl = d; - - n = new(OXXX, Z, Z); - n->sym = s; - n->complex = f; - n->addable = !f; - s->label = n; - - if(debug['d']) - dbgdecl(s); - return n; -} - -Type* -paramconv(Type *t, int f) -{ - - switch(t->etype) { - case TUNION: - case TSTRUCT: - if(t->width <= 0) - diag(Z, "incomplete structure: %s", t->tag->name); - break; - - case TARRAY: - t = typ(TIND, t->link); - t->width = types[TIND]->width; - break; - - case TFUNC: - t = typ(TIND, t); - t->width = types[TIND]->width; - break; - - case TFLOAT: - if(!f) - t = types[TDOUBLE]; - break; - - case TCHAR: - case TSHORT: - if(!f) - t = types[TINT]; - break; - - case TUCHAR: - case TUSHORT: - if(!f) - t = types[TUINT]; - break; - } - return t; -} - -void -adecl(int c, Type *t, Sym *s) -{ - - if(c == CSTATIC) - c = CLOCAL; - if(t->etype == TFUNC) { - if(c == CXXX) - c = CEXTERN; - if(c == CLOCAL) - c = CSTATIC; - if(c == CAUTO || c == CEXREG) - diag(Z, "function cannot be %s %s", cnames[c], s->name); - } - if(c == CXXX) - c = CAUTO; - if(s) { - if(s->class == CSTATIC) - if(c == CEXTERN || c == CGLOBL) { - warn(Z, "just say static: %s", s->name); - c = CSTATIC; - } - if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL) - if(s->block == autobn) - diag(Z, "auto redeclaration of: %s", s->name); - if(c != CPARAM) - push1(s); - s->block = autobn; - s->offset = 0; - s->type = t; - s->class = c; - s->aused = 0; - } - switch(c) { - case CAUTO: - autoffset = align(autoffset, t, Aaut3, nil); - stkoff = maxround(stkoff, autoffset); - s->offset = -autoffset; - break; - - case CPARAM: - if(autoffset == 0) { - firstarg = s; - firstargtype = t; - } - autoffset = align(autoffset, t, Aarg1, nil); - if(s) - s->offset = autoffset; - autoffset = align(autoffset, t, Aarg2, nil); - break; - } -} - -void -pdecl(int c, Type *t, Sym *s) -{ - if(s && s->offset != -1) { - diag(Z, "not a parameter: %s", s->name); - return; - } - t = paramconv(t, c==CPARAM); - if(c == CXXX) - c = CPARAM; - if(c != CPARAM) { - diag(Z, "parameter cannot have class: %s", s->name); - c = CPARAM; - } - adecl(c, t, s); -} - -void -xdecl(int c, Type *t, Sym *s) -{ - int32 o; - - o = 0; - switch(c) { - case CEXREG: - o = exreg(t); - if(o == 0) - c = CEXTERN; - if(s->class == CGLOBL) - c = CGLOBL; - break; - - case CEXTERN: - if(s->class == CGLOBL) - c = CGLOBL; - break; - - case CXXX: - c = CGLOBL; - if(s->class == CEXTERN) - s->class = CGLOBL; - break; - - case CAUTO: - diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]); - c = CEXTERN; - break; - - case CTYPESTR: - if(!typesuv[t->etype]) { - diag(Z, "typestr must be struct/union: %s", s->name); - break; - } - dclfunct(t, s); - break; - } - - if(s->class == CSTATIC) - if(c == CEXTERN || c == CGLOBL) { - warn(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]); - c = CSTATIC; - } - if(s->type != T) - if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) { - diag(Z, "external redeclaration of: %s", s->name); - Bprint(&diagbuf, " %s %T %L\n", cnames[c], t, nearln); - Bprint(&diagbuf, " %s %T %L\n", cnames[s->class], s->type, s->varlineno); - } - tmerge(t, s); - s->type = t; - if(c == CTYPEDEF && (typechlv[t->etype] || typefd[t->etype])) { - s->type = copytyp(t); - s->type->tag = s; - } - s->class = c; - s->block = 0; - s->offset = o; -} - -void -tmerge(Type *t1, Sym *s) -{ - Type *ta, *tb, *t2; - - t2 = s->type; - for(;;) { - if(t1 == T || t2 == T || t1 == t2) - break; - if(t1->etype != t2->etype) - break; - switch(t1->etype) { - case TFUNC: - ta = t1->down; - tb = t2->down; - if(ta == T) { - t1->down = tb; - break; - } - if(tb == T) - break; - while(ta != T && tb != T) { - if(ta == tb) - break; - /* ignore old-style flag */ - if(ta->etype == TOLD) { - ta = ta->down; - continue; - } - if(tb->etype == TOLD) { - tb = tb->down; - continue; - } - /* checking terminated by ... */ - if(ta->etype == TDOT && tb->etype == TDOT) { - ta = T; - tb = T; - break; - } - if(!sametype(ta, tb)) - break; - ta = ta->down; - tb = tb->down; - } - if(ta != tb) - diag(Z, "function inconsistently declared: %s", s->name); - - /* take new-style over old-style */ - ta = t1->down; - tb = t2->down; - if(ta != T && ta->etype == TOLD) - if(tb != T && tb->etype != TOLD) - t1->down = tb; - break; - - case TARRAY: - /* should we check array size change? */ - if(t2->width > t1->width) - t1->width = t2->width; - break; - - case TUNION: - case TSTRUCT: - return; - } - t1 = t1->link; - t2 = t2->link; - } -} - -void -edecl(int c, Type *t, Sym *s) -{ - Type *t1; - - if(s == S) - diag(Z, "unnamed structure elements not supported"); - else - if(c != CXXX) - diag(Z, "structure element cannot have class: %s", s->name); - t1 = t; - t = copytyp(t1); - t->sym = s; - t->down = T; - if(lastfield) { - t->shift = lastbit - lastfield; - t->nbits = lastfield; - if(firstbit) - t->shift = -t->shift; - if(typeu[t->etype]) - t->etype = tufield->etype; - else - t->etype = tfield->etype; - } - if(strf == T) - strf = t; - else - strl->down = t; - strl = t; -} - -/* - * this routine is very suspect. - * ansi requires the enum type to - * be represented as an 'int' - * this means that 0x81234567 - * would be illegal. this routine - * makes signed and unsigned go - * to unsigned. - */ -Type* -maxtype(Type *t1, Type *t2) -{ - - if(t1 == T) - return t2; - if(t2 == T) - return t1; - if(t1->etype > t2->etype) - return t1; - return t2; -} - -void -doenum(Sym *s, Node *n) -{ - - if(n) { - complex(n); - if(n->op != OCONST) { - diag(n, "enum not a constant: %s", s->name); - return; - } - en.cenum = n->type; - en.tenum = maxtype(en.cenum, en.tenum); - - if(!typefd[en.cenum->etype]) - en.lastenum = n->vconst; - else - en.floatenum = n->fconst; - } - if(dclstack) - push1(s); - xdecl(CXXX, types[TENUM], s); - - if(en.cenum == T) { - en.tenum = types[TINT]; - en.cenum = types[TINT]; - en.lastenum = 0; - } - s->tenum = en.cenum; - - if(!typefd[s->tenum->etype]) { - s->vconst = convvtox(en.lastenum, s->tenum->etype); - en.lastenum++; - } else { - s->fconst = en.floatenum; - en.floatenum++; - } - - if(debug['d']) - dbgdecl(s); - acidvar(s); - godefvar(s); -} - -void -symadjust(Sym *s, Node *n, int32 del) -{ - - switch(n->op) { - default: - if(n->left) - symadjust(s, n->left, del); - if(n->right) - symadjust(s, n->right, del); - return; - - case ONAME: - if(n->sym == s) - n->xoffset -= del; - return; - - case OCONST: - case OSTRING: - case OLSTRING: - case OINDREG: - case OREGISTER: - return; - } -} - -Node* -contig(Sym *s, Node *n, int32 v) -{ - Node *p, *r, *q, *m; - int32 w; - Type *zt; - - if(debug['i']) { - print("contig v = %d; s = %s\n", v, s->name); - prtree(n, "doinit value"); - } - - if(n == Z) - goto no; - w = s->type->width; - - /* - * nightmare: an automatic array whose size - * increases when it is initialized - */ - if(v != w) { - if(v != 0) - diag(n, "automatic adjustable array: %s", s->name); - v = s->offset; - autoffset = align(autoffset, s->type, Aaut3, nil); - s->offset = -autoffset; - stkoff = maxround(stkoff, autoffset); - symadjust(s, n, v - s->offset); - } - if(w <= ewidth[TIND]) - goto no; - if(n->op == OAS) - diag(Z, "oops in contig"); -/*ZZZ this appears incorrect -need to check if the list completely covers the data. -if not, bail - */ - if(n->op == OLIST) - goto no; - if(n->op == OASI) - if(n->left->type) - if(n->left->type->width == w) - goto no; - while(w & (ewidth[TIND]-1)) - w++; -/* - * insert the following code, where long becomes vlong if pointers are fat - * - *(long**)&X = (long*)((char*)X + sizeof(X)); - do { - *(long**)&X -= 1; - **(long**)&X = 0; - } while(*(long**)&X); - */ - - for(q=n; q->op != ONAME; q=q->left) - ; - - zt = ewidth[TIND] > ewidth[TLONG]? types[TVLONG]: types[TLONG]; - - p = new(ONAME, Z, Z); - *p = *q; - p->type = typ(TIND, zt); - p->xoffset = s->offset; - - r = new(ONAME, Z, Z); - *r = *p; - r = new(OPOSTDEC, r, Z); - - q = new(ONAME, Z, Z); - *q = *p; - q = new(OIND, q, Z); - - m = new(OCONST, Z, Z); - m->vconst = 0; - m->type = zt; - - q = new(OAS, q, m); - - r = new(OLIST, r, q); - - q = new(ONAME, Z, Z); - *q = *p; - r = new(ODWHILE, q, r); - - q = new(ONAME, Z, Z); - *q = *p; - q->type = q->type->link; - q->xoffset += w; - q = new(OADDR, q, 0); - - q = new(OASI, p, q); - r = new(OLIST, q, r); - - n = new(OLIST, r, n); - -no: - return n; -} |