1*17749Sralph #ifndef lint 2*17749Sralph static char *sccsid ="@(#)trees.c 4.6 (Berkeley) 01/18/85"; 3*17749Sralph #endif 4*17749Sralph 516179Sralph # include "mfile1" 616179Sralph 7*17749Sralph int bdebug = 0; 8*17749Sralph int adebug = 0; 9*17749Sralph extern ddebug; 10*17749Sralph extern eprint(); 11*17749Sralph 1216179Sralph /* corrections when in violation of lint */ 1316179Sralph 1416179Sralph /* some special actions, used in finding the type of nodes */ 1516179Sralph # define NCVT 01 1616179Sralph # define PUN 02 1716179Sralph # define TYPL 04 1816179Sralph # define TYPR 010 1916179Sralph # define TYMATCH 040 2016179Sralph # define LVAL 0100 2116179Sralph # define CVTO 0200 2216179Sralph # define CVTL 0400 2316179Sralph # define CVTR 01000 2416179Sralph # define PTMATCH 02000 2516179Sralph # define OTHER 04000 2616179Sralph # define NCVTR 010000 2716179Sralph 28*17749Sralph #ifndef BUG1 29*17749Sralph printact(t, acts) 30*17749Sralph NODE *t; 31*17749Sralph int acts; 32*17749Sralph { 33*17749Sralph static struct actions { 34*17749Sralph int a_bit; 35*17749Sralph char *a_name; 36*17749Sralph } actions[] = { 37*17749Sralph { PUN, "PUN" }, 38*17749Sralph { CVTL, "CVTL" }, 39*17749Sralph { CVTR, "CVTR" }, 40*17749Sralph { TYPL, "TYPL" }, 41*17749Sralph { TYPR, "TYPR" }, 42*17749Sralph { TYMATCH, "TYMATCH" }, 43*17749Sralph { PTMATCH, "PTMATCH" }, 44*17749Sralph { LVAL, "LVAL" }, 45*17749Sralph { CVTO, "CVTO" }, 46*17749Sralph { NCVT, "NCVT" }, 47*17749Sralph { OTHER, "OTHER" }, 48*17749Sralph { NCVTR, "NCVTR" }, 49*17749Sralph { 0 } 50*17749Sralph }; 51*17749Sralph register struct actions *p; 52*17749Sralph char *sep = " "; 53*17749Sralph 54*17749Sralph printf("actions"); 55*17749Sralph for (p = actions; p->a_name; p++) 56*17749Sralph if (p->a_bit & acts) { 57*17749Sralph printf("%s%s", sep, p->a_name); 58*17749Sralph sep = "|"; 59*17749Sralph } 60*17749Sralph if (!bdebug) { 61*17749Sralph printf(" for:\n"); 62*17749Sralph fwalk(t, eprint, 0); 63*17749Sralph } else 64*17749Sralph putchar('\n'); 65*17749Sralph } 66*17749Sralph #endif 67*17749Sralph 6816179Sralph /* node conventions: 6916179Sralph 7016179Sralph NAME: rval>0 is stab index for external 7116179Sralph rval<0 is -inlabel number 7216179Sralph lval is offset in bits 7316179Sralph ICON: lval has the value 7416179Sralph rval has the STAB index, or - label number, 7516179Sralph if a name whose address is in the constant 7616179Sralph rval = NONAME means no name 7716179Sralph REG: rval is reg. identification cookie 7816179Sralph 7916179Sralph */ 8016179Sralph 8116179Sralph NODE * 8216179Sralph buildtree( o, l, r ) register NODE *l, *r; { 8316179Sralph register NODE *p, *q; 8416179Sralph register actions; 8516179Sralph register opty; 8616179Sralph register struct symtab *sp; 8716179Sralph register NODE *lr, *ll; 88*17749Sralph NODE *fixargs(); 8916179Sralph int i; 9016179Sralph 9116179Sralph # ifndef BUG1 9216179Sralph if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r ); 9316179Sralph # endif 9416179Sralph opty = optype(o); 9516179Sralph 9616179Sralph /* check for constants */ 9716179Sralph 9816179Sralph if( opty == UTYPE && l->in.op == ICON ){ 9916179Sralph 10016179Sralph switch( o ){ 10116179Sralph 10216179Sralph case NOT: 10316179Sralph if( hflag ) werror( "constant argument to NOT" ); 10416179Sralph case UNARY MINUS: 10516179Sralph case COMPL: 10616179Sralph if( conval( l, o, l ) ) return(l); 10716179Sralph break; 10816179Sralph 10916179Sralph } 11016179Sralph } 11116179Sralph 11216179Sralph else if( o==UNARY MINUS && l->in.op==FCON ){ 113*17749Sralph l->fpn.fval = -l->fpn.fval; 11416179Sralph return(l); 11516179Sralph } 11616179Sralph 117*17749Sralph else if( o==UNARY MINUS && l->in.op==DCON ){ 118*17749Sralph l->dpn.dval = -l->dpn.dval; 119*17749Sralph return(l); 120*17749Sralph } 121*17749Sralph 12216179Sralph else if( o==QUEST && l->in.op==ICON ) { 12316179Sralph l->in.op = FREE; 12416179Sralph r->in.op = FREE; 12516179Sralph if( l->tn.lval ){ 12616179Sralph tfree( r->in.right ); 12716179Sralph return( r->in.left ); 12816179Sralph } 12916179Sralph else { 13016179Sralph tfree( r->in.left ); 13116179Sralph return( r->in.right ); 13216179Sralph } 13316179Sralph } 13416179Sralph 13516179Sralph else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn; 13616179Sralph 13716179Sralph else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){ 13816179Sralph 13916179Sralph switch( o ){ 14016179Sralph 14116179Sralph case ULT: 14216179Sralph case UGT: 14316179Sralph case ULE: 14416179Sralph case UGE: 14516179Sralph case LT: 14616179Sralph case GT: 14716179Sralph case LE: 14816179Sralph case GE: 14916179Sralph case EQ: 15016179Sralph case NE: 15116179Sralph case ANDAND: 15216179Sralph case OROR: 15316179Sralph case CBRANCH: 15416179Sralph 15516179Sralph ccwarn: 15616179Sralph if( hflag ) werror( "constant in conditional context" ); 15716179Sralph 15816179Sralph case PLUS: 15916179Sralph case MINUS: 16016179Sralph case MUL: 16116179Sralph case DIV: 16216179Sralph case MOD: 16316179Sralph case AND: 16416179Sralph case OR: 16516179Sralph case ER: 16616179Sralph case LS: 16716179Sralph case RS: 16816179Sralph if( conval( l, o, r ) ) { 16916179Sralph r->in.op = FREE; 17016179Sralph return(l); 17116179Sralph } 17216179Sralph break; 17316179Sralph } 17416179Sralph } 175*17749Sralph else if (opty == BITYPE) { 176*17749Sralph if ((l->in.op == FCON || l->in.op == ICON) && 177*17749Sralph (r->in.op == FCON || r->in.op == ICON)) 178*17749Sralph switch (o) { 17916179Sralph 180*17749Sralph case PLUS: 181*17749Sralph case MINUS: 182*17749Sralph case MUL: 183*17749Sralph case DIV: 184*17749Sralph if (l->in.op == ICON) 185*17749Sralph l->fpn.fval = l->tn.lval; 186*17749Sralph if (r->in.op == ICON) 187*17749Sralph r->fpn.fval = r->tn.lval; 188*17749Sralph l->in.op = FCON; 189*17749Sralph l->in.type = l->fn.csiz = FLOAT; 190*17749Sralph r->in.op = FREE; 191*17749Sralph switch (o) { 192*17749Sralph 193*17749Sralph case PLUS: 194*17749Sralph l->fpn.fval += r->fpn.fval; 195*17749Sralph return (l); 196*17749Sralph 197*17749Sralph case MINUS: 198*17749Sralph l->fpn.fval -= r->fpn.fval; 199*17749Sralph return (l); 200*17749Sralph 201*17749Sralph case MUL: 202*17749Sralph l->fpn.fval *= r->fpn.fval; 203*17749Sralph return (l); 204*17749Sralph 205*17749Sralph case DIV: 206*17749Sralph if (r->fpn.fval == 0) 207*17749Sralph uerror("division by 0."); 208*17749Sralph else 209*17749Sralph l->fpn.fval /= r->fpn.fval; 210*17749Sralph return (l); 21116179Sralph } 212*17749Sralph } 213*17749Sralph else if ((l->in.op == DCON || l->in.op == ICON) && 214*17749Sralph (r->in.op == DCON || r->in.op == ICON)) 215*17749Sralph switch (o) { 216*17749Sralph 21716179Sralph case PLUS: 21816179Sralph case MINUS: 21916179Sralph case MUL: 22016179Sralph case DIV: 221*17749Sralph if (l->in.op == ICON) 222*17749Sralph l->dpn.dval = l->tn.lval; 223*17749Sralph if (r->in.op == ICON) 224*17749Sralph r->dpn.dval = r->tn.lval; 225*17749Sralph l->in.op = DCON; 226*17749Sralph l->in.type = l->fn.csiz = DOUBLE; 227*17749Sralph r->in.op = FREE; 228*17749Sralph switch (o) { 229*17749Sralph 230*17749Sralph case PLUS: 231*17749Sralph l->dpn.dval += r->dpn.dval; 232*17749Sralph return (l); 233*17749Sralph 234*17749Sralph case MINUS: 235*17749Sralph l->dpn.dval -= r->dpn.dval; 236*17749Sralph return (l); 237*17749Sralph 238*17749Sralph case MUL: 239*17749Sralph l->dpn.dval *= r->dpn.dval; 240*17749Sralph return (l); 241*17749Sralph 242*17749Sralph case DIV: 243*17749Sralph if (r->dpn.dval == 0) 244*17749Sralph uerror("division by 0."); 245*17749Sralph else 246*17749Sralph l->dpn.dval /= r->dpn.dval; 247*17749Sralph return (l); 24816179Sralph } 24916179Sralph } 250*17749Sralph } 25116179Sralph 25216179Sralph /* its real; we must make a new node */ 25316179Sralph 25416179Sralph p = block( o, l, r, INT, 0, INT ); 25516179Sralph 25616179Sralph actions = opact(p); 257*17749Sralph #ifndef BUG1 258*17749Sralph if (adebug) 259*17749Sralph printact(p, actions); 260*17749Sralph #endif 26116179Sralph 26216179Sralph if( actions&LVAL ){ /* check left descendent */ 26316179Sralph if( notlval(p->in.left) ) { 26416179Sralph uerror( "illegal lhs of assignment operator" ); 26516179Sralph } 26616179Sralph } 26716179Sralph 26816179Sralph if( actions & NCVTR ){ 26916179Sralph p->in.left = pconvert( p->in.left ); 27016179Sralph } 27116179Sralph else if( !(actions & NCVT ) ){ 27216179Sralph switch( opty ){ 27316179Sralph 27416179Sralph case BITYPE: 27516179Sralph p->in.right = pconvert( p->in.right ); 27616179Sralph case UTYPE: 27716179Sralph p->in.left = pconvert( p->in.left ); 27816179Sralph 27916179Sralph } 28016179Sralph } 28116179Sralph 28216179Sralph if( (actions&PUN) && (o!=CAST||cflag) ){ 28316179Sralph chkpun(p); 28416179Sralph } 28516179Sralph 28616179Sralph if( actions & (TYPL|TYPR) ){ 28716179Sralph 28816179Sralph q = (actions&TYPL) ? p->in.left : p->in.right; 28916179Sralph 29016179Sralph p->in.type = q->in.type; 29116179Sralph p->fn.cdim = q->fn.cdim; 29216179Sralph p->fn.csiz = q->fn.csiz; 29316179Sralph } 29416179Sralph 29516179Sralph if( actions & CVTL ) p = convert( p, CVTL ); 29616179Sralph if( actions & CVTR ) p = convert( p, CVTR ); 29716179Sralph if( actions & TYMATCH ) p = tymatch(p); 29816179Sralph if( actions & PTMATCH ) p = ptmatch(p); 29916179Sralph 30016179Sralph if( actions & OTHER ){ 30116179Sralph l = p->in.left; 30216179Sralph r = p->in.right; 30316179Sralph 30416179Sralph switch(o){ 30516179Sralph 30616179Sralph case NAME: 30716179Sralph sp = &stab[idname]; 30816179Sralph if( sp->stype == UNDEF ){ 30916179Sralph #ifndef FLEXNAMES 31016179Sralph uerror( "%.8s undefined", sp->sname ); 31116179Sralph #else 31216179Sralph uerror( "%s undefined", sp->sname ); 31316179Sralph #endif 31416179Sralph /* make p look reasonable */ 31516179Sralph p->in.type = p->fn.cdim = p->fn.csiz = INT; 31616179Sralph p->tn.rval = idname; 31716179Sralph p->tn.lval = 0; 31816179Sralph defid( p, SNULL ); 31916179Sralph break; 32016179Sralph } 32116179Sralph p->in.type = sp->stype; 32216179Sralph p->fn.cdim = sp->dimoff; 32316179Sralph p->fn.csiz = sp->sizoff; 32416179Sralph p->tn.lval = 0; 32516179Sralph p->tn.rval = idname; 32616179Sralph /* special case: MOETY is really an ICON... */ 32716179Sralph if( p->in.type == MOETY ){ 32816179Sralph p->tn.rval = NONAME; 32916179Sralph p->tn.lval = sp->offset; 33016179Sralph p->fn.cdim = 0; 33116179Sralph p->in.type = ENUMTY; 33216179Sralph p->in.op = ICON; 33316179Sralph } 33416179Sralph break; 33516179Sralph 33616179Sralph case ICON: 33716179Sralph p->in.type = INT; 33816179Sralph p->fn.cdim = 0; 33916179Sralph p->fn.csiz = INT; 34016179Sralph break; 34116179Sralph 34216179Sralph case STRING: 34316179Sralph p->in.op = NAME; 34416179Sralph p->in.type = CHAR+ARY; 34516179Sralph p->tn.lval = 0; 34616179Sralph p->tn.rval = NOLAB; 34716179Sralph p->fn.cdim = curdim; 34816179Sralph p->fn.csiz = CHAR; 34916179Sralph break; 35016179Sralph 35116179Sralph case FCON: 35216179Sralph p->tn.lval = 0; 35316179Sralph p->tn.rval = 0; 354*17749Sralph p->in.type = FLOAT; 355*17749Sralph p->fn.cdim = 0; 356*17749Sralph p->fn.csiz = FLOAT; 357*17749Sralph break; 358*17749Sralph 359*17749Sralph case DCON: 360*17749Sralph p->tn.lval = 0; 361*17749Sralph p->tn.rval = 0; 36216179Sralph p->in.type = DOUBLE; 36316179Sralph p->fn.cdim = 0; 36416179Sralph p->fn.csiz = DOUBLE; 36516179Sralph break; 36616179Sralph 36716179Sralph case STREF: 36816179Sralph /* p->x turned into *(p+offset) */ 36916179Sralph /* rhs must be a name; check correctness */ 37016179Sralph 37116179Sralph i = r->tn.rval; 37216179Sralph if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ 37316179Sralph uerror( "member of structure or union required" ); 37416179Sralph }else 37516179Sralph /* if this name is non-unique, find right one */ 37616179Sralph if( stab[i].sflags & SNONUNIQ && 37716179Sralph (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) && 37816179Sralph (l->fn.csiz +1) >= 0 ){ 37916179Sralph /* nonunique name && structure defined */ 38016179Sralph char * memnam, * tabnam; 38116179Sralph register k; 38216179Sralph int j; 38316179Sralph int memi; 38416179Sralph j=dimtab[l->fn.csiz+1]; 38516179Sralph for( ; (memi=dimtab[j]) >= 0; ++j ){ 38616179Sralph tabnam = stab[memi].sname; 38716179Sralph memnam = stab[i].sname; 38816179Sralph # ifndef BUG1 38916179Sralph if( ddebug>1 ){ 39016179Sralph #ifndef FLEXNAMES 39116179Sralph printf("member %.8s==%.8s?\n", 39216179Sralph #else 39316179Sralph printf("member %s==%s?\n", 39416179Sralph #endif 39516179Sralph memnam, tabnam); 39616179Sralph } 39716179Sralph # endif 39816179Sralph if( stab[memi].sflags & SNONUNIQ ){ 39916179Sralph #ifndef FLEXNAMES 40016179Sralph for( k=0; k<NCHNAM; ++k ){ 40116179Sralph if(*memnam++!=*tabnam) 40216179Sralph goto next; 40316179Sralph if(!*tabnam++) break; 40416179Sralph } 40516179Sralph #else 40616179Sralph if (memnam != tabnam) 40716179Sralph goto next; 40816179Sralph #endif 40916179Sralph r->tn.rval = i = memi; 41016179Sralph break; 41116179Sralph } 41216179Sralph next: continue; 41316179Sralph } 41416179Sralph if( memi < 0 ) 41516179Sralph #ifndef FLEXNAMES 41616179Sralph uerror("illegal member use: %.8s", 41716179Sralph #else 41816179Sralph uerror("illegal member use: %s", 41916179Sralph #endif 42016179Sralph stab[i].sname); 42116179Sralph } 42216179Sralph else { 42316179Sralph register j; 42416179Sralph if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){ 42516179Sralph if( stab[i].sflags & SNONUNIQ ){ 42616179Sralph uerror( "nonunique name demands struct/union or struct/union pointer" ); 42716179Sralph } 42816179Sralph else werror( "struct/union or struct/union pointer required" ); 42916179Sralph } 43016179Sralph else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" ); 43116179Sralph else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){ 43216179Sralph #ifndef FLEXNAMES 43316179Sralph werror( "illegal member use: %.8s", stab[i].sname ); 43416179Sralph #else 43516179Sralph werror( "illegal member use: %s", stab[i].sname ); 43616179Sralph #endif 43716179Sralph } 43816179Sralph } 43916179Sralph 44016179Sralph p = stref( p ); 44116179Sralph break; 44216179Sralph 44316179Sralph case UNARY MUL: 44416179Sralph if( l->in.op == UNARY AND ){ 44516179Sralph p->in.op = l->in.op = FREE; 44616179Sralph p = l->in.left; 44716179Sralph } 44816179Sralph if( !ISPTR(l->in.type))uerror("illegal indirection"); 44916179Sralph p->in.type = DECREF(l->in.type); 45016179Sralph p->fn.cdim = l->fn.cdim; 45116179Sralph p->fn.csiz = l->fn.csiz; 45216179Sralph break; 45316179Sralph 45416179Sralph case UNARY AND: 45516179Sralph switch( l->in.op ){ 45616179Sralph 45716179Sralph case UNARY MUL: 45816179Sralph p->in.op = l->in.op = FREE; 45916179Sralph p = l->in.left; 46016179Sralph case NAME: 46116179Sralph p->in.type = INCREF( l->in.type ); 46216179Sralph p->fn.cdim = l->fn.cdim; 46316179Sralph p->fn.csiz = l->fn.csiz; 46416179Sralph break; 46516179Sralph 46616179Sralph case COMOP: 46716179Sralph lr = buildtree( UNARY AND, l->in.right, NIL ); 46816179Sralph p->in.op = l->in.op = FREE; 46916179Sralph p = buildtree( COMOP, l->in.left, lr ); 47016179Sralph break; 47116179Sralph 47216179Sralph case QUEST: 47316179Sralph lr = buildtree( UNARY AND, l->in.right->in.right, NIL ); 47416179Sralph ll = buildtree( UNARY AND, l->in.right->in.left, NIL ); 47516179Sralph p->in.op = l->in.op = l->in.right->in.op = FREE; 47616179Sralph p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) ); 47716179Sralph break; 47816179Sralph 47916179Sralph # ifdef ADDROREG 48016179Sralph case OREG: 48116179Sralph /* OREG was built in clocal() 48216179Sralph * for an auto or formal parameter 48316179Sralph * now its address is being taken 48416179Sralph * local code must unwind it 48516179Sralph * back to PLUS/MINUS REG ICON 48616179Sralph * according to local conventions 48716179Sralph */ 48816179Sralph { 48916179Sralph extern NODE * addroreg(); 49016179Sralph p->in.op = FREE; 49116179Sralph p = addroreg( l ); 49216179Sralph } 49316179Sralph break; 49416179Sralph 49516179Sralph # endif 49616179Sralph default: 49716179Sralph uerror( "unacceptable operand of &" ); 49816179Sralph break; 49916179Sralph } 50016179Sralph break; 50116179Sralph 50216179Sralph case LS: 50316179Sralph case RS: 50416179Sralph case ASG LS: 50516179Sralph case ASG RS: 50616179Sralph if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT) 50716179Sralph p->in.right = makety(p->in.right, INT, 0, INT ); 50816179Sralph break; 50916179Sralph 51016179Sralph case RETURN: 51116179Sralph case ASSIGN: 51216179Sralph case CAST: 51316179Sralph /* structure assignment */ 51416179Sralph /* take the addresses of the two sides; then make an 51516179Sralph /* operator using STASG and 51616179Sralph /* the addresses of left and right */ 51716179Sralph 51816179Sralph { 51916179Sralph register TWORD t; 52016179Sralph register d, s; 52116179Sralph 52216179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" ); 52316179Sralph 52416179Sralph r = buildtree( UNARY AND, r, NIL ); 52516179Sralph t = r->in.type; 52616179Sralph d = r->fn.cdim; 52716179Sralph s = r->fn.csiz; 52816179Sralph 52916179Sralph l = block( STASG, l, r, t, d, s ); 53016179Sralph 53116179Sralph if( o == RETURN ){ 53216179Sralph p->in.op = FREE; 53316179Sralph p = l; 53416179Sralph break; 53516179Sralph } 53616179Sralph 53716179Sralph p->in.op = UNARY MUL; 53816179Sralph p->in.left = l; 53916179Sralph p->in.right = NIL; 54016179Sralph break; 54116179Sralph } 54216179Sralph case COLON: 54316179Sralph /* structure colon */ 54416179Sralph 54516179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" ); 54616179Sralph break; 54716179Sralph 54816179Sralph case CALL: 549*17749Sralph p->in.right = r = fixargs( p->in.right ); 55016179Sralph case UNARY CALL: 55116179Sralph if( !ISPTR(l->in.type)) uerror("illegal function"); 55216179Sralph p->in.type = DECREF(l->in.type); 55316179Sralph if( !ISFTN(p->in.type)) uerror("illegal function"); 55416179Sralph p->in.type = DECREF( p->in.type ); 55516179Sralph p->fn.cdim = l->fn.cdim; 55616179Sralph p->fn.csiz = l->fn.csiz; 55716179Sralph if( l->in.op == UNARY AND && l->in.left->in.op == NAME && 55816179Sralph l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME && 55916179Sralph ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){ 56016179Sralph p->in.op += (FORTCALL-CALL); 56116179Sralph } 56216179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 56316179Sralph /* function returning structure */ 56416179Sralph /* make function really return ptr to str., with * */ 56516179Sralph 56616179Sralph p->in.op += STCALL-CALL; 56716179Sralph p->in.type = INCREF( p->in.type ); 56816179Sralph p = buildtree( UNARY MUL, p, NIL ); 56916179Sralph 57016179Sralph } 57116179Sralph break; 57216179Sralph 57316179Sralph default: 57416179Sralph cerror( "other code %d", o ); 57516179Sralph } 57616179Sralph 57716179Sralph } 57816179Sralph 57916179Sralph if( actions & CVTO ) p = oconvert(p); 58016179Sralph p = clocal(p); 58116179Sralph 58216179Sralph # ifndef BUG1 58316179Sralph if( bdebug ) fwalk( p, eprint, 0 ); 58416179Sralph # endif 58516179Sralph 58616179Sralph return(p); 58716179Sralph 58816179Sralph } 58916179Sralph 590*17749Sralph /* 591*17749Sralph * Rewrite arguments in a function call. 592*17749Sralph * Structure arguments are massaged, single 593*17749Sralph * precision floating point constants are 594*17749Sralph * cast to double (to eliminate convert code). 595*17749Sralph */ 59616179Sralph NODE * 597*17749Sralph fixargs( p ) register NODE *p; { 598*17749Sralph int o = p->in.op; 59916179Sralph 600*17749Sralph if( o == CM ){ 601*17749Sralph p->in.left = fixargs( p->in.left ); 602*17749Sralph p->in.right = fixargs( p->in.right ); 60316179Sralph return( p ); 60416179Sralph } 60516179Sralph 60616179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 60716179Sralph p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz ); 60816179Sralph p->in.left = buildtree( UNARY AND, p->in.left, NIL ); 60916179Sralph p = clocal(p); 61016179Sralph } 611*17749Sralph else if( o == FCON ) 612*17749Sralph p = makety(p, DOUBLE, 0, 0); 61316179Sralph return( p ); 61416179Sralph } 61516179Sralph 61616179Sralph chkstr( i, j, type ) TWORD type; { 61716179Sralph /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ 61816179Sralph /* i has been checked to contain a MOS or MOU */ 61916179Sralph /* j is the index in dimtab of the members... */ 62016179Sralph int k, kk; 62116179Sralph 62216179Sralph extern int ddebug; 62316179Sralph 62416179Sralph # ifndef BUG1 62516179Sralph #ifndef FLEXNAMES 62616179Sralph if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j ); 62716179Sralph #else 62816179Sralph if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j ); 62916179Sralph #endif 63016179Sralph # endif 63116179Sralph if( (k = j) < 0 ) uerror( "undefined structure or union" ); 63216179Sralph else { 63316179Sralph for( ; (kk = dimtab[k] ) >= 0; ++k ){ 63416179Sralph if( kk >= SYMTSZ ){ 63516179Sralph cerror( "gummy structure" ); 63616179Sralph return(1); 63716179Sralph } 63816179Sralph if( kk == i ) return( 1 ); 63916179Sralph switch( stab[kk].stype ){ 64016179Sralph 64116179Sralph case STRTY: 64216179Sralph case UNIONTY: 64316179Sralph if( type == STRTY ) continue; /* no recursive looking for strs */ 64416179Sralph if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){ 64516179Sralph if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */ 64616179Sralph werror( 64716179Sralph #ifndef FLEXNAMES 64816179Sralph "illegal member use: perhaps %.8s.%.8s?", 64916179Sralph #else 65016179Sralph "illegal member use: perhaps %s.%s?", 65116179Sralph #endif 65216179Sralph stab[kk].sname, stab[i].sname ); 65316179Sralph return(1); 65416179Sralph } 65516179Sralph } 65616179Sralph } 65716179Sralph } 65816179Sralph return( 0 ); 65916179Sralph } 66016179Sralph 66116179Sralph conval( p, o, q ) register NODE *p, *q; { 66216179Sralph /* apply the op o to the lval part of p; if binary, rhs is val */ 66316179Sralph int i, u; 66416179Sralph CONSZ val; 66516179Sralph 66616179Sralph val = q->tn.lval; 66716179Sralph u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type); 66816179Sralph if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); 66916179Sralph 67016179Sralph if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0); 67116179Sralph if( q->tn.rval != NONAME && o!=PLUS ) return(0); 67216179Sralph if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0); 67316179Sralph 67416179Sralph switch( o ){ 67516179Sralph 67616179Sralph case PLUS: 67716179Sralph p->tn.lval += val; 67816179Sralph if( p->tn.rval == NONAME ){ 67916179Sralph p->tn.rval = q->tn.rval; 68016179Sralph p->in.type = q->in.type; 68116179Sralph } 68216179Sralph break; 68316179Sralph case MINUS: 68416179Sralph p->tn.lval -= val; 68516179Sralph break; 68616179Sralph case MUL: 68716179Sralph p->tn.lval *= val; 68816179Sralph break; 68916179Sralph case DIV: 69016179Sralph if( val == 0 ) uerror( "division by 0" ); 691*17749Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val; 69216179Sralph else p->tn.lval /= val; 69316179Sralph break; 69416179Sralph case MOD: 69516179Sralph if( val == 0 ) uerror( "division by 0" ); 696*17749Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val; 69716179Sralph else p->tn.lval %= val; 69816179Sralph break; 69916179Sralph case AND: 70016179Sralph p->tn.lval &= val; 70116179Sralph break; 70216179Sralph case OR: 70316179Sralph p->tn.lval |= val; 70416179Sralph break; 70516179Sralph case ER: 706*17749Sralph p->tn.lval ^= val; 70716179Sralph break; 70816179Sralph case LS: 70916179Sralph i = val; 71016179Sralph p->tn.lval = p->tn.lval << i; 71116179Sralph break; 71216179Sralph case RS: 71316179Sralph i = val; 714*17749Sralph if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i; 715*17749Sralph else p->tn.lval = p->tn.lval >> i; 71616179Sralph break; 71716179Sralph 71816179Sralph case UNARY MINUS: 71916179Sralph p->tn.lval = - p->tn.lval; 72016179Sralph break; 72116179Sralph case COMPL: 72216179Sralph p->tn.lval = ~p->tn.lval; 72316179Sralph break; 72416179Sralph case NOT: 72516179Sralph p->tn.lval = !p->tn.lval; 72616179Sralph break; 72716179Sralph case LT: 72816179Sralph p->tn.lval = p->tn.lval < val; 72916179Sralph break; 73016179Sralph case LE: 73116179Sralph p->tn.lval = p->tn.lval <= val; 73216179Sralph break; 73316179Sralph case GT: 73416179Sralph p->tn.lval = p->tn.lval > val; 73516179Sralph break; 73616179Sralph case GE: 73716179Sralph p->tn.lval = p->tn.lval >= val; 73816179Sralph break; 73916179Sralph case ULT: 74016179Sralph p->tn.lval = (p->tn.lval-val)<0; 74116179Sralph break; 74216179Sralph case ULE: 74316179Sralph p->tn.lval = (p->tn.lval-val)<=0; 74416179Sralph break; 74516179Sralph case UGE: 74616179Sralph p->tn.lval = (p->tn.lval-val)>=0; 74716179Sralph break; 74816179Sralph case UGT: 74916179Sralph p->tn.lval = (p->tn.lval-val)>0; 75016179Sralph break; 75116179Sralph case EQ: 75216179Sralph p->tn.lval = p->tn.lval == val; 75316179Sralph break; 75416179Sralph case NE: 75516179Sralph p->tn.lval = p->tn.lval != val; 75616179Sralph break; 75716179Sralph default: 75816179Sralph return(0); 75916179Sralph } 76016179Sralph return(1); 76116179Sralph } 76216179Sralph 76316179Sralph chkpun(p) register NODE *p; { 76416179Sralph 76516179Sralph /* checks p for the existance of a pun */ 76616179Sralph 76716179Sralph /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ 76816179Sralph 76916179Sralph /* one case is when enumerations are used: this applies only to lint */ 77016179Sralph /* in the other case, one operand is a pointer, the other integer type */ 77116179Sralph /* we check that this integer is in fact a constant zero... */ 77216179Sralph 77316179Sralph /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ 77416179Sralph /* this falls out, because the LHS is never 0 */ 77516179Sralph 77616179Sralph register NODE *q; 77716179Sralph register t1, t2; 77816179Sralph register d1, d2; 77916179Sralph 78016179Sralph t1 = p->in.left->in.type; 78116179Sralph t2 = p->in.right->in.type; 78216179Sralph 78316179Sralph if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ 78416179Sralph if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) { 78516179Sralph uerror( "illegal comparison of enums" ); 78616179Sralph return; 78716179Sralph } 78816179Sralph if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return; 78916179Sralph werror( "enumeration type clash, operator %s", opst[p->in.op] ); 79016179Sralph return; 79116179Sralph } 79216179Sralph 79316179Sralph if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; 79416179Sralph else q = p->in.left; 79516179Sralph 79616179Sralph if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ 79716179Sralph if( q->in.op != ICON || q->tn.lval != 0 ){ 79816179Sralph werror( "illegal combination of pointer and integer, op %s", 79916179Sralph opst[p->in.op] ); 80016179Sralph } 80116179Sralph } 80216179Sralph else { 80316179Sralph d1 = p->in.left->fn.cdim; 80416179Sralph d2 = p->in.right->fn.cdim; 80516179Sralph for( ;; ){ 80616179Sralph if( t1 == t2 ) {; 80716179Sralph if( p->in.left->fn.csiz != p->in.right->fn.csiz ) { 80816179Sralph werror( "illegal structure pointer combination" ); 80916179Sralph } 81016179Sralph return; 81116179Sralph } 81216179Sralph if( ISARY(t1) || ISPTR(t1) ){ 81316179Sralph if( !ISARY(t2) && !ISPTR(t2) ) break; 81416179Sralph if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ 81516179Sralph werror( "illegal array size combination" ); 81616179Sralph return; 81716179Sralph } 81816179Sralph if( ISARY(t1) ) ++d1; 81916179Sralph if( ISARY(t2) ) ++d2; 82016179Sralph } 82116179Sralph else break; 82216179Sralph t1 = DECREF(t1); 82316179Sralph t2 = DECREF(t2); 82416179Sralph } 82516179Sralph werror( "illegal pointer combination" ); 82616179Sralph } 82716179Sralph 82816179Sralph } 82916179Sralph 83016179Sralph NODE * 83116179Sralph stref( p ) register NODE *p; { 83216179Sralph 83316179Sralph TWORD t; 83416179Sralph int d, s, dsc, align; 83516179Sralph OFFSZ off; 83616179Sralph register struct symtab *q; 83716179Sralph 83816179Sralph /* make p->x */ 83916179Sralph /* this is also used to reference automatic variables */ 84016179Sralph 84116179Sralph q = &stab[p->in.right->tn.rval]; 84216179Sralph p->in.right->in.op = FREE; 84316179Sralph p->in.op = FREE; 84416179Sralph p = pconvert( p->in.left ); 84516179Sralph 84616179Sralph /* make p look like ptr to x */ 84716179Sralph 84816179Sralph if( !ISPTR(p->in.type)){ 84916179Sralph p->in.type = PTR+UNIONTY; 85016179Sralph } 85116179Sralph 85216179Sralph t = INCREF( q->stype ); 85316179Sralph d = q->dimoff; 85416179Sralph s = q->sizoff; 85516179Sralph 85616179Sralph p = makety( p, t, d, s ); 85716179Sralph 85816179Sralph /* compute the offset to be added */ 85916179Sralph 86016179Sralph off = q->offset; 86116179Sralph dsc = q->sclass; 86216179Sralph 86316179Sralph if( dsc & FIELD ) { /* normalize offset */ 86416179Sralph align = ALINT; 86516179Sralph s = INT; 86616179Sralph off = (off/align)*align; 86716179Sralph } 86816179Sralph if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); 86916179Sralph 87016179Sralph p = buildtree( UNARY MUL, p, NIL ); 87116179Sralph 87216179Sralph /* if field, build field info */ 87316179Sralph 87416179Sralph if( dsc & FIELD ){ 87516179Sralph p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); 87616179Sralph p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); 87716179Sralph } 87816179Sralph 87916179Sralph return( clocal(p) ); 88016179Sralph } 88116179Sralph 88216179Sralph notlval(p) register NODE *p; { 88316179Sralph 88416179Sralph /* return 0 if p an lvalue, 1 otherwise */ 88516179Sralph 88616179Sralph again: 88716179Sralph 88816179Sralph switch( p->in.op ){ 88916179Sralph 89016179Sralph case FLD: 89116179Sralph p = p->in.left; 89216179Sralph goto again; 89316179Sralph 89416179Sralph case UNARY MUL: 89516179Sralph /* fix the &(a=b) bug, given that a and b are structures */ 89616179Sralph if( p->in.left->in.op == STASG ) return( 1 ); 89716179Sralph /* and the f().a bug, given that f returns a structure */ 89816179Sralph if( p->in.left->in.op == UNARY STCALL || 89916179Sralph p->in.left->in.op == STCALL ) return( 1 ); 90016179Sralph case NAME: 90116179Sralph case OREG: 90216179Sralph if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); 90316179Sralph case REG: 90416179Sralph return(0); 90516179Sralph 90616179Sralph default: 90716179Sralph return(1); 90816179Sralph 90916179Sralph } 91016179Sralph 91116179Sralph } 91216179Sralph 91316179Sralph NODE * 91416179Sralph bcon( i ){ /* make a constant node with value i */ 91516179Sralph register NODE *p; 91616179Sralph 91716179Sralph p = block( ICON, NIL, NIL, INT, 0, INT ); 91816179Sralph p->tn.lval = i; 91916179Sralph p->tn.rval = NONAME; 92016179Sralph return( clocal(p) ); 92116179Sralph } 92216179Sralph 92316179Sralph NODE * 92416179Sralph bpsize(p) register NODE *p; { 92516179Sralph return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); 92616179Sralph } 92716179Sralph 92816179Sralph OFFSZ 92916179Sralph psize( p ) NODE *p; { 93016179Sralph /* p is a node of type pointer; psize returns the 93116179Sralph size of the thing pointed to */ 93216179Sralph 93316179Sralph if( !ISPTR(p->in.type) ){ 93416179Sralph uerror( "pointer required"); 93516179Sralph return( SZINT ); 93616179Sralph } 93716179Sralph /* note: no pointers to fields */ 93816179Sralph return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); 93916179Sralph } 94016179Sralph 94116179Sralph NODE * 94216179Sralph convert( p, f ) register NODE *p; { 94316179Sralph /* convert an operand of p 94416179Sralph f is either CVTL or CVTR 94516179Sralph operand has type int, and is converted by the size of the other side 94616179Sralph */ 94716179Sralph 94816179Sralph register NODE *q, *r; 94916179Sralph 95016179Sralph q = (f==CVTL)?p->in.left:p->in.right; 95116179Sralph 95216179Sralph r = block( PMCONV, 95316179Sralph q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); 95416179Sralph r = clocal(r); 95516179Sralph if( f == CVTL ) 95616179Sralph p->in.left = r; 95716179Sralph else 95816179Sralph p->in.right = r; 95916179Sralph return(p); 96016179Sralph 96116179Sralph } 96216179Sralph 96316179Sralph econvert( p ) register NODE *p; { 96416179Sralph 96516179Sralph /* change enums to ints, or appropriate types */ 96616179Sralph 96716179Sralph register TWORD ty; 96816179Sralph 96916179Sralph if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 97016179Sralph if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 97116179Sralph else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 97216179Sralph else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 97316179Sralph else ty = LONG; 97416179Sralph ty = ctype( ty ); 97516179Sralph p->fn.csiz = ty; 97616179Sralph MODTYPE(p->in.type,ty); 97716179Sralph if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 97816179Sralph } 97916179Sralph } 98016179Sralph 98116179Sralph NODE * 98216179Sralph pconvert( p ) register NODE *p; { 98316179Sralph 98416179Sralph /* if p should be changed into a pointer, do so */ 98516179Sralph 98616179Sralph if( ISARY( p->in.type) ){ 98716179Sralph p->in.type = DECREF( p->in.type ); 98816179Sralph ++p->fn.cdim; 98916179Sralph return( buildtree( UNARY AND, p, NIL ) ); 99016179Sralph } 99116179Sralph if( ISFTN( p->in.type) ) 99216179Sralph return( buildtree( UNARY AND, p, NIL ) ); 99316179Sralph 99416179Sralph return( p ); 99516179Sralph } 99616179Sralph 99716179Sralph NODE * 99816179Sralph oconvert(p) register NODE *p; { 99916179Sralph /* convert the result itself: used for pointer and unsigned */ 100016179Sralph 100116179Sralph switch(p->in.op) { 100216179Sralph 100316179Sralph case LE: 100416179Sralph case LT: 100516179Sralph case GE: 100616179Sralph case GT: 100716179Sralph if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 100816179Sralph case EQ: 100916179Sralph case NE: 101016179Sralph return( p ); 101116179Sralph 101216179Sralph case MINUS: 101316179Sralph return( clocal( block( PVCONV, 101416179Sralph p, bpsize(p->in.left), INT, 0, INT ) ) ); 101516179Sralph } 101616179Sralph 101716179Sralph cerror( "illegal oconvert: %d", p->in.op ); 101816179Sralph 101916179Sralph return(p); 102016179Sralph } 102116179Sralph 102216179Sralph NODE * 102316179Sralph ptmatch(p) register NODE *p; { 102416179Sralph 102516179Sralph /* makes the operands of p agree; they are 102616179Sralph either pointers or integers, by this time */ 102716179Sralph /* with MINUS, the sizes must be the same */ 102816179Sralph /* with COLON, the types must be the same */ 102916179Sralph 103016179Sralph TWORD t1, t2, t; 103116179Sralph int o, d2, d, s2, s; 103216179Sralph 103316179Sralph o = p->in.op; 103416179Sralph t = t1 = p->in.left->in.type; 103516179Sralph t2 = p->in.right->in.type; 103616179Sralph d = p->in.left->fn.cdim; 103716179Sralph d2 = p->in.right->fn.cdim; 103816179Sralph s = p->in.left->fn.csiz; 103916179Sralph s2 = p->in.right->fn.csiz; 104016179Sralph 104116179Sralph switch( o ){ 104216179Sralph 104316179Sralph case ASSIGN: 104416179Sralph case RETURN: 104516179Sralph case CAST: 104616179Sralph { break; } 104716179Sralph 104816179Sralph case MINUS: 104916179Sralph { if( psize(p->in.left) != psize(p->in.right) ){ 105016179Sralph uerror( "illegal pointer subtraction"); 105116179Sralph } 105216179Sralph break; 105316179Sralph } 105416179Sralph case COLON: 105516179Sralph { if( t1 != t2 ) uerror( "illegal types in :"); 105616179Sralph break; 105716179Sralph } 105816179Sralph default: /* must work harder: relationals or comparisons */ 105916179Sralph 106016179Sralph if( !ISPTR(t1) ){ 106116179Sralph t = t2; 106216179Sralph d = d2; 106316179Sralph s = s2; 106416179Sralph break; 106516179Sralph } 106616179Sralph if( !ISPTR(t2) ){ 106716179Sralph break; 106816179Sralph } 106916179Sralph 107016179Sralph /* both are pointers */ 107116179Sralph if( talign(t2,s2) < talign(t,s) ){ 107216179Sralph t = t2; 107316179Sralph s = s2; 107416179Sralph } 107516179Sralph break; 107616179Sralph } 107716179Sralph 107816179Sralph p->in.left = makety( p->in.left, t, d, s ); 107916179Sralph p->in.right = makety( p->in.right, t, d, s ); 108016179Sralph if( o!=MINUS && !logop(o) ){ 108116179Sralph 108216179Sralph p->in.type = t; 108316179Sralph p->fn.cdim = d; 108416179Sralph p->fn.csiz = s; 108516179Sralph } 108616179Sralph 108716179Sralph return(clocal(p)); 108816179Sralph } 108916179Sralph 109016179Sralph int tdebug = 0; 109116179Sralph 109216179Sralph NODE * 109316179Sralph tymatch(p) register NODE *p; { 109416179Sralph 109516179Sralph /* satisfy the types of various arithmetic binary ops */ 109616179Sralph 109716179Sralph /* rules are: 109816179Sralph if assignment, op, type of LHS 109916179Sralph if any float or doubles, make double 110016179Sralph if any longs, make long 110116179Sralph otherwise, make int 110216179Sralph if either operand is unsigned, the result is... 110316179Sralph */ 110416179Sralph 110516179Sralph register TWORD t1, t2, t, tu; 110616179Sralph register o, u; 110716179Sralph 110816179Sralph o = p->in.op; 110916179Sralph 111016179Sralph t1 = p->in.left->in.type; 111116179Sralph t2 = p->in.right->in.type; 111216179Sralph if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 111316179Sralph uerror("void type illegal in expression"); 111416179Sralph 111516179Sralph u = 0; 111616179Sralph if( ISUNSIGNED(t1) ){ 111716179Sralph u = 1; 111816179Sralph t1 = DEUNSIGN(t1); 111916179Sralph } 112016179Sralph if( ISUNSIGNED(t2) ){ 112116179Sralph u = 1; 112216179Sralph t2 = DEUNSIGN(t2); 112316179Sralph } 112416179Sralph 112516179Sralph if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 112616179Sralph if( t2 == CHAR || t2 == SHORT ) t2 = INT; 112716179Sralph 1128*17749Sralph #ifdef SPRECC 1129*17749Sralph if( t1 == DOUBLE || t2 == DOUBLE ) 1130*17749Sralph t = DOUBLE; 1131*17749Sralph else if( t1 == FLOAT || t2 == FLOAT ) 1132*17749Sralph t = FLOAT; 1133*17749Sralph #else 1134*17749Sralph if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT) 1135*17749Sralph t = DOUBLE; 1136*17749Sralph #endif 113716179Sralph else if( t1==LONG || t2==LONG ) t = LONG; 113816179Sralph else t = INT; 113916179Sralph 114016179Sralph if( asgop(o) ){ 114116179Sralph tu = p->in.left->in.type; 114216179Sralph t = t1; 114316179Sralph } 114416179Sralph else { 114516179Sralph tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 114616179Sralph } 114716179Sralph 114816179Sralph /* because expressions have values that are at least as wide 114916179Sralph as INT or UNSIGNED, the only conversions needed 115016179Sralph are those involving FLOAT/DOUBLE, and those 115116179Sralph from LONG to INT and ULONG to UNSIGNED */ 115216179Sralph 115316179Sralph if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu ); 115416179Sralph 115516179Sralph if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); 115616179Sralph 115716179Sralph if( asgop(o) ){ 115816179Sralph p->in.type = p->in.left->in.type; 115916179Sralph p->fn.cdim = p->in.left->fn.cdim; 116016179Sralph p->fn.csiz = p->in.left->fn.csiz; 116116179Sralph } 116216179Sralph else if( !logop(o) ){ 116316179Sralph p->in.type = tu; 116416179Sralph p->fn.cdim = 0; 116516179Sralph p->fn.csiz = t; 116616179Sralph } 116716179Sralph 116816179Sralph # ifndef BUG1 116916179Sralph if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 117016179Sralph # endif 117116179Sralph 117216179Sralph return(p); 117316179Sralph } 117416179Sralph 117516179Sralph NODE * 117616179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; { 117716179Sralph /* make p into type t by inserting a conversion */ 117816179Sralph 117916179Sralph if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 118016179Sralph if( t == p->in.type ){ 118116179Sralph p->fn.cdim = d; 118216179Sralph p->fn.csiz = s; 118316179Sralph return( p ); 118416179Sralph } 118516179Sralph 118616179Sralph if( t & TMASK ){ 118716179Sralph /* non-simple type */ 118817228Sralph return( block( PCONV, p, NIL, t, d, s ) ); 118916179Sralph } 119016179Sralph 119116179Sralph if( p->in.op == ICON ){ 1192*17749Sralph if (t == DOUBLE) { 1193*17749Sralph p->in.op = DCON; 1194*17749Sralph if (ISUNSIGNED(p->in.type)) 1195*17749Sralph p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval; 1196*17749Sralph else 1197*17749Sralph p->dpn.dval = p->tn.lval; 1198*17749Sralph p->in.type = p->fn.csiz = t; 1199*17749Sralph return (clocal(p)); 1200*17749Sralph } 1201*17749Sralph if (t == FLOAT) { 120216179Sralph p->in.op = FCON; 120316179Sralph if( ISUNSIGNED(p->in.type) ){ 1204*17749Sralph p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval; 120516179Sralph } 120616179Sralph else { 1207*17749Sralph p->fpn.fval = p->tn.lval; 120816179Sralph } 120916179Sralph 121016179Sralph p->in.type = p->fn.csiz = t; 121116179Sralph return( clocal(p) ); 121216179Sralph } 121316179Sralph } 1214*17749Sralph else if (p->in.op == FCON && t == DOUBLE) { 1215*17749Sralph double db; 121616179Sralph 1217*17749Sralph p->in.op = DCON; 1218*17749Sralph db = p->fpn.fval; 1219*17749Sralph p->dpn.dval = db; 1220*17749Sralph p->in.type = p->fn.csiz = t; 1221*17749Sralph return (clocal(p)); 1222*17749Sralph } else if (p->in.op == DCON && t == FLOAT) { 1223*17749Sralph float fl; 1224*17749Sralph 1225*17749Sralph p->in.op = FCON; 1226*17749Sralph fl = p->dpn.dval; 1227*17749Sralph #ifdef notdef 1228*17749Sralph if (fl != p->dpn.dval) 1229*17749Sralph werror("float conversion loses precision"); 1230*17749Sralph #endif 1231*17749Sralph p->fpn.fval = fl; 1232*17749Sralph p->in.type = p->fn.csiz = t; 1233*17749Sralph return (clocal(p)); 1234*17749Sralph } 1235*17749Sralph 123617049Sralph return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); 123716179Sralph 123816179Sralph } 123916179Sralph 124016179Sralph NODE * 124116179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 124216179Sralph 124316179Sralph register NODE *p; 124416179Sralph 124516179Sralph p = talloc(); 124616179Sralph p->in.op = o; 124716179Sralph p->in.left = l; 124816179Sralph p->in.right = r; 124916179Sralph p->in.type = t; 125016179Sralph p->fn.cdim = d; 125116179Sralph p->fn.csiz = s; 125216179Sralph return(p); 125316179Sralph } 125416179Sralph 125516179Sralph icons(p) register NODE *p; { 125616179Sralph /* if p is an integer constant, return its value */ 125716179Sralph int val; 125816179Sralph 125916179Sralph if( p->in.op != ICON ){ 126016179Sralph uerror( "constant expected"); 126116179Sralph val = 1; 126216179Sralph } 126316179Sralph else { 126416179Sralph val = p->tn.lval; 126516179Sralph if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 126616179Sralph } 126716179Sralph tfree( p ); 126816179Sralph return(val); 126916179Sralph } 127016179Sralph 127116179Sralph /* the intent of this table is to examine the 127216179Sralph operators, and to check them for 127316179Sralph correctness. 127416179Sralph 127516179Sralph The table is searched for the op and the 127616179Sralph modified type (where this is one of the 127716179Sralph types INT (includes char and short), LONG, 127816179Sralph DOUBLE (includes FLOAT), and POINTER 127916179Sralph 128016179Sralph The default action is to make the node type integer 128116179Sralph 128216179Sralph The actions taken include: 128316179Sralph PUN check for puns 128416179Sralph CVTL convert the left operand 128516179Sralph CVTR convert the right operand 128616179Sralph TYPL the type is determined by the left operand 128716179Sralph TYPR the type is determined by the right operand 128816179Sralph TYMATCH force type of left and right to match, by inserting conversions 128916179Sralph PTMATCH like TYMATCH, but for pointers 129016179Sralph LVAL left operand must be lval 129116179Sralph CVTO convert the op 129216179Sralph NCVT do not convert the operands 129316179Sralph OTHER handled by code 129416179Sralph NCVTR convert the left operand, not the right... 129516179Sralph 129616179Sralph */ 129716179Sralph 129816179Sralph # define MINT 01 /* integer */ 129916179Sralph # define MDBI 02 /* integer or double */ 130016179Sralph # define MSTR 04 /* structure */ 130116179Sralph # define MPTR 010 /* pointer */ 130216179Sralph # define MPTI 020 /* pointer or integer */ 130316179Sralph # define MENU 040 /* enumeration variable or member */ 130416179Sralph 130516179Sralph opact( p ) NODE *p; { 130616179Sralph 130716179Sralph register mt12, mt1, mt2, o; 130816179Sralph 130916179Sralph mt12 = 0; 131016179Sralph 131116179Sralph switch( optype(o=p->in.op) ){ 131216179Sralph 131316179Sralph case BITYPE: 131416179Sralph mt12=mt2 = moditype( p->in.right->in.type ); 131516179Sralph case UTYPE: 131616179Sralph mt12 &= (mt1 = moditype( p->in.left->in.type )); 131716179Sralph 131816179Sralph } 131916179Sralph 132016179Sralph switch( o ){ 132116179Sralph 132216179Sralph case NAME : 132316179Sralph case STRING : 132416179Sralph case ICON : 132516179Sralph case FCON : 1326*17749Sralph case DCON : 132716179Sralph case CALL : 132816179Sralph case UNARY CALL: 132916179Sralph case UNARY MUL: 133016179Sralph { return( OTHER ); } 133116179Sralph case UNARY MINUS: 133216179Sralph if( mt1 & MDBI ) return( TYPL ); 133316179Sralph break; 133416179Sralph 133516179Sralph case COMPL: 133616179Sralph if( mt1 & MINT ) return( TYPL ); 133716179Sralph break; 133816179Sralph 133916179Sralph case UNARY AND: 134016179Sralph { return( NCVT+OTHER ); } 134116179Sralph case INIT: 134216179Sralph case CM: 134316180Sralph return( 0 ); 134416180Sralph 134516179Sralph case NOT: 134616179Sralph case CBRANCH: 134716180Sralph if( mt1 & MSTR ) break; 134816180Sralph return( 0 ); 134916180Sralph 135016179Sralph case ANDAND: 135116179Sralph case OROR: 135216180Sralph if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 135316179Sralph return( 0 ); 135416179Sralph 135516179Sralph case MUL: 135616179Sralph case DIV: 135716179Sralph if( mt12 & MDBI ) return( TYMATCH ); 135816179Sralph break; 135916179Sralph 136016179Sralph case MOD: 136116179Sralph case AND: 136216179Sralph case OR: 136316179Sralph case ER: 136416179Sralph if( mt12 & MINT ) return( TYMATCH ); 136516179Sralph break; 136616179Sralph 136716179Sralph case LS: 136816179Sralph case RS: 136916179Sralph if( mt12 & MINT ) return( TYMATCH+OTHER ); 137016179Sralph break; 137116179Sralph 137216179Sralph case EQ: 137316179Sralph case NE: 137416179Sralph case LT: 137516179Sralph case LE: 137616179Sralph case GT: 137716179Sralph case GE: 137816179Sralph if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 137916179Sralph if( mt12 & MDBI ) return( TYMATCH+CVTO ); 138016179Sralph else if( mt12 & MPTR ) return( PTMATCH+PUN ); 138116179Sralph else if( mt12 & MPTI ) return( PTMATCH+PUN ); 138216179Sralph else break; 138316179Sralph 138416179Sralph case QUEST: 138516179Sralph case COMOP: 138616179Sralph if( mt2&MENU ) return( TYPR+NCVTR ); 138716179Sralph return( TYPR ); 138816179Sralph 138916179Sralph case STREF: 139016179Sralph return( NCVTR+OTHER ); 139116179Sralph 139216179Sralph case FORCE: 139316179Sralph return( TYPL ); 139416179Sralph 139516179Sralph case COLON: 139616179Sralph if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 139716179Sralph else if( mt12 & MDBI ) return( TYMATCH ); 139816179Sralph else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 139916179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 140016179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 140116179Sralph else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 140216179Sralph break; 140316179Sralph 140416179Sralph case ASSIGN: 140516179Sralph case RETURN: 140616179Sralph if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 140716179Sralph case CAST: 140816179Sralph if(o==CAST && mt1==0)return(TYPL+TYMATCH); 140916179Sralph if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 141016179Sralph else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 141116179Sralph else if( mt12 == 0 ) break; 141216179Sralph else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 141316179Sralph else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 141416179Sralph break; 141516179Sralph 141616179Sralph case ASG LS: 141716179Sralph case ASG RS: 141816179Sralph if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 141916179Sralph break; 142016179Sralph 142116179Sralph case ASG MUL: 142216179Sralph case ASG DIV: 142316179Sralph if( mt12 & MDBI ) return( LVAL+TYMATCH ); 142416179Sralph break; 142516179Sralph 142616179Sralph case ASG MOD: 142716179Sralph case ASG AND: 142816179Sralph case ASG OR: 142916179Sralph case ASG ER: 143016179Sralph if( mt12 & MINT ) return( LVAL+TYMATCH ); 143116179Sralph break; 143216179Sralph 143316179Sralph case ASG PLUS: 143416179Sralph case ASG MINUS: 143516179Sralph case INCR: 143616179Sralph case DECR: 143716179Sralph if( mt12 & MDBI ) return( TYMATCH+LVAL ); 143816179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 143916179Sralph break; 144016179Sralph 144116179Sralph case MINUS: 144216179Sralph if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 144316179Sralph if( mt2 & MPTR ) break; 144416179Sralph case PLUS: 144516179Sralph if( mt12 & MDBI ) return( TYMATCH ); 144616179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 144716179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 144816179Sralph 144916179Sralph } 145016179Sralph uerror( "operands of %s have incompatible types", opst[o] ); 145116179Sralph return( NCVT ); 145216179Sralph } 145316179Sralph 145416179Sralph moditype( ty ) TWORD ty; { 145516179Sralph 145616179Sralph switch( ty ){ 145716179Sralph 145816179Sralph case TVOID: 145917206Sralph return( MPTR ); 146016179Sralph case UNDEF: 146116179Sralph return(0); /* type is void */ 146216179Sralph case ENUMTY: 146316179Sralph case MOETY: 146416179Sralph return( MENU ); 146516179Sralph 146616179Sralph case STRTY: 146716179Sralph case UNIONTY: 146816179Sralph return( MSTR ); 146916179Sralph 147016179Sralph case CHAR: 147116179Sralph case SHORT: 147216179Sralph case UCHAR: 147316179Sralph case USHORT: 147416179Sralph return( MINT|MPTI|MDBI ); 147516179Sralph case UNSIGNED: 147616179Sralph case ULONG: 147716179Sralph case INT: 147816179Sralph case LONG: 147916179Sralph return( MINT|MDBI|MPTI ); 148016179Sralph case FLOAT: 148116179Sralph case DOUBLE: 148216179Sralph return( MDBI ); 148316179Sralph default: 148416179Sralph return( MPTR|MPTI ); 148516179Sralph 148616179Sralph } 148716179Sralph } 148816179Sralph 148916179Sralph NODE * 149016179Sralph doszof( p ) register NODE *p; { 149116179Sralph /* do sizeof p */ 149216179Sralph int i; 149316179Sralph 149416179Sralph /* whatever is the meaning of this if it is a bitfield? */ 149516179Sralph i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 149616179Sralph 149716179Sralph tfree(p); 149816179Sralph if( i <= 0 ) werror( "sizeof returns 0" ); 149916179Sralph return( bcon( i ) ); 150016179Sralph } 150116179Sralph 150216179Sralph # ifndef BUG2 150316179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; { 150416179Sralph register ty; 150516179Sralph 150616179Sralph *a = *b = down+1; 150716179Sralph while( down > 1 ){ 150816179Sralph printf( "\t" ); 150916179Sralph down -= 2; 151016179Sralph } 151116179Sralph if( down ) printf( " " ); 151216179Sralph 151316179Sralph ty = optype( p->in.op ); 151416179Sralph 151516179Sralph printf("%o) %s, ", p, opst[p->in.op] ); 151616179Sralph if( ty == LTYPE ){ 151716179Sralph printf( CONFMT, p->tn.lval ); 151816179Sralph printf( ", %d, ", p->tn.rval ); 151916179Sralph } 152016179Sralph tprint( p->in.type ); 152116179Sralph printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 152216179Sralph } 152316179Sralph # endif 152416179Sralph 152516179Sralph prtdcon( p ) register NODE *p; { 1526*17749Sralph int o = p->in.op, i; 152716179Sralph 1528*17749Sralph if( o == DCON || o == FCON ){ 152916179Sralph locctr( DATA ); 1530*17749Sralph defalign( o == DCON ? ALDOUBLE : ALFLOAT ); 153116179Sralph deflab( i = getlab() ); 1532*17749Sralph if( o == FCON ) 1533*17749Sralph fincode( p->fpn.fval, SZFLOAT ); 1534*17749Sralph else 1535*17749Sralph fincode( p->dpn.dval, SZDOUBLE ); 153616179Sralph p->tn.lval = 0; 153716179Sralph p->tn.rval = -i; 1538*17749Sralph p->in.type = (o == DCON ? DOUBLE : FLOAT); 153916179Sralph p->in.op = NAME; 154016179Sralph } 154116179Sralph } 154216179Sralph 154316179Sralph 154416179Sralph int edebug = 0; 154516179Sralph ecomp( p ) register NODE *p; { 154616179Sralph # ifndef BUG2 154716179Sralph if( edebug ) fwalk( p, eprint, 0 ); 154816179Sralph # endif 154916179Sralph if( !reached ){ 155016179Sralph werror( "statement not reached" ); 155116179Sralph reached = 1; 155216179Sralph } 155316179Sralph p = optim(p); 155416179Sralph walkf( p, prtdcon ); 155516179Sralph locctr( PROG ); 155616179Sralph ecode( p ); 155716179Sralph tfree(p); 155816179Sralph } 155916179Sralph 156016179Sralph # ifdef STDPRTREE 156116179Sralph # ifndef ONEPASS 156216179Sralph 156316179Sralph prtree(p) register NODE *p; { 156416179Sralph 156516179Sralph register struct symtab *q; 156616179Sralph register ty; 156716179Sralph 156816179Sralph # ifdef MYPRTREE 156916179Sralph MYPRTREE(p); /* local action can be taken here; then return... */ 157016179Sralph #endif 157116179Sralph 157216179Sralph ty = optype(p->in.op); 157316179Sralph 157416179Sralph printf( "%d\t", p->in.op ); 157516179Sralph 157616179Sralph if( ty == LTYPE ) { 157716179Sralph printf( CONFMT, p->tn.lval ); 157816179Sralph printf( "\t" ); 157916179Sralph } 158016179Sralph if( ty != BITYPE ) { 158116179Sralph if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 158216179Sralph else printf( "%d\t", p->tn.rval ); 158316179Sralph } 158416179Sralph 158516179Sralph printf( "%o\t", p->in.type ); 158616179Sralph 158716179Sralph /* handle special cases */ 158816179Sralph 158916179Sralph switch( p->in.op ){ 159016179Sralph 159116179Sralph case NAME: 159216179Sralph case ICON: 159316179Sralph /* print external name */ 159416179Sralph if( p->tn.rval == NONAME ) printf( "\n" ); 159516179Sralph else if( p->tn.rval >= 0 ){ 159616179Sralph q = &stab[p->tn.rval]; 159716179Sralph printf( "%s\n", exname(q->sname) ); 159816179Sralph } 159916179Sralph else { /* label */ 160016179Sralph printf( LABFMT, -p->tn.rval ); 160116179Sralph } 160216179Sralph break; 160316179Sralph 160416179Sralph case STARG: 160516179Sralph case STASG: 160616179Sralph case STCALL: 160716179Sralph case UNARY STCALL: 160816179Sralph /* print out size */ 160916179Sralph /* use lhs size, in order to avoid hassles with the structure `.' operator */ 161016179Sralph 161116179Sralph /* note: p->in.left not a field... */ 161216179Sralph printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 161316179Sralph printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 161416179Sralph break; 161516179Sralph 161616179Sralph default: 161716179Sralph printf( "\n" ); 161816179Sralph } 161916179Sralph 162016179Sralph if( ty != LTYPE ) prtree( p->in.left ); 162116179Sralph if( ty == BITYPE ) prtree( p->in.right ); 162216179Sralph 162316179Sralph } 162416179Sralph 162516179Sralph # else 162616179Sralph 162716179Sralph p2tree(p) register NODE *p; { 162816179Sralph register ty; 162916179Sralph 163016179Sralph # ifdef MYP2TREE 163116179Sralph MYP2TREE(p); /* local action can be taken here; then return... */ 163216179Sralph # endif 163316179Sralph 163416179Sralph ty = optype(p->in.op); 163516179Sralph 163616179Sralph switch( p->in.op ){ 163716179Sralph 163816179Sralph case NAME: 163916179Sralph case ICON: 164016179Sralph #ifndef FLEXNAMES 164116179Sralph if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 164216179Sralph #else 164316179Sralph if( p->tn.rval == NONAME ) p->in.name = ""; 164416179Sralph #endif 164516179Sralph else if( p->tn.rval >= 0 ){ /* copy name from exname */ 164616179Sralph register char *cp; 164716179Sralph register i; 164816179Sralph cp = exname( stab[p->tn.rval].sname ); 164916179Sralph #ifndef FLEXNAMES 165016179Sralph for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 165116179Sralph #else 165216179Sralph p->in.name = tstr(cp); 165316179Sralph #endif 165416179Sralph } 165516179Sralph #ifndef FLEXNAMES 165616179Sralph else sprintf( p->in.name, LABFMT, -p->tn.rval ); 165716179Sralph #else 165816179Sralph else { 165916179Sralph char temp[32]; 166016179Sralph sprintf( temp, LABFMT, -p->tn.rval ); 166116179Sralph p->in.name = tstr(temp); 166216179Sralph } 166316179Sralph #endif 166416179Sralph break; 166516179Sralph 166616179Sralph case STARG: 166716179Sralph case STASG: 166816179Sralph case STCALL: 166916179Sralph case UNARY STCALL: 167016179Sralph /* set up size parameters */ 167116179Sralph p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 167216179Sralph p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 167316179Sralph break; 167416179Sralph 167516179Sralph case REG: 167616179Sralph rbusy( p->tn.rval, p->in.type ); 167716179Sralph default: 167816179Sralph #ifndef FLEXNAMES 167916179Sralph p->in.name[0] = '\0'; 168016179Sralph #else 168116179Sralph p->in.name = ""; 168216179Sralph #endif 168316179Sralph } 168416179Sralph 168516179Sralph p->in.rall = NOPREF; 168616179Sralph 168716179Sralph if( ty != LTYPE ) p2tree( p->in.left ); 168816179Sralph if( ty == BITYPE ) p2tree( p->in.right ); 168916179Sralph } 169016179Sralph 169116179Sralph # endif 169216179Sralph # endif 1693