117749Sralph #ifndef lint 2*24408Smckusick static char *sccsid ="@(#)trees.c 4.9 (Berkeley) 08/22/85"; 317749Sralph #endif 417749Sralph 518396Sralph # include "pass1.h" 616179Sralph 7*24408Smckusick # include <setjmp.h> 8*24408Smckusick 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: 15316179Sralph case ANDAND: 15416179Sralph case OROR: 15516179Sralph case CBRANCH: 15616179Sralph 15716179Sralph ccwarn: 15816179Sralph if( hflag ) werror( "constant in conditional context" ); 15916179Sralph 16016179Sralph case PLUS: 16116179Sralph case MINUS: 16216179Sralph case MUL: 16316179Sralph case DIV: 16416179Sralph case MOD: 16516179Sralph case AND: 16616179Sralph case OR: 16716179Sralph case ER: 16816179Sralph case LS: 16916179Sralph case RS: 17016179Sralph if( conval( l, o, r ) ) { 17116179Sralph r->in.op = FREE; 17216179Sralph return(l); 17316179Sralph } 17416179Sralph break; 17516179Sralph } 17616179Sralph } 177*24408Smckusick else if (opty == BITYPE && 178*24408Smckusick (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) && 179*24408Smckusick (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) { 180*24408Smckusick if (o == PLUS || o == MINUS || o == MUL || o == DIV) { 181*24408Smckusick extern int fpe_count; 182*24408Smckusick extern jmp_buf gotfpe; 18316179Sralph 184*24408Smckusick fpe_count = 0; 185*24408Smckusick if (setjmp(gotfpe)) 186*24408Smckusick goto treatfpe; 18717749Sralph if (l->in.op == ICON) 18817749Sralph l->dpn.dval = l->tn.lval; 189*24408Smckusick else if (l->in.op == FCON) 190*24408Smckusick l->dpn.dval = l->fpn.fval; 19117749Sralph if (r->in.op == ICON) 19217749Sralph r->dpn.dval = r->tn.lval; 193*24408Smckusick else if (r->in.op == FCON) 194*24408Smckusick r->dpn.dval = r->fpn.fval; 19517749Sralph switch (o) { 19617749Sralph 19717749Sralph case PLUS: 19817749Sralph l->dpn.dval += r->dpn.dval; 199*24408Smckusick break; 20017749Sralph 20117749Sralph case MINUS: 20217749Sralph l->dpn.dval -= r->dpn.dval; 203*24408Smckusick break; 20417749Sralph 20517749Sralph case MUL: 20617749Sralph l->dpn.dval *= r->dpn.dval; 207*24408Smckusick break; 20817749Sralph 20917749Sralph case DIV: 21017749Sralph if (r->dpn.dval == 0) 21117749Sralph uerror("division by 0."); 21217749Sralph else 21317749Sralph l->dpn.dval /= r->dpn.dval; 214*24408Smckusick break; 215*24408Smckusick } 216*24408Smckusick treatfpe: 217*24408Smckusick if (fpe_count > 0) { 218*24408Smckusick uerror("floating point exception in constant expression"); 219*24408Smckusick l->dpn.dval = 1.0; /* Fairly harmless */ 220*24408Smckusick } 221*24408Smckusick fpe_count = -1; 222*24408Smckusick l->in.op = DCON; 223*24408Smckusick l->in.type = l->fn.csiz = DOUBLE; 224*24408Smckusick r->in.op = FREE; 225*24408Smckusick return (l); 22616179Sralph } 227*24408Smckusick } 22816179Sralph 229*24408Smckusick /* it's real; we must make a new node */ 23016179Sralph 23116179Sralph p = block( o, l, r, INT, 0, INT ); 23216179Sralph 23316179Sralph actions = opact(p); 23417749Sralph #ifndef BUG1 23517749Sralph if (adebug) 23617749Sralph printact(p, actions); 23717749Sralph #endif 23816179Sralph 23916179Sralph if( actions&LVAL ){ /* check left descendent */ 24016179Sralph if( notlval(p->in.left) ) { 24116179Sralph uerror( "illegal lhs of assignment operator" ); 24216179Sralph } 24316179Sralph } 24416179Sralph 24516179Sralph if( actions & NCVTR ){ 24616179Sralph p->in.left = pconvert( p->in.left ); 24716179Sralph } 24816179Sralph else if( !(actions & NCVT ) ){ 24916179Sralph switch( opty ){ 25016179Sralph 25116179Sralph case BITYPE: 25216179Sralph p->in.right = pconvert( p->in.right ); 25316179Sralph case UTYPE: 25416179Sralph p->in.left = pconvert( p->in.left ); 25516179Sralph 25616179Sralph } 25716179Sralph } 25816179Sralph 25916179Sralph if( (actions&PUN) && (o!=CAST||cflag) ){ 26016179Sralph chkpun(p); 26116179Sralph } 26216179Sralph 26316179Sralph if( actions & (TYPL|TYPR) ){ 26416179Sralph 26516179Sralph q = (actions&TYPL) ? p->in.left : p->in.right; 26616179Sralph 26716179Sralph p->in.type = q->in.type; 26816179Sralph p->fn.cdim = q->fn.cdim; 26916179Sralph p->fn.csiz = q->fn.csiz; 27016179Sralph } 27116179Sralph 27216179Sralph if( actions & CVTL ) p = convert( p, CVTL ); 27316179Sralph if( actions & CVTR ) p = convert( p, CVTR ); 27416179Sralph if( actions & TYMATCH ) p = tymatch(p); 27516179Sralph if( actions & PTMATCH ) p = ptmatch(p); 27616179Sralph 27716179Sralph if( actions & OTHER ){ 27816179Sralph l = p->in.left; 27916179Sralph r = p->in.right; 28016179Sralph 28116179Sralph switch(o){ 28216179Sralph 28316179Sralph case NAME: 28416179Sralph sp = &stab[idname]; 28516179Sralph if( sp->stype == UNDEF ){ 28616179Sralph #ifndef FLEXNAMES 28716179Sralph uerror( "%.8s undefined", sp->sname ); 28816179Sralph #else 28916179Sralph uerror( "%s undefined", sp->sname ); 29016179Sralph #endif 29116179Sralph /* make p look reasonable */ 29216179Sralph p->in.type = p->fn.cdim = p->fn.csiz = INT; 29316179Sralph p->tn.rval = idname; 29416179Sralph p->tn.lval = 0; 29516179Sralph defid( p, SNULL ); 29616179Sralph break; 29716179Sralph } 29816179Sralph p->in.type = sp->stype; 29916179Sralph p->fn.cdim = sp->dimoff; 30016179Sralph p->fn.csiz = sp->sizoff; 30116179Sralph p->tn.lval = 0; 30216179Sralph p->tn.rval = idname; 30316179Sralph /* special case: MOETY is really an ICON... */ 30416179Sralph if( p->in.type == MOETY ){ 30516179Sralph p->tn.rval = NONAME; 30616179Sralph p->tn.lval = sp->offset; 30716179Sralph p->fn.cdim = 0; 30816179Sralph p->in.type = ENUMTY; 30916179Sralph p->in.op = ICON; 31016179Sralph } 31116179Sralph break; 31216179Sralph 31316179Sralph case ICON: 31416179Sralph p->in.type = INT; 31516179Sralph p->fn.cdim = 0; 31616179Sralph p->fn.csiz = INT; 31716179Sralph break; 31816179Sralph 31916179Sralph case STRING: 32016179Sralph p->in.op = NAME; 32116179Sralph p->in.type = CHAR+ARY; 32216179Sralph p->tn.lval = 0; 32316179Sralph p->tn.rval = NOLAB; 32416179Sralph p->fn.cdim = curdim; 32516179Sralph p->fn.csiz = CHAR; 32616179Sralph break; 32716179Sralph 32816179Sralph case FCON: 32916179Sralph p->tn.lval = 0; 33016179Sralph p->tn.rval = 0; 33117749Sralph p->in.type = FLOAT; 33217749Sralph p->fn.cdim = 0; 33317749Sralph p->fn.csiz = FLOAT; 33417749Sralph break; 33517749Sralph 33617749Sralph case DCON: 33717749Sralph p->tn.lval = 0; 33817749Sralph p->tn.rval = 0; 33916179Sralph p->in.type = DOUBLE; 34016179Sralph p->fn.cdim = 0; 34116179Sralph p->fn.csiz = DOUBLE; 34216179Sralph break; 34316179Sralph 34416179Sralph case STREF: 34516179Sralph /* p->x turned into *(p+offset) */ 34616179Sralph /* rhs must be a name; check correctness */ 34716179Sralph 34816179Sralph i = r->tn.rval; 34916179Sralph if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ 35016179Sralph uerror( "member of structure or union required" ); 35116179Sralph }else 35216179Sralph /* if this name is non-unique, find right one */ 35316179Sralph if( stab[i].sflags & SNONUNIQ && 35416179Sralph (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) && 35516179Sralph (l->fn.csiz +1) >= 0 ){ 35616179Sralph /* nonunique name && structure defined */ 35716179Sralph char * memnam, * tabnam; 35816179Sralph register k; 35916179Sralph int j; 36016179Sralph int memi; 36116179Sralph j=dimtab[l->fn.csiz+1]; 36216179Sralph for( ; (memi=dimtab[j]) >= 0; ++j ){ 36316179Sralph tabnam = stab[memi].sname; 36416179Sralph memnam = stab[i].sname; 36516179Sralph # ifndef BUG1 36616179Sralph if( ddebug>1 ){ 36716179Sralph #ifndef FLEXNAMES 36816179Sralph printf("member %.8s==%.8s?\n", 36916179Sralph #else 37016179Sralph printf("member %s==%s?\n", 37116179Sralph #endif 37216179Sralph memnam, tabnam); 37316179Sralph } 37416179Sralph # endif 37516179Sralph if( stab[memi].sflags & SNONUNIQ ){ 37616179Sralph #ifndef FLEXNAMES 37716179Sralph for( k=0; k<NCHNAM; ++k ){ 37816179Sralph if(*memnam++!=*tabnam) 37916179Sralph goto next; 38016179Sralph if(!*tabnam++) break; 38116179Sralph } 38216179Sralph #else 38316179Sralph if (memnam != tabnam) 38416179Sralph goto next; 38516179Sralph #endif 38616179Sralph r->tn.rval = i = memi; 38716179Sralph break; 38816179Sralph } 38916179Sralph next: continue; 39016179Sralph } 39116179Sralph if( memi < 0 ) 39216179Sralph #ifndef FLEXNAMES 39316179Sralph uerror("illegal member use: %.8s", 39416179Sralph #else 39516179Sralph uerror("illegal member use: %s", 39616179Sralph #endif 39716179Sralph stab[i].sname); 39816179Sralph } 39916179Sralph else { 40016179Sralph register j; 40116179Sralph if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){ 40216179Sralph if( stab[i].sflags & SNONUNIQ ){ 40316179Sralph uerror( "nonunique name demands struct/union or struct/union pointer" ); 40416179Sralph } 40516179Sralph else werror( "struct/union or struct/union pointer required" ); 40616179Sralph } 40716179Sralph else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" ); 40816179Sralph else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){ 40916179Sralph #ifndef FLEXNAMES 41016179Sralph werror( "illegal member use: %.8s", stab[i].sname ); 41116179Sralph #else 41216179Sralph werror( "illegal member use: %s", stab[i].sname ); 41316179Sralph #endif 41416179Sralph } 41516179Sralph } 41616179Sralph 41716179Sralph p = stref( p ); 41816179Sralph break; 41916179Sralph 42016179Sralph case UNARY MUL: 42116179Sralph if( l->in.op == UNARY AND ){ 42216179Sralph p->in.op = l->in.op = FREE; 42316179Sralph p = l->in.left; 42416179Sralph } 42516179Sralph if( !ISPTR(l->in.type))uerror("illegal indirection"); 42616179Sralph p->in.type = DECREF(l->in.type); 42716179Sralph p->fn.cdim = l->fn.cdim; 42816179Sralph p->fn.csiz = l->fn.csiz; 42916179Sralph break; 43016179Sralph 43116179Sralph case UNARY AND: 43216179Sralph switch( l->in.op ){ 43316179Sralph 43416179Sralph case UNARY MUL: 43516179Sralph p->in.op = l->in.op = FREE; 43616179Sralph p = l->in.left; 43716179Sralph case NAME: 43816179Sralph p->in.type = INCREF( l->in.type ); 43916179Sralph p->fn.cdim = l->fn.cdim; 44016179Sralph p->fn.csiz = l->fn.csiz; 44116179Sralph break; 44216179Sralph 44316179Sralph case COMOP: 44416179Sralph lr = buildtree( UNARY AND, l->in.right, NIL ); 44516179Sralph p->in.op = l->in.op = FREE; 44616179Sralph p = buildtree( COMOP, l->in.left, lr ); 44716179Sralph break; 44816179Sralph 44916179Sralph case QUEST: 45016179Sralph lr = buildtree( UNARY AND, l->in.right->in.right, NIL ); 45116179Sralph ll = buildtree( UNARY AND, l->in.right->in.left, NIL ); 45216179Sralph p->in.op = l->in.op = l->in.right->in.op = FREE; 45316179Sralph p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) ); 45416179Sralph break; 45516179Sralph 45616179Sralph # ifdef ADDROREG 45716179Sralph case OREG: 45816179Sralph /* OREG was built in clocal() 45916179Sralph * for an auto or formal parameter 46016179Sralph * now its address is being taken 46116179Sralph * local code must unwind it 46216179Sralph * back to PLUS/MINUS REG ICON 46316179Sralph * according to local conventions 46416179Sralph */ 46516179Sralph { 46616179Sralph extern NODE * addroreg(); 46716179Sralph p->in.op = FREE; 46816179Sralph p = addroreg( l ); 46916179Sralph } 47016179Sralph break; 47116179Sralph 47216179Sralph # endif 47316179Sralph default: 47416179Sralph uerror( "unacceptable operand of &" ); 47516179Sralph break; 47616179Sralph } 47716179Sralph break; 47816179Sralph 47916179Sralph case LS: 48016179Sralph case RS: 48116179Sralph case ASG LS: 48216179Sralph case ASG RS: 48316179Sralph if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT) 48416179Sralph p->in.right = makety(p->in.right, INT, 0, INT ); 48516179Sralph break; 48616179Sralph 48716179Sralph case RETURN: 48816179Sralph case ASSIGN: 48916179Sralph case CAST: 49016179Sralph /* structure assignment */ 49116179Sralph /* take the addresses of the two sides; then make an 49216179Sralph /* operator using STASG and 49316179Sralph /* the addresses of left and right */ 49416179Sralph 49516179Sralph { 49616179Sralph register TWORD t; 49716179Sralph register d, s; 49816179Sralph 49916179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" ); 50016179Sralph 50116179Sralph r = buildtree( UNARY AND, r, NIL ); 50216179Sralph t = r->in.type; 50316179Sralph d = r->fn.cdim; 50416179Sralph s = r->fn.csiz; 50516179Sralph 50616179Sralph l = block( STASG, l, r, t, d, s ); 50716179Sralph 50816179Sralph if( o == RETURN ){ 50916179Sralph p->in.op = FREE; 51016179Sralph p = l; 51116179Sralph break; 51216179Sralph } 51316179Sralph 51416179Sralph p->in.op = UNARY MUL; 51516179Sralph p->in.left = l; 51616179Sralph p->in.right = NIL; 51716179Sralph break; 51816179Sralph } 51916179Sralph case COLON: 52016179Sralph /* structure colon */ 52116179Sralph 52216179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" ); 52316179Sralph break; 52416179Sralph 52516179Sralph case CALL: 52617749Sralph p->in.right = r = fixargs( p->in.right ); 52716179Sralph case UNARY CALL: 52816179Sralph if( !ISPTR(l->in.type)) uerror("illegal function"); 52916179Sralph p->in.type = DECREF(l->in.type); 53016179Sralph if( !ISFTN(p->in.type)) uerror("illegal function"); 53116179Sralph p->in.type = DECREF( p->in.type ); 53216179Sralph p->fn.cdim = l->fn.cdim; 53316179Sralph p->fn.csiz = l->fn.csiz; 53416179Sralph if( l->in.op == UNARY AND && l->in.left->in.op == NAME && 53516179Sralph l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME && 53616179Sralph ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){ 53716179Sralph p->in.op += (FORTCALL-CALL); 53816179Sralph } 53916179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 54016179Sralph /* function returning structure */ 54116179Sralph /* make function really return ptr to str., with * */ 54216179Sralph 54316179Sralph p->in.op += STCALL-CALL; 54416179Sralph p->in.type = INCREF( p->in.type ); 54516179Sralph p = buildtree( UNARY MUL, p, NIL ); 54616179Sralph 54716179Sralph } 54816179Sralph break; 54916179Sralph 55016179Sralph default: 55116179Sralph cerror( "other code %d", o ); 55216179Sralph } 55316179Sralph 55416179Sralph } 55516179Sralph 55616179Sralph if( actions & CVTO ) p = oconvert(p); 55716179Sralph p = clocal(p); 55816179Sralph 55916179Sralph # ifndef BUG1 56016179Sralph if( bdebug ) fwalk( p, eprint, 0 ); 56116179Sralph # endif 56216179Sralph 56316179Sralph return(p); 56416179Sralph 56516179Sralph } 56616179Sralph 567*24408Smckusick int fpe_count = -1; 568*24408Smckusick jmp_buf gotfpe; 569*24408Smckusick 570*24408Smckusick fpe() { 571*24408Smckusick if (fpe_count < 0) 572*24408Smckusick cerror("floating point exception"); 573*24408Smckusick ++fpe_count; 574*24408Smckusick longjmp(gotfpe, 1); 575*24408Smckusick } 576*24408Smckusick 57717749Sralph /* 57817749Sralph * Rewrite arguments in a function call. 57917749Sralph * Structure arguments are massaged, single 58017749Sralph * precision floating point constants are 58117749Sralph * cast to double (to eliminate convert code). 58217749Sralph */ 58316179Sralph NODE * 58417749Sralph fixargs( p ) register NODE *p; { 58517749Sralph int o = p->in.op; 58616179Sralph 58717749Sralph if( o == CM ){ 58817749Sralph p->in.left = fixargs( p->in.left ); 58917749Sralph p->in.right = fixargs( p->in.right ); 59016179Sralph return( p ); 59116179Sralph } 59216179Sralph 59316179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 59416179Sralph p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz ); 59516179Sralph p->in.left = buildtree( UNARY AND, p->in.left, NIL ); 59616179Sralph p = clocal(p); 59716179Sralph } 59817749Sralph else if( o == FCON ) 59917749Sralph p = makety(p, DOUBLE, 0, 0); 60016179Sralph return( p ); 60116179Sralph } 60216179Sralph 60316179Sralph chkstr( i, j, type ) TWORD type; { 60416179Sralph /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ 60516179Sralph /* i has been checked to contain a MOS or MOU */ 60616179Sralph /* j is the index in dimtab of the members... */ 60716179Sralph int k, kk; 60816179Sralph 60916179Sralph extern int ddebug; 61016179Sralph 61116179Sralph # ifndef BUG1 61216179Sralph #ifndef FLEXNAMES 61316179Sralph if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j ); 61416179Sralph #else 61516179Sralph if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j ); 61616179Sralph #endif 61716179Sralph # endif 61816179Sralph if( (k = j) < 0 ) uerror( "undefined structure or union" ); 61916179Sralph else { 62016179Sralph for( ; (kk = dimtab[k] ) >= 0; ++k ){ 62116179Sralph if( kk >= SYMTSZ ){ 62216179Sralph cerror( "gummy structure" ); 62316179Sralph return(1); 62416179Sralph } 62516179Sralph if( kk == i ) return( 1 ); 62616179Sralph switch( stab[kk].stype ){ 62716179Sralph 62816179Sralph case STRTY: 62916179Sralph case UNIONTY: 63016179Sralph if( type == STRTY ) continue; /* no recursive looking for strs */ 63116179Sralph if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){ 63216179Sralph if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */ 63316179Sralph werror( 63416179Sralph #ifndef FLEXNAMES 63516179Sralph "illegal member use: perhaps %.8s.%.8s?", 63616179Sralph #else 63716179Sralph "illegal member use: perhaps %s.%s?", 63816179Sralph #endif 63916179Sralph stab[kk].sname, stab[i].sname ); 64016179Sralph return(1); 64116179Sralph } 64216179Sralph } 64316179Sralph } 64416179Sralph } 64516179Sralph return( 0 ); 64616179Sralph } 64716179Sralph 64816179Sralph conval( p, o, q ) register NODE *p, *q; { 64916179Sralph /* apply the op o to the lval part of p; if binary, rhs is val */ 65016179Sralph int i, u; 65116179Sralph CONSZ val; 65216179Sralph 65316179Sralph val = q->tn.lval; 65416179Sralph u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type); 65516179Sralph if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); 65616179Sralph 65716179Sralph if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0); 65816179Sralph if( q->tn.rval != NONAME && o!=PLUS ) return(0); 65916179Sralph if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0); 66016179Sralph 66116179Sralph switch( o ){ 66216179Sralph 66316179Sralph case PLUS: 66416179Sralph p->tn.lval += val; 66516179Sralph if( p->tn.rval == NONAME ){ 66616179Sralph p->tn.rval = q->tn.rval; 66716179Sralph p->in.type = q->in.type; 66816179Sralph } 66916179Sralph break; 67016179Sralph case MINUS: 67116179Sralph p->tn.lval -= val; 67216179Sralph break; 67316179Sralph case MUL: 67416179Sralph p->tn.lval *= val; 67516179Sralph break; 67616179Sralph case DIV: 67716179Sralph if( val == 0 ) uerror( "division by 0" ); 67817749Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val; 67916179Sralph else p->tn.lval /= val; 68016179Sralph break; 68116179Sralph case MOD: 68216179Sralph if( val == 0 ) uerror( "division by 0" ); 68317749Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val; 68416179Sralph else p->tn.lval %= val; 68516179Sralph break; 68616179Sralph case AND: 68716179Sralph p->tn.lval &= val; 68816179Sralph break; 68916179Sralph case OR: 69016179Sralph p->tn.lval |= val; 69116179Sralph break; 69216179Sralph case ER: 69317749Sralph p->tn.lval ^= val; 69416179Sralph break; 69516179Sralph case LS: 69616179Sralph i = val; 69716179Sralph p->tn.lval = p->tn.lval << i; 69816179Sralph break; 69916179Sralph case RS: 70016179Sralph i = val; 70117749Sralph if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i; 70217749Sralph else p->tn.lval = p->tn.lval >> i; 70316179Sralph break; 70416179Sralph 70516179Sralph case UNARY MINUS: 70616179Sralph p->tn.lval = - p->tn.lval; 70716179Sralph break; 70816179Sralph case COMPL: 70916179Sralph p->tn.lval = ~p->tn.lval; 71016179Sralph break; 71116179Sralph case NOT: 71216179Sralph p->tn.lval = !p->tn.lval; 71316179Sralph break; 71416179Sralph case LT: 71516179Sralph p->tn.lval = p->tn.lval < val; 71616179Sralph break; 71716179Sralph case LE: 71816179Sralph p->tn.lval = p->tn.lval <= val; 71916179Sralph break; 72016179Sralph case GT: 72116179Sralph p->tn.lval = p->tn.lval > val; 72216179Sralph break; 72316179Sralph case GE: 72416179Sralph p->tn.lval = p->tn.lval >= val; 72516179Sralph break; 72616179Sralph case ULT: 72716179Sralph p->tn.lval = (p->tn.lval-val)<0; 72816179Sralph break; 72916179Sralph case ULE: 73016179Sralph p->tn.lval = (p->tn.lval-val)<=0; 73116179Sralph break; 73216179Sralph case UGE: 73316179Sralph p->tn.lval = (p->tn.lval-val)>=0; 73416179Sralph break; 73516179Sralph case UGT: 73616179Sralph p->tn.lval = (p->tn.lval-val)>0; 73716179Sralph break; 73816179Sralph case EQ: 73916179Sralph p->tn.lval = p->tn.lval == val; 74016179Sralph break; 74116179Sralph case NE: 74216179Sralph p->tn.lval = p->tn.lval != val; 74316179Sralph break; 74416179Sralph default: 74516179Sralph return(0); 74616179Sralph } 74716179Sralph return(1); 74816179Sralph } 74916179Sralph 75016179Sralph chkpun(p) register NODE *p; { 75116179Sralph 75216179Sralph /* checks p for the existance of a pun */ 75316179Sralph 75416179Sralph /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ 75516179Sralph 75616179Sralph /* one case is when enumerations are used: this applies only to lint */ 75716179Sralph /* in the other case, one operand is a pointer, the other integer type */ 75816179Sralph /* we check that this integer is in fact a constant zero... */ 75916179Sralph 76016179Sralph /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ 76116179Sralph /* this falls out, because the LHS is never 0 */ 76216179Sralph 76316179Sralph register NODE *q; 76416179Sralph register t1, t2; 76516179Sralph register d1, d2; 76616179Sralph 76716179Sralph t1 = p->in.left->in.type; 76816179Sralph t2 = p->in.right->in.type; 76916179Sralph 77016179Sralph if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ 77116179Sralph if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) { 77216179Sralph uerror( "illegal comparison of enums" ); 77316179Sralph return; 77416179Sralph } 77516179Sralph if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return; 77616179Sralph werror( "enumeration type clash, operator %s", opst[p->in.op] ); 77716179Sralph return; 77816179Sralph } 77916179Sralph 78016179Sralph if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; 78116179Sralph else q = p->in.left; 78216179Sralph 78316179Sralph if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ 78416179Sralph if( q->in.op != ICON || q->tn.lval != 0 ){ 78516179Sralph werror( "illegal combination of pointer and integer, op %s", 78616179Sralph opst[p->in.op] ); 78716179Sralph } 78816179Sralph } 78916179Sralph else { 79016179Sralph d1 = p->in.left->fn.cdim; 79116179Sralph d2 = p->in.right->fn.cdim; 79216179Sralph for( ;; ){ 79316179Sralph if( t1 == t2 ) {; 79416179Sralph if( p->in.left->fn.csiz != p->in.right->fn.csiz ) { 79516179Sralph werror( "illegal structure pointer combination" ); 79616179Sralph } 79716179Sralph return; 79816179Sralph } 79916179Sralph if( ISARY(t1) || ISPTR(t1) ){ 80016179Sralph if( !ISARY(t2) && !ISPTR(t2) ) break; 80116179Sralph if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ 80216179Sralph werror( "illegal array size combination" ); 80316179Sralph return; 80416179Sralph } 80516179Sralph if( ISARY(t1) ) ++d1; 80616179Sralph if( ISARY(t2) ) ++d2; 80716179Sralph } 80816179Sralph else break; 80916179Sralph t1 = DECREF(t1); 81016179Sralph t2 = DECREF(t2); 81116179Sralph } 81216179Sralph werror( "illegal pointer combination" ); 81316179Sralph } 81416179Sralph 81516179Sralph } 81616179Sralph 81716179Sralph NODE * 81816179Sralph stref( p ) register NODE *p; { 81916179Sralph 82016179Sralph TWORD t; 82116179Sralph int d, s, dsc, align; 82216179Sralph OFFSZ off; 82316179Sralph register struct symtab *q; 82416179Sralph 82516179Sralph /* make p->x */ 82616179Sralph /* this is also used to reference automatic variables */ 82716179Sralph 82816179Sralph q = &stab[p->in.right->tn.rval]; 82916179Sralph p->in.right->in.op = FREE; 83016179Sralph p->in.op = FREE; 83116179Sralph p = pconvert( p->in.left ); 83216179Sralph 83316179Sralph /* make p look like ptr to x */ 83416179Sralph 83516179Sralph if( !ISPTR(p->in.type)){ 83616179Sralph p->in.type = PTR+UNIONTY; 83716179Sralph } 83816179Sralph 83916179Sralph t = INCREF( q->stype ); 84016179Sralph d = q->dimoff; 84116179Sralph s = q->sizoff; 84216179Sralph 84316179Sralph p = makety( p, t, d, s ); 84416179Sralph 84516179Sralph /* compute the offset to be added */ 84616179Sralph 84716179Sralph off = q->offset; 84816179Sralph dsc = q->sclass; 84916179Sralph 85016179Sralph if( dsc & FIELD ) { /* normalize offset */ 85116179Sralph align = ALINT; 85216179Sralph s = INT; 85316179Sralph off = (off/align)*align; 85416179Sralph } 85516179Sralph if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); 85616179Sralph 85716179Sralph p = buildtree( UNARY MUL, p, NIL ); 85816179Sralph 85916179Sralph /* if field, build field info */ 86016179Sralph 86116179Sralph if( dsc & FIELD ){ 86216179Sralph p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); 86316179Sralph p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); 86416179Sralph } 86516179Sralph 86616179Sralph return( clocal(p) ); 86716179Sralph } 86816179Sralph 86916179Sralph notlval(p) register NODE *p; { 87016179Sralph 87116179Sralph /* return 0 if p an lvalue, 1 otherwise */ 87216179Sralph 87316179Sralph again: 87416179Sralph 87516179Sralph switch( p->in.op ){ 87616179Sralph 87716179Sralph case FLD: 87816179Sralph p = p->in.left; 87916179Sralph goto again; 88016179Sralph 88116179Sralph case UNARY MUL: 88216179Sralph /* fix the &(a=b) bug, given that a and b are structures */ 88316179Sralph if( p->in.left->in.op == STASG ) return( 1 ); 88416179Sralph /* and the f().a bug, given that f returns a structure */ 88516179Sralph if( p->in.left->in.op == UNARY STCALL || 88616179Sralph p->in.left->in.op == STCALL ) return( 1 ); 88716179Sralph case NAME: 88816179Sralph case OREG: 88916179Sralph if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); 89016179Sralph case REG: 89116179Sralph return(0); 89216179Sralph 89316179Sralph default: 89416179Sralph return(1); 89516179Sralph 89616179Sralph } 89716179Sralph 89816179Sralph } 89916179Sralph 90016179Sralph NODE * 90116179Sralph bcon( i ){ /* make a constant node with value i */ 90216179Sralph register NODE *p; 90316179Sralph 90416179Sralph p = block( ICON, NIL, NIL, INT, 0, INT ); 90516179Sralph p->tn.lval = i; 90616179Sralph p->tn.rval = NONAME; 90716179Sralph return( clocal(p) ); 90816179Sralph } 90916179Sralph 91016179Sralph NODE * 91116179Sralph bpsize(p) register NODE *p; { 91216179Sralph return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); 91316179Sralph } 91416179Sralph 91516179Sralph OFFSZ 91616179Sralph psize( p ) NODE *p; { 91716179Sralph /* p is a node of type pointer; psize returns the 91816179Sralph size of the thing pointed to */ 91916179Sralph 92016179Sralph if( !ISPTR(p->in.type) ){ 92116179Sralph uerror( "pointer required"); 92216179Sralph return( SZINT ); 92316179Sralph } 92416179Sralph /* note: no pointers to fields */ 92516179Sralph return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); 92616179Sralph } 92716179Sralph 92816179Sralph NODE * 92916179Sralph convert( p, f ) register NODE *p; { 93016179Sralph /* convert an operand of p 93116179Sralph f is either CVTL or CVTR 93216179Sralph operand has type int, and is converted by the size of the other side 93316179Sralph */ 93416179Sralph 93516179Sralph register NODE *q, *r; 93616179Sralph 93716179Sralph q = (f==CVTL)?p->in.left:p->in.right; 93816179Sralph 93916179Sralph r = block( PMCONV, 94016179Sralph q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); 94116179Sralph r = clocal(r); 94216179Sralph if( f == CVTL ) 94316179Sralph p->in.left = r; 94416179Sralph else 94516179Sralph p->in.right = r; 94616179Sralph return(p); 94716179Sralph 94816179Sralph } 94916179Sralph 95016179Sralph econvert( p ) register NODE *p; { 95116179Sralph 95216179Sralph /* change enums to ints, or appropriate types */ 95316179Sralph 95416179Sralph register TWORD ty; 95516179Sralph 95616179Sralph if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 95716179Sralph if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 95816179Sralph else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 95916179Sralph else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 96016179Sralph else ty = LONG; 96116179Sralph ty = ctype( ty ); 96216179Sralph p->fn.csiz = ty; 96316179Sralph MODTYPE(p->in.type,ty); 96416179Sralph if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 96516179Sralph } 96616179Sralph } 96716179Sralph 96816179Sralph NODE * 96916179Sralph pconvert( p ) register NODE *p; { 97016179Sralph 97116179Sralph /* if p should be changed into a pointer, do so */ 97216179Sralph 97316179Sralph if( ISARY( p->in.type) ){ 97416179Sralph p->in.type = DECREF( p->in.type ); 97516179Sralph ++p->fn.cdim; 97616179Sralph return( buildtree( UNARY AND, p, NIL ) ); 97716179Sralph } 97816179Sralph if( ISFTN( p->in.type) ) 97916179Sralph return( buildtree( UNARY AND, p, NIL ) ); 98016179Sralph 98116179Sralph return( p ); 98216179Sralph } 98316179Sralph 98416179Sralph NODE * 98516179Sralph oconvert(p) register NODE *p; { 98616179Sralph /* convert the result itself: used for pointer and unsigned */ 98716179Sralph 98816179Sralph switch(p->in.op) { 98916179Sralph 99016179Sralph case LE: 99116179Sralph case LT: 99216179Sralph case GE: 99316179Sralph case GT: 99416179Sralph if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 99516179Sralph case EQ: 99616179Sralph case NE: 99716179Sralph return( p ); 99816179Sralph 99916179Sralph case MINUS: 100016179Sralph return( clocal( block( PVCONV, 100116179Sralph p, bpsize(p->in.left), INT, 0, INT ) ) ); 100216179Sralph } 100316179Sralph 100416179Sralph cerror( "illegal oconvert: %d", p->in.op ); 100516179Sralph 100616179Sralph return(p); 100716179Sralph } 100816179Sralph 100916179Sralph NODE * 101016179Sralph ptmatch(p) register NODE *p; { 101116179Sralph 101216179Sralph /* makes the operands of p agree; they are 101316179Sralph either pointers or integers, by this time */ 101416179Sralph /* with MINUS, the sizes must be the same */ 101516179Sralph /* with COLON, the types must be the same */ 101616179Sralph 101716179Sralph TWORD t1, t2, t; 101816179Sralph int o, d2, d, s2, s; 101916179Sralph 102016179Sralph o = p->in.op; 102116179Sralph t = t1 = p->in.left->in.type; 102216179Sralph t2 = p->in.right->in.type; 102316179Sralph d = p->in.left->fn.cdim; 102416179Sralph d2 = p->in.right->fn.cdim; 102516179Sralph s = p->in.left->fn.csiz; 102616179Sralph s2 = p->in.right->fn.csiz; 102716179Sralph 102816179Sralph switch( o ){ 102916179Sralph 103016179Sralph case ASSIGN: 103116179Sralph case RETURN: 103216179Sralph case CAST: 103316179Sralph { break; } 103416179Sralph 103516179Sralph case MINUS: 103616179Sralph { if( psize(p->in.left) != psize(p->in.right) ){ 103716179Sralph uerror( "illegal pointer subtraction"); 103816179Sralph } 103916179Sralph break; 104016179Sralph } 104116179Sralph case COLON: 104216179Sralph { if( t1 != t2 ) uerror( "illegal types in :"); 104316179Sralph break; 104416179Sralph } 104516179Sralph default: /* must work harder: relationals or comparisons */ 104616179Sralph 104716179Sralph if( !ISPTR(t1) ){ 104816179Sralph t = t2; 104916179Sralph d = d2; 105016179Sralph s = s2; 105116179Sralph break; 105216179Sralph } 105316179Sralph if( !ISPTR(t2) ){ 105416179Sralph break; 105516179Sralph } 105616179Sralph 105716179Sralph /* both are pointers */ 105816179Sralph if( talign(t2,s2) < talign(t,s) ){ 105916179Sralph t = t2; 106016179Sralph s = s2; 106116179Sralph } 106216179Sralph break; 106316179Sralph } 106416179Sralph 106516179Sralph p->in.left = makety( p->in.left, t, d, s ); 106616179Sralph p->in.right = makety( p->in.right, t, d, s ); 106716179Sralph if( o!=MINUS && !logop(o) ){ 106816179Sralph 106916179Sralph p->in.type = t; 107016179Sralph p->fn.cdim = d; 107116179Sralph p->fn.csiz = s; 107216179Sralph } 107316179Sralph 107416179Sralph return(clocal(p)); 107516179Sralph } 107616179Sralph 107716179Sralph int tdebug = 0; 107816179Sralph 107916179Sralph NODE * 108016179Sralph tymatch(p) register NODE *p; { 108116179Sralph 108216179Sralph /* satisfy the types of various arithmetic binary ops */ 108316179Sralph 108416179Sralph /* rules are: 108516179Sralph if assignment, op, type of LHS 108616179Sralph if any float or doubles, make double 108716179Sralph if any longs, make long 108816179Sralph otherwise, make int 108916179Sralph if either operand is unsigned, the result is... 109016179Sralph */ 109116179Sralph 109216179Sralph register TWORD t1, t2, t, tu; 109316179Sralph register o, u; 109416179Sralph 109516179Sralph o = p->in.op; 109616179Sralph 109716179Sralph t1 = p->in.left->in.type; 109816179Sralph t2 = p->in.right->in.type; 109916179Sralph if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 110016179Sralph uerror("void type illegal in expression"); 110116179Sralph 110216179Sralph u = 0; 110316179Sralph if( ISUNSIGNED(t1) ){ 110416179Sralph u = 1; 110516179Sralph t1 = DEUNSIGN(t1); 110616179Sralph } 110716179Sralph if( ISUNSIGNED(t2) ){ 110816179Sralph u = 1; 110916179Sralph t2 = DEUNSIGN(t2); 111016179Sralph } 111116179Sralph 111216179Sralph if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 111316179Sralph if( t2 == CHAR || t2 == SHORT ) t2 = INT; 111416179Sralph 111517749Sralph #ifdef SPRECC 111617749Sralph if( t1 == DOUBLE || t2 == DOUBLE ) 111717749Sralph t = DOUBLE; 111817749Sralph else if( t1 == FLOAT || t2 == FLOAT ) 111917749Sralph t = FLOAT; 112017749Sralph #else 112117749Sralph if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT) 112217749Sralph t = DOUBLE; 112317749Sralph #endif 112416179Sralph else if( t1==LONG || t2==LONG ) t = LONG; 112516179Sralph else t = INT; 112616179Sralph 112716179Sralph if( asgop(o) ){ 112816179Sralph tu = p->in.left->in.type; 112916179Sralph t = t1; 113016179Sralph } 113116179Sralph else { 113216179Sralph tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 113316179Sralph } 113416179Sralph 113516179Sralph /* because expressions have values that are at least as wide 113616179Sralph as INT or UNSIGNED, the only conversions needed 113716179Sralph are those involving FLOAT/DOUBLE, and those 113816179Sralph from LONG to INT and ULONG to UNSIGNED */ 113916179Sralph 114016179Sralph if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu ); 114116179Sralph 114216179Sralph if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); 114316179Sralph 114416179Sralph if( asgop(o) ){ 114516179Sralph p->in.type = p->in.left->in.type; 114616179Sralph p->fn.cdim = p->in.left->fn.cdim; 114716179Sralph p->fn.csiz = p->in.left->fn.csiz; 114816179Sralph } 114916179Sralph else if( !logop(o) ){ 115016179Sralph p->in.type = tu; 115116179Sralph p->fn.cdim = 0; 115216179Sralph p->fn.csiz = t; 115316179Sralph } 115416179Sralph 115516179Sralph # ifndef BUG1 115616179Sralph if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 115716179Sralph # endif 115816179Sralph 115916179Sralph return(p); 116016179Sralph } 116116179Sralph 116216179Sralph NODE * 116316179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; { 116416179Sralph /* make p into type t by inserting a conversion */ 116516179Sralph 116616179Sralph if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 116716179Sralph if( t == p->in.type ){ 116816179Sralph p->fn.cdim = d; 116916179Sralph p->fn.csiz = s; 117016179Sralph return( p ); 117116179Sralph } 117216179Sralph 117316179Sralph if( t & TMASK ){ 117416179Sralph /* non-simple type */ 117517228Sralph return( block( PCONV, p, NIL, t, d, s ) ); 117616179Sralph } 117716179Sralph 117816179Sralph if( p->in.op == ICON ){ 117917749Sralph if (t == DOUBLE) { 118017749Sralph p->in.op = DCON; 118117749Sralph if (ISUNSIGNED(p->in.type)) 118217749Sralph p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval; 118317749Sralph else 118417749Sralph p->dpn.dval = p->tn.lval; 118517749Sralph p->in.type = p->fn.csiz = t; 118617749Sralph return (clocal(p)); 118717749Sralph } 118817749Sralph if (t == FLOAT) { 118916179Sralph p->in.op = FCON; 119016179Sralph if( ISUNSIGNED(p->in.type) ){ 119117749Sralph p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval; 119216179Sralph } 119316179Sralph else { 119417749Sralph p->fpn.fval = p->tn.lval; 119516179Sralph } 119616179Sralph 119716179Sralph p->in.type = p->fn.csiz = t; 119816179Sralph return( clocal(p) ); 119916179Sralph } 120016179Sralph } 120117749Sralph else if (p->in.op == FCON && t == DOUBLE) { 120217749Sralph double db; 120316179Sralph 120417749Sralph p->in.op = DCON; 120517749Sralph db = p->fpn.fval; 120617749Sralph p->dpn.dval = db; 120717749Sralph p->in.type = p->fn.csiz = t; 120817749Sralph return (clocal(p)); 120917749Sralph } else if (p->in.op == DCON && t == FLOAT) { 121017749Sralph float fl; 121117749Sralph 121217749Sralph p->in.op = FCON; 121317749Sralph fl = p->dpn.dval; 121417749Sralph #ifdef notdef 121517749Sralph if (fl != p->dpn.dval) 121617749Sralph werror("float conversion loses precision"); 121717749Sralph #endif 121817749Sralph p->fpn.fval = fl; 121917749Sralph p->in.type = p->fn.csiz = t; 122017749Sralph return (clocal(p)); 122117749Sralph } 122217749Sralph 122317049Sralph return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); 122416179Sralph 122516179Sralph } 122616179Sralph 122716179Sralph NODE * 122816179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 122916179Sralph 123016179Sralph register NODE *p; 123116179Sralph 123216179Sralph p = talloc(); 123316179Sralph p->in.op = o; 123416179Sralph p->in.left = l; 123516179Sralph p->in.right = r; 123616179Sralph p->in.type = t; 123716179Sralph p->fn.cdim = d; 123816179Sralph p->fn.csiz = s; 123916179Sralph return(p); 124016179Sralph } 124116179Sralph 124216179Sralph icons(p) register NODE *p; { 124316179Sralph /* if p is an integer constant, return its value */ 124416179Sralph int val; 124516179Sralph 124616179Sralph if( p->in.op != ICON ){ 124716179Sralph uerror( "constant expected"); 124816179Sralph val = 1; 124916179Sralph } 125016179Sralph else { 125116179Sralph val = p->tn.lval; 125216179Sralph if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 125316179Sralph } 125416179Sralph tfree( p ); 125516179Sralph return(val); 125616179Sralph } 125716179Sralph 125816179Sralph /* the intent of this table is to examine the 125916179Sralph operators, and to check them for 126016179Sralph correctness. 126116179Sralph 126216179Sralph The table is searched for the op and the 126316179Sralph modified type (where this is one of the 126416179Sralph types INT (includes char and short), LONG, 126516179Sralph DOUBLE (includes FLOAT), and POINTER 126616179Sralph 126716179Sralph The default action is to make the node type integer 126816179Sralph 126916179Sralph The actions taken include: 127016179Sralph PUN check for puns 127116179Sralph CVTL convert the left operand 127216179Sralph CVTR convert the right operand 127316179Sralph TYPL the type is determined by the left operand 127416179Sralph TYPR the type is determined by the right operand 127516179Sralph TYMATCH force type of left and right to match, by inserting conversions 127616179Sralph PTMATCH like TYMATCH, but for pointers 127716179Sralph LVAL left operand must be lval 127816179Sralph CVTO convert the op 127916179Sralph NCVT do not convert the operands 128016179Sralph OTHER handled by code 128116179Sralph NCVTR convert the left operand, not the right... 128216179Sralph 128316179Sralph */ 128416179Sralph 128516179Sralph # define MINT 01 /* integer */ 128616179Sralph # define MDBI 02 /* integer or double */ 128716179Sralph # define MSTR 04 /* structure */ 128816179Sralph # define MPTR 010 /* pointer */ 128916179Sralph # define MPTI 020 /* pointer or integer */ 129016179Sralph # define MENU 040 /* enumeration variable or member */ 1291*24408Smckusick # define MVOID 0100000 /* void type */ 129216179Sralph 129316179Sralph opact( p ) NODE *p; { 129416179Sralph 129516179Sralph register mt12, mt1, mt2, o; 129616179Sralph 1297*24408Smckusick mt1 = mt2 = mt12 = 0; 129816179Sralph 129916179Sralph switch( optype(o=p->in.op) ){ 130016179Sralph 130116179Sralph case BITYPE: 1302*24408Smckusick mt2 = moditype( p->in.right->in.type ); 130316179Sralph case UTYPE: 1304*24408Smckusick mt1 = moditype( p->in.left->in.type ); 1305*24408Smckusick break; 130616179Sralph 130716179Sralph } 130816179Sralph 1309*24408Smckusick if( ((mt1 | mt2) & MVOID) && 1310*24408Smckusick o != COMOP && 1311*24408Smckusick !(o == CAST && (mt1 & MVOID)) ){ 1312*24408Smckusick /* if lhs of RETURN is void, grammar will complain */ 1313*24408Smckusick if( o != RETURN ) 1314*24408Smckusick uerror( "value of void expression used" ); 1315*24408Smckusick return( NCVT ); 1316*24408Smckusick } 1317*24408Smckusick mt1 &= ~MVOID; 1318*24408Smckusick mt2 &= ~MVOID; 1319*24408Smckusick mt12 = mt1 & mt2; 1320*24408Smckusick 132116179Sralph switch( o ){ 132216179Sralph 132316179Sralph case NAME : 132416179Sralph case STRING : 132516179Sralph case ICON : 132616179Sralph case FCON : 132717749Sralph case DCON : 132816179Sralph case CALL : 132916179Sralph case UNARY CALL: 133016179Sralph case UNARY MUL: 133116179Sralph { return( OTHER ); } 133216179Sralph case UNARY MINUS: 133316179Sralph if( mt1 & MDBI ) return( TYPL ); 133416179Sralph break; 133516179Sralph 133616179Sralph case COMPL: 133716179Sralph if( mt1 & MINT ) return( TYPL ); 133816179Sralph break; 133916179Sralph 134016179Sralph case UNARY AND: 134116179Sralph { return( NCVT+OTHER ); } 134216179Sralph case INIT: 134316179Sralph case CM: 134416180Sralph return( 0 ); 134516180Sralph 134616179Sralph case NOT: 134716179Sralph case CBRANCH: 134816180Sralph if( mt1 & MSTR ) break; 134916180Sralph return( 0 ); 135016180Sralph 135116179Sralph case ANDAND: 135216179Sralph case OROR: 135316180Sralph if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 135416179Sralph return( 0 ); 135516179Sralph 135616179Sralph case MUL: 135716179Sralph case DIV: 135816179Sralph if( mt12 & MDBI ) return( TYMATCH ); 135916179Sralph break; 136016179Sralph 136116179Sralph case MOD: 136216179Sralph case AND: 136316179Sralph case OR: 136416179Sralph case ER: 136516179Sralph if( mt12 & MINT ) return( TYMATCH ); 136616179Sralph break; 136716179Sralph 136816179Sralph case LS: 136916179Sralph case RS: 137016179Sralph if( mt12 & MINT ) return( TYMATCH+OTHER ); 137116179Sralph break; 137216179Sralph 137316179Sralph case EQ: 137416179Sralph case NE: 137516179Sralph case LT: 137616179Sralph case LE: 137716179Sralph case GT: 137816179Sralph case GE: 137916179Sralph if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 138016179Sralph if( mt12 & MDBI ) return( TYMATCH+CVTO ); 138116179Sralph else if( mt12 & MPTR ) return( PTMATCH+PUN ); 138216179Sralph else if( mt12 & MPTI ) return( PTMATCH+PUN ); 138316179Sralph else break; 138416179Sralph 138516179Sralph case QUEST: 138616179Sralph case COMOP: 138716179Sralph if( mt2&MENU ) return( TYPR+NCVTR ); 138816179Sralph return( TYPR ); 138916179Sralph 139016179Sralph case STREF: 139116179Sralph return( NCVTR+OTHER ); 139216179Sralph 139316179Sralph case FORCE: 139416179Sralph return( TYPL ); 139516179Sralph 139616179Sralph case COLON: 139716179Sralph if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 139816179Sralph else if( mt12 & MDBI ) return( TYMATCH ); 139916179Sralph else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 140016179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 140116179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 140216179Sralph else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 140316179Sralph break; 140416179Sralph 140516179Sralph case ASSIGN: 140616179Sralph case RETURN: 140716179Sralph if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 140816179Sralph case CAST: 140916179Sralph if(o==CAST && mt1==0)return(TYPL+TYMATCH); 141016179Sralph if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 141116179Sralph else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 141218436Smckusick else if( mt2 == 0 && 141318436Smckusick ( p->in.right->in.op == CALL || 141418436Smckusick p->in.right->in.op == UNARY CALL)) break; 141516179Sralph else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 141616179Sralph else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 141716179Sralph break; 141816179Sralph 141916179Sralph case ASG LS: 142016179Sralph case ASG RS: 142116179Sralph if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 142216179Sralph break; 142316179Sralph 142416179Sralph case ASG MUL: 142516179Sralph case ASG DIV: 142616179Sralph if( mt12 & MDBI ) return( LVAL+TYMATCH ); 142716179Sralph break; 142816179Sralph 142916179Sralph case ASG MOD: 143016179Sralph case ASG AND: 143116179Sralph case ASG OR: 143216179Sralph case ASG ER: 143316179Sralph if( mt12 & MINT ) return( LVAL+TYMATCH ); 143416179Sralph break; 143516179Sralph 143616179Sralph case ASG PLUS: 143716179Sralph case ASG MINUS: 143816179Sralph case INCR: 143916179Sralph case DECR: 144016179Sralph if( mt12 & MDBI ) return( TYMATCH+LVAL ); 144116179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 144216179Sralph break; 144316179Sralph 144416179Sralph case MINUS: 144516179Sralph if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 144616179Sralph if( mt2 & MPTR ) break; 144716179Sralph case PLUS: 144816179Sralph if( mt12 & MDBI ) return( TYMATCH ); 144916179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 145016179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 145116179Sralph 145216179Sralph } 1453*24408Smckusick if( mt12 == MSTR ) 1454*24408Smckusick uerror( "%s is not a permitted struct/union operation", opst[o] ); 1455*24408Smckusick else 1456*24408Smckusick uerror( "operands of %s have incompatible types", opst[o] ); 145716179Sralph return( NCVT ); 145816179Sralph } 145916179Sralph 146016179Sralph moditype( ty ) TWORD ty; { 146116179Sralph 146216179Sralph switch( ty ){ 146316179Sralph 146416179Sralph case TVOID: 146517206Sralph return( MPTR ); 146616179Sralph case UNDEF: 1467*24408Smckusick return( MVOID ); 146816179Sralph case ENUMTY: 146916179Sralph case MOETY: 147016179Sralph return( MENU ); 147116179Sralph 147216179Sralph case STRTY: 147316179Sralph case UNIONTY: 147416179Sralph return( MSTR ); 147516179Sralph 147616179Sralph case CHAR: 147716179Sralph case SHORT: 147816179Sralph case UCHAR: 147916179Sralph case USHORT: 148016179Sralph return( MINT|MPTI|MDBI ); 148116179Sralph case UNSIGNED: 148216179Sralph case ULONG: 148316179Sralph case INT: 148416179Sralph case LONG: 148516179Sralph return( MINT|MDBI|MPTI ); 148616179Sralph case FLOAT: 148716179Sralph case DOUBLE: 148816179Sralph return( MDBI ); 148916179Sralph default: 149016179Sralph return( MPTR|MPTI ); 149116179Sralph 149216179Sralph } 149316179Sralph } 149416179Sralph 149516179Sralph NODE * 149616179Sralph doszof( p ) register NODE *p; { 149716179Sralph /* do sizeof p */ 149816179Sralph int i; 149916179Sralph 150016179Sralph /* whatever is the meaning of this if it is a bitfield? */ 150116179Sralph i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 150216179Sralph 150316179Sralph tfree(p); 150416179Sralph if( i <= 0 ) werror( "sizeof returns 0" ); 150516179Sralph return( bcon( i ) ); 150616179Sralph } 150716179Sralph 150816179Sralph # ifndef BUG2 150916179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; { 151016179Sralph register ty; 151116179Sralph 151216179Sralph *a = *b = down+1; 151316179Sralph while( down > 1 ){ 151416179Sralph printf( "\t" ); 151516179Sralph down -= 2; 151616179Sralph } 151716179Sralph if( down ) printf( " " ); 151816179Sralph 151916179Sralph ty = optype( p->in.op ); 152016179Sralph 152116179Sralph printf("%o) %s, ", p, opst[p->in.op] ); 152216179Sralph if( ty == LTYPE ){ 152316179Sralph printf( CONFMT, p->tn.lval ); 152416179Sralph printf( ", %d, ", p->tn.rval ); 152516179Sralph } 152616179Sralph tprint( p->in.type ); 152716179Sralph printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 152816179Sralph } 152916179Sralph # endif 153016179Sralph 153116179Sralph prtdcon( p ) register NODE *p; { 153217749Sralph int o = p->in.op, i; 153316179Sralph 153417749Sralph if( o == DCON || o == FCON ){ 153516179Sralph locctr( DATA ); 153617749Sralph defalign( o == DCON ? ALDOUBLE : ALFLOAT ); 153716179Sralph deflab( i = getlab() ); 153817749Sralph if( o == FCON ) 153917749Sralph fincode( p->fpn.fval, SZFLOAT ); 154017749Sralph else 154117749Sralph fincode( p->dpn.dval, SZDOUBLE ); 154216179Sralph p->tn.lval = 0; 154316179Sralph p->tn.rval = -i; 154417749Sralph p->in.type = (o == DCON ? DOUBLE : FLOAT); 154516179Sralph p->in.op = NAME; 154616179Sralph } 154716179Sralph } 154816179Sralph 154916179Sralph 155016179Sralph int edebug = 0; 155116179Sralph ecomp( p ) register NODE *p; { 155216179Sralph # ifndef BUG2 155316179Sralph if( edebug ) fwalk( p, eprint, 0 ); 155416179Sralph # endif 155516179Sralph if( !reached ){ 155616179Sralph werror( "statement not reached" ); 155716179Sralph reached = 1; 155816179Sralph } 155916179Sralph p = optim(p); 156016179Sralph walkf( p, prtdcon ); 156116179Sralph locctr( PROG ); 156216179Sralph ecode( p ); 156316179Sralph tfree(p); 156416179Sralph } 156516179Sralph 156616179Sralph # ifdef STDPRTREE 156716179Sralph # ifndef ONEPASS 156816179Sralph 156916179Sralph prtree(p) register NODE *p; { 157016179Sralph 157116179Sralph register struct symtab *q; 157216179Sralph register ty; 157316179Sralph 157416179Sralph # ifdef MYPRTREE 157516179Sralph MYPRTREE(p); /* local action can be taken here; then return... */ 157616179Sralph #endif 157716179Sralph 157816179Sralph ty = optype(p->in.op); 157916179Sralph 158016179Sralph printf( "%d\t", p->in.op ); 158116179Sralph 158216179Sralph if( ty == LTYPE ) { 158316179Sralph printf( CONFMT, p->tn.lval ); 158416179Sralph printf( "\t" ); 158516179Sralph } 158616179Sralph if( ty != BITYPE ) { 158716179Sralph if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 158816179Sralph else printf( "%d\t", p->tn.rval ); 158916179Sralph } 159016179Sralph 159116179Sralph printf( "%o\t", p->in.type ); 159216179Sralph 159316179Sralph /* handle special cases */ 159416179Sralph 159516179Sralph switch( p->in.op ){ 159616179Sralph 159716179Sralph case NAME: 159816179Sralph case ICON: 159916179Sralph /* print external name */ 160016179Sralph if( p->tn.rval == NONAME ) printf( "\n" ); 160116179Sralph else if( p->tn.rval >= 0 ){ 160216179Sralph q = &stab[p->tn.rval]; 160316179Sralph printf( "%s\n", exname(q->sname) ); 160416179Sralph } 160516179Sralph else { /* label */ 160616179Sralph printf( LABFMT, -p->tn.rval ); 160716179Sralph } 160816179Sralph break; 160916179Sralph 161016179Sralph case STARG: 161116179Sralph case STASG: 161216179Sralph case STCALL: 161316179Sralph case UNARY STCALL: 161416179Sralph /* print out size */ 161516179Sralph /* use lhs size, in order to avoid hassles with the structure `.' operator */ 161616179Sralph 161716179Sralph /* note: p->in.left not a field... */ 161816179Sralph printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 161916179Sralph printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 162016179Sralph break; 162116179Sralph 162216179Sralph default: 162316179Sralph printf( "\n" ); 162416179Sralph } 162516179Sralph 162616179Sralph if( ty != LTYPE ) prtree( p->in.left ); 162716179Sralph if( ty == BITYPE ) prtree( p->in.right ); 162816179Sralph 162916179Sralph } 163016179Sralph 163116179Sralph # else 163216179Sralph 163316179Sralph p2tree(p) register NODE *p; { 163416179Sralph register ty; 163516179Sralph 163616179Sralph # ifdef MYP2TREE 163716179Sralph MYP2TREE(p); /* local action can be taken here; then return... */ 163816179Sralph # endif 163916179Sralph 164016179Sralph ty = optype(p->in.op); 164116179Sralph 164216179Sralph switch( p->in.op ){ 164316179Sralph 164416179Sralph case NAME: 164516179Sralph case ICON: 164616179Sralph #ifndef FLEXNAMES 164716179Sralph if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 164816179Sralph #else 164916179Sralph if( p->tn.rval == NONAME ) p->in.name = ""; 165016179Sralph #endif 165116179Sralph else if( p->tn.rval >= 0 ){ /* copy name from exname */ 165216179Sralph register char *cp; 165316179Sralph register i; 165416179Sralph cp = exname( stab[p->tn.rval].sname ); 165516179Sralph #ifndef FLEXNAMES 165616179Sralph for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 165716179Sralph #else 165816179Sralph p->in.name = tstr(cp); 165916179Sralph #endif 166016179Sralph } 166116179Sralph #ifndef FLEXNAMES 166216179Sralph else sprintf( p->in.name, LABFMT, -p->tn.rval ); 166316179Sralph #else 166416179Sralph else { 166516179Sralph char temp[32]; 166616179Sralph sprintf( temp, LABFMT, -p->tn.rval ); 166716179Sralph p->in.name = tstr(temp); 166816179Sralph } 166916179Sralph #endif 167016179Sralph break; 167116179Sralph 167216179Sralph case STARG: 167316179Sralph case STASG: 167416179Sralph case STCALL: 167516179Sralph case UNARY STCALL: 167616179Sralph /* set up size parameters */ 167716179Sralph p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 167816179Sralph p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 167916179Sralph break; 168016179Sralph 168116179Sralph case REG: 168216179Sralph rbusy( p->tn.rval, p->in.type ); 168316179Sralph default: 168416179Sralph #ifndef FLEXNAMES 168516179Sralph p->in.name[0] = '\0'; 168616179Sralph #else 168716179Sralph p->in.name = ""; 168816179Sralph #endif 168916179Sralph } 169016179Sralph 169116179Sralph p->in.rall = NOPREF; 169216179Sralph 169316179Sralph if( ty != LTYPE ) p2tree( p->in.left ); 169416179Sralph if( ty == BITYPE ) p2tree( p->in.right ); 169516179Sralph } 169616179Sralph 169716179Sralph # endif 169816179Sralph # endif 1699