117749Sralph #ifndef lint 2*32841Sdonn static char *sccsid ="@(#)trees.c 4.16 (Berkeley) 12/10/87"; 317749Sralph #endif 417749Sralph 518396Sralph # include "pass1.h" 616179Sralph 724408Smckusick # include <setjmp.h> 824408Smckusick 917749Sralph int bdebug = 0; 1017749Sralph int adebug = 0; 1117749Sralph extern ddebug; 1217749Sralph extern eprint(); 1317749Sralph 1416179Sralph /* corrections when in violation of lint */ 1516179Sralph 1616179Sralph /* some special actions, used in finding the type of nodes */ 1716179Sralph # define NCVT 01 1816179Sralph # define PUN 02 1916179Sralph # define TYPL 04 2016179Sralph # define TYPR 010 2116179Sralph # define TYMATCH 040 2216179Sralph # define LVAL 0100 2316179Sralph # define CVTO 0200 2416179Sralph # define CVTL 0400 2516179Sralph # define CVTR 01000 2616179Sralph # define PTMATCH 02000 2716179Sralph # define OTHER 04000 2816179Sralph # define NCVTR 010000 2916179Sralph 3017749Sralph #ifndef BUG1 3117749Sralph printact(t, acts) 3217749Sralph NODE *t; 3317749Sralph int acts; 3417749Sralph { 3517749Sralph static struct actions { 3617749Sralph int a_bit; 3717749Sralph char *a_name; 3817749Sralph } actions[] = { 3917749Sralph { PUN, "PUN" }, 4017749Sralph { CVTL, "CVTL" }, 4117749Sralph { CVTR, "CVTR" }, 4217749Sralph { TYPL, "TYPL" }, 4317749Sralph { TYPR, "TYPR" }, 4417749Sralph { TYMATCH, "TYMATCH" }, 4517749Sralph { PTMATCH, "PTMATCH" }, 4617749Sralph { LVAL, "LVAL" }, 4717749Sralph { CVTO, "CVTO" }, 4817749Sralph { NCVT, "NCVT" }, 4917749Sralph { OTHER, "OTHER" }, 5017749Sralph { NCVTR, "NCVTR" }, 5117749Sralph { 0 } 5217749Sralph }; 5317749Sralph register struct actions *p; 5417749Sralph char *sep = " "; 5517749Sralph 5617749Sralph printf("actions"); 5717749Sralph for (p = actions; p->a_name; p++) 5817749Sralph if (p->a_bit & acts) { 5917749Sralph printf("%s%s", sep, p->a_name); 6017749Sralph sep = "|"; 6117749Sralph } 6217749Sralph if (!bdebug) { 6317749Sralph printf(" for:\n"); 6417749Sralph fwalk(t, eprint, 0); 6517749Sralph } else 6617749Sralph putchar('\n'); 6717749Sralph } 6817749Sralph #endif 6917749Sralph 7016179Sralph /* node conventions: 7116179Sralph 7216179Sralph NAME: rval>0 is stab index for external 7316179Sralph rval<0 is -inlabel number 7416179Sralph lval is offset in bits 7516179Sralph ICON: lval has the value 7616179Sralph rval has the STAB index, or - label number, 7716179Sralph if a name whose address is in the constant 7816179Sralph rval = NONAME means no name 7916179Sralph REG: rval is reg. identification cookie 8016179Sralph 8116179Sralph */ 8216179Sralph 8316179Sralph NODE * 8416179Sralph buildtree( o, l, r ) register NODE *l, *r; { 8516179Sralph register NODE *p, *q; 8616179Sralph register actions; 8716179Sralph register opty; 8816179Sralph register struct symtab *sp; 8916179Sralph register NODE *lr, *ll; 9017749Sralph NODE *fixargs(); 9116179Sralph int i; 9216179Sralph 9316179Sralph # ifndef BUG1 9416179Sralph if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r ); 9516179Sralph # endif 9616179Sralph opty = optype(o); 9716179Sralph 9816179Sralph /* check for constants */ 9916179Sralph 10016179Sralph if( opty == UTYPE && l->in.op == ICON ){ 10116179Sralph 10216179Sralph switch( o ){ 10316179Sralph 10416179Sralph case NOT: 10516179Sralph if( hflag ) werror( "constant argument to NOT" ); 10616179Sralph case UNARY MINUS: 10716179Sralph case COMPL: 10816179Sralph if( conval( l, o, l ) ) return(l); 10916179Sralph break; 11016179Sralph 11116179Sralph } 11216179Sralph } 11316179Sralph 11416179Sralph else if( o==UNARY MINUS && l->in.op==FCON ){ 11517749Sralph l->fpn.fval = -l->fpn.fval; 11616179Sralph return(l); 11716179Sralph } 11816179Sralph 11917749Sralph else if( o==UNARY MINUS && l->in.op==DCON ){ 12017749Sralph l->dpn.dval = -l->dpn.dval; 12117749Sralph return(l); 12217749Sralph } 12317749Sralph 12416179Sralph else if( o==QUEST && l->in.op==ICON ) { 12516179Sralph l->in.op = FREE; 12616179Sralph r->in.op = FREE; 12716179Sralph if( l->tn.lval ){ 12816179Sralph tfree( r->in.right ); 12916179Sralph return( r->in.left ); 13016179Sralph } 13116179Sralph else { 13216179Sralph tfree( r->in.left ); 13316179Sralph return( r->in.right ); 13416179Sralph } 13516179Sralph } 13616179Sralph 13716179Sralph else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn; 13816179Sralph 13916179Sralph else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){ 14016179Sralph 14116179Sralph switch( o ){ 14216179Sralph 14316179Sralph case ULT: 14416179Sralph case UGT: 14516179Sralph case ULE: 14616179Sralph case UGE: 14716179Sralph case LT: 14816179Sralph case GT: 14916179Sralph case LE: 15016179Sralph case GE: 15116179Sralph case EQ: 15216179Sralph case NE: 15332840Sdonn if( l->in.type == ENUMTY && r->in.type == ENUMTY ) 15432840Sdonn chkpun( p ); 15532840Sdonn 15616179Sralph case ANDAND: 15716179Sralph case OROR: 15816179Sralph case CBRANCH: 15916179Sralph 16016179Sralph ccwarn: 16116179Sralph if( hflag ) werror( "constant in conditional context" ); 16216179Sralph 16316179Sralph case PLUS: 16416179Sralph case MINUS: 16516179Sralph case MUL: 16616179Sralph case DIV: 16716179Sralph case MOD: 16816179Sralph case AND: 16916179Sralph case OR: 17016179Sralph case ER: 17116179Sralph case LS: 17216179Sralph case RS: 17316179Sralph if( conval( l, o, r ) ) { 17416179Sralph r->in.op = FREE; 17516179Sralph return(l); 17616179Sralph } 17716179Sralph break; 17816179Sralph } 17916179Sralph } 18024408Smckusick else if (opty == BITYPE && 18124408Smckusick (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) && 18224408Smckusick (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) { 18324408Smckusick if (o == PLUS || o == MINUS || o == MUL || o == DIV) { 18424408Smckusick extern int fpe_count; 18524408Smckusick extern jmp_buf gotfpe; 18616179Sralph 18724408Smckusick fpe_count = 0; 18824408Smckusick if (setjmp(gotfpe)) 18924408Smckusick goto treatfpe; 19017749Sralph if (l->in.op == ICON) 19117749Sralph l->dpn.dval = l->tn.lval; 19224408Smckusick else if (l->in.op == FCON) 19324408Smckusick l->dpn.dval = l->fpn.fval; 19417749Sralph if (r->in.op == ICON) 19517749Sralph r->dpn.dval = r->tn.lval; 19624408Smckusick else if (r->in.op == FCON) 19724408Smckusick r->dpn.dval = r->fpn.fval; 19817749Sralph switch (o) { 19917749Sralph 20017749Sralph case PLUS: 20117749Sralph l->dpn.dval += r->dpn.dval; 20224408Smckusick break; 20317749Sralph 20417749Sralph case MINUS: 20517749Sralph l->dpn.dval -= r->dpn.dval; 20624408Smckusick break; 20717749Sralph 20817749Sralph case MUL: 20917749Sralph l->dpn.dval *= r->dpn.dval; 21024408Smckusick break; 21117749Sralph 21217749Sralph case DIV: 21317749Sralph if (r->dpn.dval == 0) 21417749Sralph uerror("division by 0."); 21517749Sralph else 21617749Sralph l->dpn.dval /= r->dpn.dval; 21724408Smckusick break; 21824408Smckusick } 21924408Smckusick treatfpe: 22024408Smckusick if (fpe_count > 0) { 22124408Smckusick uerror("floating point exception in constant expression"); 22224408Smckusick l->dpn.dval = 1.0; /* Fairly harmless */ 22324408Smckusick } 22424408Smckusick fpe_count = -1; 22524408Smckusick l->in.op = DCON; 22624408Smckusick l->in.type = l->fn.csiz = DOUBLE; 22724408Smckusick r->in.op = FREE; 22824408Smckusick return (l); 22916179Sralph } 23024408Smckusick } 23116179Sralph 23224408Smckusick /* it's real; we must make a new node */ 23316179Sralph 23416179Sralph p = block( o, l, r, INT, 0, INT ); 23516179Sralph 23616179Sralph actions = opact(p); 23717749Sralph #ifndef BUG1 23817749Sralph if (adebug) 23917749Sralph printact(p, actions); 24017749Sralph #endif 24116179Sralph 24216179Sralph if( actions&LVAL ){ /* check left descendent */ 24316179Sralph if( notlval(p->in.left) ) { 24416179Sralph uerror( "illegal lhs of assignment operator" ); 24516179Sralph } 24616179Sralph } 24716179Sralph 24816179Sralph if( actions & NCVTR ){ 24916179Sralph p->in.left = pconvert( p->in.left ); 25016179Sralph } 25116179Sralph else if( !(actions & NCVT ) ){ 25216179Sralph switch( opty ){ 25316179Sralph 25416179Sralph case BITYPE: 25516179Sralph p->in.right = pconvert( p->in.right ); 25616179Sralph case UTYPE: 25716179Sralph p->in.left = pconvert( p->in.left ); 25816179Sralph 25916179Sralph } 26016179Sralph } 26116179Sralph 26216179Sralph if( (actions&PUN) && (o!=CAST||cflag) ){ 26316179Sralph chkpun(p); 26416179Sralph } 26516179Sralph 26616179Sralph if( actions & (TYPL|TYPR) ){ 26716179Sralph 26816179Sralph q = (actions&TYPL) ? p->in.left : p->in.right; 26916179Sralph 27016179Sralph p->in.type = q->in.type; 27116179Sralph p->fn.cdim = q->fn.cdim; 27216179Sralph p->fn.csiz = q->fn.csiz; 27316179Sralph } 27416179Sralph 27516179Sralph if( actions & CVTL ) p = convert( p, CVTL ); 27616179Sralph if( actions & CVTR ) p = convert( p, CVTR ); 27716179Sralph if( actions & TYMATCH ) p = tymatch(p); 27816179Sralph if( actions & PTMATCH ) p = ptmatch(p); 27916179Sralph 28016179Sralph if( actions & OTHER ){ 28116179Sralph l = p->in.left; 28216179Sralph r = p->in.right; 28316179Sralph 28416179Sralph switch(o){ 28516179Sralph 28616179Sralph case NAME: 28716179Sralph sp = &stab[idname]; 28816179Sralph if( sp->stype == UNDEF ){ 28916179Sralph #ifndef FLEXNAMES 29016179Sralph uerror( "%.8s undefined", sp->sname ); 29116179Sralph #else 29216179Sralph uerror( "%s undefined", sp->sname ); 29316179Sralph #endif 29416179Sralph /* make p look reasonable */ 29516179Sralph p->in.type = p->fn.cdim = p->fn.csiz = INT; 29616179Sralph p->tn.rval = idname; 29716179Sralph p->tn.lval = 0; 29816179Sralph defid( p, SNULL ); 29916179Sralph break; 30016179Sralph } 30116179Sralph p->in.type = sp->stype; 30216179Sralph p->fn.cdim = sp->dimoff; 30316179Sralph p->fn.csiz = sp->sizoff; 30416179Sralph p->tn.lval = 0; 30516179Sralph p->tn.rval = idname; 30616179Sralph /* special case: MOETY is really an ICON... */ 30716179Sralph if( p->in.type == MOETY ){ 30816179Sralph p->tn.rval = NONAME; 30916179Sralph p->tn.lval = sp->offset; 31016179Sralph p->fn.cdim = 0; 31116179Sralph p->in.type = ENUMTY; 31216179Sralph p->in.op = ICON; 31316179Sralph } 31416179Sralph break; 31516179Sralph 31616179Sralph case ICON: 31716179Sralph p->in.type = INT; 31816179Sralph p->fn.cdim = 0; 31916179Sralph p->fn.csiz = INT; 32016179Sralph break; 32116179Sralph 32216179Sralph case STRING: 32316179Sralph p->in.op = NAME; 32416179Sralph p->in.type = CHAR+ARY; 32516179Sralph p->tn.lval = 0; 32616179Sralph p->tn.rval = NOLAB; 32716179Sralph p->fn.cdim = curdim; 32816179Sralph p->fn.csiz = CHAR; 32916179Sralph break; 33016179Sralph 33116179Sralph case FCON: 33216179Sralph p->tn.lval = 0; 33316179Sralph p->tn.rval = 0; 33417749Sralph p->in.type = FLOAT; 33517749Sralph p->fn.cdim = 0; 33617749Sralph p->fn.csiz = FLOAT; 33717749Sralph break; 33817749Sralph 33917749Sralph case DCON: 34017749Sralph p->tn.lval = 0; 34117749Sralph p->tn.rval = 0; 34216179Sralph p->in.type = DOUBLE; 34316179Sralph p->fn.cdim = 0; 34416179Sralph p->fn.csiz = DOUBLE; 34516179Sralph break; 34616179Sralph 34716179Sralph case STREF: 34816179Sralph /* p->x turned into *(p+offset) */ 34916179Sralph /* rhs must be a name; check correctness */ 35016179Sralph 35116179Sralph i = r->tn.rval; 35216179Sralph if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ 35316179Sralph uerror( "member of structure or union required" ); 35416179Sralph }else 35516179Sralph /* if this name is non-unique, find right one */ 35616179Sralph if( stab[i].sflags & SNONUNIQ && 35716179Sralph (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) && 35816179Sralph (l->fn.csiz +1) >= 0 ){ 35916179Sralph /* nonunique name && structure defined */ 36016179Sralph char * memnam, * tabnam; 36116179Sralph register k; 36216179Sralph int j; 36316179Sralph int memi; 36416179Sralph j=dimtab[l->fn.csiz+1]; 36516179Sralph for( ; (memi=dimtab[j]) >= 0; ++j ){ 36616179Sralph tabnam = stab[memi].sname; 36716179Sralph memnam = stab[i].sname; 36816179Sralph # ifndef BUG1 36916179Sralph if( ddebug>1 ){ 37016179Sralph #ifndef FLEXNAMES 37116179Sralph printf("member %.8s==%.8s?\n", 37216179Sralph #else 37316179Sralph printf("member %s==%s?\n", 37416179Sralph #endif 37516179Sralph memnam, tabnam); 37616179Sralph } 37716179Sralph # endif 37816179Sralph if( stab[memi].sflags & SNONUNIQ ){ 37916179Sralph #ifndef FLEXNAMES 38016179Sralph for( k=0; k<NCHNAM; ++k ){ 38116179Sralph if(*memnam++!=*tabnam) 38216179Sralph goto next; 38316179Sralph if(!*tabnam++) break; 38416179Sralph } 38516179Sralph #else 38616179Sralph if (memnam != tabnam) 38716179Sralph goto next; 38816179Sralph #endif 38916179Sralph r->tn.rval = i = memi; 39016179Sralph break; 39116179Sralph } 39216179Sralph next: continue; 39316179Sralph } 39416179Sralph if( memi < 0 ) 39516179Sralph #ifndef FLEXNAMES 39616179Sralph uerror("illegal member use: %.8s", 39716179Sralph #else 39816179Sralph uerror("illegal member use: %s", 39916179Sralph #endif 40016179Sralph stab[i].sname); 40116179Sralph } 40216179Sralph else { 40316179Sralph register j; 40416179Sralph if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){ 40516179Sralph if( stab[i].sflags & SNONUNIQ ){ 40616179Sralph uerror( "nonunique name demands struct/union or struct/union pointer" ); 40716179Sralph } 40816179Sralph else werror( "struct/union or struct/union pointer required" ); 40916179Sralph } 41016179Sralph else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" ); 41116179Sralph else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){ 41216179Sralph #ifndef FLEXNAMES 41316179Sralph werror( "illegal member use: %.8s", stab[i].sname ); 41416179Sralph #else 41516179Sralph werror( "illegal member use: %s", stab[i].sname ); 41616179Sralph #endif 41716179Sralph } 41816179Sralph } 41916179Sralph 42016179Sralph p = stref( p ); 42116179Sralph break; 42216179Sralph 42316179Sralph case UNARY MUL: 42416179Sralph if( l->in.op == UNARY AND ){ 42516179Sralph p->in.op = l->in.op = FREE; 42616179Sralph p = l->in.left; 42716179Sralph } 42816179Sralph if( !ISPTR(l->in.type))uerror("illegal indirection"); 42916179Sralph p->in.type = DECREF(l->in.type); 43016179Sralph p->fn.cdim = l->fn.cdim; 43116179Sralph p->fn.csiz = l->fn.csiz; 43216179Sralph break; 43316179Sralph 43416179Sralph case UNARY AND: 43516179Sralph switch( l->in.op ){ 43616179Sralph 43716179Sralph case UNARY MUL: 43816179Sralph p->in.op = l->in.op = FREE; 43916179Sralph p = l->in.left; 44016179Sralph case NAME: 44116179Sralph p->in.type = INCREF( l->in.type ); 44216179Sralph p->fn.cdim = l->fn.cdim; 44316179Sralph p->fn.csiz = l->fn.csiz; 44416179Sralph break; 44516179Sralph 44616179Sralph case COMOP: 44716179Sralph lr = buildtree( UNARY AND, l->in.right, NIL ); 44816179Sralph p->in.op = l->in.op = FREE; 44916179Sralph p = buildtree( COMOP, l->in.left, lr ); 45016179Sralph break; 45116179Sralph 45216179Sralph case QUEST: 45316179Sralph lr = buildtree( UNARY AND, l->in.right->in.right, NIL ); 45416179Sralph ll = buildtree( UNARY AND, l->in.right->in.left, NIL ); 45516179Sralph p->in.op = l->in.op = l->in.right->in.op = FREE; 45616179Sralph p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) ); 45716179Sralph break; 45816179Sralph 45916179Sralph # ifdef ADDROREG 46016179Sralph case OREG: 46116179Sralph /* OREG was built in clocal() 46216179Sralph * for an auto or formal parameter 46316179Sralph * now its address is being taken 46416179Sralph * local code must unwind it 46516179Sralph * back to PLUS/MINUS REG ICON 46616179Sralph * according to local conventions 46716179Sralph */ 46816179Sralph { 46916179Sralph extern NODE * addroreg(); 47016179Sralph p->in.op = FREE; 47116179Sralph p = addroreg( l ); 47216179Sralph } 47316179Sralph break; 47416179Sralph 47516179Sralph # endif 47616179Sralph default: 47716179Sralph uerror( "unacceptable operand of &" ); 47816179Sralph break; 47916179Sralph } 48016179Sralph break; 48116179Sralph 48216179Sralph case LS: 48316179Sralph case RS: 48416179Sralph case ASG LS: 48516179Sralph case ASG RS: 48616179Sralph if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT) 48716179Sralph p->in.right = makety(p->in.right, INT, 0, INT ); 48816179Sralph break; 48916179Sralph 49016179Sralph case RETURN: 49116179Sralph case ASSIGN: 49216179Sralph case CAST: 49316179Sralph /* structure assignment */ 49416179Sralph /* take the addresses of the two sides; then make an 49516179Sralph /* operator using STASG and 49616179Sralph /* the addresses of left and right */ 49716179Sralph 49816179Sralph { 49916179Sralph register TWORD t; 50016179Sralph register d, s; 50116179Sralph 50216179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" ); 50316179Sralph 50416179Sralph r = buildtree( UNARY AND, r, NIL ); 50516179Sralph t = r->in.type; 50616179Sralph d = r->fn.cdim; 50716179Sralph s = r->fn.csiz; 50816179Sralph 50916179Sralph l = block( STASG, l, r, t, d, s ); 51016179Sralph 51116179Sralph if( o == RETURN ){ 51216179Sralph p->in.op = FREE; 51316179Sralph p = l; 51416179Sralph break; 51516179Sralph } 51616179Sralph 51716179Sralph p->in.op = UNARY MUL; 51816179Sralph p->in.left = l; 51916179Sralph p->in.right = NIL; 52016179Sralph break; 52116179Sralph } 52216179Sralph case COLON: 52316179Sralph /* structure colon */ 52416179Sralph 52516179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" ); 52616179Sralph break; 52716179Sralph 52816179Sralph case CALL: 52917749Sralph p->in.right = r = fixargs( p->in.right ); 53016179Sralph case UNARY CALL: 53116179Sralph if( !ISPTR(l->in.type)) uerror("illegal function"); 53216179Sralph p->in.type = DECREF(l->in.type); 53316179Sralph if( !ISFTN(p->in.type)) uerror("illegal function"); 53416179Sralph p->in.type = DECREF( p->in.type ); 53516179Sralph p->fn.cdim = l->fn.cdim; 53616179Sralph p->fn.csiz = l->fn.csiz; 53716179Sralph if( l->in.op == UNARY AND && l->in.left->in.op == NAME && 53816179Sralph l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME && 53916179Sralph ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){ 54016179Sralph p->in.op += (FORTCALL-CALL); 54116179Sralph } 54216179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 54316179Sralph /* function returning structure */ 54416179Sralph /* make function really return ptr to str., with * */ 54516179Sralph 54616179Sralph p->in.op += STCALL-CALL; 54716179Sralph p->in.type = INCREF( p->in.type ); 54816179Sralph p = buildtree( UNARY MUL, p, NIL ); 54916179Sralph 55016179Sralph } 55116179Sralph break; 55216179Sralph 55316179Sralph default: 55416179Sralph cerror( "other code %d", o ); 55516179Sralph } 55616179Sralph 55716179Sralph } 55816179Sralph 55916179Sralph if( actions & CVTO ) p = oconvert(p); 56016179Sralph p = clocal(p); 56116179Sralph 56216179Sralph # ifndef BUG1 56316179Sralph if( bdebug ) fwalk( p, eprint, 0 ); 56416179Sralph # endif 56516179Sralph 56616179Sralph return(p); 56716179Sralph 56816179Sralph } 56916179Sralph 57024408Smckusick int fpe_count = -1; 57124408Smckusick jmp_buf gotfpe; 57224408Smckusick 57324408Smckusick fpe() { 57424408Smckusick if (fpe_count < 0) 57524408Smckusick cerror("floating point exception"); 57624408Smckusick ++fpe_count; 57724408Smckusick longjmp(gotfpe, 1); 57824408Smckusick } 57924408Smckusick 58017749Sralph /* 58117749Sralph * Rewrite arguments in a function call. 58217749Sralph * Structure arguments are massaged, single 58317749Sralph * precision floating point constants are 58417749Sralph * cast to double (to eliminate convert code). 58517749Sralph */ 58616179Sralph NODE * 58717749Sralph fixargs( p ) register NODE *p; { 58817749Sralph int o = p->in.op; 58916179Sralph 59017749Sralph if( o == CM ){ 59117749Sralph p->in.left = fixargs( p->in.left ); 59217749Sralph p->in.right = fixargs( p->in.right ); 59316179Sralph return( p ); 59416179Sralph } 59516179Sralph 59616179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 59716179Sralph p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz ); 59816179Sralph p->in.left = buildtree( UNARY AND, p->in.left, NIL ); 59916179Sralph p = clocal(p); 60016179Sralph } 60117749Sralph else if( o == FCON ) 60217749Sralph p = makety(p, DOUBLE, 0, 0); 60316179Sralph return( p ); 60416179Sralph } 60516179Sralph 60616179Sralph chkstr( i, j, type ) TWORD type; { 60716179Sralph /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ 60816179Sralph /* i has been checked to contain a MOS or MOU */ 60916179Sralph /* j is the index in dimtab of the members... */ 61016179Sralph int k, kk; 61116179Sralph 61216179Sralph extern int ddebug; 61316179Sralph 61416179Sralph # ifndef BUG1 61516179Sralph #ifndef FLEXNAMES 61616179Sralph if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j ); 61716179Sralph #else 61816179Sralph if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j ); 61916179Sralph #endif 62016179Sralph # endif 62116179Sralph if( (k = j) < 0 ) uerror( "undefined structure or union" ); 62216179Sralph else { 62316179Sralph for( ; (kk = dimtab[k] ) >= 0; ++k ){ 62416179Sralph if( kk >= SYMTSZ ){ 62516179Sralph cerror( "gummy structure" ); 62616179Sralph return(1); 62716179Sralph } 62816179Sralph if( kk == i ) return( 1 ); 62916179Sralph switch( stab[kk].stype ){ 63016179Sralph 63116179Sralph case STRTY: 63216179Sralph case UNIONTY: 63316179Sralph if( type == STRTY ) continue; /* no recursive looking for strs */ 63416179Sralph if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){ 63516179Sralph if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */ 63616179Sralph werror( 63716179Sralph #ifndef FLEXNAMES 63816179Sralph "illegal member use: perhaps %.8s.%.8s?", 63916179Sralph #else 64016179Sralph "illegal member use: perhaps %s.%s?", 64116179Sralph #endif 64216179Sralph stab[kk].sname, stab[i].sname ); 64316179Sralph return(1); 64416179Sralph } 64516179Sralph } 64616179Sralph } 64716179Sralph } 64816179Sralph return( 0 ); 64916179Sralph } 65016179Sralph 65116179Sralph conval( p, o, q ) register NODE *p, *q; { 65216179Sralph /* apply the op o to the lval part of p; if binary, rhs is val */ 65316179Sralph int i, u; 65416179Sralph CONSZ val; 65516179Sralph 65616179Sralph val = q->tn.lval; 65716179Sralph u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type); 65816179Sralph if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); 65916179Sralph 66016179Sralph if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0); 66116179Sralph if( q->tn.rval != NONAME && o!=PLUS ) return(0); 66216179Sralph if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0); 66316179Sralph 66416179Sralph switch( o ){ 66516179Sralph 66616179Sralph case PLUS: 66716179Sralph p->tn.lval += val; 66816179Sralph if( p->tn.rval == NONAME ){ 66916179Sralph p->tn.rval = q->tn.rval; 67016179Sralph p->in.type = q->in.type; 67116179Sralph } 67216179Sralph break; 67316179Sralph case MINUS: 67416179Sralph p->tn.lval -= val; 67516179Sralph break; 67616179Sralph case MUL: 67732840Sdonn p->tn.lval *= val; 67816179Sralph break; 67916179Sralph case DIV: 68016179Sralph if( val == 0 ) uerror( "division by 0" ); 68117749Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val; 68216179Sralph else p->tn.lval /= val; 68316179Sralph break; 68416179Sralph case MOD: 68516179Sralph if( val == 0 ) uerror( "division by 0" ); 68617749Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val; 68716179Sralph else p->tn.lval %= val; 68816179Sralph break; 68916179Sralph case AND: 69016179Sralph p->tn.lval &= val; 69116179Sralph break; 69216179Sralph case OR: 69316179Sralph p->tn.lval |= val; 69416179Sralph break; 69516179Sralph case ER: 69617749Sralph p->tn.lval ^= val; 69716179Sralph break; 69816179Sralph case LS: 69916179Sralph i = val; 70016179Sralph p->tn.lval = p->tn.lval << i; 70116179Sralph break; 70216179Sralph case RS: 70316179Sralph i = val; 70417749Sralph if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i; 70517749Sralph else p->tn.lval = p->tn.lval >> i; 70616179Sralph break; 70716179Sralph 70816179Sralph case UNARY MINUS: 70916179Sralph p->tn.lval = - p->tn.lval; 71016179Sralph break; 71116179Sralph case COMPL: 71216179Sralph p->tn.lval = ~p->tn.lval; 71316179Sralph break; 71416179Sralph case NOT: 71516179Sralph p->tn.lval = !p->tn.lval; 71616179Sralph break; 71716179Sralph case LT: 71816179Sralph p->tn.lval = p->tn.lval < val; 71916179Sralph break; 72016179Sralph case LE: 72116179Sralph p->tn.lval = p->tn.lval <= val; 72216179Sralph break; 72316179Sralph case GT: 72416179Sralph p->tn.lval = p->tn.lval > val; 72516179Sralph break; 72616179Sralph case GE: 72716179Sralph p->tn.lval = p->tn.lval >= val; 72816179Sralph break; 72916179Sralph case ULT: 73032840Sdonn p->tn.lval = (p->tn.lval-val)<0; 73116179Sralph break; 73216179Sralph case ULE: 73332840Sdonn p->tn.lval = (p->tn.lval-val)<=0; 73416179Sralph break; 73532840Sdonn case UGE: 73632840Sdonn p->tn.lval = (p->tn.lval-val)>=0; 73732840Sdonn break; 73830242Sbostic case UGT: 73932840Sdonn p->tn.lval = (p->tn.lval-val)>0; 74030242Sbostic break; 74116179Sralph case EQ: 74216179Sralph p->tn.lval = p->tn.lval == val; 74316179Sralph break; 74416179Sralph case NE: 74516179Sralph p->tn.lval = p->tn.lval != val; 74616179Sralph break; 74716179Sralph default: 74816179Sralph return(0); 74916179Sralph } 75016179Sralph return(1); 75116179Sralph } 75216179Sralph 75316179Sralph chkpun(p) register NODE *p; { 75416179Sralph 75516179Sralph /* checks p for the existance of a pun */ 75616179Sralph 75716179Sralph /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ 75816179Sralph 75916179Sralph /* one case is when enumerations are used: this applies only to lint */ 76016179Sralph /* in the other case, one operand is a pointer, the other integer type */ 76116179Sralph /* we check that this integer is in fact a constant zero... */ 76216179Sralph 76316179Sralph /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ 76416179Sralph /* this falls out, because the LHS is never 0 */ 76516179Sralph 76616179Sralph register NODE *q; 76716179Sralph register t1, t2; 76816179Sralph register d1, d2; 76916179Sralph 77016179Sralph t1 = p->in.left->in.type; 77116179Sralph t2 = p->in.right->in.type; 77216179Sralph 77316179Sralph if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ 774*32841Sdonn /* rob pike says this is obnoxious... 77532840Sdonn if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) 776*32841Sdonn werror( "comparison of enums" ); */ 777*32841Sdonn if( t1==ENUMTY && t2==ENUMTY ) { 778*32841Sdonn if ( p->in.left->fn.csiz!=p->in.right->fn.csiz ) 779*32841Sdonn werror( "enumeration type clash, operator %s", opst[p->in.op] ); 780*32841Sdonn return; 781*32841Sdonn } 782*32841Sdonn if ( t1 == ENUMTY ) t1 = INT; 783*32841Sdonn if ( t2 == ENUMTY ) t2 = INT; 78416179Sralph } 78516179Sralph 78616179Sralph if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; 78716179Sralph else q = p->in.left; 78816179Sralph 78916179Sralph if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ 79016179Sralph if( q->in.op != ICON || q->tn.lval != 0 ){ 79116179Sralph werror( "illegal combination of pointer and integer, op %s", 79216179Sralph opst[p->in.op] ); 79316179Sralph } 79416179Sralph } 79516179Sralph else { 79616179Sralph d1 = p->in.left->fn.cdim; 79716179Sralph d2 = p->in.right->fn.cdim; 79816179Sralph for( ;; ){ 79916179Sralph if( t1 == t2 ) {; 80016179Sralph if( p->in.left->fn.csiz != p->in.right->fn.csiz ) { 80116179Sralph werror( "illegal structure pointer combination" ); 80216179Sralph } 80316179Sralph return; 80416179Sralph } 80516179Sralph if( ISARY(t1) || ISPTR(t1) ){ 80616179Sralph if( !ISARY(t2) && !ISPTR(t2) ) break; 80716179Sralph if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ 80816179Sralph werror( "illegal array size combination" ); 80916179Sralph return; 81016179Sralph } 81116179Sralph if( ISARY(t1) ) ++d1; 81216179Sralph if( ISARY(t2) ) ++d2; 81316179Sralph } 81416179Sralph else break; 81516179Sralph t1 = DECREF(t1); 81616179Sralph t2 = DECREF(t2); 81716179Sralph } 81816179Sralph werror( "illegal pointer combination" ); 81916179Sralph } 82016179Sralph 82116179Sralph } 82216179Sralph 82316179Sralph NODE * 82416179Sralph stref( p ) register NODE *p; { 82516179Sralph 82616179Sralph TWORD t; 82716179Sralph int d, s, dsc, align; 82816179Sralph OFFSZ off; 82916179Sralph register struct symtab *q; 83016179Sralph 83116179Sralph /* make p->x */ 83216179Sralph /* this is also used to reference automatic variables */ 83316179Sralph 83416179Sralph q = &stab[p->in.right->tn.rval]; 83516179Sralph p->in.right->in.op = FREE; 83616179Sralph p->in.op = FREE; 83716179Sralph p = pconvert( p->in.left ); 83816179Sralph 83916179Sralph /* make p look like ptr to x */ 84016179Sralph 84116179Sralph if( !ISPTR(p->in.type)){ 84216179Sralph p->in.type = PTR+UNIONTY; 84316179Sralph } 84416179Sralph 84516179Sralph t = INCREF( q->stype ); 84616179Sralph d = q->dimoff; 84716179Sralph s = q->sizoff; 84816179Sralph 84916179Sralph p = makety( p, t, d, s ); 85016179Sralph 85116179Sralph /* compute the offset to be added */ 85216179Sralph 85316179Sralph off = q->offset; 85416179Sralph dsc = q->sclass; 85516179Sralph 85616179Sralph if( dsc & FIELD ) { /* normalize offset */ 85716179Sralph align = ALINT; 85816179Sralph s = INT; 85916179Sralph off = (off/align)*align; 86016179Sralph } 86116179Sralph if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); 86216179Sralph 86316179Sralph p = buildtree( UNARY MUL, p, NIL ); 86416179Sralph 86516179Sralph /* if field, build field info */ 86616179Sralph 86716179Sralph if( dsc & FIELD ){ 86816179Sralph p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); 86916179Sralph p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); 87016179Sralph } 87116179Sralph 87216179Sralph return( clocal(p) ); 87316179Sralph } 87416179Sralph 87516179Sralph notlval(p) register NODE *p; { 87616179Sralph 87716179Sralph /* return 0 if p an lvalue, 1 otherwise */ 87816179Sralph 87916179Sralph again: 88016179Sralph 88116179Sralph switch( p->in.op ){ 88216179Sralph 88316179Sralph case FLD: 88416179Sralph p = p->in.left; 88516179Sralph goto again; 88616179Sralph 88716179Sralph case UNARY MUL: 88816179Sralph /* fix the &(a=b) bug, given that a and b are structures */ 88916179Sralph if( p->in.left->in.op == STASG ) return( 1 ); 89016179Sralph /* and the f().a bug, given that f returns a structure */ 89116179Sralph if( p->in.left->in.op == UNARY STCALL || 89216179Sralph p->in.left->in.op == STCALL ) return( 1 ); 89316179Sralph case NAME: 89416179Sralph case OREG: 89516179Sralph if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); 89616179Sralph case REG: 89716179Sralph return(0); 89816179Sralph 89916179Sralph default: 90016179Sralph return(1); 90116179Sralph 90216179Sralph } 90316179Sralph 90416179Sralph } 90516179Sralph 90616179Sralph NODE * 90716179Sralph bcon( i ){ /* make a constant node with value i */ 90816179Sralph register NODE *p; 90916179Sralph 91016179Sralph p = block( ICON, NIL, NIL, INT, 0, INT ); 91116179Sralph p->tn.lval = i; 91216179Sralph p->tn.rval = NONAME; 91316179Sralph return( clocal(p) ); 91416179Sralph } 91516179Sralph 91616179Sralph NODE * 91716179Sralph bpsize(p) register NODE *p; { 91816179Sralph return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); 91916179Sralph } 92016179Sralph 92116179Sralph OFFSZ 92216179Sralph psize( p ) NODE *p; { 92316179Sralph /* p is a node of type pointer; psize returns the 92416179Sralph size of the thing pointed to */ 92516179Sralph 92616179Sralph if( !ISPTR(p->in.type) ){ 92716179Sralph uerror( "pointer required"); 92816179Sralph return( SZINT ); 92916179Sralph } 93016179Sralph /* note: no pointers to fields */ 93116179Sralph return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); 93216179Sralph } 93316179Sralph 93416179Sralph NODE * 93516179Sralph convert( p, f ) register NODE *p; { 93616179Sralph /* convert an operand of p 93716179Sralph f is either CVTL or CVTR 93816179Sralph operand has type int, and is converted by the size of the other side 93916179Sralph */ 94016179Sralph 94116179Sralph register NODE *q, *r; 94216179Sralph 94316179Sralph q = (f==CVTL)?p->in.left:p->in.right; 94416179Sralph 94516179Sralph r = block( PMCONV, 94616179Sralph q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); 94716179Sralph r = clocal(r); 94816179Sralph if( f == CVTL ) 94916179Sralph p->in.left = r; 95016179Sralph else 95116179Sralph p->in.right = r; 95216179Sralph return(p); 95316179Sralph 95416179Sralph } 95516179Sralph 95625750Sdonn #ifndef econvert 95716179Sralph econvert( p ) register NODE *p; { 95816179Sralph 95916179Sralph /* change enums to ints, or appropriate types */ 96016179Sralph 96116179Sralph register TWORD ty; 96216179Sralph 96316179Sralph if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 96416179Sralph if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 96516179Sralph else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 96616179Sralph else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 96716179Sralph else ty = LONG; 96816179Sralph ty = ctype( ty ); 96916179Sralph p->fn.csiz = ty; 97016179Sralph MODTYPE(p->in.type,ty); 97116179Sralph if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 97216179Sralph } 97316179Sralph } 97425750Sdonn #endif 97516179Sralph 97616179Sralph NODE * 97716179Sralph pconvert( p ) register NODE *p; { 97816179Sralph 97916179Sralph /* if p should be changed into a pointer, do so */ 98016179Sralph 98116179Sralph if( ISARY( p->in.type) ){ 98216179Sralph p->in.type = DECREF( p->in.type ); 98316179Sralph ++p->fn.cdim; 98416179Sralph return( buildtree( UNARY AND, p, NIL ) ); 98516179Sralph } 98616179Sralph if( ISFTN( p->in.type) ) 98716179Sralph return( buildtree( UNARY AND, p, NIL ) ); 98816179Sralph 98916179Sralph return( p ); 99016179Sralph } 99116179Sralph 99216179Sralph NODE * 99316179Sralph oconvert(p) register NODE *p; { 99416179Sralph /* convert the result itself: used for pointer and unsigned */ 99516179Sralph 99616179Sralph switch(p->in.op) { 99716179Sralph 99816179Sralph case LE: 99916179Sralph case LT: 100016179Sralph case GE: 100116179Sralph case GT: 100216179Sralph if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 100316179Sralph case EQ: 100416179Sralph case NE: 100516179Sralph return( p ); 100616179Sralph 100716179Sralph case MINUS: 100816179Sralph return( clocal( block( PVCONV, 100916179Sralph p, bpsize(p->in.left), INT, 0, INT ) ) ); 101016179Sralph } 101116179Sralph 101216179Sralph cerror( "illegal oconvert: %d", p->in.op ); 101316179Sralph 101416179Sralph return(p); 101516179Sralph } 101616179Sralph 101716179Sralph NODE * 101816179Sralph ptmatch(p) register NODE *p; { 101916179Sralph 102016179Sralph /* makes the operands of p agree; they are 102116179Sralph either pointers or integers, by this time */ 102216179Sralph /* with MINUS, the sizes must be the same */ 102316179Sralph /* with COLON, the types must be the same */ 102416179Sralph 102516179Sralph TWORD t1, t2, t; 102616179Sralph int o, d2, d, s2, s; 102716179Sralph 102816179Sralph o = p->in.op; 102916179Sralph t = t1 = p->in.left->in.type; 103016179Sralph t2 = p->in.right->in.type; 103116179Sralph d = p->in.left->fn.cdim; 103216179Sralph d2 = p->in.right->fn.cdim; 103316179Sralph s = p->in.left->fn.csiz; 103416179Sralph s2 = p->in.right->fn.csiz; 103516179Sralph 103616179Sralph switch( o ){ 103716179Sralph 103816179Sralph case ASSIGN: 103916179Sralph case RETURN: 104016179Sralph case CAST: 104116179Sralph { break; } 104216179Sralph 104316179Sralph case MINUS: 104416179Sralph { if( psize(p->in.left) != psize(p->in.right) ){ 104516179Sralph uerror( "illegal pointer subtraction"); 104616179Sralph } 104716179Sralph break; 104816179Sralph } 104916179Sralph case COLON: 105016179Sralph { if( t1 != t2 ) uerror( "illegal types in :"); 105116179Sralph break; 105216179Sralph } 105316179Sralph default: /* must work harder: relationals or comparisons */ 105416179Sralph 105516179Sralph if( !ISPTR(t1) ){ 105616179Sralph t = t2; 105716179Sralph d = d2; 105816179Sralph s = s2; 105916179Sralph break; 106016179Sralph } 106116179Sralph if( !ISPTR(t2) ){ 106216179Sralph break; 106316179Sralph } 106416179Sralph 106516179Sralph /* both are pointers */ 106616179Sralph if( talign(t2,s2) < talign(t,s) ){ 106716179Sralph t = t2; 106816179Sralph s = s2; 106916179Sralph } 107016179Sralph break; 107116179Sralph } 107216179Sralph 107316179Sralph p->in.left = makety( p->in.left, t, d, s ); 107416179Sralph p->in.right = makety( p->in.right, t, d, s ); 107516179Sralph if( o!=MINUS && !logop(o) ){ 107616179Sralph 107716179Sralph p->in.type = t; 107816179Sralph p->fn.cdim = d; 107916179Sralph p->fn.csiz = s; 108016179Sralph } 108116179Sralph 108216179Sralph return(clocal(p)); 108316179Sralph } 108416179Sralph 108516179Sralph int tdebug = 0; 108616179Sralph 108716179Sralph NODE * 108816179Sralph tymatch(p) register NODE *p; { 108916179Sralph 109016179Sralph /* satisfy the types of various arithmetic binary ops */ 109116179Sralph 109216179Sralph /* rules are: 109325750Sdonn if assignment, type of LHS 109416179Sralph if any float or doubles, make double 109516179Sralph if any longs, make long 109616179Sralph otherwise, make int 109716179Sralph if either operand is unsigned, the result is... 109816179Sralph */ 109916179Sralph 110016179Sralph register TWORD t1, t2, t, tu; 110116179Sralph register o, u; 110216179Sralph 110316179Sralph o = p->in.op; 110416179Sralph 110516179Sralph t1 = p->in.left->in.type; 110616179Sralph t2 = p->in.right->in.type; 110716179Sralph if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 110816179Sralph uerror("void type illegal in expression"); 110916179Sralph 111016179Sralph u = 0; 111116179Sralph if( ISUNSIGNED(t1) ){ 111216179Sralph u = 1; 111316179Sralph t1 = DEUNSIGN(t1); 111416179Sralph } 111516179Sralph if( ISUNSIGNED(t2) ){ 111616179Sralph u = 1; 111716179Sralph t2 = DEUNSIGN(t2); 111816179Sralph } 111916179Sralph 112016179Sralph if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 112116179Sralph if( t2 == CHAR || t2 == SHORT ) t2 = INT; 112216179Sralph 112317749Sralph #ifdef SPRECC 112417749Sralph if( t1 == DOUBLE || t2 == DOUBLE ) 112517749Sralph t = DOUBLE; 112617749Sralph else if( t1 == FLOAT || t2 == FLOAT ) 112717749Sralph t = FLOAT; 112817749Sralph #else 112917749Sralph if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT) 113017749Sralph t = DOUBLE; 113117749Sralph #endif 113216179Sralph else if( t1==LONG || t2==LONG ) t = LONG; 113316179Sralph else t = INT; 113416179Sralph 113525750Sdonn if( o == ASSIGN || o == CAST || o == RETURN ){ 113616179Sralph tu = p->in.left->in.type; 113716179Sralph t = t1; 113816179Sralph } 113916179Sralph else { 114016179Sralph tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 114116179Sralph } 114216179Sralph 114316179Sralph /* because expressions have values that are at least as wide 114416179Sralph as INT or UNSIGNED, the only conversions needed 114516179Sralph are those involving FLOAT/DOUBLE, and those 114616179Sralph from LONG to INT and ULONG to UNSIGNED */ 114716179Sralph 114825750Sdonn if( t != t1 && ! asgop(o) ) 114925750Sdonn p->in.left = makety( p->in.left, tu, 0, (int)tu ); 115016179Sralph 115132840Sdonn if( t != t2 || o==CAST) 115232840Sdonn if ( tu == ENUMTY ) {/* always asgop */ 115332840Sdonn p->in.right = makety( p->in.right, INT, 0, INT ); 115432840Sdonn p->in.right->in.type = tu; 115532840Sdonn p->in.right->fn.cdim = p->in.left->fn.cdim; 115632840Sdonn p->in.right->fn.csiz = p->in.left->fn.csiz; 115732840Sdonn } 115832840Sdonn else 115932840Sdonn p->in.right = makety( p->in.right, tu, 0, (int)tu ); 116016179Sralph 116116179Sralph if( asgop(o) ){ 116216179Sralph p->in.type = p->in.left->in.type; 116316179Sralph p->fn.cdim = p->in.left->fn.cdim; 116416179Sralph p->fn.csiz = p->in.left->fn.csiz; 116516179Sralph } 116616179Sralph else if( !logop(o) ){ 116716179Sralph p->in.type = tu; 116816179Sralph p->fn.cdim = 0; 116916179Sralph p->fn.csiz = t; 117016179Sralph } 117116179Sralph 117216179Sralph # ifndef BUG1 117316179Sralph if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 117416179Sralph # endif 117516179Sralph 117616179Sralph return(p); 117716179Sralph } 117816179Sralph 117916179Sralph NODE * 118016179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; { 118116179Sralph /* make p into type t by inserting a conversion */ 118216179Sralph 118316179Sralph if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 118416179Sralph if( t == p->in.type ){ 118516179Sralph p->fn.cdim = d; 118616179Sralph p->fn.csiz = s; 118716179Sralph return( p ); 118816179Sralph } 118916179Sralph 119016179Sralph if( t & TMASK ){ 119116179Sralph /* non-simple type */ 119217228Sralph return( block( PCONV, p, NIL, t, d, s ) ); 119316179Sralph } 119416179Sralph 119516179Sralph if( p->in.op == ICON ){ 119617749Sralph if (t == DOUBLE) { 119717749Sralph p->in.op = DCON; 119817749Sralph if (ISUNSIGNED(p->in.type)) 119932840Sdonn p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval; 120017749Sralph else 120117749Sralph p->dpn.dval = p->tn.lval; 120217749Sralph p->in.type = p->fn.csiz = t; 120317749Sralph return (clocal(p)); 120417749Sralph } 120517749Sralph if (t == FLOAT) { 120616179Sralph p->in.op = FCON; 120716179Sralph if( ISUNSIGNED(p->in.type) ){ 120832840Sdonn p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval; 120916179Sralph } 121016179Sralph else { 121117749Sralph p->fpn.fval = p->tn.lval; 121216179Sralph } 121316179Sralph 121416179Sralph p->in.type = p->fn.csiz = t; 121516179Sralph return( clocal(p) ); 121616179Sralph } 121716179Sralph } 121817749Sralph else if (p->in.op == FCON && t == DOUBLE) { 121917749Sralph double db; 122016179Sralph 122117749Sralph p->in.op = DCON; 122217749Sralph db = p->fpn.fval; 122317749Sralph p->dpn.dval = db; 122417749Sralph p->in.type = p->fn.csiz = t; 122517749Sralph return (clocal(p)); 122617749Sralph } else if (p->in.op == DCON && t == FLOAT) { 122717749Sralph float fl; 122817749Sralph 122917749Sralph p->in.op = FCON; 123017749Sralph fl = p->dpn.dval; 123117749Sralph #ifdef notdef 123217749Sralph if (fl != p->dpn.dval) 123317749Sralph werror("float conversion loses precision"); 123417749Sralph #endif 123517749Sralph p->fpn.fval = fl; 123617749Sralph p->in.type = p->fn.csiz = t; 123717749Sralph return (clocal(p)); 123817749Sralph } 123917749Sralph 124017049Sralph return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); 124116179Sralph 124216179Sralph } 124316179Sralph 124416179Sralph NODE * 124516179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 124616179Sralph 124716179Sralph register NODE *p; 124816179Sralph 124916179Sralph p = talloc(); 125016179Sralph p->in.op = o; 125116179Sralph p->in.left = l; 125216179Sralph p->in.right = r; 125316179Sralph p->in.type = t; 125416179Sralph p->fn.cdim = d; 125516179Sralph p->fn.csiz = s; 125616179Sralph return(p); 125716179Sralph } 125816179Sralph 125916179Sralph icons(p) register NODE *p; { 126016179Sralph /* if p is an integer constant, return its value */ 126116179Sralph int val; 126216179Sralph 126316179Sralph if( p->in.op != ICON ){ 126416179Sralph uerror( "constant expected"); 126516179Sralph val = 1; 126616179Sralph } 126716179Sralph else { 126816179Sralph val = p->tn.lval; 126916179Sralph if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 127016179Sralph } 127116179Sralph tfree( p ); 127216179Sralph return(val); 127316179Sralph } 127416179Sralph 127516179Sralph /* the intent of this table is to examine the 127616179Sralph operators, and to check them for 127716179Sralph correctness. 127816179Sralph 127916179Sralph The table is searched for the op and the 128016179Sralph modified type (where this is one of the 128116179Sralph types INT (includes char and short), LONG, 128216179Sralph DOUBLE (includes FLOAT), and POINTER 128316179Sralph 128416179Sralph The default action is to make the node type integer 128516179Sralph 128616179Sralph The actions taken include: 128716179Sralph PUN check for puns 128816179Sralph CVTL convert the left operand 128916179Sralph CVTR convert the right operand 129016179Sralph TYPL the type is determined by the left operand 129116179Sralph TYPR the type is determined by the right operand 129216179Sralph TYMATCH force type of left and right to match, by inserting conversions 129316179Sralph PTMATCH like TYMATCH, but for pointers 129416179Sralph LVAL left operand must be lval 129516179Sralph CVTO convert the op 129616179Sralph NCVT do not convert the operands 129716179Sralph OTHER handled by code 129816179Sralph NCVTR convert the left operand, not the right... 129916179Sralph 130016179Sralph */ 130116179Sralph 130216179Sralph # define MINT 01 /* integer */ 130316179Sralph # define MDBI 02 /* integer or double */ 130416179Sralph # define MSTR 04 /* structure */ 130516179Sralph # define MPTR 010 /* pointer */ 130616179Sralph # define MPTI 020 /* pointer or integer */ 130716179Sralph # define MENU 040 /* enumeration variable or member */ 130824408Smckusick # define MVOID 0100000 /* void type */ 130916179Sralph 131016179Sralph opact( p ) NODE *p; { 131116179Sralph 131216179Sralph register mt12, mt1, mt2, o; 131316179Sralph 131424408Smckusick mt1 = mt2 = mt12 = 0; 131516179Sralph 131616179Sralph switch( optype(o=p->in.op) ){ 131716179Sralph 131816179Sralph case BITYPE: 131924408Smckusick mt2 = moditype( p->in.right->in.type ); 132016179Sralph case UTYPE: 132124408Smckusick mt1 = moditype( p->in.left->in.type ); 132224408Smckusick break; 132316179Sralph 132416179Sralph } 132516179Sralph 132624408Smckusick if( ((mt1 | mt2) & MVOID) && 132724408Smckusick o != COMOP && 132824408Smckusick !(o == CAST && (mt1 & MVOID)) ){ 132924408Smckusick /* if lhs of RETURN is void, grammar will complain */ 133024408Smckusick if( o != RETURN ) 133124408Smckusick uerror( "value of void expression used" ); 133224408Smckusick return( NCVT ); 133324408Smckusick } 133424408Smckusick mt1 &= ~MVOID; 133524408Smckusick mt2 &= ~MVOID; 133624408Smckusick mt12 = mt1 & mt2; 133724408Smckusick 133816179Sralph switch( o ){ 133916179Sralph 134016179Sralph case NAME : 134116179Sralph case STRING : 134216179Sralph case ICON : 134316179Sralph case FCON : 134417749Sralph case DCON : 134516179Sralph case CALL : 134616179Sralph case UNARY CALL: 134716179Sralph case UNARY MUL: 134816179Sralph { return( OTHER ); } 134916179Sralph case UNARY MINUS: 135016179Sralph if( mt1 & MDBI ) return( TYPL ); 135116179Sralph break; 135216179Sralph 135316179Sralph case COMPL: 135416179Sralph if( mt1 & MINT ) return( TYPL ); 135516179Sralph break; 135616179Sralph 135716179Sralph case UNARY AND: 135816179Sralph { return( NCVT+OTHER ); } 135916179Sralph case INIT: 136016179Sralph case CM: 136116180Sralph return( 0 ); 136216180Sralph 136316179Sralph case NOT: 136416179Sralph case CBRANCH: 136516180Sralph if( mt1 & MSTR ) break; 136616180Sralph return( 0 ); 136716180Sralph 136816179Sralph case ANDAND: 136916179Sralph case OROR: 137016180Sralph if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 137116179Sralph return( 0 ); 137216179Sralph 137316179Sralph case MUL: 137416179Sralph case DIV: 137516179Sralph if( mt12 & MDBI ) return( TYMATCH ); 137616179Sralph break; 137716179Sralph 137816179Sralph case MOD: 137916179Sralph case AND: 138016179Sralph case OR: 138116179Sralph case ER: 138216179Sralph if( mt12 & MINT ) return( TYMATCH ); 138316179Sralph break; 138416179Sralph 138516179Sralph case LS: 138616179Sralph case RS: 138716179Sralph if( mt12 & MINT ) return( TYMATCH+OTHER ); 138816179Sralph break; 138916179Sralph 139016179Sralph case EQ: 139116179Sralph case NE: 139216179Sralph case LT: 139316179Sralph case LE: 139416179Sralph case GT: 139516179Sralph case GE: 139616179Sralph if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 139716179Sralph if( mt12 & MDBI ) return( TYMATCH+CVTO ); 139816179Sralph else if( mt12 & MPTR ) return( PTMATCH+PUN ); 139916179Sralph else if( mt12 & MPTI ) return( PTMATCH+PUN ); 140016179Sralph else break; 140116179Sralph 140216179Sralph case QUEST: 140316179Sralph case COMOP: 140416179Sralph if( mt2&MENU ) return( TYPR+NCVTR ); 140516179Sralph return( TYPR ); 140616179Sralph 140716179Sralph case STREF: 140816179Sralph return( NCVTR+OTHER ); 140916179Sralph 141016179Sralph case FORCE: 141116179Sralph return( TYPL ); 141216179Sralph 141316179Sralph case COLON: 141416179Sralph if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 141516179Sralph else if( mt12 & MDBI ) return( TYMATCH ); 141616179Sralph else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 141716179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 141816179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 141916179Sralph else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 142016179Sralph break; 142116179Sralph 142216179Sralph case ASSIGN: 142316179Sralph case RETURN: 142416179Sralph if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 142532840Sdonn else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 142616179Sralph case CAST: 142716179Sralph if(o==CAST && mt1==0)return(TYPL+TYMATCH); 142832840Sdonn else if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 142918436Smckusick else if( mt2 == 0 && 143018436Smckusick ( p->in.right->in.op == CALL || 143118436Smckusick p->in.right->in.op == UNARY CALL)) break; 143216179Sralph else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 143316179Sralph else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 143416179Sralph break; 143516179Sralph 143616179Sralph case ASG LS: 143716179Sralph case ASG RS: 143816179Sralph if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 143916179Sralph break; 144016179Sralph 144116179Sralph case ASG MUL: 144216179Sralph case ASG DIV: 144316179Sralph if( mt12 & MDBI ) return( LVAL+TYMATCH ); 144416179Sralph break; 144516179Sralph 144616179Sralph case ASG MOD: 144716179Sralph case ASG AND: 144816179Sralph case ASG OR: 144916179Sralph case ASG ER: 145016179Sralph if( mt12 & MINT ) return( LVAL+TYMATCH ); 145116179Sralph break; 145216179Sralph 145316179Sralph case ASG PLUS: 145416179Sralph case ASG MINUS: 145516179Sralph case INCR: 145616179Sralph case DECR: 145716179Sralph if( mt12 & MDBI ) return( TYMATCH+LVAL ); 145816179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 145916179Sralph break; 146016179Sralph 146116179Sralph case MINUS: 146216179Sralph if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 146316179Sralph if( mt2 & MPTR ) break; 146416179Sralph case PLUS: 146516179Sralph if( mt12 & MDBI ) return( TYMATCH ); 146616179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 146716179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 146816179Sralph 146916179Sralph } 147024408Smckusick if( mt12 == MSTR ) 147124408Smckusick uerror( "%s is not a permitted struct/union operation", opst[o] ); 147224408Smckusick else 147324408Smckusick uerror( "operands of %s have incompatible types", opst[o] ); 147416179Sralph return( NCVT ); 147516179Sralph } 147616179Sralph 147716179Sralph moditype( ty ) TWORD ty; { 147816179Sralph 147916179Sralph switch( ty ){ 148016179Sralph 148116179Sralph case TVOID: 148217206Sralph return( MPTR ); 148316179Sralph case UNDEF: 148424408Smckusick return( MVOID ); 148516179Sralph case ENUMTY: 148616179Sralph case MOETY: 148732840Sdonn return( MENU|MINT|MDBI|MPTI ); /* enums are ints */ 148816179Sralph 148916179Sralph case STRTY: 149016179Sralph case UNIONTY: 149116179Sralph return( MSTR ); 149216179Sralph 149316179Sralph case CHAR: 149416179Sralph case SHORT: 149516179Sralph case UCHAR: 149616179Sralph case USHORT: 149716179Sralph return( MINT|MPTI|MDBI ); 149816179Sralph case UNSIGNED: 149916179Sralph case ULONG: 150016179Sralph case INT: 150116179Sralph case LONG: 150216179Sralph return( MINT|MDBI|MPTI ); 150316179Sralph case FLOAT: 150416179Sralph case DOUBLE: 150516179Sralph return( MDBI ); 150616179Sralph default: 150716179Sralph return( MPTR|MPTI ); 150816179Sralph 150916179Sralph } 151016179Sralph } 151116179Sralph 151216179Sralph NODE * 151316179Sralph doszof( p ) register NODE *p; { 151416179Sralph /* do sizeof p */ 151516179Sralph int i; 151616179Sralph 151716179Sralph /* whatever is the meaning of this if it is a bitfield? */ 151816179Sralph i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 151916179Sralph 152016179Sralph tfree(p); 152116179Sralph if( i <= 0 ) werror( "sizeof returns 0" ); 152216179Sralph return( bcon( i ) ); 152316179Sralph } 152416179Sralph 152516179Sralph # ifndef BUG2 152616179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; { 152716179Sralph register ty; 152816179Sralph 152916179Sralph *a = *b = down+1; 153016179Sralph while( down > 1 ){ 153116179Sralph printf( "\t" ); 153216179Sralph down -= 2; 153316179Sralph } 153416179Sralph if( down ) printf( " " ); 153516179Sralph 153616179Sralph ty = optype( p->in.op ); 153716179Sralph 153816179Sralph printf("%o) %s, ", p, opst[p->in.op] ); 153916179Sralph if( ty == LTYPE ){ 154016179Sralph printf( CONFMT, p->tn.lval ); 154116179Sralph printf( ", %d, ", p->tn.rval ); 154216179Sralph } 154316179Sralph tprint( p->in.type ); 154416179Sralph printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 154516179Sralph } 154616179Sralph # endif 154716179Sralph 154816179Sralph prtdcon( p ) register NODE *p; { 154917749Sralph int o = p->in.op, i; 155016179Sralph 155117749Sralph if( o == DCON || o == FCON ){ 155216179Sralph locctr( DATA ); 155317749Sralph defalign( o == DCON ? ALDOUBLE : ALFLOAT ); 155416179Sralph deflab( i = getlab() ); 155517749Sralph if( o == FCON ) 155617749Sralph fincode( p->fpn.fval, SZFLOAT ); 155717749Sralph else 155817749Sralph fincode( p->dpn.dval, SZDOUBLE ); 155916179Sralph p->tn.lval = 0; 156016179Sralph p->tn.rval = -i; 156117749Sralph p->in.type = (o == DCON ? DOUBLE : FLOAT); 156216179Sralph p->in.op = NAME; 156316179Sralph } 156416179Sralph } 156516179Sralph 156616179Sralph 156716179Sralph int edebug = 0; 156816179Sralph ecomp( p ) register NODE *p; { 156916179Sralph # ifndef BUG2 157016179Sralph if( edebug ) fwalk( p, eprint, 0 ); 157116179Sralph # endif 157216179Sralph if( !reached ){ 157316179Sralph werror( "statement not reached" ); 157416179Sralph reached = 1; 157516179Sralph } 157616179Sralph p = optim(p); 157716179Sralph walkf( p, prtdcon ); 157816179Sralph locctr( PROG ); 157916179Sralph ecode( p ); 158016179Sralph tfree(p); 158116179Sralph } 158216179Sralph 158316179Sralph # ifdef STDPRTREE 158416179Sralph # ifndef ONEPASS 158516179Sralph 158616179Sralph prtree(p) register NODE *p; { 158716179Sralph 158816179Sralph register struct symtab *q; 158916179Sralph register ty; 159016179Sralph 159116179Sralph # ifdef MYPRTREE 159216179Sralph MYPRTREE(p); /* local action can be taken here; then return... */ 159316179Sralph #endif 159416179Sralph 159516179Sralph ty = optype(p->in.op); 159616179Sralph 159716179Sralph printf( "%d\t", p->in.op ); 159816179Sralph 159916179Sralph if( ty == LTYPE ) { 160016179Sralph printf( CONFMT, p->tn.lval ); 160116179Sralph printf( "\t" ); 160216179Sralph } 160316179Sralph if( ty != BITYPE ) { 160416179Sralph if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 160516179Sralph else printf( "%d\t", p->tn.rval ); 160616179Sralph } 160716179Sralph 160816179Sralph printf( "%o\t", p->in.type ); 160916179Sralph 161016179Sralph /* handle special cases */ 161116179Sralph 161216179Sralph switch( p->in.op ){ 161316179Sralph 161416179Sralph case NAME: 161516179Sralph case ICON: 161616179Sralph /* print external name */ 161716179Sralph if( p->tn.rval == NONAME ) printf( "\n" ); 161816179Sralph else if( p->tn.rval >= 0 ){ 161916179Sralph q = &stab[p->tn.rval]; 162016179Sralph printf( "%s\n", exname(q->sname) ); 162116179Sralph } 162216179Sralph else { /* label */ 162316179Sralph printf( LABFMT, -p->tn.rval ); 162416179Sralph } 162516179Sralph break; 162616179Sralph 162716179Sralph case STARG: 162816179Sralph case STASG: 162916179Sralph case STCALL: 163016179Sralph case UNARY STCALL: 163116179Sralph /* print out size */ 163216179Sralph /* use lhs size, in order to avoid hassles with the structure `.' operator */ 163316179Sralph 163416179Sralph /* note: p->in.left not a field... */ 163516179Sralph printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 163616179Sralph printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 163716179Sralph break; 163816179Sralph 163916179Sralph default: 164016179Sralph printf( "\n" ); 164116179Sralph } 164216179Sralph 164316179Sralph if( ty != LTYPE ) prtree( p->in.left ); 164416179Sralph if( ty == BITYPE ) prtree( p->in.right ); 164516179Sralph 164616179Sralph } 164716179Sralph 164816179Sralph # else 164916179Sralph 165016179Sralph p2tree(p) register NODE *p; { 165116179Sralph register ty; 165216179Sralph 165316179Sralph # ifdef MYP2TREE 165416179Sralph MYP2TREE(p); /* local action can be taken here; then return... */ 165516179Sralph # endif 165616179Sralph 165716179Sralph ty = optype(p->in.op); 165816179Sralph 165916179Sralph switch( p->in.op ){ 166016179Sralph 166116179Sralph case NAME: 166216179Sralph case ICON: 166316179Sralph #ifndef FLEXNAMES 166416179Sralph if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 166516179Sralph #else 166616179Sralph if( p->tn.rval == NONAME ) p->in.name = ""; 166716179Sralph #endif 166816179Sralph else if( p->tn.rval >= 0 ){ /* copy name from exname */ 166916179Sralph register char *cp; 167016179Sralph register i; 167116179Sralph cp = exname( stab[p->tn.rval].sname ); 167216179Sralph #ifndef FLEXNAMES 167316179Sralph for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 167416179Sralph #else 167516179Sralph p->in.name = tstr(cp); 167616179Sralph #endif 167716179Sralph } 167816179Sralph #ifndef FLEXNAMES 167916179Sralph else sprintf( p->in.name, LABFMT, -p->tn.rval ); 168016179Sralph #else 168116179Sralph else { 168216179Sralph char temp[32]; 168316179Sralph sprintf( temp, LABFMT, -p->tn.rval ); 168416179Sralph p->in.name = tstr(temp); 168516179Sralph } 168616179Sralph #endif 168716179Sralph break; 168816179Sralph 168916179Sralph case STARG: 169016179Sralph case STASG: 169116179Sralph case STCALL: 169216179Sralph case UNARY STCALL: 169316179Sralph /* set up size parameters */ 169416179Sralph p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 169516179Sralph p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 169616179Sralph break; 169716179Sralph 169816179Sralph case REG: 169916179Sralph rbusy( p->tn.rval, p->in.type ); 170016179Sralph default: 170116179Sralph #ifndef FLEXNAMES 170216179Sralph p->in.name[0] = '\0'; 170316179Sralph #else 170416179Sralph p->in.name = ""; 170516179Sralph #endif 170616179Sralph } 170716179Sralph 170816179Sralph p->in.rall = NOPREF; 170916179Sralph 171016179Sralph if( ty != LTYPE ) p2tree( p->in.left ); 171116179Sralph if( ty == BITYPE ) p2tree( p->in.right ); 171216179Sralph } 171316179Sralph 171416179Sralph # endif 171516179Sralph # endif 1716