117749Sralph #ifndef lint 2*25750Sdonn static char *sccsid ="@(#)trees.c 4.10 (Berkeley) 01/08/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: 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 950*25750Sdonn #ifndef econvert 95116179Sralph econvert( p ) register NODE *p; { 95216179Sralph 95316179Sralph /* change enums to ints, or appropriate types */ 95416179Sralph 95516179Sralph register TWORD ty; 95616179Sralph 95716179Sralph if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 95816179Sralph if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 95916179Sralph else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 96016179Sralph else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 96116179Sralph else ty = LONG; 96216179Sralph ty = ctype( ty ); 96316179Sralph p->fn.csiz = ty; 96416179Sralph MODTYPE(p->in.type,ty); 96516179Sralph if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 96616179Sralph } 96716179Sralph } 968*25750Sdonn #endif 96916179Sralph 97016179Sralph NODE * 97116179Sralph pconvert( p ) register NODE *p; { 97216179Sralph 97316179Sralph /* if p should be changed into a pointer, do so */ 97416179Sralph 97516179Sralph if( ISARY( p->in.type) ){ 97616179Sralph p->in.type = DECREF( p->in.type ); 97716179Sralph ++p->fn.cdim; 97816179Sralph return( buildtree( UNARY AND, p, NIL ) ); 97916179Sralph } 98016179Sralph if( ISFTN( p->in.type) ) 98116179Sralph return( buildtree( UNARY AND, p, NIL ) ); 98216179Sralph 98316179Sralph return( p ); 98416179Sralph } 98516179Sralph 98616179Sralph NODE * 98716179Sralph oconvert(p) register NODE *p; { 98816179Sralph /* convert the result itself: used for pointer and unsigned */ 98916179Sralph 99016179Sralph switch(p->in.op) { 99116179Sralph 99216179Sralph case LE: 99316179Sralph case LT: 99416179Sralph case GE: 99516179Sralph case GT: 99616179Sralph if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 99716179Sralph case EQ: 99816179Sralph case NE: 99916179Sralph return( p ); 100016179Sralph 100116179Sralph case MINUS: 100216179Sralph return( clocal( block( PVCONV, 100316179Sralph p, bpsize(p->in.left), INT, 0, INT ) ) ); 100416179Sralph } 100516179Sralph 100616179Sralph cerror( "illegal oconvert: %d", p->in.op ); 100716179Sralph 100816179Sralph return(p); 100916179Sralph } 101016179Sralph 101116179Sralph NODE * 101216179Sralph ptmatch(p) register NODE *p; { 101316179Sralph 101416179Sralph /* makes the operands of p agree; they are 101516179Sralph either pointers or integers, by this time */ 101616179Sralph /* with MINUS, the sizes must be the same */ 101716179Sralph /* with COLON, the types must be the same */ 101816179Sralph 101916179Sralph TWORD t1, t2, t; 102016179Sralph int o, d2, d, s2, s; 102116179Sralph 102216179Sralph o = p->in.op; 102316179Sralph t = t1 = p->in.left->in.type; 102416179Sralph t2 = p->in.right->in.type; 102516179Sralph d = p->in.left->fn.cdim; 102616179Sralph d2 = p->in.right->fn.cdim; 102716179Sralph s = p->in.left->fn.csiz; 102816179Sralph s2 = p->in.right->fn.csiz; 102916179Sralph 103016179Sralph switch( o ){ 103116179Sralph 103216179Sralph case ASSIGN: 103316179Sralph case RETURN: 103416179Sralph case CAST: 103516179Sralph { break; } 103616179Sralph 103716179Sralph case MINUS: 103816179Sralph { if( psize(p->in.left) != psize(p->in.right) ){ 103916179Sralph uerror( "illegal pointer subtraction"); 104016179Sralph } 104116179Sralph break; 104216179Sralph } 104316179Sralph case COLON: 104416179Sralph { if( t1 != t2 ) uerror( "illegal types in :"); 104516179Sralph break; 104616179Sralph } 104716179Sralph default: /* must work harder: relationals or comparisons */ 104816179Sralph 104916179Sralph if( !ISPTR(t1) ){ 105016179Sralph t = t2; 105116179Sralph d = d2; 105216179Sralph s = s2; 105316179Sralph break; 105416179Sralph } 105516179Sralph if( !ISPTR(t2) ){ 105616179Sralph break; 105716179Sralph } 105816179Sralph 105916179Sralph /* both are pointers */ 106016179Sralph if( talign(t2,s2) < talign(t,s) ){ 106116179Sralph t = t2; 106216179Sralph s = s2; 106316179Sralph } 106416179Sralph break; 106516179Sralph } 106616179Sralph 106716179Sralph p->in.left = makety( p->in.left, t, d, s ); 106816179Sralph p->in.right = makety( p->in.right, t, d, s ); 106916179Sralph if( o!=MINUS && !logop(o) ){ 107016179Sralph 107116179Sralph p->in.type = t; 107216179Sralph p->fn.cdim = d; 107316179Sralph p->fn.csiz = s; 107416179Sralph } 107516179Sralph 107616179Sralph return(clocal(p)); 107716179Sralph } 107816179Sralph 107916179Sralph int tdebug = 0; 108016179Sralph 108116179Sralph NODE * 108216179Sralph tymatch(p) register NODE *p; { 108316179Sralph 108416179Sralph /* satisfy the types of various arithmetic binary ops */ 108516179Sralph 108616179Sralph /* rules are: 1087*25750Sdonn if assignment, type of LHS 108816179Sralph if any float or doubles, make double 108916179Sralph if any longs, make long 109016179Sralph otherwise, make int 109116179Sralph if either operand is unsigned, the result is... 109216179Sralph */ 109316179Sralph 109416179Sralph register TWORD t1, t2, t, tu; 109516179Sralph register o, u; 109616179Sralph 109716179Sralph o = p->in.op; 109816179Sralph 109916179Sralph t1 = p->in.left->in.type; 110016179Sralph t2 = p->in.right->in.type; 110116179Sralph if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 110216179Sralph uerror("void type illegal in expression"); 110316179Sralph 110416179Sralph u = 0; 110516179Sralph if( ISUNSIGNED(t1) ){ 110616179Sralph u = 1; 110716179Sralph t1 = DEUNSIGN(t1); 110816179Sralph } 110916179Sralph if( ISUNSIGNED(t2) ){ 111016179Sralph u = 1; 111116179Sralph t2 = DEUNSIGN(t2); 111216179Sralph } 111316179Sralph 111416179Sralph if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 111516179Sralph if( t2 == CHAR || t2 == SHORT ) t2 = INT; 111616179Sralph 111717749Sralph #ifdef SPRECC 111817749Sralph if( t1 == DOUBLE || t2 == DOUBLE ) 111917749Sralph t = DOUBLE; 112017749Sralph else if( t1 == FLOAT || t2 == FLOAT ) 112117749Sralph t = FLOAT; 112217749Sralph #else 112317749Sralph if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT) 112417749Sralph t = DOUBLE; 112517749Sralph #endif 112616179Sralph else if( t1==LONG || t2==LONG ) t = LONG; 112716179Sralph else t = INT; 112816179Sralph 1129*25750Sdonn if( o == ASSIGN || o == CAST || o == RETURN ){ 113016179Sralph tu = p->in.left->in.type; 113116179Sralph t = t1; 113216179Sralph } 113316179Sralph else { 113416179Sralph tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 113516179Sralph } 113616179Sralph 113716179Sralph /* because expressions have values that are at least as wide 113816179Sralph as INT or UNSIGNED, the only conversions needed 113916179Sralph are those involving FLOAT/DOUBLE, and those 114016179Sralph from LONG to INT and ULONG to UNSIGNED */ 114116179Sralph 1142*25750Sdonn if( t != t1 && ! asgop(o) ) 1143*25750Sdonn p->in.left = makety( p->in.left, tu, 0, (int)tu ); 114416179Sralph 1145*25750Sdonn if( t != t2 || o==CAST ) 1146*25750Sdonn p->in.right = makety( p->in.right, tu, 0, (int)tu ); 114716179Sralph 114816179Sralph if( asgop(o) ){ 114916179Sralph p->in.type = p->in.left->in.type; 115016179Sralph p->fn.cdim = p->in.left->fn.cdim; 115116179Sralph p->fn.csiz = p->in.left->fn.csiz; 115216179Sralph } 115316179Sralph else if( !logop(o) ){ 115416179Sralph p->in.type = tu; 115516179Sralph p->fn.cdim = 0; 115616179Sralph p->fn.csiz = t; 115716179Sralph } 115816179Sralph 115916179Sralph # ifndef BUG1 116016179Sralph if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 116116179Sralph # endif 116216179Sralph 116316179Sralph return(p); 116416179Sralph } 116516179Sralph 116616179Sralph NODE * 116716179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; { 116816179Sralph /* make p into type t by inserting a conversion */ 116916179Sralph 117016179Sralph if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 117116179Sralph if( t == p->in.type ){ 117216179Sralph p->fn.cdim = d; 117316179Sralph p->fn.csiz = s; 117416179Sralph return( p ); 117516179Sralph } 117616179Sralph 117716179Sralph if( t & TMASK ){ 117816179Sralph /* non-simple type */ 117917228Sralph return( block( PCONV, p, NIL, t, d, s ) ); 118016179Sralph } 118116179Sralph 118216179Sralph if( p->in.op == ICON ){ 118317749Sralph if (t == DOUBLE) { 118417749Sralph p->in.op = DCON; 118517749Sralph if (ISUNSIGNED(p->in.type)) 118617749Sralph p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval; 118717749Sralph else 118817749Sralph p->dpn.dval = p->tn.lval; 118917749Sralph p->in.type = p->fn.csiz = t; 119017749Sralph return (clocal(p)); 119117749Sralph } 119217749Sralph if (t == FLOAT) { 119316179Sralph p->in.op = FCON; 119416179Sralph if( ISUNSIGNED(p->in.type) ){ 119517749Sralph p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval; 119616179Sralph } 119716179Sralph else { 119817749Sralph p->fpn.fval = p->tn.lval; 119916179Sralph } 120016179Sralph 120116179Sralph p->in.type = p->fn.csiz = t; 120216179Sralph return( clocal(p) ); 120316179Sralph } 120416179Sralph } 120517749Sralph else if (p->in.op == FCON && t == DOUBLE) { 120617749Sralph double db; 120716179Sralph 120817749Sralph p->in.op = DCON; 120917749Sralph db = p->fpn.fval; 121017749Sralph p->dpn.dval = db; 121117749Sralph p->in.type = p->fn.csiz = t; 121217749Sralph return (clocal(p)); 121317749Sralph } else if (p->in.op == DCON && t == FLOAT) { 121417749Sralph float fl; 121517749Sralph 121617749Sralph p->in.op = FCON; 121717749Sralph fl = p->dpn.dval; 121817749Sralph #ifdef notdef 121917749Sralph if (fl != p->dpn.dval) 122017749Sralph werror("float conversion loses precision"); 122117749Sralph #endif 122217749Sralph p->fpn.fval = fl; 122317749Sralph p->in.type = p->fn.csiz = t; 122417749Sralph return (clocal(p)); 122517749Sralph } 122617749Sralph 122717049Sralph return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); 122816179Sralph 122916179Sralph } 123016179Sralph 123116179Sralph NODE * 123216179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 123316179Sralph 123416179Sralph register NODE *p; 123516179Sralph 123616179Sralph p = talloc(); 123716179Sralph p->in.op = o; 123816179Sralph p->in.left = l; 123916179Sralph p->in.right = r; 124016179Sralph p->in.type = t; 124116179Sralph p->fn.cdim = d; 124216179Sralph p->fn.csiz = s; 124316179Sralph return(p); 124416179Sralph } 124516179Sralph 124616179Sralph icons(p) register NODE *p; { 124716179Sralph /* if p is an integer constant, return its value */ 124816179Sralph int val; 124916179Sralph 125016179Sralph if( p->in.op != ICON ){ 125116179Sralph uerror( "constant expected"); 125216179Sralph val = 1; 125316179Sralph } 125416179Sralph else { 125516179Sralph val = p->tn.lval; 125616179Sralph if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 125716179Sralph } 125816179Sralph tfree( p ); 125916179Sralph return(val); 126016179Sralph } 126116179Sralph 126216179Sralph /* the intent of this table is to examine the 126316179Sralph operators, and to check them for 126416179Sralph correctness. 126516179Sralph 126616179Sralph The table is searched for the op and the 126716179Sralph modified type (where this is one of the 126816179Sralph types INT (includes char and short), LONG, 126916179Sralph DOUBLE (includes FLOAT), and POINTER 127016179Sralph 127116179Sralph The default action is to make the node type integer 127216179Sralph 127316179Sralph The actions taken include: 127416179Sralph PUN check for puns 127516179Sralph CVTL convert the left operand 127616179Sralph CVTR convert the right operand 127716179Sralph TYPL the type is determined by the left operand 127816179Sralph TYPR the type is determined by the right operand 127916179Sralph TYMATCH force type of left and right to match, by inserting conversions 128016179Sralph PTMATCH like TYMATCH, but for pointers 128116179Sralph LVAL left operand must be lval 128216179Sralph CVTO convert the op 128316179Sralph NCVT do not convert the operands 128416179Sralph OTHER handled by code 128516179Sralph NCVTR convert the left operand, not the right... 128616179Sralph 128716179Sralph */ 128816179Sralph 128916179Sralph # define MINT 01 /* integer */ 129016179Sralph # define MDBI 02 /* integer or double */ 129116179Sralph # define MSTR 04 /* structure */ 129216179Sralph # define MPTR 010 /* pointer */ 129316179Sralph # define MPTI 020 /* pointer or integer */ 129416179Sralph # define MENU 040 /* enumeration variable or member */ 129524408Smckusick # define MVOID 0100000 /* void type */ 129616179Sralph 129716179Sralph opact( p ) NODE *p; { 129816179Sralph 129916179Sralph register mt12, mt1, mt2, o; 130016179Sralph 130124408Smckusick mt1 = mt2 = mt12 = 0; 130216179Sralph 130316179Sralph switch( optype(o=p->in.op) ){ 130416179Sralph 130516179Sralph case BITYPE: 130624408Smckusick mt2 = moditype( p->in.right->in.type ); 130716179Sralph case UTYPE: 130824408Smckusick mt1 = moditype( p->in.left->in.type ); 130924408Smckusick break; 131016179Sralph 131116179Sralph } 131216179Sralph 131324408Smckusick if( ((mt1 | mt2) & MVOID) && 131424408Smckusick o != COMOP && 131524408Smckusick !(o == CAST && (mt1 & MVOID)) ){ 131624408Smckusick /* if lhs of RETURN is void, grammar will complain */ 131724408Smckusick if( o != RETURN ) 131824408Smckusick uerror( "value of void expression used" ); 131924408Smckusick return( NCVT ); 132024408Smckusick } 132124408Smckusick mt1 &= ~MVOID; 132224408Smckusick mt2 &= ~MVOID; 132324408Smckusick mt12 = mt1 & mt2; 132424408Smckusick 132516179Sralph switch( o ){ 132616179Sralph 132716179Sralph case NAME : 132816179Sralph case STRING : 132916179Sralph case ICON : 133016179Sralph case FCON : 133117749Sralph case DCON : 133216179Sralph case CALL : 133316179Sralph case UNARY CALL: 133416179Sralph case UNARY MUL: 133516179Sralph { return( OTHER ); } 133616179Sralph case UNARY MINUS: 133716179Sralph if( mt1 & MDBI ) return( TYPL ); 133816179Sralph break; 133916179Sralph 134016179Sralph case COMPL: 134116179Sralph if( mt1 & MINT ) return( TYPL ); 134216179Sralph break; 134316179Sralph 134416179Sralph case UNARY AND: 134516179Sralph { return( NCVT+OTHER ); } 134616179Sralph case INIT: 134716179Sralph case CM: 134816180Sralph return( 0 ); 134916180Sralph 135016179Sralph case NOT: 135116179Sralph case CBRANCH: 135216180Sralph if( mt1 & MSTR ) break; 135316180Sralph return( 0 ); 135416180Sralph 135516179Sralph case ANDAND: 135616179Sralph case OROR: 135716180Sralph if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 135816179Sralph return( 0 ); 135916179Sralph 136016179Sralph case MUL: 136116179Sralph case DIV: 136216179Sralph if( mt12 & MDBI ) return( TYMATCH ); 136316179Sralph break; 136416179Sralph 136516179Sralph case MOD: 136616179Sralph case AND: 136716179Sralph case OR: 136816179Sralph case ER: 136916179Sralph if( mt12 & MINT ) return( TYMATCH ); 137016179Sralph break; 137116179Sralph 137216179Sralph case LS: 137316179Sralph case RS: 137416179Sralph if( mt12 & MINT ) return( TYMATCH+OTHER ); 137516179Sralph break; 137616179Sralph 137716179Sralph case EQ: 137816179Sralph case NE: 137916179Sralph case LT: 138016179Sralph case LE: 138116179Sralph case GT: 138216179Sralph case GE: 138316179Sralph if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 138416179Sralph if( mt12 & MDBI ) return( TYMATCH+CVTO ); 138516179Sralph else if( mt12 & MPTR ) return( PTMATCH+PUN ); 138616179Sralph else if( mt12 & MPTI ) return( PTMATCH+PUN ); 138716179Sralph else break; 138816179Sralph 138916179Sralph case QUEST: 139016179Sralph case COMOP: 139116179Sralph if( mt2&MENU ) return( TYPR+NCVTR ); 139216179Sralph return( TYPR ); 139316179Sralph 139416179Sralph case STREF: 139516179Sralph return( NCVTR+OTHER ); 139616179Sralph 139716179Sralph case FORCE: 139816179Sralph return( TYPL ); 139916179Sralph 140016179Sralph case COLON: 140116179Sralph if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 140216179Sralph else if( mt12 & MDBI ) return( TYMATCH ); 140316179Sralph else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 140416179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 140516179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 140616179Sralph else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 140716179Sralph break; 140816179Sralph 140916179Sralph case ASSIGN: 141016179Sralph case RETURN: 141116179Sralph if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 141216179Sralph case CAST: 141316179Sralph if(o==CAST && mt1==0)return(TYPL+TYMATCH); 141416179Sralph if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 141516179Sralph else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 141618436Smckusick else if( mt2 == 0 && 141718436Smckusick ( p->in.right->in.op == CALL || 141818436Smckusick p->in.right->in.op == UNARY CALL)) break; 141916179Sralph else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 142016179Sralph else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 142116179Sralph break; 142216179Sralph 142316179Sralph case ASG LS: 142416179Sralph case ASG RS: 142516179Sralph if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 142616179Sralph break; 142716179Sralph 142816179Sralph case ASG MUL: 142916179Sralph case ASG DIV: 143016179Sralph if( mt12 & MDBI ) return( LVAL+TYMATCH ); 143116179Sralph break; 143216179Sralph 143316179Sralph case ASG MOD: 143416179Sralph case ASG AND: 143516179Sralph case ASG OR: 143616179Sralph case ASG ER: 143716179Sralph if( mt12 & MINT ) return( LVAL+TYMATCH ); 143816179Sralph break; 143916179Sralph 144016179Sralph case ASG PLUS: 144116179Sralph case ASG MINUS: 144216179Sralph case INCR: 144316179Sralph case DECR: 144416179Sralph if( mt12 & MDBI ) return( TYMATCH+LVAL ); 144516179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 144616179Sralph break; 144716179Sralph 144816179Sralph case MINUS: 144916179Sralph if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 145016179Sralph if( mt2 & MPTR ) break; 145116179Sralph case PLUS: 145216179Sralph if( mt12 & MDBI ) return( TYMATCH ); 145316179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 145416179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 145516179Sralph 145616179Sralph } 145724408Smckusick if( mt12 == MSTR ) 145824408Smckusick uerror( "%s is not a permitted struct/union operation", opst[o] ); 145924408Smckusick else 146024408Smckusick uerror( "operands of %s have incompatible types", opst[o] ); 146116179Sralph return( NCVT ); 146216179Sralph } 146316179Sralph 146416179Sralph moditype( ty ) TWORD ty; { 146516179Sralph 146616179Sralph switch( ty ){ 146716179Sralph 146816179Sralph case TVOID: 146917206Sralph return( MPTR ); 147016179Sralph case UNDEF: 147124408Smckusick return( MVOID ); 147216179Sralph case ENUMTY: 147316179Sralph case MOETY: 147416179Sralph return( MENU ); 147516179Sralph 147616179Sralph case STRTY: 147716179Sralph case UNIONTY: 147816179Sralph return( MSTR ); 147916179Sralph 148016179Sralph case CHAR: 148116179Sralph case SHORT: 148216179Sralph case UCHAR: 148316179Sralph case USHORT: 148416179Sralph return( MINT|MPTI|MDBI ); 148516179Sralph case UNSIGNED: 148616179Sralph case ULONG: 148716179Sralph case INT: 148816179Sralph case LONG: 148916179Sralph return( MINT|MDBI|MPTI ); 149016179Sralph case FLOAT: 149116179Sralph case DOUBLE: 149216179Sralph return( MDBI ); 149316179Sralph default: 149416179Sralph return( MPTR|MPTI ); 149516179Sralph 149616179Sralph } 149716179Sralph } 149816179Sralph 149916179Sralph NODE * 150016179Sralph doszof( p ) register NODE *p; { 150116179Sralph /* do sizeof p */ 150216179Sralph int i; 150316179Sralph 150416179Sralph /* whatever is the meaning of this if it is a bitfield? */ 150516179Sralph i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 150616179Sralph 150716179Sralph tfree(p); 150816179Sralph if( i <= 0 ) werror( "sizeof returns 0" ); 150916179Sralph return( bcon( i ) ); 151016179Sralph } 151116179Sralph 151216179Sralph # ifndef BUG2 151316179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; { 151416179Sralph register ty; 151516179Sralph 151616179Sralph *a = *b = down+1; 151716179Sralph while( down > 1 ){ 151816179Sralph printf( "\t" ); 151916179Sralph down -= 2; 152016179Sralph } 152116179Sralph if( down ) printf( " " ); 152216179Sralph 152316179Sralph ty = optype( p->in.op ); 152416179Sralph 152516179Sralph printf("%o) %s, ", p, opst[p->in.op] ); 152616179Sralph if( ty == LTYPE ){ 152716179Sralph printf( CONFMT, p->tn.lval ); 152816179Sralph printf( ", %d, ", p->tn.rval ); 152916179Sralph } 153016179Sralph tprint( p->in.type ); 153116179Sralph printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 153216179Sralph } 153316179Sralph # endif 153416179Sralph 153516179Sralph prtdcon( p ) register NODE *p; { 153617749Sralph int o = p->in.op, i; 153716179Sralph 153817749Sralph if( o == DCON || o == FCON ){ 153916179Sralph locctr( DATA ); 154017749Sralph defalign( o == DCON ? ALDOUBLE : ALFLOAT ); 154116179Sralph deflab( i = getlab() ); 154217749Sralph if( o == FCON ) 154317749Sralph fincode( p->fpn.fval, SZFLOAT ); 154417749Sralph else 154517749Sralph fincode( p->dpn.dval, SZDOUBLE ); 154616179Sralph p->tn.lval = 0; 154716179Sralph p->tn.rval = -i; 154817749Sralph p->in.type = (o == DCON ? DOUBLE : FLOAT); 154916179Sralph p->in.op = NAME; 155016179Sralph } 155116179Sralph } 155216179Sralph 155316179Sralph 155416179Sralph int edebug = 0; 155516179Sralph ecomp( p ) register NODE *p; { 155616179Sralph # ifndef BUG2 155716179Sralph if( edebug ) fwalk( p, eprint, 0 ); 155816179Sralph # endif 155916179Sralph if( !reached ){ 156016179Sralph werror( "statement not reached" ); 156116179Sralph reached = 1; 156216179Sralph } 156316179Sralph p = optim(p); 156416179Sralph walkf( p, prtdcon ); 156516179Sralph locctr( PROG ); 156616179Sralph ecode( p ); 156716179Sralph tfree(p); 156816179Sralph } 156916179Sralph 157016179Sralph # ifdef STDPRTREE 157116179Sralph # ifndef ONEPASS 157216179Sralph 157316179Sralph prtree(p) register NODE *p; { 157416179Sralph 157516179Sralph register struct symtab *q; 157616179Sralph register ty; 157716179Sralph 157816179Sralph # ifdef MYPRTREE 157916179Sralph MYPRTREE(p); /* local action can be taken here; then return... */ 158016179Sralph #endif 158116179Sralph 158216179Sralph ty = optype(p->in.op); 158316179Sralph 158416179Sralph printf( "%d\t", p->in.op ); 158516179Sralph 158616179Sralph if( ty == LTYPE ) { 158716179Sralph printf( CONFMT, p->tn.lval ); 158816179Sralph printf( "\t" ); 158916179Sralph } 159016179Sralph if( ty != BITYPE ) { 159116179Sralph if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 159216179Sralph else printf( "%d\t", p->tn.rval ); 159316179Sralph } 159416179Sralph 159516179Sralph printf( "%o\t", p->in.type ); 159616179Sralph 159716179Sralph /* handle special cases */ 159816179Sralph 159916179Sralph switch( p->in.op ){ 160016179Sralph 160116179Sralph case NAME: 160216179Sralph case ICON: 160316179Sralph /* print external name */ 160416179Sralph if( p->tn.rval == NONAME ) printf( "\n" ); 160516179Sralph else if( p->tn.rval >= 0 ){ 160616179Sralph q = &stab[p->tn.rval]; 160716179Sralph printf( "%s\n", exname(q->sname) ); 160816179Sralph } 160916179Sralph else { /* label */ 161016179Sralph printf( LABFMT, -p->tn.rval ); 161116179Sralph } 161216179Sralph break; 161316179Sralph 161416179Sralph case STARG: 161516179Sralph case STASG: 161616179Sralph case STCALL: 161716179Sralph case UNARY STCALL: 161816179Sralph /* print out size */ 161916179Sralph /* use lhs size, in order to avoid hassles with the structure `.' operator */ 162016179Sralph 162116179Sralph /* note: p->in.left not a field... */ 162216179Sralph printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 162316179Sralph printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 162416179Sralph break; 162516179Sralph 162616179Sralph default: 162716179Sralph printf( "\n" ); 162816179Sralph } 162916179Sralph 163016179Sralph if( ty != LTYPE ) prtree( p->in.left ); 163116179Sralph if( ty == BITYPE ) prtree( p->in.right ); 163216179Sralph 163316179Sralph } 163416179Sralph 163516179Sralph # else 163616179Sralph 163716179Sralph p2tree(p) register NODE *p; { 163816179Sralph register ty; 163916179Sralph 164016179Sralph # ifdef MYP2TREE 164116179Sralph MYP2TREE(p); /* local action can be taken here; then return... */ 164216179Sralph # endif 164316179Sralph 164416179Sralph ty = optype(p->in.op); 164516179Sralph 164616179Sralph switch( p->in.op ){ 164716179Sralph 164816179Sralph case NAME: 164916179Sralph case ICON: 165016179Sralph #ifndef FLEXNAMES 165116179Sralph if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 165216179Sralph #else 165316179Sralph if( p->tn.rval == NONAME ) p->in.name = ""; 165416179Sralph #endif 165516179Sralph else if( p->tn.rval >= 0 ){ /* copy name from exname */ 165616179Sralph register char *cp; 165716179Sralph register i; 165816179Sralph cp = exname( stab[p->tn.rval].sname ); 165916179Sralph #ifndef FLEXNAMES 166016179Sralph for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 166116179Sralph #else 166216179Sralph p->in.name = tstr(cp); 166316179Sralph #endif 166416179Sralph } 166516179Sralph #ifndef FLEXNAMES 166616179Sralph else sprintf( p->in.name, LABFMT, -p->tn.rval ); 166716179Sralph #else 166816179Sralph else { 166916179Sralph char temp[32]; 167016179Sralph sprintf( temp, LABFMT, -p->tn.rval ); 167116179Sralph p->in.name = tstr(temp); 167216179Sralph } 167316179Sralph #endif 167416179Sralph break; 167516179Sralph 167616179Sralph case STARG: 167716179Sralph case STASG: 167816179Sralph case STCALL: 167916179Sralph case UNARY STCALL: 168016179Sralph /* set up size parameters */ 168116179Sralph p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 168216179Sralph p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 168316179Sralph break; 168416179Sralph 168516179Sralph case REG: 168616179Sralph rbusy( p->tn.rval, p->in.type ); 168716179Sralph default: 168816179Sralph #ifndef FLEXNAMES 168916179Sralph p->in.name[0] = '\0'; 169016179Sralph #else 169116179Sralph p->in.name = ""; 169216179Sralph #endif 169316179Sralph } 169416179Sralph 169516179Sralph p->in.rall = NOPREF; 169616179Sralph 169716179Sralph if( ty != LTYPE ) p2tree( p->in.left ); 169816179Sralph if( ty == BITYPE ) p2tree( p->in.right ); 169916179Sralph } 170016179Sralph 170116179Sralph # endif 170216179Sralph # endif 1703