117749Sralph #ifndef lint 2*30242Sbostic static char *sccsid ="@(#)trees.c 4.13 (Berkeley) 12/02/86"; 317749Sralph #endif 417749Sralph 518396Sralph # include "pass1.h" 616179Sralph 724408Smckusick # include <setjmp.h> 824408Smckusick 917749Sralph int bdebug = 0; 1017749Sralph int adebug = 0; 1117749Sralph extern ddebug; 1217749Sralph extern eprint(); 1317749Sralph 1416179Sralph /* corrections when in violation of lint */ 1516179Sralph 1616179Sralph /* some special actions, used in finding the type of nodes */ 1716179Sralph # define NCVT 01 1816179Sralph # define PUN 02 1916179Sralph # define TYPL 04 2016179Sralph # define TYPR 010 2116179Sralph # define TYMATCH 040 2216179Sralph # define LVAL 0100 2316179Sralph # define CVTO 0200 2416179Sralph # define CVTL 0400 2516179Sralph # define CVTR 01000 2616179Sralph # define PTMATCH 02000 2716179Sralph # define OTHER 04000 2816179Sralph # define NCVTR 010000 2916179Sralph 3017749Sralph #ifndef BUG1 3117749Sralph printact(t, acts) 3217749Sralph NODE *t; 3317749Sralph int acts; 3417749Sralph { 3517749Sralph static struct actions { 3617749Sralph int a_bit; 3717749Sralph char *a_name; 3817749Sralph } actions[] = { 3917749Sralph { PUN, "PUN" }, 4017749Sralph { CVTL, "CVTL" }, 4117749Sralph { CVTR, "CVTR" }, 4217749Sralph { TYPL, "TYPL" }, 4317749Sralph { TYPR, "TYPR" }, 4417749Sralph { TYMATCH, "TYMATCH" }, 4517749Sralph { PTMATCH, "PTMATCH" }, 4617749Sralph { LVAL, "LVAL" }, 4717749Sralph { CVTO, "CVTO" }, 4817749Sralph { NCVT, "NCVT" }, 4917749Sralph { OTHER, "OTHER" }, 5017749Sralph { NCVTR, "NCVTR" }, 5117749Sralph { 0 } 5217749Sralph }; 5317749Sralph register struct actions *p; 5417749Sralph char *sep = " "; 5517749Sralph 5617749Sralph printf("actions"); 5717749Sralph for (p = actions; p->a_name; p++) 5817749Sralph if (p->a_bit & acts) { 5917749Sralph printf("%s%s", sep, p->a_name); 6017749Sralph sep = "|"; 6117749Sralph } 6217749Sralph if (!bdebug) { 6317749Sralph printf(" for:\n"); 6417749Sralph fwalk(t, eprint, 0); 6517749Sralph } else 6617749Sralph putchar('\n'); 6717749Sralph } 6817749Sralph #endif 6917749Sralph 7016179Sralph /* node conventions: 7116179Sralph 7216179Sralph NAME: rval>0 is stab index for external 7316179Sralph rval<0 is -inlabel number 7416179Sralph lval is offset in bits 7516179Sralph ICON: lval has the value 7616179Sralph rval has the STAB index, or - label number, 7716179Sralph if a name whose address is in the constant 7816179Sralph rval = NONAME means no name 7916179Sralph REG: rval is reg. identification cookie 8016179Sralph 8116179Sralph */ 8216179Sralph 8316179Sralph NODE * 8416179Sralph buildtree( o, l, r ) register NODE *l, *r; { 8516179Sralph register NODE *p, *q; 8616179Sralph register actions; 8716179Sralph register opty; 8816179Sralph register struct symtab *sp; 8916179Sralph register NODE *lr, *ll; 9017749Sralph NODE *fixargs(); 9116179Sralph int i; 9216179Sralph 9316179Sralph # ifndef BUG1 9416179Sralph if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r ); 9516179Sralph # endif 9616179Sralph opty = optype(o); 9716179Sralph 9816179Sralph /* check for constants */ 9916179Sralph 10016179Sralph if( opty == UTYPE && l->in.op == ICON ){ 10116179Sralph 10216179Sralph switch( o ){ 10316179Sralph 10416179Sralph case NOT: 10516179Sralph if( hflag ) werror( "constant argument to NOT" ); 10616179Sralph case UNARY MINUS: 10716179Sralph case COMPL: 10816179Sralph if( conval( l, o, l ) ) return(l); 10916179Sralph break; 11016179Sralph 11116179Sralph } 11216179Sralph } 11316179Sralph 11416179Sralph else if( o==UNARY MINUS && l->in.op==FCON ){ 11517749Sralph l->fpn.fval = -l->fpn.fval; 11616179Sralph return(l); 11716179Sralph } 11816179Sralph 11917749Sralph else if( o==UNARY MINUS && l->in.op==DCON ){ 12017749Sralph l->dpn.dval = -l->dpn.dval; 12117749Sralph return(l); 12217749Sralph } 12317749Sralph 12416179Sralph else if( o==QUEST && l->in.op==ICON ) { 12516179Sralph l->in.op = FREE; 12616179Sralph r->in.op = FREE; 12716179Sralph if( l->tn.lval ){ 12816179Sralph tfree( r->in.right ); 12916179Sralph return( r->in.left ); 13016179Sralph } 13116179Sralph else { 13216179Sralph tfree( r->in.left ); 13316179Sralph return( r->in.right ); 13416179Sralph } 13516179Sralph } 13616179Sralph 13716179Sralph else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn; 13816179Sralph 13916179Sralph else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){ 14016179Sralph 14116179Sralph switch( o ){ 14216179Sralph 14316179Sralph case ULT: 14416179Sralph case UGT: 14516179Sralph case ULE: 14616179Sralph case UGE: 14716179Sralph case LT: 14816179Sralph case GT: 14916179Sralph case LE: 15016179Sralph case GE: 15116179Sralph case EQ: 15216179Sralph case NE: 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 } 17724408Smckusick else if (opty == BITYPE && 17824408Smckusick (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) && 17924408Smckusick (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) { 18024408Smckusick if (o == PLUS || o == MINUS || o == MUL || o == DIV) { 18124408Smckusick extern int fpe_count; 18224408Smckusick extern jmp_buf gotfpe; 18316179Sralph 18424408Smckusick fpe_count = 0; 18524408Smckusick if (setjmp(gotfpe)) 18624408Smckusick goto treatfpe; 18717749Sralph if (l->in.op == ICON) 18817749Sralph l->dpn.dval = l->tn.lval; 18924408Smckusick else if (l->in.op == FCON) 19024408Smckusick l->dpn.dval = l->fpn.fval; 19117749Sralph if (r->in.op == ICON) 19217749Sralph r->dpn.dval = r->tn.lval; 19324408Smckusick else if (r->in.op == FCON) 19424408Smckusick r->dpn.dval = r->fpn.fval; 19517749Sralph switch (o) { 19617749Sralph 19717749Sralph case PLUS: 19817749Sralph l->dpn.dval += r->dpn.dval; 19924408Smckusick break; 20017749Sralph 20117749Sralph case MINUS: 20217749Sralph l->dpn.dval -= r->dpn.dval; 20324408Smckusick break; 20417749Sralph 20517749Sralph case MUL: 20617749Sralph l->dpn.dval *= r->dpn.dval; 20724408Smckusick 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; 21424408Smckusick break; 21524408Smckusick } 21624408Smckusick treatfpe: 21724408Smckusick if (fpe_count > 0) { 21824408Smckusick uerror("floating point exception in constant expression"); 21924408Smckusick l->dpn.dval = 1.0; /* Fairly harmless */ 22024408Smckusick } 22124408Smckusick fpe_count = -1; 22224408Smckusick l->in.op = DCON; 22324408Smckusick l->in.type = l->fn.csiz = DOUBLE; 22424408Smckusick r->in.op = FREE; 22524408Smckusick return (l); 22616179Sralph } 22724408Smckusick } 22816179Sralph 22924408Smckusick /* 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 56724408Smckusick int fpe_count = -1; 56824408Smckusick jmp_buf gotfpe; 56924408Smckusick 57024408Smckusick fpe() { 57124408Smckusick if (fpe_count < 0) 57224408Smckusick cerror("floating point exception"); 57324408Smckusick ++fpe_count; 57424408Smckusick longjmp(gotfpe, 1); 57524408Smckusick } 57624408Smckusick 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: 67429889Ssam if ( u ) p->tn.lval *= (unsigned) val; 67529889Ssam else p->tn.lval *= val; 67616179Sralph break; 67716179Sralph case DIV: 67816179Sralph if( val == 0 ) uerror( "division by 0" ); 67917749Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val; 68016179Sralph else p->tn.lval /= val; 68116179Sralph break; 68216179Sralph case MOD: 68316179Sralph if( val == 0 ) uerror( "division by 0" ); 68417749Sralph else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val; 68516179Sralph else p->tn.lval %= val; 68616179Sralph break; 68716179Sralph case AND: 68816179Sralph p->tn.lval &= val; 68916179Sralph break; 69016179Sralph case OR: 69116179Sralph p->tn.lval |= val; 69216179Sralph break; 69316179Sralph case ER: 69417749Sralph p->tn.lval ^= val; 69516179Sralph break; 69616179Sralph case LS: 69716179Sralph i = val; 69816179Sralph p->tn.lval = p->tn.lval << i; 69916179Sralph break; 70016179Sralph case RS: 70116179Sralph i = val; 70217749Sralph if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i; 70317749Sralph else p->tn.lval = p->tn.lval >> i; 70416179Sralph break; 70516179Sralph 70616179Sralph case UNARY MINUS: 70716179Sralph p->tn.lval = - p->tn.lval; 70816179Sralph break; 70916179Sralph case COMPL: 71016179Sralph p->tn.lval = ~p->tn.lval; 71116179Sralph break; 71216179Sralph case NOT: 71316179Sralph p->tn.lval = !p->tn.lval; 71416179Sralph break; 71516179Sralph case LT: 71616179Sralph p->tn.lval = p->tn.lval < val; 71716179Sralph break; 71816179Sralph case LE: 71916179Sralph p->tn.lval = p->tn.lval <= val; 72016179Sralph break; 72116179Sralph case GT: 72216179Sralph p->tn.lval = p->tn.lval > val; 72316179Sralph break; 72416179Sralph case GE: 72516179Sralph p->tn.lval = p->tn.lval >= val; 72616179Sralph break; 72716179Sralph case ULT: 728*30242Sbostic p->tn.lval = p->tn.lval < (unsigned) val; 72916179Sralph break; 73016179Sralph case ULE: 731*30242Sbostic p->tn.lval = p->tn.lval <= (unsigned) val; 73216179Sralph break; 733*30242Sbostic case UGT: 734*30242Sbostic p->tn.lval = p->tn.lval > (unsigned) val; 735*30242Sbostic break; 73616179Sralph case UGE: 737*30242Sbostic p->tn.lval = p->tn.lval >= (unsigned) val; 73816179Sralph break; 73916179Sralph case EQ: 74016179Sralph p->tn.lval = p->tn.lval == val; 74116179Sralph break; 74216179Sralph case NE: 74316179Sralph p->tn.lval = p->tn.lval != val; 74416179Sralph break; 74516179Sralph default: 74616179Sralph return(0); 74716179Sralph } 74816179Sralph return(1); 74916179Sralph } 75016179Sralph 75116179Sralph chkpun(p) register NODE *p; { 75216179Sralph 75316179Sralph /* checks p for the existance of a pun */ 75416179Sralph 75516179Sralph /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ 75616179Sralph 75716179Sralph /* one case is when enumerations are used: this applies only to lint */ 75816179Sralph /* in the other case, one operand is a pointer, the other integer type */ 75916179Sralph /* we check that this integer is in fact a constant zero... */ 76016179Sralph 76116179Sralph /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ 76216179Sralph /* this falls out, because the LHS is never 0 */ 76316179Sralph 76416179Sralph register NODE *q; 76516179Sralph register t1, t2; 76616179Sralph register d1, d2; 76716179Sralph 76816179Sralph t1 = p->in.left->in.type; 76916179Sralph t2 = p->in.right->in.type; 77016179Sralph 77116179Sralph if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ 77216179Sralph if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) { 77316179Sralph uerror( "illegal comparison of enums" ); 77416179Sralph return; 77516179Sralph } 77616179Sralph if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return; 77716179Sralph werror( "enumeration type clash, operator %s", opst[p->in.op] ); 77816179Sralph return; 77916179Sralph } 78016179Sralph 78116179Sralph if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; 78216179Sralph else q = p->in.left; 78316179Sralph 78416179Sralph if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ 78516179Sralph if( q->in.op != ICON || q->tn.lval != 0 ){ 78616179Sralph werror( "illegal combination of pointer and integer, op %s", 78716179Sralph opst[p->in.op] ); 78816179Sralph } 78916179Sralph } 79016179Sralph else { 79116179Sralph d1 = p->in.left->fn.cdim; 79216179Sralph d2 = p->in.right->fn.cdim; 79316179Sralph for( ;; ){ 79416179Sralph if( t1 == t2 ) {; 79516179Sralph if( p->in.left->fn.csiz != p->in.right->fn.csiz ) { 79616179Sralph werror( "illegal structure pointer combination" ); 79716179Sralph } 79816179Sralph return; 79916179Sralph } 80016179Sralph if( ISARY(t1) || ISPTR(t1) ){ 80116179Sralph if( !ISARY(t2) && !ISPTR(t2) ) break; 80216179Sralph if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ 80316179Sralph werror( "illegal array size combination" ); 80416179Sralph return; 80516179Sralph } 80616179Sralph if( ISARY(t1) ) ++d1; 80716179Sralph if( ISARY(t2) ) ++d2; 80816179Sralph } 80916179Sralph else break; 81016179Sralph t1 = DECREF(t1); 81116179Sralph t2 = DECREF(t2); 81216179Sralph } 81316179Sralph werror( "illegal pointer combination" ); 81416179Sralph } 81516179Sralph 81616179Sralph } 81716179Sralph 81816179Sralph NODE * 81916179Sralph stref( p ) register NODE *p; { 82016179Sralph 82116179Sralph TWORD t; 82216179Sralph int d, s, dsc, align; 82316179Sralph OFFSZ off; 82416179Sralph register struct symtab *q; 82516179Sralph 82616179Sralph /* make p->x */ 82716179Sralph /* this is also used to reference automatic variables */ 82816179Sralph 82916179Sralph q = &stab[p->in.right->tn.rval]; 83016179Sralph p->in.right->in.op = FREE; 83116179Sralph p->in.op = FREE; 83216179Sralph p = pconvert( p->in.left ); 83316179Sralph 83416179Sralph /* make p look like ptr to x */ 83516179Sralph 83616179Sralph if( !ISPTR(p->in.type)){ 83716179Sralph p->in.type = PTR+UNIONTY; 83816179Sralph } 83916179Sralph 84016179Sralph t = INCREF( q->stype ); 84116179Sralph d = q->dimoff; 84216179Sralph s = q->sizoff; 84316179Sralph 84416179Sralph p = makety( p, t, d, s ); 84516179Sralph 84616179Sralph /* compute the offset to be added */ 84716179Sralph 84816179Sralph off = q->offset; 84916179Sralph dsc = q->sclass; 85016179Sralph 85116179Sralph if( dsc & FIELD ) { /* normalize offset */ 85216179Sralph align = ALINT; 85316179Sralph s = INT; 85416179Sralph off = (off/align)*align; 85516179Sralph } 85616179Sralph if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); 85716179Sralph 85816179Sralph p = buildtree( UNARY MUL, p, NIL ); 85916179Sralph 86016179Sralph /* if field, build field info */ 86116179Sralph 86216179Sralph if( dsc & FIELD ){ 86316179Sralph p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); 86416179Sralph p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); 86516179Sralph } 86616179Sralph 86716179Sralph return( clocal(p) ); 86816179Sralph } 86916179Sralph 87016179Sralph notlval(p) register NODE *p; { 87116179Sralph 87216179Sralph /* return 0 if p an lvalue, 1 otherwise */ 87316179Sralph 87416179Sralph again: 87516179Sralph 87616179Sralph switch( p->in.op ){ 87716179Sralph 87816179Sralph case FLD: 87916179Sralph p = p->in.left; 88016179Sralph goto again; 88116179Sralph 88216179Sralph case UNARY MUL: 88316179Sralph /* fix the &(a=b) bug, given that a and b are structures */ 88416179Sralph if( p->in.left->in.op == STASG ) return( 1 ); 88516179Sralph /* and the f().a bug, given that f returns a structure */ 88616179Sralph if( p->in.left->in.op == UNARY STCALL || 88716179Sralph p->in.left->in.op == STCALL ) return( 1 ); 88816179Sralph case NAME: 88916179Sralph case OREG: 89016179Sralph if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); 89116179Sralph case REG: 89216179Sralph return(0); 89316179Sralph 89416179Sralph default: 89516179Sralph return(1); 89616179Sralph 89716179Sralph } 89816179Sralph 89916179Sralph } 90016179Sralph 90116179Sralph NODE * 90216179Sralph bcon( i ){ /* make a constant node with value i */ 90316179Sralph register NODE *p; 90416179Sralph 90516179Sralph p = block( ICON, NIL, NIL, INT, 0, INT ); 90616179Sralph p->tn.lval = i; 90716179Sralph p->tn.rval = NONAME; 90816179Sralph return( clocal(p) ); 90916179Sralph } 91016179Sralph 91116179Sralph NODE * 91216179Sralph bpsize(p) register NODE *p; { 91316179Sralph return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); 91416179Sralph } 91516179Sralph 91616179Sralph OFFSZ 91716179Sralph psize( p ) NODE *p; { 91816179Sralph /* p is a node of type pointer; psize returns the 91916179Sralph size of the thing pointed to */ 92016179Sralph 92116179Sralph if( !ISPTR(p->in.type) ){ 92216179Sralph uerror( "pointer required"); 92316179Sralph return( SZINT ); 92416179Sralph } 92516179Sralph /* note: no pointers to fields */ 92616179Sralph return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); 92716179Sralph } 92816179Sralph 92916179Sralph NODE * 93016179Sralph convert( p, f ) register NODE *p; { 93116179Sralph /* convert an operand of p 93216179Sralph f is either CVTL or CVTR 93316179Sralph operand has type int, and is converted by the size of the other side 93416179Sralph */ 93516179Sralph 93616179Sralph register NODE *q, *r; 93716179Sralph 93816179Sralph q = (f==CVTL)?p->in.left:p->in.right; 93916179Sralph 94016179Sralph r = block( PMCONV, 94116179Sralph q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); 94216179Sralph r = clocal(r); 94316179Sralph if( f == CVTL ) 94416179Sralph p->in.left = r; 94516179Sralph else 94616179Sralph p->in.right = r; 94716179Sralph return(p); 94816179Sralph 94916179Sralph } 95016179Sralph 95125750Sdonn #ifndef econvert 95216179Sralph econvert( p ) register NODE *p; { 95316179Sralph 95416179Sralph /* change enums to ints, or appropriate types */ 95516179Sralph 95616179Sralph register TWORD ty; 95716179Sralph 95816179Sralph if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 95916179Sralph if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 96016179Sralph else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 96116179Sralph else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 96216179Sralph else ty = LONG; 96316179Sralph ty = ctype( ty ); 96416179Sralph p->fn.csiz = ty; 96516179Sralph MODTYPE(p->in.type,ty); 96616179Sralph if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 96716179Sralph } 96816179Sralph } 96925750Sdonn #endif 97016179Sralph 97116179Sralph NODE * 97216179Sralph pconvert( p ) register NODE *p; { 97316179Sralph 97416179Sralph /* if p should be changed into a pointer, do so */ 97516179Sralph 97616179Sralph if( ISARY( p->in.type) ){ 97716179Sralph p->in.type = DECREF( p->in.type ); 97816179Sralph ++p->fn.cdim; 97916179Sralph return( buildtree( UNARY AND, p, NIL ) ); 98016179Sralph } 98116179Sralph if( ISFTN( p->in.type) ) 98216179Sralph return( buildtree( UNARY AND, p, NIL ) ); 98316179Sralph 98416179Sralph return( p ); 98516179Sralph } 98616179Sralph 98716179Sralph NODE * 98816179Sralph oconvert(p) register NODE *p; { 98916179Sralph /* convert the result itself: used for pointer and unsigned */ 99016179Sralph 99116179Sralph switch(p->in.op) { 99216179Sralph 99316179Sralph case LE: 99416179Sralph case LT: 99516179Sralph case GE: 99616179Sralph case GT: 99716179Sralph if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 99816179Sralph case EQ: 99916179Sralph case NE: 100016179Sralph return( p ); 100116179Sralph 100216179Sralph case MINUS: 100316179Sralph return( clocal( block( PVCONV, 100416179Sralph p, bpsize(p->in.left), INT, 0, INT ) ) ); 100516179Sralph } 100616179Sralph 100716179Sralph cerror( "illegal oconvert: %d", p->in.op ); 100816179Sralph 100916179Sralph return(p); 101016179Sralph } 101116179Sralph 101216179Sralph NODE * 101316179Sralph ptmatch(p) register NODE *p; { 101416179Sralph 101516179Sralph /* makes the operands of p agree; they are 101616179Sralph either pointers or integers, by this time */ 101716179Sralph /* with MINUS, the sizes must be the same */ 101816179Sralph /* with COLON, the types must be the same */ 101916179Sralph 102016179Sralph TWORD t1, t2, t; 102116179Sralph int o, d2, d, s2, s; 102216179Sralph 102316179Sralph o = p->in.op; 102416179Sralph t = t1 = p->in.left->in.type; 102516179Sralph t2 = p->in.right->in.type; 102616179Sralph d = p->in.left->fn.cdim; 102716179Sralph d2 = p->in.right->fn.cdim; 102816179Sralph s = p->in.left->fn.csiz; 102916179Sralph s2 = p->in.right->fn.csiz; 103016179Sralph 103116179Sralph switch( o ){ 103216179Sralph 103316179Sralph case ASSIGN: 103416179Sralph case RETURN: 103516179Sralph case CAST: 103616179Sralph { break; } 103716179Sralph 103816179Sralph case MINUS: 103916179Sralph { if( psize(p->in.left) != psize(p->in.right) ){ 104016179Sralph uerror( "illegal pointer subtraction"); 104116179Sralph } 104216179Sralph break; 104316179Sralph } 104416179Sralph case COLON: 104516179Sralph { if( t1 != t2 ) uerror( "illegal types in :"); 104616179Sralph break; 104716179Sralph } 104816179Sralph default: /* must work harder: relationals or comparisons */ 104916179Sralph 105016179Sralph if( !ISPTR(t1) ){ 105116179Sralph t = t2; 105216179Sralph d = d2; 105316179Sralph s = s2; 105416179Sralph break; 105516179Sralph } 105616179Sralph if( !ISPTR(t2) ){ 105716179Sralph break; 105816179Sralph } 105916179Sralph 106016179Sralph /* both are pointers */ 106116179Sralph if( talign(t2,s2) < talign(t,s) ){ 106216179Sralph t = t2; 106316179Sralph s = s2; 106416179Sralph } 106516179Sralph break; 106616179Sralph } 106716179Sralph 106816179Sralph p->in.left = makety( p->in.left, t, d, s ); 106916179Sralph p->in.right = makety( p->in.right, t, d, s ); 107016179Sralph if( o!=MINUS && !logop(o) ){ 107116179Sralph 107216179Sralph p->in.type = t; 107316179Sralph p->fn.cdim = d; 107416179Sralph p->fn.csiz = s; 107516179Sralph } 107616179Sralph 107716179Sralph return(clocal(p)); 107816179Sralph } 107916179Sralph 108016179Sralph int tdebug = 0; 108116179Sralph 108216179Sralph NODE * 108316179Sralph tymatch(p) register NODE *p; { 108416179Sralph 108516179Sralph /* satisfy the types of various arithmetic binary ops */ 108616179Sralph 108716179Sralph /* rules are: 108825750Sdonn if assignment, type of LHS 108916179Sralph if any float or doubles, make double 109016179Sralph if any longs, make long 109116179Sralph otherwise, make int 109216179Sralph if either operand is unsigned, the result is... 109316179Sralph */ 109416179Sralph 109516179Sralph register TWORD t1, t2, t, tu; 109616179Sralph register o, u; 109716179Sralph 109816179Sralph o = p->in.op; 109916179Sralph 110016179Sralph t1 = p->in.left->in.type; 110116179Sralph t2 = p->in.right->in.type; 110216179Sralph if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 110316179Sralph uerror("void type illegal in expression"); 110416179Sralph 110516179Sralph u = 0; 110616179Sralph if( ISUNSIGNED(t1) ){ 110716179Sralph u = 1; 110816179Sralph t1 = DEUNSIGN(t1); 110916179Sralph } 111016179Sralph if( ISUNSIGNED(t2) ){ 111116179Sralph u = 1; 111216179Sralph t2 = DEUNSIGN(t2); 111316179Sralph } 111416179Sralph 111516179Sralph if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 111616179Sralph if( t2 == CHAR || t2 == SHORT ) t2 = INT; 111716179Sralph 111817749Sralph #ifdef SPRECC 111917749Sralph if( t1 == DOUBLE || t2 == DOUBLE ) 112017749Sralph t = DOUBLE; 112117749Sralph else if( t1 == FLOAT || t2 == FLOAT ) 112217749Sralph t = FLOAT; 112317749Sralph #else 112417749Sralph if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT) 112517749Sralph t = DOUBLE; 112617749Sralph #endif 112716179Sralph else if( t1==LONG || t2==LONG ) t = LONG; 112816179Sralph else t = INT; 112916179Sralph 113029889Ssam #ifdef tahoe 113129889Ssam if( asgop(o) ){ 113229889Ssam #else 113325750Sdonn if( o == ASSIGN || o == CAST || o == RETURN ){ 113429889Ssam #endif 113516179Sralph tu = p->in.left->in.type; 113616179Sralph t = t1; 113716179Sralph } 113816179Sralph else { 113916179Sralph tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 114016179Sralph } 114116179Sralph 114216179Sralph /* because expressions have values that are at least as wide 114316179Sralph as INT or UNSIGNED, the only conversions needed 114416179Sralph are those involving FLOAT/DOUBLE, and those 114516179Sralph from LONG to INT and ULONG to UNSIGNED */ 114616179Sralph 114729889Ssam #ifdef tahoe 114829889Ssam if( t != t1 ) 114929889Ssam #else 115025750Sdonn if( t != t1 && ! asgop(o) ) 115129889Ssam #endif 115225750Sdonn p->in.left = makety( p->in.left, tu, 0, (int)tu ); 115316179Sralph 115425750Sdonn if( t != t2 || o==CAST ) 115525750Sdonn 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 ){ 119217749Sralph if (t == DOUBLE) { 119317749Sralph p->in.op = DCON; 119417749Sralph if (ISUNSIGNED(p->in.type)) 119530241Sbostic p->dpn.dval = (unsigned CONSZ) p->tn.lval; 119617749Sralph else 119717749Sralph p->dpn.dval = p->tn.lval; 119817749Sralph p->in.type = p->fn.csiz = t; 119917749Sralph return (clocal(p)); 120017749Sralph } 120117749Sralph if (t == FLOAT) { 120216179Sralph p->in.op = FCON; 120316179Sralph if( ISUNSIGNED(p->in.type) ){ 120430241Sbostic p->fpn.fval = (unsigned CONSZ) p->tn.lval; 120516179Sralph } 120616179Sralph else { 120717749Sralph p->fpn.fval = p->tn.lval; 120816179Sralph } 120916179Sralph 121016179Sralph p->in.type = p->fn.csiz = t; 121116179Sralph return( clocal(p) ); 121216179Sralph } 121316179Sralph } 121417749Sralph else if (p->in.op == FCON && t == DOUBLE) { 121517749Sralph double db; 121616179Sralph 121717749Sralph p->in.op = DCON; 121817749Sralph db = p->fpn.fval; 121917749Sralph p->dpn.dval = db; 122017749Sralph p->in.type = p->fn.csiz = t; 122117749Sralph return (clocal(p)); 122217749Sralph } else if (p->in.op == DCON && t == FLOAT) { 122317749Sralph float fl; 122417749Sralph 122517749Sralph p->in.op = FCON; 122617749Sralph fl = p->dpn.dval; 122717749Sralph #ifdef notdef 122817749Sralph if (fl != p->dpn.dval) 122917749Sralph werror("float conversion loses precision"); 123017749Sralph #endif 123117749Sralph p->fpn.fval = fl; 123217749Sralph p->in.type = p->fn.csiz = t; 123317749Sralph return (clocal(p)); 123417749Sralph } 123517749Sralph 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 */ 130424408Smckusick # define MVOID 0100000 /* void type */ 130516179Sralph 130616179Sralph opact( p ) NODE *p; { 130716179Sralph 130816179Sralph register mt12, mt1, mt2, o; 130916179Sralph 131024408Smckusick mt1 = mt2 = mt12 = 0; 131116179Sralph 131216179Sralph switch( optype(o=p->in.op) ){ 131316179Sralph 131416179Sralph case BITYPE: 131524408Smckusick mt2 = moditype( p->in.right->in.type ); 131616179Sralph case UTYPE: 131724408Smckusick mt1 = moditype( p->in.left->in.type ); 131824408Smckusick break; 131916179Sralph 132016179Sralph } 132116179Sralph 132224408Smckusick if( ((mt1 | mt2) & MVOID) && 132324408Smckusick o != COMOP && 132424408Smckusick !(o == CAST && (mt1 & MVOID)) ){ 132524408Smckusick /* if lhs of RETURN is void, grammar will complain */ 132624408Smckusick if( o != RETURN ) 132724408Smckusick uerror( "value of void expression used" ); 132824408Smckusick return( NCVT ); 132924408Smckusick } 133024408Smckusick mt1 &= ~MVOID; 133124408Smckusick mt2 &= ~MVOID; 133224408Smckusick mt12 = mt1 & mt2; 133324408Smckusick 133416179Sralph switch( o ){ 133516179Sralph 133616179Sralph case NAME : 133716179Sralph case STRING : 133816179Sralph case ICON : 133916179Sralph case FCON : 134017749Sralph case DCON : 134116179Sralph case CALL : 134216179Sralph case UNARY CALL: 134316179Sralph case UNARY MUL: 134416179Sralph { return( OTHER ); } 134516179Sralph case UNARY MINUS: 134616179Sralph if( mt1 & MDBI ) return( TYPL ); 134716179Sralph break; 134816179Sralph 134916179Sralph case COMPL: 135016179Sralph if( mt1 & MINT ) return( TYPL ); 135116179Sralph break; 135216179Sralph 135316179Sralph case UNARY AND: 135416179Sralph { return( NCVT+OTHER ); } 135516179Sralph case INIT: 135616179Sralph case CM: 135716180Sralph return( 0 ); 135816180Sralph 135916179Sralph case NOT: 136016179Sralph case CBRANCH: 136116180Sralph if( mt1 & MSTR ) break; 136216180Sralph return( 0 ); 136316180Sralph 136416179Sralph case ANDAND: 136516179Sralph case OROR: 136616180Sralph if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 136716179Sralph return( 0 ); 136816179Sralph 136916179Sralph case MUL: 137016179Sralph case DIV: 137116179Sralph if( mt12 & MDBI ) return( TYMATCH ); 137216179Sralph break; 137316179Sralph 137416179Sralph case MOD: 137516179Sralph case AND: 137616179Sralph case OR: 137716179Sralph case ER: 137816179Sralph if( mt12 & MINT ) return( TYMATCH ); 137916179Sralph break; 138016179Sralph 138116179Sralph case LS: 138216179Sralph case RS: 138316179Sralph if( mt12 & MINT ) return( TYMATCH+OTHER ); 138416179Sralph break; 138516179Sralph 138616179Sralph case EQ: 138716179Sralph case NE: 138816179Sralph case LT: 138916179Sralph case LE: 139016179Sralph case GT: 139116179Sralph case GE: 139216179Sralph if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 139316179Sralph if( mt12 & MDBI ) return( TYMATCH+CVTO ); 139416179Sralph else if( mt12 & MPTR ) return( PTMATCH+PUN ); 139516179Sralph else if( mt12 & MPTI ) return( PTMATCH+PUN ); 139616179Sralph else break; 139716179Sralph 139816179Sralph case QUEST: 139916179Sralph case COMOP: 140016179Sralph if( mt2&MENU ) return( TYPR+NCVTR ); 140116179Sralph return( TYPR ); 140216179Sralph 140316179Sralph case STREF: 140416179Sralph return( NCVTR+OTHER ); 140516179Sralph 140616179Sralph case FORCE: 140716179Sralph return( TYPL ); 140816179Sralph 140916179Sralph case COLON: 141016179Sralph if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 141116179Sralph else if( mt12 & MDBI ) return( TYMATCH ); 141216179Sralph else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 141316179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 141416179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 141516179Sralph else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 141616179Sralph break; 141716179Sralph 141816179Sralph case ASSIGN: 141916179Sralph case RETURN: 142016179Sralph if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 142116179Sralph case CAST: 142216179Sralph if(o==CAST && mt1==0)return(TYPL+TYMATCH); 142316179Sralph if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 142416179Sralph else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 142518436Smckusick else if( mt2 == 0 && 142618436Smckusick ( p->in.right->in.op == CALL || 142718436Smckusick p->in.right->in.op == UNARY CALL)) break; 142816179Sralph else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 142916179Sralph else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 143016179Sralph break; 143116179Sralph 143216179Sralph case ASG LS: 143316179Sralph case ASG RS: 143416179Sralph if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 143516179Sralph break; 143616179Sralph 143716179Sralph case ASG MUL: 143816179Sralph case ASG DIV: 143916179Sralph if( mt12 & MDBI ) return( LVAL+TYMATCH ); 144016179Sralph break; 144116179Sralph 144216179Sralph case ASG MOD: 144316179Sralph case ASG AND: 144416179Sralph case ASG OR: 144516179Sralph case ASG ER: 144616179Sralph if( mt12 & MINT ) return( LVAL+TYMATCH ); 144716179Sralph break; 144816179Sralph 144916179Sralph case ASG PLUS: 145016179Sralph case ASG MINUS: 145116179Sralph case INCR: 145216179Sralph case DECR: 145316179Sralph if( mt12 & MDBI ) return( TYMATCH+LVAL ); 145416179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 145516179Sralph break; 145616179Sralph 145716179Sralph case MINUS: 145816179Sralph if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 145916179Sralph if( mt2 & MPTR ) break; 146016179Sralph case PLUS: 146116179Sralph if( mt12 & MDBI ) return( TYMATCH ); 146216179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 146316179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 146416179Sralph 146516179Sralph } 146624408Smckusick if( mt12 == MSTR ) 146724408Smckusick uerror( "%s is not a permitted struct/union operation", opst[o] ); 146824408Smckusick else 146924408Smckusick uerror( "operands of %s have incompatible types", opst[o] ); 147016179Sralph return( NCVT ); 147116179Sralph } 147216179Sralph 147316179Sralph moditype( ty ) TWORD ty; { 147416179Sralph 147516179Sralph switch( ty ){ 147616179Sralph 147716179Sralph case TVOID: 147817206Sralph return( MPTR ); 147916179Sralph case UNDEF: 148024408Smckusick return( MVOID ); 148116179Sralph case ENUMTY: 148216179Sralph case MOETY: 148316179Sralph return( MENU ); 148416179Sralph 148516179Sralph case STRTY: 148616179Sralph case UNIONTY: 148716179Sralph return( MSTR ); 148816179Sralph 148916179Sralph case CHAR: 149016179Sralph case SHORT: 149116179Sralph case UCHAR: 149216179Sralph case USHORT: 149316179Sralph return( MINT|MPTI|MDBI ); 149416179Sralph case UNSIGNED: 149516179Sralph case ULONG: 149616179Sralph case INT: 149716179Sralph case LONG: 149816179Sralph return( MINT|MDBI|MPTI ); 149916179Sralph case FLOAT: 150016179Sralph case DOUBLE: 150116179Sralph return( MDBI ); 150216179Sralph default: 150316179Sralph return( MPTR|MPTI ); 150416179Sralph 150516179Sralph } 150616179Sralph } 150716179Sralph 150816179Sralph NODE * 150916179Sralph doszof( p ) register NODE *p; { 151016179Sralph /* do sizeof p */ 151116179Sralph int i; 151216179Sralph 151316179Sralph /* whatever is the meaning of this if it is a bitfield? */ 151416179Sralph i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 151516179Sralph 151616179Sralph tfree(p); 151716179Sralph if( i <= 0 ) werror( "sizeof returns 0" ); 151816179Sralph return( bcon( i ) ); 151916179Sralph } 152016179Sralph 152116179Sralph # ifndef BUG2 152216179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; { 152316179Sralph register ty; 152416179Sralph 152516179Sralph *a = *b = down+1; 152616179Sralph while( down > 1 ){ 152716179Sralph printf( "\t" ); 152816179Sralph down -= 2; 152916179Sralph } 153016179Sralph if( down ) printf( " " ); 153116179Sralph 153216179Sralph ty = optype( p->in.op ); 153316179Sralph 153416179Sralph printf("%o) %s, ", p, opst[p->in.op] ); 153516179Sralph if( ty == LTYPE ){ 153616179Sralph printf( CONFMT, p->tn.lval ); 153716179Sralph printf( ", %d, ", p->tn.rval ); 153816179Sralph } 153916179Sralph tprint( p->in.type ); 154016179Sralph printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 154116179Sralph } 154216179Sralph # endif 154316179Sralph 154429889Ssam #ifndef PRTDCON 154516179Sralph prtdcon( p ) register NODE *p; { 154617749Sralph int o = p->in.op, i; 154716179Sralph 154817749Sralph if( o == DCON || o == FCON ){ 154916179Sralph locctr( DATA ); 155017749Sralph defalign( o == DCON ? ALDOUBLE : ALFLOAT ); 155116179Sralph deflab( i = getlab() ); 155217749Sralph if( o == FCON ) 155317749Sralph fincode( p->fpn.fval, SZFLOAT ); 155417749Sralph else 155517749Sralph fincode( p->dpn.dval, SZDOUBLE ); 155616179Sralph p->tn.lval = 0; 155716179Sralph p->tn.rval = -i; 155817749Sralph p->in.type = (o == DCON ? DOUBLE : FLOAT); 155916179Sralph p->in.op = NAME; 156016179Sralph } 156116179Sralph } 156229889Ssam #endif PRTDCON 156316179Sralph 156416179Sralph 156516179Sralph int edebug = 0; 156616179Sralph ecomp( p ) register NODE *p; { 156716179Sralph # ifndef BUG2 156816179Sralph if( edebug ) fwalk( p, eprint, 0 ); 156916179Sralph # endif 157016179Sralph if( !reached ){ 157116179Sralph werror( "statement not reached" ); 157216179Sralph reached = 1; 157316179Sralph } 157416179Sralph p = optim(p); 157516179Sralph walkf( p, prtdcon ); 157616179Sralph locctr( PROG ); 157716179Sralph ecode( p ); 157816179Sralph tfree(p); 157916179Sralph } 158016179Sralph 158116179Sralph # ifdef STDPRTREE 158216179Sralph # ifndef ONEPASS 158316179Sralph 158416179Sralph prtree(p) register NODE *p; { 158516179Sralph 158616179Sralph register struct symtab *q; 158716179Sralph register ty; 158816179Sralph 158916179Sralph # ifdef MYPRTREE 159016179Sralph MYPRTREE(p); /* local action can be taken here; then return... */ 159116179Sralph #endif 159216179Sralph 159316179Sralph ty = optype(p->in.op); 159416179Sralph 159516179Sralph printf( "%d\t", p->in.op ); 159616179Sralph 159716179Sralph if( ty == LTYPE ) { 159816179Sralph printf( CONFMT, p->tn.lval ); 159916179Sralph printf( "\t" ); 160016179Sralph } 160116179Sralph if( ty != BITYPE ) { 160216179Sralph if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 160316179Sralph else printf( "%d\t", p->tn.rval ); 160416179Sralph } 160516179Sralph 160616179Sralph printf( "%o\t", p->in.type ); 160716179Sralph 160816179Sralph /* handle special cases */ 160916179Sralph 161016179Sralph switch( p->in.op ){ 161116179Sralph 161216179Sralph case NAME: 161316179Sralph case ICON: 161416179Sralph /* print external name */ 161516179Sralph if( p->tn.rval == NONAME ) printf( "\n" ); 161616179Sralph else if( p->tn.rval >= 0 ){ 161716179Sralph q = &stab[p->tn.rval]; 161816179Sralph printf( "%s\n", exname(q->sname) ); 161916179Sralph } 162016179Sralph else { /* label */ 162116179Sralph printf( LABFMT, -p->tn.rval ); 162216179Sralph } 162316179Sralph break; 162416179Sralph 162516179Sralph case STARG: 162616179Sralph case STASG: 162716179Sralph case STCALL: 162816179Sralph case UNARY STCALL: 162916179Sralph /* print out size */ 163016179Sralph /* use lhs size, in order to avoid hassles with the structure `.' operator */ 163116179Sralph 163216179Sralph /* note: p->in.left not a field... */ 163316179Sralph printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 163416179Sralph printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 163516179Sralph break; 163616179Sralph 163716179Sralph default: 163816179Sralph printf( "\n" ); 163916179Sralph } 164016179Sralph 164116179Sralph if( ty != LTYPE ) prtree( p->in.left ); 164216179Sralph if( ty == BITYPE ) prtree( p->in.right ); 164316179Sralph 164416179Sralph } 164516179Sralph 164616179Sralph # else 164716179Sralph 164816179Sralph p2tree(p) register NODE *p; { 164916179Sralph register ty; 165016179Sralph 165116179Sralph # ifdef MYP2TREE 165216179Sralph MYP2TREE(p); /* local action can be taken here; then return... */ 165316179Sralph # endif 165416179Sralph 165516179Sralph ty = optype(p->in.op); 165616179Sralph 165716179Sralph switch( p->in.op ){ 165816179Sralph 165916179Sralph case NAME: 166016179Sralph case ICON: 166116179Sralph #ifndef FLEXNAMES 166216179Sralph if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 166316179Sralph #else 166416179Sralph if( p->tn.rval == NONAME ) p->in.name = ""; 166516179Sralph #endif 166616179Sralph else if( p->tn.rval >= 0 ){ /* copy name from exname */ 166716179Sralph register char *cp; 166816179Sralph register i; 166916179Sralph cp = exname( stab[p->tn.rval].sname ); 167016179Sralph #ifndef FLEXNAMES 167116179Sralph for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 167216179Sralph #else 167316179Sralph p->in.name = tstr(cp); 167416179Sralph #endif 167516179Sralph } 167616179Sralph #ifndef FLEXNAMES 167716179Sralph else sprintf( p->in.name, LABFMT, -p->tn.rval ); 167816179Sralph #else 167916179Sralph else { 168016179Sralph char temp[32]; 168116179Sralph sprintf( temp, LABFMT, -p->tn.rval ); 168216179Sralph p->in.name = tstr(temp); 168316179Sralph } 168416179Sralph #endif 168516179Sralph break; 168616179Sralph 168716179Sralph case STARG: 168816179Sralph case STASG: 168916179Sralph case STCALL: 169016179Sralph case UNARY STCALL: 169116179Sralph /* set up size parameters */ 169216179Sralph p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 169316179Sralph p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 169416179Sralph break; 169516179Sralph 169616179Sralph case REG: 169716179Sralph rbusy( p->tn.rval, p->in.type ); 169816179Sralph default: 169916179Sralph #ifndef FLEXNAMES 170016179Sralph p->in.name[0] = '\0'; 170116179Sralph #else 170216179Sralph p->in.name = ""; 170316179Sralph #endif 170416179Sralph } 170516179Sralph 170616179Sralph p->in.rall = NOPREF; 170716179Sralph 170816179Sralph if( ty != LTYPE ) p2tree( p->in.left ); 170916179Sralph if( ty == BITYPE ) p2tree( p->in.right ); 171016179Sralph } 171116179Sralph 171216179Sralph # endif 171316179Sralph # endif 1714