12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346 |
- #include "cc.h"
- int compar(Node*, int);
- void
- complex(Node *n)
- {
- if(n == Z)
- return;
- nearln = n->lineno;
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "pre complex");
- if(tcom(n))
- return;
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "t complex");
- ccom(n);
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "c complex");
- acom(n);
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "a complex");
- xcom(n);
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "x complex");
- }
- /*
- * evaluate types
- * evaluate lvalues (addable == 1)
- */
- enum
- {
- ADDROF = 1<<0,
- CASTOF = 1<<1,
- ADDROP = 1<<2,
- };
- int
- tcom(Node *n)
- {
- return tcomo(n, ADDROF);
- }
- int
- tcomo(Node *n, int f)
- {
- Node *l, *r;
- Type *t;
- int o;
- if(n == Z) {
- diag(Z, "Z in tcom");
- errorexit();
- }
- n->addable = 0;
- l = n->left;
- r = n->right;
- switch(n->op) {
- default:
- diag(n, "unknown op in type complex: %O", n->op);
- goto bad;
- case ODOTDOT:
- /*
- * tcom has already been called on this subtree
- */
- *n = *n->left;
- if(n->type == T)
- goto bad;
- break;
- case OCAST:
- if(n->type == T)
- break;
- if(n->type->width == types[TLONG]->width) {
- if(tcomo(l, ADDROF|CASTOF))
- goto bad;
- } else
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, n->type, tcast))
- goto bad;
- break;
- case ORETURN:
- if(l == Z) {
- if(n->type->etype != TVOID)
- warn(n, "null return of a typed function");
- break;
- }
- if(tcom(l))
- goto bad;
- typeext(n->type, l);
- if(tcompat(n, n->type, l->type, tasign))
- break;
- constas(n, n->type, l->type);
- if(!sametype(n->type, l->type)) {
- l = new1(OCAST, l, Z);
- l->type = n->type;
- n->left = l;
- }
- break;
- case OASI: /* same as as, but no test for const */
- n->op = OAS;
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- typeext(l->type, r);
- if(tlvalue(l) || tcompat(n, l->type, r->type, tasign))
- goto bad;
- if(!sametype(l->type, r->type)) {
- r = new1(OCAST, r, Z);
- r->type = l->type;
- n->right = r;
- }
- n->type = l->type;
- break;
- case OAS:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- typeext(l->type, r);
- if(tcompat(n, l->type, r->type, tasign))
- goto bad;
- constas(n, l->type, r->type);
- if(!sametype(l->type, r->type)) {
- r = new1(OCAST, r, Z);
- r->type = l->type;
- n->right = r;
- }
- n->type = l->type;
- break;
- case OASADD:
- case OASSUB:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- typeext1(l->type, r);
- if(tcompat(n, l->type, r->type, tasadd))
- goto bad;
- constas(n, l->type, r->type);
- t = l->type;
- arith(n, 0);
- while(n->left->op == OCAST)
- n->left = n->left->left;
- if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
- r = new1(OCAST, n->right, Z);
- r->type = t;
- n->right = r;
- n->type = t;
- }
- break;
- case OASMUL:
- case OASLMUL:
- case OASDIV:
- case OASLDIV:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- typeext1(l->type, r);
- if(tcompat(n, l->type, r->type, tmul))
- goto bad;
- constas(n, l->type, r->type);
- t = l->type;
- arith(n, 0);
- while(n->left->op == OCAST)
- n->left = n->left->left;
- if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
- r = new1(OCAST, n->right, Z);
- r->type = t;
- n->right = r;
- n->type = t;
- }
- if(typeu[n->type->etype]) {
- if(n->op == OASDIV)
- n->op = OASLDIV;
- if(n->op == OASMUL)
- n->op = OASLMUL;
- }
- break;
- case OASLSHR:
- case OASASHR:
- case OASASHL:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- n->type = l->type;
- if(typeu[n->type->etype]) {
- if(n->op == OASASHR)
- n->op = OASLSHR;
- }
- break;
- case OASMOD:
- case OASLMOD:
- case OASOR:
- case OASAND:
- case OASXOR:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- t = l->type;
- arith(n, 0);
- while(n->left->op == OCAST)
- n->left = n->left->left;
- if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
- r = new1(OCAST, n->right, Z);
- r->type = t;
- n->right = r;
- n->type = t;
- }
- if(typeu[n->type->etype]) {
- if(n->op == OASMOD)
- n->op = OASLMOD;
- }
- break;
- case OPREINC:
- case OPREDEC:
- case OPOSTINC:
- case OPOSTDEC:
- if(tcom(l))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, types[TINT], tadd))
- goto bad;
- n->type = l->type;
- if(n->type->etype == TIND)
- if(n->type->link->width < 1)
- diag(n, "inc/dec of a void pointer");
- break;
- case OEQ:
- case ONE:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- typeext(l->type, r);
- typeext(r->type, l);
- if(tcompat(n, l->type, r->type, trel))
- goto bad;
- arith(n, 0);
- n->type = types[TINT];
- break;
- case OLT:
- case OGE:
- case OGT:
- case OLE:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- typeext1(l->type, r);
- typeext1(r->type, l);
- if(tcompat(n, l->type, r->type, trel))
- goto bad;
- arith(n, 0);
- if(typeu[n->type->etype])
- n->op = logrel[relindex(n->op)];
- n->type = types[TINT];
- break;
- case OCOND:
- o = tcom(l);
- o |= tcom(r->left);
- if(o | tcom(r->right))
- goto bad;
- if(r->right->type->etype == TIND && vconst(r->left) == 0) {
- r->left->type = r->right->type;
- r->left->vconst = 0;
- }
- if(r->left->type->etype == TIND && vconst(r->right) == 0) {
- r->right->type = r->left->type;
- r->right->vconst = 0;
- }
- if(sametype(r->right->type, r->left->type)) {
- r->type = r->right->type;
- n->type = r->type;
- break;
- }
- if(tcompat(r, r->left->type, r->right->type, trel))
- goto bad;
- arith(r, 0);
- n->type = r->type;
- break;
- case OADD:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tadd))
- goto bad;
- arith(n, 1);
- break;
- case OSUB:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tsub))
- goto bad;
- arith(n, 1);
- break;
- case OMUL:
- case OLMUL:
- case ODIV:
- case OLDIV:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tmul))
- goto bad;
- arith(n, 1);
- if(typeu[n->type->etype]) {
- if(n->op == ODIV)
- n->op = OLDIV;
- if(n->op == OMUL)
- n->op = OLMUL;
- }
- break;
- case OLSHR:
- case OASHL:
- case OASHR:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- n->right = Z;
- arith(n, 1);
- n->right = new1(OCAST, r, Z);
- n->right->type = types[TINT];
- if(typeu[n->type->etype])
- if(n->op == OASHR)
- n->op = OLSHR;
- break;
- case OAND:
- case OOR:
- case OXOR:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- arith(n, 1);
- break;
- case OMOD:
- case OLMOD:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- arith(n, 1);
- if(typeu[n->type->etype])
- n->op = OLMOD;
- break;
- case OPOS:
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
- r = l;
- l = new(OCONST, Z, Z);
- l->vconst = 0;
- l->type = types[TINT];
- n->op = OADD;
- n->right = r;
- n->left = l;
- if(tcom(l))
- goto bad;
- if(tcompat(n, l->type, r->type, tsub))
- goto bad;
- arith(n, 1);
- break;
- case ONEG:
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
- if(!machcap(n)) {
- r = l;
- l = new(OCONST, Z, Z);
- l->vconst = 0;
- l->type = types[TINT];
- n->op = OSUB;
- n->right = r;
- n->left = l;
- if(tcom(l))
- goto bad;
- if(tcompat(n, l->type, r->type, tsub))
- goto bad;
- }
- arith(n, 1);
- break;
- case OCOM:
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
- if(!machcap(n)) {
- r = l;
- l = new(OCONST, Z, Z);
- l->vconst = -1;
- l->type = types[TINT];
- n->op = OXOR;
- n->right = r;
- n->left = l;
- if(tcom(l))
- goto bad;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- }
- arith(n, 1);
- break;
- case ONOT:
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, T, l->type, tnot))
- goto bad;
- n->type = types[TINT];
- break;
- case OANDAND:
- case OOROR:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tcompat(n, T, l->type, tnot) |
- tcompat(n, T, r->type, tnot))
- goto bad;
- n->type = types[TINT];
- break;
- case OCOMMA:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- n->type = r->type;
- break;
- case OSIGN: /* extension signof(type) returns a hash */
- if(l != Z) {
- if(l->op != OSTRING && l->op != OLSTRING)
- if(tcomo(l, 0))
- goto bad;
- if(l->op == OBIT) {
- diag(n, "signof bitfield");
- goto bad;
- }
- n->type = l->type;
- }
- if(n->type == T)
- goto bad;
- if(n->type->width < 0) {
- diag(n, "signof undefined type");
- goto bad;
- }
- n->op = OCONST;
- n->left = Z;
- n->right = Z;
- n->vconst = convvtox(signature(n->type), TULONG);
- n->type = types[TULONG];
- break;
- case OSIZE:
- if(l != Z) {
- if(l->op != OSTRING && l->op != OLSTRING)
- if(tcomo(l, 0))
- goto bad;
- if(l->op == OBIT) {
- diag(n, "sizeof bitfield");
- goto bad;
- }
- n->type = l->type;
- }
- if(n->type == T)
- goto bad;
- if(n->type->width <= 0) {
- diag(n, "sizeof undefined type");
- goto bad;
- }
- if(n->type->etype == TFUNC) {
- diag(n, "sizeof function");
- goto bad;
- }
- n->op = OCONST;
- n->left = Z;
- n->right = Z;
- n->vconst = convvtox(n->type->width, TINT);
- n->type = types[TINT];
- break;
- case OFUNC:
- o = tcomo(l, 0);
- if(o)
- goto bad;
- if(l->type->etype == TIND && l->type->link->etype == TFUNC) {
- l = new1(OIND, l, Z);
- l->type = l->left->type->link;
- n->left = l;
- }
- if(tcompat(n, T, l->type, tfunct))
- goto bad;
- if(o | tcoma(l, r, l->type->down, 1))
- goto bad;
- n->type = l->type->link;
- if(!debug['B'])
- if(l->type->down == T || l->type->down->etype == TOLD) {
- nerrors--;
- diag(n, "function args not checked: %F", l);
- }
- dpcheck(n);
- break;
- case ONAME:
- if(n->type == T) {
- diag(n, "name not declared: %F", n);
- goto bad;
- }
- if(n->type->etype == TENUM) {
- n->op = OCONST;
- n->type = n->sym->tenum;
- if(!typefd[n->type->etype])
- n->vconst = n->sym->vconst;
- else
- n->fconst = n->sym->fconst;
- break;
- }
- n->addable = 1;
- if(n->class == CEXREG) {
- n->op = OREGISTER;
- n->reg = n->sym->offset;
- n->xoffset = 0;
- break;
- }
- break;
- case OLSTRING:
- if(n->type->link != types[TUSHORT]) {
- o = outstring(0, 0);
- while(o & 3) {
- outlstring(L"", sizeof(ushort));
- o = outlstring(0, 0);
- }
- }
- n->op = ONAME;
- n->xoffset = outlstring(n->rstring, n->type->width);
- n->addable = 1;
- break;
- case OSTRING:
- if(n->type->link != types[TCHAR]) {
- o = outstring(0, 0);
- while(o & 3) {
- outstring("", 1);
- o = outstring(0, 0);
- }
- }
- n->op = ONAME;
- n->xoffset = outstring(n->cstring, n->type->width);
- n->addable = 1;
- break;
- case OCONST:
- break;
- case ODOT:
- if(tcom(l))
- goto bad;
- if(tcompat(n, T, l->type, tdot))
- goto bad;
- if(tcomd(n))
- goto bad;
- break;
- case OADDR:
- if(tcomo(l, ADDROP))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(l->type->nbits) {
- diag(n, "address of a bit field");
- goto bad;
- }
- if(l->op == OREGISTER) {
- diag(n, "address of a register");
- goto bad;
- }
- n->type = typ(TIND, l->type);
- n->type->width = types[TIND]->width;
- break;
- case OIND:
- if(tcom(l))
- goto bad;
- if(tcompat(n, T, l->type, tindir))
- goto bad;
- n->type = l->type->link;
- n->addable = 1;
- break;
- case OSTRUCT:
- if(tcomx(n))
- goto bad;
- break;
- }
- t = n->type;
- if(t == T)
- goto bad;
- if(t->width < 0) {
- snap(t);
- if(t->width < 0) {
- if(typesu[t->etype] && t->tag)
- diag(n, "structure not fully declared %s", t->tag->name);
- else
- diag(n, "structure not fully declared");
- goto bad;
- }
- }
- if(typeaf[t->etype]) {
- if(f & ADDROF)
- goto addaddr;
- if(f & ADDROP)
- warn(n, "address of array/func ignored");
- }
- return 0;
- addaddr:
- if(tlvalue(n))
- goto bad;
- l = new1(OXXX, Z, Z);
- *l = *n;
- n->op = OADDR;
- if(l->type->etype == TARRAY)
- l->type = l->type->link;
- n->left = l;
- n->right = Z;
- n->addable = 0;
- n->type = typ(TIND, l->type);
- n->type->width = types[TIND]->width;
- return 0;
- bad:
- n->type = T;
- return 1;
- }
- int
- tcoma(Node *l, Node *n, Type *t, int f)
- {
- Node *n1;
- int o;
- if(t != T)
- if(t->etype == TOLD || t->etype == TDOT) /* .../old in prototype */
- t = T;
- if(n == Z) {
- if(t != T && !sametype(t, types[TVOID])) {
- diag(n, "not enough function arguments: %F", l);
- return 1;
- }
- return 0;
- }
- if(n->op == OLIST) {
- o = tcoma(l, n->left, t, 0);
- if(t != T) {
- t = t->down;
- if(t == T)
- t = types[TVOID];
- }
- return o | tcoma(l, n->right, t, 1);
- }
- if(f && t != T)
- tcoma(l, Z, t->down, 0);
- if(tcom(n) || tcompat(n, T, n->type, targ))
- return 1;
- if(sametype(t, types[TVOID])) {
- diag(n, "too many function arguments: %F", l);
- return 1;
- }
- if(t != T) {
- typeext(t, n);
- if(stcompat(nodproto, t, n->type, tasign)) {
- diag(l, "argument prototype mismatch \"%T\" for \"%T\": %F",
- n->type, t, l);
- return 1;
- }
- switch(t->etype) {
- case TCHAR:
- case TSHORT:
- t = types[TINT];
- break;
- case TUCHAR:
- case TUSHORT:
- t = types[TUINT];
- break;
- }
- } else
- switch(n->type->etype)
- {
- case TCHAR:
- case TSHORT:
- t = types[TINT];
- break;
- case TUCHAR:
- case TUSHORT:
- t = types[TUINT];
- break;
- case TFLOAT:
- t = types[TDOUBLE];
- }
- if(t != T && !sametype(t, n->type)) {
- n1 = new1(OXXX, Z, Z);
- *n1 = *n;
- n->op = OCAST;
- n->left = n1;
- n->right = Z;
- n->type = t;
- n->addable = 0;
- }
- return 0;
- }
- int
- tcomd(Node *n)
- {
- Type *t;
- long o;
- o = 0;
- t = dotsearch(n->sym, n->left->type->link, n, &o);
- if(t == T) {
- diag(n, "not a member of struct/union: %F", n);
- return 1;
- }
- makedot(n, t, o);
- return 0;
- }
- int
- tcomx(Node *n)
- {
- Type *t;
- Node *l, *r, **ar, **al;
- int e;
- e = 0;
- if(n->type->etype != TSTRUCT) {
- diag(n, "constructor must be a structure");
- return 1;
- }
- l = invert(n->left);
- n->left = l;
- al = &n->left;
- for(t = n->type->link; t != T; t = t->down) {
- if(l == Z) {
- diag(n, "constructor list too short");
- return 1;
- }
- if(l->op == OLIST) {
- r = l->left;
- ar = &l->left;
- al = &l->right;
- l = l->right;
- } else {
- r = l;
- ar = al;
- l = Z;
- }
- if(tcom(r))
- e++;
- typeext(t, r);
- if(tcompat(n, t, r->type, tasign))
- e++;
- constas(n, t, r->type);
- if(!e && !sametype(t, r->type)) {
- r = new1(OCAST, r, Z);
- r->type = t;
- *ar = r;
- }
- }
- if(l != Z) {
- diag(n, "constructor list too long");
- return 1;
- }
- return e;
- }
- int
- tlvalue(Node *n)
- {
- if(!n->addable) {
- diag(n, "not an l-value");
- return 1;
- }
- return 0;
- }
- /*
- * general rewrite
- * (IND(ADDR x)) ==> x
- * (ADDR(IND x)) ==> x
- * remove some zero operands
- * remove no op casts
- * evaluate constants
- */
- void
- ccom(Node *n)
- {
- Node *l, *r;
- int t;
- loop:
- if(n == Z)
- return;
- l = n->left;
- r = n->right;
- switch(n->op) {
- case OAS:
- case OASXOR:
- case OASAND:
- case OASOR:
- case OASMOD:
- case OASLMOD:
- case OASLSHR:
- case OASASHR:
- case OASASHL:
- case OASDIV:
- case OASLDIV:
- case OASMUL:
- case OASLMUL:
- case OASSUB:
- case OASADD:
- ccom(l);
- ccom(r);
- if(n->op == OASLSHR || n->op == OASASHR || n->op == OASASHL)
- if(r->op == OCONST) {
- t = n->type->width * 8; /* bits per byte */
- if(r->vconst >= t || r->vconst < 0)
- warn(n, "stupid shift: %lld", r->vconst);
- }
- break;
- case OCAST:
- ccom(l);
- if(l->op == OCONST) {
- evconst(n);
- if(n->op == OCONST)
- break;
- }
- if(nocast(l->type, n->type)) {
- l->type = n->type;
- *n = *l;
- }
- break;
- case OCOND:
- ccom(l);
- ccom(r);
- if(l->op == OCONST)
- if(vconst(l) == 0)
- *n = *r->right;
- else
- *n = *r->left;
- break;
- case OREGISTER:
- case OINDREG:
- case OCONST:
- case ONAME:
- break;
- case OADDR:
- ccom(l);
- l->etype = TVOID;
- if(l->op == OIND) {
- l->left->type = n->type;
- *n = *l->left;
- break;
- }
- goto common;
- case OIND:
- ccom(l);
- if(l->op == OADDR) {
- l->left->type = n->type;
- *n = *l->left;
- break;
- }
- goto common;
- case OEQ:
- case ONE:
- case OLE:
- case OGE:
- case OLT:
- case OGT:
- case OLS:
- case OHS:
- case OLO:
- case OHI:
- ccom(l);
- ccom(r);
- if(compar(n, 0) || compar(n, 1))
- break;
- relcon(l, r);
- relcon(r, l);
- goto common;
- case OASHR:
- case OASHL:
- case OLSHR:
- ccom(l);
- if(vconst(l) == 0 && !side(r)) {
- *n = *l;
- break;
- }
- ccom(r);
- if(vconst(r) == 0) {
- *n = *l;
- break;
- }
- if(r->op == OCONST) {
- t = n->type->width * 8; /* bits per byte */
- if(r->vconst >= t || r->vconst <= -t)
- warn(n, "stupid shift: %lld", r->vconst);
- }
- goto common;
- case OMUL:
- case OLMUL:
- ccom(l);
- t = vconst(l);
- if(t == 0 && !side(r)) {
- *n = *l;
- break;
- }
- if(t == 1) {
- *n = *r;
- goto loop;
- }
- ccom(r);
- t = vconst(r);
- if(t == 0 && !side(l)) {
- *n = *r;
- break;
- }
- if(t == 1) {
- *n = *l;
- break;
- }
- goto common;
- case ODIV:
- case OLDIV:
- ccom(l);
- if(vconst(l) == 0 && !side(r)) {
- *n = *l;
- break;
- }
- ccom(r);
- t = vconst(r);
- if(t == 0) {
- diag(n, "divide check");
- *n = *r;
- break;
- }
- if(t == 1) {
- *n = *l;
- break;
- }
- goto common;
- case OSUB:
- ccom(r);
- if(r->op == OCONST) {
- if(typefd[r->type->etype]) {
- n->op = OADD;
- r->fconst = -r->fconst;
- goto loop;
- } else {
- n->op = OADD;
- r->vconst = -r->vconst;
- goto loop;
- }
- }
- ccom(l);
- goto common;
- case OXOR:
- case OOR:
- case OADD:
- ccom(l);
- if(vconst(l) == 0) {
- *n = *r;
- goto loop;
- }
- ccom(r);
- if(vconst(r) == 0) {
- *n = *l;
- break;
- }
- goto commute;
- case OAND:
- ccom(l);
- ccom(r);
- if(vconst(l) == 0 && !side(r)) {
- *n = *l;
- break;
- }
- if(vconst(r) == 0 && !side(l)) {
- *n = *r;
- break;
- }
- commute:
- /* look for commutative constant */
- if(r->op == OCONST) {
- if(l->op == n->op) {
- if(l->left->op == OCONST) {
- n->right = l->right;
- l->right = r;
- goto loop;
- }
- if(l->right->op == OCONST) {
- n->right = l->left;
- l->left = r;
- goto loop;
- }
- }
- }
- if(l->op == OCONST) {
- if(r->op == n->op) {
- if(r->left->op == OCONST) {
- n->left = r->right;
- r->right = l;
- goto loop;
- }
- if(r->right->op == OCONST) {
- n->left = r->left;
- r->left = l;
- goto loop;
- }
- }
- }
- goto common;
- case OANDAND:
- ccom(l);
- if(vconst(l) == 0) {
- *n = *l;
- break;
- }
- ccom(r);
- goto common;
- case OOROR:
- ccom(l);
- if(l->op == OCONST && l->vconst != 0) {
- *n = *l;
- n->vconst = 1;
- break;
- }
- ccom(r);
- goto common;
- default:
- if(l != Z)
- ccom(l);
- if(r != Z)
- ccom(r);
- common:
- if(l != Z)
- if(l->op != OCONST)
- break;
- if(r != Z)
- if(r->op != OCONST)
- break;
- evconst(n);
- }
- }
- /* OEQ, ONE, OLE, OLS, OLT, OLO, OGE, OHS, OGT, OHI */
- static char *cmps[12] =
- {
- "==", "!=", "<=", "<=", "<", "<", ">=", ">=", ">", ">",
- };
- /* 128-bit numbers */
- typedef struct Big Big;
- struct Big
- {
- vlong a;
- uvlong b;
- };
- static int
- cmp(Big x, Big y)
- {
- if(x.a != y.a){
- if(x.a < y.a)
- return -1;
- return 1;
- }
- if(x.b != y.b){
- if(x.b < y.b)
- return -1;
- return 1;
- }
- return 0;
- }
- static Big
- add(Big x, int y)
- {
- uvlong ob;
-
- ob = x.b;
- x.b += y;
- if(y > 0 && x.b < ob)
- x.a++;
- if(y < 0 && x.b > ob)
- x.a--;
- return x;
- }
- Big
- big(vlong a, uvlong b)
- {
- Big x;
- x.a = a;
- x.b = b;
- return x;
- }
- int
- compar(Node *n, int reverse)
- {
- Big lo, hi, x;
- int op;
- char xbuf[40], cmpbuf[50];
- Node *l, *r;
- Type *lt, *rt;
- /*
- * The point of this function is to diagnose comparisons
- * that can never be true or that look misleading because
- * of the `usual arithmetic conversions'. As an example
- * of the latter, if x is a ulong, then if(x <= -1) really means
- * if(x <= 0xFFFFFFFF), while if(x <= -1LL) really means
- * what it says (but 8c compiles it wrong anyway).
- */
- if(reverse){
- r = n->left;
- l = n->right;
- op = comrel[relindex(n->op)];
- }else{
- l = n->left;
- r = n->right;
- op = n->op;
- }
- /*
- * Skip over left casts to find out the original expression range.
- */
- while(l->op == OCAST)
- l = l->left;
- if(l->op == OCONST)
- return 0;
- lt = l->type;
- if(l->op == ONAME && l->sym->type){
- lt = l->sym->type;
- if(lt->etype == TARRAY)
- lt = lt->link;
- }
- if(lt == T)
- return 0;
- if(lt->etype == TXXX || lt->etype > TUVLONG)
- return 0;
-
- /*
- * Skip over the right casts to find the on-screen value.
- */
- if(r->op != OCONST)
- return 0;
- while(r->oldop == OCAST && !r->xcast)
- r = r->left;
- rt = r->type;
- if(rt == T)
- return 0;
- x.b = r->vconst;
- x.a = 0;
- if((rt->etype&1) && r->vconst < 0) /* signed negative */
- x.a = ~0ULL;
- if((lt->etype&1)==0){
- /* unsigned */
- lo = big(0, 0);
- if(lt->width == 8)
- hi = big(0, ~0ULL);
- else
- hi = big(0, (1LL<<(l->type->width*8))-1);
- }else{
- lo = big(~0ULL, -(1LL<<(l->type->width*8-1)));
- hi = big(0, (1LL<<(l->type->width*8-1))-1);
- }
- switch(op){
- case OLT:
- case OLO:
- case OGE:
- case OHS:
- if(cmp(x, lo) <= 0)
- goto useless;
- if(cmp(x, add(hi, 1)) >= 0)
- goto useless;
- break;
- case OLE:
- case OLS:
- case OGT:
- case OHI:
- if(cmp(x, add(lo, -1)) <= 0)
- goto useless;
- if(cmp(x, hi) >= 0)
- goto useless;
- break;
- case OEQ:
- case ONE:
- /*
- * Don't warn about comparisons if the expression
- * is as wide as the value: the compiler-supplied casts
- * will make both outcomes possible.
- */
- if(lt->width >= rt->width && debug['w'] < 2)
- return 0;
- if(cmp(x, lo) < 0 || cmp(x, hi) > 0)
- goto useless;
- break;
- }
- return 0;
- useless:
- if((x.a==0 && x.b<=9) || (x.a==~0LL && x.b >= -9ULL))
- snprint(xbuf, sizeof xbuf, "%lld", x.b);
- else if(x.a == 0)
- snprint(xbuf, sizeof xbuf, "%#llux", x.b);
- else
- snprint(xbuf, sizeof xbuf, "%#llx", x.b);
- if(reverse)
- snprint(cmpbuf, sizeof cmpbuf, "%s %s %T",
- xbuf, cmps[relindex(n->op)], lt);
- else
- snprint(cmpbuf, sizeof cmpbuf, "%T %s %s",
- lt, cmps[relindex(n->op)], xbuf);
- warn(n, "useless or misleading comparison: %s", cmpbuf);
- return 0;
- }
|