12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634 |
- #include "cc.h"
- Node*
- dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n)
- {
- Sym *s;
- Node *n1;
- long 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);
- 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);
- 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, long 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 = %ld; 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, TUSHORT);
- 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, long o, int exflag)
- {
- Node *a, *l, *r, nod;
- Type *t1;
- long e, w, so, mw;
- a = peekinit();
- if(a == Z)
- return Z;
- if(debug['i']) {
- print("t = %T; o = %ld; 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: %ld", 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);
- }
- void
- suallign(Type *t)
- {
- Type *l;
- long o, w;
- o = 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 = round(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);
- l->offset = w;
- w = align(w, l, Ael2);
- }
- }
- w = align(w, t, Asu2);
- t->width = w;
- acidtype(t);
- pickletype(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;
- o = align(align(0, l, Ael1), l, Ael2);
- if(o > w)
- w = o;
- }
- w = align(w, t, Asu2);
- t->width = w;
- acidtype(t);
- pickletype(t);
- return;
- default:
- diag(Z, "unknown type in suallign: %T", t);
- break;
- }
- }
- long
- round(long 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;
- autoffset = align(0, thisfn->link, Aarg0);
- 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);
- s->offset = autoffset;
- autoffset = align(autoffset, s->type, Aarg2);
- } 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=%ld] 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*));
- memmove(na, a, n*sizeof(Type*));
- free(a);
- a = tt->a = na;
- }
- a[tt->n++] = t;
- return -1;
- }
- static ulong
- signat(Type *t, Typetab *tt)
- {
- int i;
- Type *t1;
- long 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;
- }
- ulong
- signature(Type *t)
- {
- ulong s;
- Typetab tt;
- tt.n = 0;
- tt.a = nil;
- s = signat(t, &tt);
- free(tt.a);
- return s;
- }
- ulong
- sign(Sym *s)
- {
- ulong 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);
- stkoff = maxround(stkoff, autoffset);
- s->offset = -autoffset;
- break;
- case CPARAM:
- if(autoffset == 0) {
- firstarg = s;
- firstargtype = t;
- }
- autoffset = align(autoffset, t, Aarg1);
- if(s)
- s->offset = autoffset;
- autoffset = align(autoffset, t, Aarg2);
- 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)
- {
- long 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;
- s->class = c;
- s->block = 0;
- s->offset = o;
- }
- void
- tmerge(Type *t1, Sym *s)
- {
- Type *ta, *tb, *t2;
- t2 = s->type;
- /*print("merge %T; %T\n", t1, t2);/**/
- 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) {
- if(!typesu[t->etype])
- diag(Z, "unnamed structure element must be struct/union");
- if(c != CXXX)
- diag(Z, "unnamed structure element cannot have class");
- } 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);
- }
- void
- symadjust(Sym *s, Node *n, long 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, long v)
- {
- Node *p, *r, *q, *m;
- long w;
- Type *zt;
- if(debug['i']) {
- print("contig v = %ld; 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);
- 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;
- }
|