1*17228Sralph static char *sccsid ="@(#)trees.c 4.5 (Berkeley) 10/03/84"; 216179Sralph # include "mfile1" 316179Sralph 416179Sralph /* corrections when in violation of lint */ 516179Sralph 616179Sralph /* some special actions, used in finding the type of nodes */ 716179Sralph # define NCVT 01 816179Sralph # define PUN 02 916179Sralph # define TYPL 04 1016179Sralph # define TYPR 010 1116179Sralph # define TYMATCH 040 1216179Sralph # define LVAL 0100 1316179Sralph # define CVTO 0200 1416179Sralph # define CVTL 0400 1516179Sralph # define CVTR 01000 1616179Sralph # define PTMATCH 02000 1716179Sralph # define OTHER 04000 1816179Sralph # define NCVTR 010000 1916179Sralph 2016179Sralph /* node conventions: 2116179Sralph 2216179Sralph NAME: rval>0 is stab index for external 2316179Sralph rval<0 is -inlabel number 2416179Sralph lval is offset in bits 2516179Sralph ICON: lval has the value 2616179Sralph rval has the STAB index, or - label number, 2716179Sralph if a name whose address is in the constant 2816179Sralph rval = NONAME means no name 2916179Sralph REG: rval is reg. identification cookie 3016179Sralph 3116179Sralph */ 3216179Sralph 3316179Sralph int bdebug = 0; 3416179Sralph extern ddebug; 3516179Sralph 3616179Sralph NODE * 3716179Sralph buildtree( o, l, r ) register NODE *l, *r; { 3816179Sralph register NODE *p, *q; 3916179Sralph register actions; 4016179Sralph register opty; 4116179Sralph register struct symtab *sp; 4216179Sralph register NODE *lr, *ll; 4316179Sralph int i; 4416179Sralph extern int eprint(); 4516179Sralph 4616179Sralph # ifndef BUG1 4716179Sralph if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r ); 4816179Sralph # endif 4916179Sralph opty = optype(o); 5016179Sralph 5116179Sralph /* check for constants */ 5216179Sralph 5316179Sralph if( opty == UTYPE && l->in.op == ICON ){ 5416179Sralph 5516179Sralph switch( o ){ 5616179Sralph 5716179Sralph case NOT: 5816179Sralph if( hflag ) werror( "constant argument to NOT" ); 5916179Sralph case UNARY MINUS: 6016179Sralph case COMPL: 6116179Sralph if( conval( l, o, l ) ) return(l); 6216179Sralph break; 6316179Sralph 6416179Sralph } 6516179Sralph } 6616179Sralph 6716179Sralph else if( o==UNARY MINUS && l->in.op==FCON ){ 6816179Sralph l->fpn.dval = -l->fpn.dval; 6916179Sralph return(l); 7016179Sralph } 7116179Sralph 7216179Sralph else if( o==QUEST && l->in.op==ICON ) { 7316179Sralph l->in.op = FREE; 7416179Sralph r->in.op = FREE; 7516179Sralph if( l->tn.lval ){ 7616179Sralph tfree( r->in.right ); 7716179Sralph return( r->in.left ); 7816179Sralph } 7916179Sralph else { 8016179Sralph tfree( r->in.left ); 8116179Sralph return( r->in.right ); 8216179Sralph } 8316179Sralph } 8416179Sralph 8516179Sralph else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn; 8616179Sralph 8716179Sralph else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){ 8816179Sralph 8916179Sralph switch( o ){ 9016179Sralph 9116179Sralph case ULT: 9216179Sralph case UGT: 9316179Sralph case ULE: 9416179Sralph case UGE: 9516179Sralph case LT: 9616179Sralph case GT: 9716179Sralph case LE: 9816179Sralph case GE: 9916179Sralph case EQ: 10016179Sralph case NE: 10116179Sralph case ANDAND: 10216179Sralph case OROR: 10316179Sralph case CBRANCH: 10416179Sralph 10516179Sralph ccwarn: 10616179Sralph if( hflag ) werror( "constant in conditional context" ); 10716179Sralph 10816179Sralph case PLUS: 10916179Sralph case MINUS: 11016179Sralph case MUL: 11116179Sralph case DIV: 11216179Sralph case MOD: 11316179Sralph case AND: 11416179Sralph case OR: 11516179Sralph case ER: 11616179Sralph case LS: 11716179Sralph case RS: 11816179Sralph if( conval( l, o, r ) ) { 11916179Sralph r->in.op = FREE; 12016179Sralph return(l); 12116179Sralph } 12216179Sralph break; 12316179Sralph } 12416179Sralph } 12516179Sralph 12616179Sralph else if( opty == BITYPE && (l->in.op==FCON||l->in.op==ICON) && 12716179Sralph (r->in.op==FCON||r->in.op==ICON) ){ 12816179Sralph switch(o){ 12916179Sralph case PLUS: 13016179Sralph case MINUS: 13116179Sralph case MUL: 13216179Sralph case DIV: 13316179Sralph if( l->in.op == ICON ){ 13416179Sralph l->fpn.dval = l->tn.lval; 13516179Sralph } 13616179Sralph if( r->in.op == ICON ){ 13716179Sralph r->fpn.dval = r->tn.lval; 13816179Sralph } 13916179Sralph l->in.op = FCON; 14016179Sralph l->in.type = l->fn.csiz = DOUBLE; 14116179Sralph r->in.op = FREE; 14216179Sralph switch(o){ 14316179Sralph case PLUS: 14416179Sralph l->fpn.dval += r->fpn.dval; 14516179Sralph return(l); 14616179Sralph case MINUS: 14716179Sralph l->fpn.dval -= r->fpn.dval; 14816179Sralph return(l); 14916179Sralph case MUL: 15016179Sralph l->fpn.dval *= r->fpn.dval; 15116179Sralph return(l); 15216179Sralph case DIV: 15316179Sralph if( r->fpn.dval == 0 ) uerror( "division by 0." ); 15416179Sralph else l->fpn.dval /= r->fpn.dval; 15516179Sralph return(l); 15616179Sralph } 15716179Sralph } 15816179Sralph } 15916179Sralph 16016179Sralph /* its real; we must make a new node */ 16116179Sralph 16216179Sralph p = block( o, l, r, INT, 0, INT ); 16316179Sralph 16416179Sralph actions = opact(p); 16516179Sralph 16616179Sralph if( actions&LVAL ){ /* check left descendent */ 16716179Sralph if( notlval(p->in.left) ) { 16816179Sralph uerror( "illegal lhs of assignment operator" ); 16916179Sralph } 17016179Sralph } 17116179Sralph 17216179Sralph if( actions & NCVTR ){ 17316179Sralph p->in.left = pconvert( p->in.left ); 17416179Sralph } 17516179Sralph else if( !(actions & NCVT ) ){ 17616179Sralph switch( opty ){ 17716179Sralph 17816179Sralph case BITYPE: 17916179Sralph p->in.right = pconvert( p->in.right ); 18016179Sralph case UTYPE: 18116179Sralph p->in.left = pconvert( p->in.left ); 18216179Sralph 18316179Sralph } 18416179Sralph } 18516179Sralph 18616179Sralph if( (actions&PUN) && (o!=CAST||cflag) ){ 18716179Sralph chkpun(p); 18816179Sralph } 18916179Sralph 19016179Sralph if( actions & (TYPL|TYPR) ){ 19116179Sralph 19216179Sralph q = (actions&TYPL) ? p->in.left : p->in.right; 19316179Sralph 19416179Sralph p->in.type = q->in.type; 19516179Sralph p->fn.cdim = q->fn.cdim; 19616179Sralph p->fn.csiz = q->fn.csiz; 19716179Sralph } 19816179Sralph 19916179Sralph if( actions & CVTL ) p = convert( p, CVTL ); 20016179Sralph if( actions & CVTR ) p = convert( p, CVTR ); 20116179Sralph if( actions & TYMATCH ) p = tymatch(p); 20216179Sralph if( actions & PTMATCH ) p = ptmatch(p); 20316179Sralph 20416179Sralph if( actions & OTHER ){ 20516179Sralph l = p->in.left; 20616179Sralph r = p->in.right; 20716179Sralph 20816179Sralph switch(o){ 20916179Sralph 21016179Sralph case NAME: 21116179Sralph sp = &stab[idname]; 21216179Sralph if( sp->stype == UNDEF ){ 21316179Sralph #ifndef FLEXNAMES 21416179Sralph uerror( "%.8s undefined", sp->sname ); 21516179Sralph #else 21616179Sralph uerror( "%s undefined", sp->sname ); 21716179Sralph #endif 21816179Sralph /* make p look reasonable */ 21916179Sralph p->in.type = p->fn.cdim = p->fn.csiz = INT; 22016179Sralph p->tn.rval = idname; 22116179Sralph p->tn.lval = 0; 22216179Sralph defid( p, SNULL ); 22316179Sralph break; 22416179Sralph } 22516179Sralph p->in.type = sp->stype; 22616179Sralph p->fn.cdim = sp->dimoff; 22716179Sralph p->fn.csiz = sp->sizoff; 22816179Sralph p->tn.lval = 0; 22916179Sralph p->tn.rval = idname; 23016179Sralph /* special case: MOETY is really an ICON... */ 23116179Sralph if( p->in.type == MOETY ){ 23216179Sralph p->tn.rval = NONAME; 23316179Sralph p->tn.lval = sp->offset; 23416179Sralph p->fn.cdim = 0; 23516179Sralph p->in.type = ENUMTY; 23616179Sralph p->in.op = ICON; 23716179Sralph } 23816179Sralph break; 23916179Sralph 24016179Sralph case ICON: 24116179Sralph p->in.type = INT; 24216179Sralph p->fn.cdim = 0; 24316179Sralph p->fn.csiz = INT; 24416179Sralph break; 24516179Sralph 24616179Sralph case STRING: 24716179Sralph p->in.op = NAME; 24816179Sralph p->in.type = CHAR+ARY; 24916179Sralph p->tn.lval = 0; 25016179Sralph p->tn.rval = NOLAB; 25116179Sralph p->fn.cdim = curdim; 25216179Sralph p->fn.csiz = CHAR; 25316179Sralph break; 25416179Sralph 25516179Sralph case FCON: 25616179Sralph p->tn.lval = 0; 25716179Sralph p->tn.rval = 0; 25816179Sralph p->in.type = DOUBLE; 25916179Sralph p->fn.cdim = 0; 26016179Sralph p->fn.csiz = DOUBLE; 26116179Sralph break; 26216179Sralph 26316179Sralph case STREF: 26416179Sralph /* p->x turned into *(p+offset) */ 26516179Sralph /* rhs must be a name; check correctness */ 26616179Sralph 26716179Sralph i = r->tn.rval; 26816179Sralph if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ 26916179Sralph uerror( "member of structure or union required" ); 27016179Sralph }else 27116179Sralph /* if this name is non-unique, find right one */ 27216179Sralph if( stab[i].sflags & SNONUNIQ && 27316179Sralph (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) && 27416179Sralph (l->fn.csiz +1) >= 0 ){ 27516179Sralph /* nonunique name && structure defined */ 27616179Sralph char * memnam, * tabnam; 27716179Sralph register k; 27816179Sralph int j; 27916179Sralph int memi; 28016179Sralph j=dimtab[l->fn.csiz+1]; 28116179Sralph for( ; (memi=dimtab[j]) >= 0; ++j ){ 28216179Sralph tabnam = stab[memi].sname; 28316179Sralph memnam = stab[i].sname; 28416179Sralph # ifndef BUG1 28516179Sralph if( ddebug>1 ){ 28616179Sralph #ifndef FLEXNAMES 28716179Sralph printf("member %.8s==%.8s?\n", 28816179Sralph #else 28916179Sralph printf("member %s==%s?\n", 29016179Sralph #endif 29116179Sralph memnam, tabnam); 29216179Sralph } 29316179Sralph # endif 29416179Sralph if( stab[memi].sflags & SNONUNIQ ){ 29516179Sralph #ifndef FLEXNAMES 29616179Sralph for( k=0; k<NCHNAM; ++k ){ 29716179Sralph if(*memnam++!=*tabnam) 29816179Sralph goto next; 29916179Sralph if(!*tabnam++) break; 30016179Sralph } 30116179Sralph #else 30216179Sralph if (memnam != tabnam) 30316179Sralph goto next; 30416179Sralph #endif 30516179Sralph r->tn.rval = i = memi; 30616179Sralph break; 30716179Sralph } 30816179Sralph next: continue; 30916179Sralph } 31016179Sralph if( memi < 0 ) 31116179Sralph #ifndef FLEXNAMES 31216179Sralph uerror("illegal member use: %.8s", 31316179Sralph #else 31416179Sralph uerror("illegal member use: %s", 31516179Sralph #endif 31616179Sralph stab[i].sname); 31716179Sralph } 31816179Sralph else { 31916179Sralph register j; 32016179Sralph if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){ 32116179Sralph if( stab[i].sflags & SNONUNIQ ){ 32216179Sralph uerror( "nonunique name demands struct/union or struct/union pointer" ); 32316179Sralph } 32416179Sralph else werror( "struct/union or struct/union pointer required" ); 32516179Sralph } 32616179Sralph else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" ); 32716179Sralph else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){ 32816179Sralph #ifndef FLEXNAMES 32916179Sralph werror( "illegal member use: %.8s", stab[i].sname ); 33016179Sralph #else 33116179Sralph werror( "illegal member use: %s", stab[i].sname ); 33216179Sralph #endif 33316179Sralph } 33416179Sralph } 33516179Sralph 33616179Sralph p = stref( p ); 33716179Sralph break; 33816179Sralph 33916179Sralph case UNARY MUL: 34016179Sralph if( l->in.op == UNARY AND ){ 34116179Sralph p->in.op = l->in.op = FREE; 34216179Sralph p = l->in.left; 34316179Sralph } 34416179Sralph if( !ISPTR(l->in.type))uerror("illegal indirection"); 34516179Sralph p->in.type = DECREF(l->in.type); 34616179Sralph p->fn.cdim = l->fn.cdim; 34716179Sralph p->fn.csiz = l->fn.csiz; 34816179Sralph break; 34916179Sralph 35016179Sralph case UNARY AND: 35116179Sralph switch( l->in.op ){ 35216179Sralph 35316179Sralph case UNARY MUL: 35416179Sralph p->in.op = l->in.op = FREE; 35516179Sralph p = l->in.left; 35616179Sralph case NAME: 35716179Sralph p->in.type = INCREF( l->in.type ); 35816179Sralph p->fn.cdim = l->fn.cdim; 35916179Sralph p->fn.csiz = l->fn.csiz; 36016179Sralph break; 36116179Sralph 36216179Sralph case COMOP: 36316179Sralph lr = buildtree( UNARY AND, l->in.right, NIL ); 36416179Sralph p->in.op = l->in.op = FREE; 36516179Sralph p = buildtree( COMOP, l->in.left, lr ); 36616179Sralph break; 36716179Sralph 36816179Sralph case QUEST: 36916179Sralph lr = buildtree( UNARY AND, l->in.right->in.right, NIL ); 37016179Sralph ll = buildtree( UNARY AND, l->in.right->in.left, NIL ); 37116179Sralph p->in.op = l->in.op = l->in.right->in.op = FREE; 37216179Sralph p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) ); 37316179Sralph break; 37416179Sralph 37516179Sralph # ifdef ADDROREG 37616179Sralph case OREG: 37716179Sralph /* OREG was built in clocal() 37816179Sralph * for an auto or formal parameter 37916179Sralph * now its address is being taken 38016179Sralph * local code must unwind it 38116179Sralph * back to PLUS/MINUS REG ICON 38216179Sralph * according to local conventions 38316179Sralph */ 38416179Sralph { 38516179Sralph extern NODE * addroreg(); 38616179Sralph p->in.op = FREE; 38716179Sralph p = addroreg( l ); 38816179Sralph } 38916179Sralph break; 39016179Sralph 39116179Sralph # endif 39216179Sralph default: 39316179Sralph uerror( "unacceptable operand of &" ); 39416179Sralph break; 39516179Sralph } 39616179Sralph break; 39716179Sralph 39816179Sralph case LS: 39916179Sralph case RS: 40016179Sralph case ASG LS: 40116179Sralph case ASG RS: 40216179Sralph if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT) 40316179Sralph p->in.right = makety(p->in.right, INT, 0, INT ); 40416179Sralph break; 40516179Sralph 40616179Sralph case RETURN: 40716179Sralph case ASSIGN: 40816179Sralph case CAST: 40916179Sralph /* structure assignment */ 41016179Sralph /* take the addresses of the two sides; then make an 41116179Sralph /* operator using STASG and 41216179Sralph /* the addresses of left and right */ 41316179Sralph 41416179Sralph { 41516179Sralph register TWORD t; 41616179Sralph register d, s; 41716179Sralph 41816179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" ); 41916179Sralph 42016179Sralph r = buildtree( UNARY AND, r, NIL ); 42116179Sralph t = r->in.type; 42216179Sralph d = r->fn.cdim; 42316179Sralph s = r->fn.csiz; 42416179Sralph 42516179Sralph l = block( STASG, l, r, t, d, s ); 42616179Sralph 42716179Sralph if( o == RETURN ){ 42816179Sralph p->in.op = FREE; 42916179Sralph p = l; 43016179Sralph break; 43116179Sralph } 43216179Sralph 43316179Sralph p->in.op = UNARY MUL; 43416179Sralph p->in.left = l; 43516179Sralph p->in.right = NIL; 43616179Sralph break; 43716179Sralph } 43816179Sralph case COLON: 43916179Sralph /* structure colon */ 44016179Sralph 44116179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" ); 44216179Sralph break; 44316179Sralph 44416179Sralph case CALL: 44516179Sralph p->in.right = r = strargs( p->in.right ); 44616179Sralph case UNARY CALL: 44716179Sralph if( !ISPTR(l->in.type)) uerror("illegal function"); 44816179Sralph p->in.type = DECREF(l->in.type); 44916179Sralph if( !ISFTN(p->in.type)) uerror("illegal function"); 45016179Sralph p->in.type = DECREF( p->in.type ); 45116179Sralph p->fn.cdim = l->fn.cdim; 45216179Sralph p->fn.csiz = l->fn.csiz; 45316179Sralph if( l->in.op == UNARY AND && l->in.left->in.op == NAME && 45416179Sralph l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME && 45516179Sralph ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){ 45616179Sralph p->in.op += (FORTCALL-CALL); 45716179Sralph } 45816179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 45916179Sralph /* function returning structure */ 46016179Sralph /* make function really return ptr to str., with * */ 46116179Sralph 46216179Sralph p->in.op += STCALL-CALL; 46316179Sralph p->in.type = INCREF( p->in.type ); 46416179Sralph p = buildtree( UNARY MUL, p, NIL ); 46516179Sralph 46616179Sralph } 46716179Sralph break; 46816179Sralph 46916179Sralph default: 47016179Sralph cerror( "other code %d", o ); 47116179Sralph } 47216179Sralph 47316179Sralph } 47416179Sralph 47516179Sralph if( actions & CVTO ) p = oconvert(p); 47616179Sralph p = clocal(p); 47716179Sralph 47816179Sralph # ifndef BUG1 47916179Sralph if( bdebug ) fwalk( p, eprint, 0 ); 48016179Sralph # endif 48116179Sralph 48216179Sralph return(p); 48316179Sralph 48416179Sralph } 48516179Sralph 48616179Sralph NODE * 48716179Sralph strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */ 48816179Sralph 48916179Sralph if( p->in.op == CM ){ 49016179Sralph p->in.left = strargs( p->in.left ); 49116179Sralph p->in.right = strargs( p->in.right ); 49216179Sralph return( p ); 49316179Sralph } 49416179Sralph 49516179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 49616179Sralph p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz ); 49716179Sralph p->in.left = buildtree( UNARY AND, p->in.left, NIL ); 49816179Sralph p = clocal(p); 49916179Sralph } 50016179Sralph return( p ); 50116179Sralph } 50216179Sralph 50316179Sralph chkstr( i, j, type ) TWORD type; { 50416179Sralph /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ 50516179Sralph /* i has been checked to contain a MOS or MOU */ 50616179Sralph /* j is the index in dimtab of the members... */ 50716179Sralph int k, kk; 50816179Sralph 50916179Sralph extern int ddebug; 51016179Sralph 51116179Sralph # ifndef BUG1 51216179Sralph #ifndef FLEXNAMES 51316179Sralph if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j ); 51416179Sralph #else 51516179Sralph if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j ); 51616179Sralph #endif 51716179Sralph # endif 51816179Sralph if( (k = j) < 0 ) uerror( "undefined structure or union" ); 51916179Sralph else { 52016179Sralph for( ; (kk = dimtab[k] ) >= 0; ++k ){ 52116179Sralph if( kk >= SYMTSZ ){ 52216179Sralph cerror( "gummy structure" ); 52316179Sralph return(1); 52416179Sralph } 52516179Sralph if( kk == i ) return( 1 ); 52616179Sralph switch( stab[kk].stype ){ 52716179Sralph 52816179Sralph case STRTY: 52916179Sralph case UNIONTY: 53016179Sralph if( type == STRTY ) continue; /* no recursive looking for strs */ 53116179Sralph if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){ 53216179Sralph if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */ 53316179Sralph werror( 53416179Sralph #ifndef FLEXNAMES 53516179Sralph "illegal member use: perhaps %.8s.%.8s?", 53616179Sralph #else 53716179Sralph "illegal member use: perhaps %s.%s?", 53816179Sralph #endif 53916179Sralph stab[kk].sname, stab[i].sname ); 54016179Sralph return(1); 54116179Sralph } 54216179Sralph } 54316179Sralph } 54416179Sralph } 54516179Sralph return( 0 ); 54616179Sralph } 54716179Sralph 54816179Sralph conval( p, o, q ) register NODE *p, *q; { 54916179Sralph /* apply the op o to the lval part of p; if binary, rhs is val */ 55016179Sralph int i, u; 55116179Sralph CONSZ val; 55216179Sralph 55316179Sralph val = q->tn.lval; 55416179Sralph u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type); 55516179Sralph if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); 55616179Sralph 55716179Sralph if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0); 55816179Sralph if( q->tn.rval != NONAME && o!=PLUS ) return(0); 55916179Sralph if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0); 56016179Sralph 56116179Sralph switch( o ){ 56216179Sralph 56316179Sralph case PLUS: 56416179Sralph p->tn.lval += val; 56516179Sralph if( p->tn.rval == NONAME ){ 56616179Sralph p->tn.rval = q->tn.rval; 56716179Sralph p->in.type = q->in.type; 56816179Sralph } 56916179Sralph break; 57016179Sralph case MINUS: 57116179Sralph p->tn.lval -= val; 57216179Sralph break; 57316179Sralph case MUL: 57416179Sralph p->tn.lval *= val; 57516179Sralph break; 57616179Sralph case DIV: 57716179Sralph if( val == 0 ) uerror( "division by 0" ); 57816179Sralph else p->tn.lval /= val; 57916179Sralph break; 58016179Sralph case MOD: 58116179Sralph if( val == 0 ) uerror( "division by 0" ); 58216179Sralph else p->tn.lval %= val; 58316179Sralph break; 58416179Sralph case AND: 58516179Sralph p->tn.lval &= val; 58616179Sralph break; 58716179Sralph case OR: 58816179Sralph p->tn.lval |= val; 58916179Sralph break; 59016179Sralph case ER: 59116179Sralph p->tn.lval ^= val; 59216179Sralph break; 59316179Sralph case LS: 59416179Sralph i = val; 59516179Sralph p->tn.lval = p->tn.lval << i; 59616179Sralph break; 59716179Sralph case RS: 59816179Sralph i = val; 59916179Sralph p->tn.lval = p->tn.lval >> i; 60016179Sralph break; 60116179Sralph 60216179Sralph case UNARY MINUS: 60316179Sralph p->tn.lval = - p->tn.lval; 60416179Sralph break; 60516179Sralph case COMPL: 60616179Sralph p->tn.lval = ~p->tn.lval; 60716179Sralph break; 60816179Sralph case NOT: 60916179Sralph p->tn.lval = !p->tn.lval; 61016179Sralph break; 61116179Sralph case LT: 61216179Sralph p->tn.lval = p->tn.lval < val; 61316179Sralph break; 61416179Sralph case LE: 61516179Sralph p->tn.lval = p->tn.lval <= val; 61616179Sralph break; 61716179Sralph case GT: 61816179Sralph p->tn.lval = p->tn.lval > val; 61916179Sralph break; 62016179Sralph case GE: 62116179Sralph p->tn.lval = p->tn.lval >= val; 62216179Sralph break; 62316179Sralph case ULT: 62416179Sralph p->tn.lval = (p->tn.lval-val)<0; 62516179Sralph break; 62616179Sralph case ULE: 62716179Sralph p->tn.lval = (p->tn.lval-val)<=0; 62816179Sralph break; 62916179Sralph case UGE: 63016179Sralph p->tn.lval = (p->tn.lval-val)>=0; 63116179Sralph break; 63216179Sralph case UGT: 63316179Sralph p->tn.lval = (p->tn.lval-val)>0; 63416179Sralph break; 63516179Sralph case EQ: 63616179Sralph p->tn.lval = p->tn.lval == val; 63716179Sralph break; 63816179Sralph case NE: 63916179Sralph p->tn.lval = p->tn.lval != val; 64016179Sralph break; 64116179Sralph default: 64216179Sralph return(0); 64316179Sralph } 64416179Sralph return(1); 64516179Sralph } 64616179Sralph 64716179Sralph chkpun(p) register NODE *p; { 64816179Sralph 64916179Sralph /* checks p for the existance of a pun */ 65016179Sralph 65116179Sralph /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ 65216179Sralph 65316179Sralph /* one case is when enumerations are used: this applies only to lint */ 65416179Sralph /* in the other case, one operand is a pointer, the other integer type */ 65516179Sralph /* we check that this integer is in fact a constant zero... */ 65616179Sralph 65716179Sralph /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ 65816179Sralph /* this falls out, because the LHS is never 0 */ 65916179Sralph 66016179Sralph register NODE *q; 66116179Sralph register t1, t2; 66216179Sralph register d1, d2; 66316179Sralph 66416179Sralph t1 = p->in.left->in.type; 66516179Sralph t2 = p->in.right->in.type; 66616179Sralph 66716179Sralph if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ 66816179Sralph if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) { 66916179Sralph uerror( "illegal comparison of enums" ); 67016179Sralph return; 67116179Sralph } 67216179Sralph if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return; 67316179Sralph werror( "enumeration type clash, operator %s", opst[p->in.op] ); 67416179Sralph return; 67516179Sralph } 67616179Sralph 67716179Sralph if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; 67816179Sralph else q = p->in.left; 67916179Sralph 68016179Sralph if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ 68116179Sralph if( q->in.op != ICON || q->tn.lval != 0 ){ 68216179Sralph werror( "illegal combination of pointer and integer, op %s", 68316179Sralph opst[p->in.op] ); 68416179Sralph } 68516179Sralph } 68616179Sralph else { 68716179Sralph d1 = p->in.left->fn.cdim; 68816179Sralph d2 = p->in.right->fn.cdim; 68916179Sralph for( ;; ){ 69016179Sralph if( t1 == t2 ) {; 69116179Sralph if( p->in.left->fn.csiz != p->in.right->fn.csiz ) { 69216179Sralph werror( "illegal structure pointer combination" ); 69316179Sralph } 69416179Sralph return; 69516179Sralph } 69616179Sralph if( ISARY(t1) || ISPTR(t1) ){ 69716179Sralph if( !ISARY(t2) && !ISPTR(t2) ) break; 69816179Sralph if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ 69916179Sralph werror( "illegal array size combination" ); 70016179Sralph return; 70116179Sralph } 70216179Sralph if( ISARY(t1) ) ++d1; 70316179Sralph if( ISARY(t2) ) ++d2; 70416179Sralph } 70516179Sralph else break; 70616179Sralph t1 = DECREF(t1); 70716179Sralph t2 = DECREF(t2); 70816179Sralph } 70916179Sralph werror( "illegal pointer combination" ); 71016179Sralph } 71116179Sralph 71216179Sralph } 71316179Sralph 71416179Sralph NODE * 71516179Sralph stref( p ) register NODE *p; { 71616179Sralph 71716179Sralph TWORD t; 71816179Sralph int d, s, dsc, align; 71916179Sralph OFFSZ off; 72016179Sralph register struct symtab *q; 72116179Sralph 72216179Sralph /* make p->x */ 72316179Sralph /* this is also used to reference automatic variables */ 72416179Sralph 72516179Sralph q = &stab[p->in.right->tn.rval]; 72616179Sralph p->in.right->in.op = FREE; 72716179Sralph p->in.op = FREE; 72816179Sralph p = pconvert( p->in.left ); 72916179Sralph 73016179Sralph /* make p look like ptr to x */ 73116179Sralph 73216179Sralph if( !ISPTR(p->in.type)){ 73316179Sralph p->in.type = PTR+UNIONTY; 73416179Sralph } 73516179Sralph 73616179Sralph t = INCREF( q->stype ); 73716179Sralph d = q->dimoff; 73816179Sralph s = q->sizoff; 73916179Sralph 74016179Sralph p = makety( p, t, d, s ); 74116179Sralph 74216179Sralph /* compute the offset to be added */ 74316179Sralph 74416179Sralph off = q->offset; 74516179Sralph dsc = q->sclass; 74616179Sralph 74716179Sralph if( dsc & FIELD ) { /* normalize offset */ 74816179Sralph align = ALINT; 74916179Sralph s = INT; 75016179Sralph off = (off/align)*align; 75116179Sralph } 75216179Sralph if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); 75316179Sralph 75416179Sralph p = buildtree( UNARY MUL, p, NIL ); 75516179Sralph 75616179Sralph /* if field, build field info */ 75716179Sralph 75816179Sralph if( dsc & FIELD ){ 75916179Sralph p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); 76016179Sralph p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); 76116179Sralph } 76216179Sralph 76316179Sralph return( clocal(p) ); 76416179Sralph } 76516179Sralph 76616179Sralph notlval(p) register NODE *p; { 76716179Sralph 76816179Sralph /* return 0 if p an lvalue, 1 otherwise */ 76916179Sralph 77016179Sralph again: 77116179Sralph 77216179Sralph switch( p->in.op ){ 77316179Sralph 77416179Sralph case FLD: 77516179Sralph p = p->in.left; 77616179Sralph goto again; 77716179Sralph 77816179Sralph case UNARY MUL: 77916179Sralph /* fix the &(a=b) bug, given that a and b are structures */ 78016179Sralph if( p->in.left->in.op == STASG ) return( 1 ); 78116179Sralph /* and the f().a bug, given that f returns a structure */ 78216179Sralph if( p->in.left->in.op == UNARY STCALL || 78316179Sralph p->in.left->in.op == STCALL ) return( 1 ); 78416179Sralph case NAME: 78516179Sralph case OREG: 78616179Sralph if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); 78716179Sralph case REG: 78816179Sralph return(0); 78916179Sralph 79016179Sralph default: 79116179Sralph return(1); 79216179Sralph 79316179Sralph } 79416179Sralph 79516179Sralph } 79616179Sralph 79716179Sralph NODE * 79816179Sralph bcon( i ){ /* make a constant node with value i */ 79916179Sralph register NODE *p; 80016179Sralph 80116179Sralph p = block( ICON, NIL, NIL, INT, 0, INT ); 80216179Sralph p->tn.lval = i; 80316179Sralph p->tn.rval = NONAME; 80416179Sralph return( clocal(p) ); 80516179Sralph } 80616179Sralph 80716179Sralph NODE * 80816179Sralph bpsize(p) register NODE *p; { 80916179Sralph return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); 81016179Sralph } 81116179Sralph 81216179Sralph OFFSZ 81316179Sralph psize( p ) NODE *p; { 81416179Sralph /* p is a node of type pointer; psize returns the 81516179Sralph size of the thing pointed to */ 81616179Sralph 81716179Sralph if( !ISPTR(p->in.type) ){ 81816179Sralph uerror( "pointer required"); 81916179Sralph return( SZINT ); 82016179Sralph } 82116179Sralph /* note: no pointers to fields */ 82216179Sralph return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); 82316179Sralph } 82416179Sralph 82516179Sralph NODE * 82616179Sralph convert( p, f ) register NODE *p; { 82716179Sralph /* convert an operand of p 82816179Sralph f is either CVTL or CVTR 82916179Sralph operand has type int, and is converted by the size of the other side 83016179Sralph */ 83116179Sralph 83216179Sralph register NODE *q, *r; 83316179Sralph 83416179Sralph q = (f==CVTL)?p->in.left:p->in.right; 83516179Sralph 83616179Sralph r = block( PMCONV, 83716179Sralph q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); 83816179Sralph r = clocal(r); 83916179Sralph if( f == CVTL ) 84016179Sralph p->in.left = r; 84116179Sralph else 84216179Sralph p->in.right = r; 84316179Sralph return(p); 84416179Sralph 84516179Sralph } 84616179Sralph 84716179Sralph econvert( p ) register NODE *p; { 84816179Sralph 84916179Sralph /* change enums to ints, or appropriate types */ 85016179Sralph 85116179Sralph register TWORD ty; 85216179Sralph 85316179Sralph if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 85416179Sralph if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 85516179Sralph else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 85616179Sralph else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 85716179Sralph else ty = LONG; 85816179Sralph ty = ctype( ty ); 85916179Sralph p->fn.csiz = ty; 86016179Sralph MODTYPE(p->in.type,ty); 86116179Sralph if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 86216179Sralph } 86316179Sralph } 86416179Sralph 86516179Sralph NODE * 86616179Sralph pconvert( p ) register NODE *p; { 86716179Sralph 86816179Sralph /* if p should be changed into a pointer, do so */ 86916179Sralph 87016179Sralph if( ISARY( p->in.type) ){ 87116179Sralph p->in.type = DECREF( p->in.type ); 87216179Sralph ++p->fn.cdim; 87316179Sralph return( buildtree( UNARY AND, p, NIL ) ); 87416179Sralph } 87516179Sralph if( ISFTN( p->in.type) ) 87616179Sralph return( buildtree( UNARY AND, p, NIL ) ); 87716179Sralph 87816179Sralph return( p ); 87916179Sralph } 88016179Sralph 88116179Sralph NODE * 88216179Sralph oconvert(p) register NODE *p; { 88316179Sralph /* convert the result itself: used for pointer and unsigned */ 88416179Sralph 88516179Sralph switch(p->in.op) { 88616179Sralph 88716179Sralph case LE: 88816179Sralph case LT: 88916179Sralph case GE: 89016179Sralph case GT: 89116179Sralph if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 89216179Sralph case EQ: 89316179Sralph case NE: 89416179Sralph return( p ); 89516179Sralph 89616179Sralph case MINUS: 89716179Sralph return( clocal( block( PVCONV, 89816179Sralph p, bpsize(p->in.left), INT, 0, INT ) ) ); 89916179Sralph } 90016179Sralph 90116179Sralph cerror( "illegal oconvert: %d", p->in.op ); 90216179Sralph 90316179Sralph return(p); 90416179Sralph } 90516179Sralph 90616179Sralph NODE * 90716179Sralph ptmatch(p) register NODE *p; { 90816179Sralph 90916179Sralph /* makes the operands of p agree; they are 91016179Sralph either pointers or integers, by this time */ 91116179Sralph /* with MINUS, the sizes must be the same */ 91216179Sralph /* with COLON, the types must be the same */ 91316179Sralph 91416179Sralph TWORD t1, t2, t; 91516179Sralph int o, d2, d, s2, s; 91616179Sralph 91716179Sralph o = p->in.op; 91816179Sralph t = t1 = p->in.left->in.type; 91916179Sralph t2 = p->in.right->in.type; 92016179Sralph d = p->in.left->fn.cdim; 92116179Sralph d2 = p->in.right->fn.cdim; 92216179Sralph s = p->in.left->fn.csiz; 92316179Sralph s2 = p->in.right->fn.csiz; 92416179Sralph 92516179Sralph switch( o ){ 92616179Sralph 92716179Sralph case ASSIGN: 92816179Sralph case RETURN: 92916179Sralph case CAST: 93016179Sralph { break; } 93116179Sralph 93216179Sralph case MINUS: 93316179Sralph { if( psize(p->in.left) != psize(p->in.right) ){ 93416179Sralph uerror( "illegal pointer subtraction"); 93516179Sralph } 93616179Sralph break; 93716179Sralph } 93816179Sralph case COLON: 93916179Sralph { if( t1 != t2 ) uerror( "illegal types in :"); 94016179Sralph break; 94116179Sralph } 94216179Sralph default: /* must work harder: relationals or comparisons */ 94316179Sralph 94416179Sralph if( !ISPTR(t1) ){ 94516179Sralph t = t2; 94616179Sralph d = d2; 94716179Sralph s = s2; 94816179Sralph break; 94916179Sralph } 95016179Sralph if( !ISPTR(t2) ){ 95116179Sralph break; 95216179Sralph } 95316179Sralph 95416179Sralph /* both are pointers */ 95516179Sralph if( talign(t2,s2) < talign(t,s) ){ 95616179Sralph t = t2; 95716179Sralph s = s2; 95816179Sralph } 95916179Sralph break; 96016179Sralph } 96116179Sralph 96216179Sralph p->in.left = makety( p->in.left, t, d, s ); 96316179Sralph p->in.right = makety( p->in.right, t, d, s ); 96416179Sralph if( o!=MINUS && !logop(o) ){ 96516179Sralph 96616179Sralph p->in.type = t; 96716179Sralph p->fn.cdim = d; 96816179Sralph p->fn.csiz = s; 96916179Sralph } 97016179Sralph 97116179Sralph return(clocal(p)); 97216179Sralph } 97316179Sralph 97416179Sralph int tdebug = 0; 97516179Sralph 97616179Sralph NODE * 97716179Sralph tymatch(p) register NODE *p; { 97816179Sralph 97916179Sralph /* satisfy the types of various arithmetic binary ops */ 98016179Sralph 98116179Sralph /* rules are: 98216179Sralph if assignment, op, type of LHS 98316179Sralph if any float or doubles, make double 98416179Sralph if any longs, make long 98516179Sralph otherwise, make int 98616179Sralph if either operand is unsigned, the result is... 98716179Sralph */ 98816179Sralph 98916179Sralph register TWORD t1, t2, t, tu; 99016179Sralph register o, u; 99116179Sralph 99216179Sralph o = p->in.op; 99316179Sralph 99416179Sralph t1 = p->in.left->in.type; 99516179Sralph t2 = p->in.right->in.type; 99616179Sralph if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 99716179Sralph uerror("void type illegal in expression"); 99816179Sralph 99916179Sralph u = 0; 100016179Sralph if( ISUNSIGNED(t1) ){ 100116179Sralph u = 1; 100216179Sralph t1 = DEUNSIGN(t1); 100316179Sralph } 100416179Sralph if( ISUNSIGNED(t2) ){ 100516179Sralph u = 1; 100616179Sralph t2 = DEUNSIGN(t2); 100716179Sralph } 100816179Sralph 100916179Sralph if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 101016179Sralph if( t2 == CHAR || t2 == SHORT ) t2 = INT; 101116179Sralph 101216179Sralph if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE; 101316179Sralph else if( t1==LONG || t2==LONG ) t = LONG; 101416179Sralph else t = INT; 101516179Sralph 101616179Sralph if( asgop(o) ){ 101716179Sralph tu = p->in.left->in.type; 101816179Sralph t = t1; 101916179Sralph } 102016179Sralph else { 102116179Sralph tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 102216179Sralph } 102316179Sralph 102416179Sralph /* because expressions have values that are at least as wide 102516179Sralph as INT or UNSIGNED, the only conversions needed 102616179Sralph are those involving FLOAT/DOUBLE, and those 102716179Sralph from LONG to INT and ULONG to UNSIGNED */ 102816179Sralph 102916179Sralph if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu ); 103016179Sralph 103116179Sralph if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); 103216179Sralph 103316179Sralph if( asgop(o) ){ 103416179Sralph p->in.type = p->in.left->in.type; 103516179Sralph p->fn.cdim = p->in.left->fn.cdim; 103616179Sralph p->fn.csiz = p->in.left->fn.csiz; 103716179Sralph } 103816179Sralph else if( !logop(o) ){ 103916179Sralph p->in.type = tu; 104016179Sralph p->fn.cdim = 0; 104116179Sralph p->fn.csiz = t; 104216179Sralph } 104316179Sralph 104416179Sralph # ifndef BUG1 104516179Sralph if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 104616179Sralph # endif 104716179Sralph 104816179Sralph return(p); 104916179Sralph } 105016179Sralph 105116179Sralph NODE * 105216179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; { 105316179Sralph /* make p into type t by inserting a conversion */ 105416179Sralph 105516179Sralph if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 105616179Sralph if( t == p->in.type ){ 105716179Sralph p->fn.cdim = d; 105816179Sralph p->fn.csiz = s; 105916179Sralph return( p ); 106016179Sralph } 106116179Sralph 106216179Sralph if( t & TMASK ){ 106316179Sralph /* non-simple type */ 1064*17228Sralph return( block( PCONV, p, NIL, t, d, s ) ); 106516179Sralph } 106616179Sralph 106716179Sralph if( p->in.op == ICON ){ 106816179Sralph if( t==DOUBLE||t==FLOAT ){ 106916179Sralph p->in.op = FCON; 107016179Sralph if( ISUNSIGNED(p->in.type) ){ 107116179Sralph p->fpn.dval = /* (unsigned CONSZ) */ p->tn.lval; 107216179Sralph } 107316179Sralph else { 107416179Sralph p->fpn.dval = p->tn.lval; 107516179Sralph } 107616179Sralph 107716179Sralph p->in.type = p->fn.csiz = t; 107816179Sralph return( clocal(p) ); 107916179Sralph } 108016179Sralph } 108116179Sralph 108217049Sralph return( clocal( block( SCONV, p, NIL, t, d, s ) ) ); 108316179Sralph 108416179Sralph } 108516179Sralph 108616179Sralph NODE * 108716179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 108816179Sralph 108916179Sralph register NODE *p; 109016179Sralph 109116179Sralph p = talloc(); 109216179Sralph p->in.op = o; 109316179Sralph p->in.left = l; 109416179Sralph p->in.right = r; 109516179Sralph p->in.type = t; 109616179Sralph p->fn.cdim = d; 109716179Sralph p->fn.csiz = s; 109816179Sralph return(p); 109916179Sralph } 110016179Sralph 110116179Sralph icons(p) register NODE *p; { 110216179Sralph /* if p is an integer constant, return its value */ 110316179Sralph int val; 110416179Sralph 110516179Sralph if( p->in.op != ICON ){ 110616179Sralph uerror( "constant expected"); 110716179Sralph val = 1; 110816179Sralph } 110916179Sralph else { 111016179Sralph val = p->tn.lval; 111116179Sralph if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 111216179Sralph } 111316179Sralph tfree( p ); 111416179Sralph return(val); 111516179Sralph } 111616179Sralph 111716179Sralph /* the intent of this table is to examine the 111816179Sralph operators, and to check them for 111916179Sralph correctness. 112016179Sralph 112116179Sralph The table is searched for the op and the 112216179Sralph modified type (where this is one of the 112316179Sralph types INT (includes char and short), LONG, 112416179Sralph DOUBLE (includes FLOAT), and POINTER 112516179Sralph 112616179Sralph The default action is to make the node type integer 112716179Sralph 112816179Sralph The actions taken include: 112916179Sralph PUN check for puns 113016179Sralph CVTL convert the left operand 113116179Sralph CVTR convert the right operand 113216179Sralph TYPL the type is determined by the left operand 113316179Sralph TYPR the type is determined by the right operand 113416179Sralph TYMATCH force type of left and right to match, by inserting conversions 113516179Sralph PTMATCH like TYMATCH, but for pointers 113616179Sralph LVAL left operand must be lval 113716179Sralph CVTO convert the op 113816179Sralph NCVT do not convert the operands 113916179Sralph OTHER handled by code 114016179Sralph NCVTR convert the left operand, not the right... 114116179Sralph 114216179Sralph */ 114316179Sralph 114416179Sralph # define MINT 01 /* integer */ 114516179Sralph # define MDBI 02 /* integer or double */ 114616179Sralph # define MSTR 04 /* structure */ 114716179Sralph # define MPTR 010 /* pointer */ 114816179Sralph # define MPTI 020 /* pointer or integer */ 114916179Sralph # define MENU 040 /* enumeration variable or member */ 115016179Sralph 115116179Sralph opact( p ) NODE *p; { 115216179Sralph 115316179Sralph register mt12, mt1, mt2, o; 115416179Sralph 115516179Sralph mt12 = 0; 115616179Sralph 115716179Sralph switch( optype(o=p->in.op) ){ 115816179Sralph 115916179Sralph case BITYPE: 116016179Sralph mt12=mt2 = moditype( p->in.right->in.type ); 116116179Sralph case UTYPE: 116216179Sralph mt12 &= (mt1 = moditype( p->in.left->in.type )); 116316179Sralph 116416179Sralph } 116516179Sralph 116616179Sralph switch( o ){ 116716179Sralph 116816179Sralph case NAME : 116916179Sralph case STRING : 117016179Sralph case ICON : 117116179Sralph case FCON : 117216179Sralph case CALL : 117316179Sralph case UNARY CALL: 117416179Sralph case UNARY MUL: 117516179Sralph { return( OTHER ); } 117616179Sralph case UNARY MINUS: 117716179Sralph if( mt1 & MDBI ) return( TYPL ); 117816179Sralph break; 117916179Sralph 118016179Sralph case COMPL: 118116179Sralph if( mt1 & MINT ) return( TYPL ); 118216179Sralph break; 118316179Sralph 118416179Sralph case UNARY AND: 118516179Sralph { return( NCVT+OTHER ); } 118616179Sralph case INIT: 118716179Sralph case CM: 118816180Sralph return( 0 ); 118916180Sralph 119016179Sralph case NOT: 119116179Sralph case CBRANCH: 119216180Sralph if( mt1 & MSTR ) break; 119316180Sralph return( 0 ); 119416180Sralph 119516179Sralph case ANDAND: 119616179Sralph case OROR: 119716180Sralph if( (mt1 & MSTR) || (mt2 & MSTR) ) break; 119816179Sralph return( 0 ); 119916179Sralph 120016179Sralph case MUL: 120116179Sralph case DIV: 120216179Sralph if( mt12 & MDBI ) return( TYMATCH ); 120316179Sralph break; 120416179Sralph 120516179Sralph case MOD: 120616179Sralph case AND: 120716179Sralph case OR: 120816179Sralph case ER: 120916179Sralph if( mt12 & MINT ) return( TYMATCH ); 121016179Sralph break; 121116179Sralph 121216179Sralph case LS: 121316179Sralph case RS: 121416179Sralph if( mt12 & MINT ) return( TYMATCH+OTHER ); 121516179Sralph break; 121616179Sralph 121716179Sralph case EQ: 121816179Sralph case NE: 121916179Sralph case LT: 122016179Sralph case LE: 122116179Sralph case GT: 122216179Sralph case GE: 122316179Sralph if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 122416179Sralph if( mt12 & MDBI ) return( TYMATCH+CVTO ); 122516179Sralph else if( mt12 & MPTR ) return( PTMATCH+PUN ); 122616179Sralph else if( mt12 & MPTI ) return( PTMATCH+PUN ); 122716179Sralph else break; 122816179Sralph 122916179Sralph case QUEST: 123016179Sralph case COMOP: 123116179Sralph if( mt2&MENU ) return( TYPR+NCVTR ); 123216179Sralph return( TYPR ); 123316179Sralph 123416179Sralph case STREF: 123516179Sralph return( NCVTR+OTHER ); 123616179Sralph 123716179Sralph case FORCE: 123816179Sralph return( TYPL ); 123916179Sralph 124016179Sralph case COLON: 124116179Sralph if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 124216179Sralph else if( mt12 & MDBI ) return( TYMATCH ); 124316179Sralph else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 124416179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 124516179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 124616179Sralph else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 124716179Sralph break; 124816179Sralph 124916179Sralph case ASSIGN: 125016179Sralph case RETURN: 125116179Sralph if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 125216179Sralph case CAST: 125316179Sralph if(o==CAST && mt1==0)return(TYPL+TYMATCH); 125416179Sralph if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 125516179Sralph else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 125616179Sralph else if( mt12 == 0 ) break; 125716179Sralph else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 125816179Sralph else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 125916179Sralph break; 126016179Sralph 126116179Sralph case ASG LS: 126216179Sralph case ASG RS: 126316179Sralph if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 126416179Sralph break; 126516179Sralph 126616179Sralph case ASG MUL: 126716179Sralph case ASG DIV: 126816179Sralph if( mt12 & MDBI ) return( LVAL+TYMATCH ); 126916179Sralph break; 127016179Sralph 127116179Sralph case ASG MOD: 127216179Sralph case ASG AND: 127316179Sralph case ASG OR: 127416179Sralph case ASG ER: 127516179Sralph if( mt12 & MINT ) return( LVAL+TYMATCH ); 127616179Sralph break; 127716179Sralph 127816179Sralph case ASG PLUS: 127916179Sralph case ASG MINUS: 128016179Sralph case INCR: 128116179Sralph case DECR: 128216179Sralph if( mt12 & MDBI ) return( TYMATCH+LVAL ); 128316179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 128416179Sralph break; 128516179Sralph 128616179Sralph case MINUS: 128716179Sralph if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 128816179Sralph if( mt2 & MPTR ) break; 128916179Sralph case PLUS: 129016179Sralph if( mt12 & MDBI ) return( TYMATCH ); 129116179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 129216179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 129316179Sralph 129416179Sralph } 129516179Sralph uerror( "operands of %s have incompatible types", opst[o] ); 129616179Sralph return( NCVT ); 129716179Sralph } 129816179Sralph 129916179Sralph moditype( ty ) TWORD ty; { 130016179Sralph 130116179Sralph switch( ty ){ 130216179Sralph 130316179Sralph case TVOID: 130417206Sralph return( MPTR ); 130516179Sralph case UNDEF: 130616179Sralph return(0); /* type is void */ 130716179Sralph case ENUMTY: 130816179Sralph case MOETY: 130916179Sralph return( MENU ); 131016179Sralph 131116179Sralph case STRTY: 131216179Sralph case UNIONTY: 131316179Sralph return( MSTR ); 131416179Sralph 131516179Sralph case CHAR: 131616179Sralph case SHORT: 131716179Sralph case UCHAR: 131816179Sralph case USHORT: 131916179Sralph return( MINT|MPTI|MDBI ); 132016179Sralph case UNSIGNED: 132116179Sralph case ULONG: 132216179Sralph case INT: 132316179Sralph case LONG: 132416179Sralph return( MINT|MDBI|MPTI ); 132516179Sralph case FLOAT: 132616179Sralph case DOUBLE: 132716179Sralph return( MDBI ); 132816179Sralph default: 132916179Sralph return( MPTR|MPTI ); 133016179Sralph 133116179Sralph } 133216179Sralph } 133316179Sralph 133416179Sralph NODE * 133516179Sralph doszof( p ) register NODE *p; { 133616179Sralph /* do sizeof p */ 133716179Sralph int i; 133816179Sralph 133916179Sralph /* whatever is the meaning of this if it is a bitfield? */ 134016179Sralph i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 134116179Sralph 134216179Sralph tfree(p); 134316179Sralph if( i <= 0 ) werror( "sizeof returns 0" ); 134416179Sralph return( bcon( i ) ); 134516179Sralph } 134616179Sralph 134716179Sralph # ifndef BUG2 134816179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; { 134916179Sralph register ty; 135016179Sralph 135116179Sralph *a = *b = down+1; 135216179Sralph while( down > 1 ){ 135316179Sralph printf( "\t" ); 135416179Sralph down -= 2; 135516179Sralph } 135616179Sralph if( down ) printf( " " ); 135716179Sralph 135816179Sralph ty = optype( p->in.op ); 135916179Sralph 136016179Sralph printf("%o) %s, ", p, opst[p->in.op] ); 136116179Sralph if( ty == LTYPE ){ 136216179Sralph printf( CONFMT, p->tn.lval ); 136316179Sralph printf( ", %d, ", p->tn.rval ); 136416179Sralph } 136516179Sralph tprint( p->in.type ); 136616179Sralph printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 136716179Sralph } 136816179Sralph # endif 136916179Sralph 137016179Sralph prtdcon( p ) register NODE *p; { 137116179Sralph int i; 137216179Sralph 137316179Sralph if( p->in.op == FCON ){ 137416179Sralph locctr( DATA ); 137516179Sralph defalign( ALDOUBLE ); 137616179Sralph deflab( i = getlab() ); 137716179Sralph fincode( p->fpn.dval, SZDOUBLE ); 137816179Sralph p->tn.lval = 0; 137916179Sralph p->tn.rval = -i; 138016179Sralph p->in.type = DOUBLE; 138116179Sralph p->in.op = NAME; 138216179Sralph } 138316179Sralph } 138416179Sralph 138516179Sralph 138616179Sralph int edebug = 0; 138716179Sralph ecomp( p ) register NODE *p; { 138816179Sralph # ifndef BUG2 138916179Sralph if( edebug ) fwalk( p, eprint, 0 ); 139016179Sralph # endif 139116179Sralph if( !reached ){ 139216179Sralph werror( "statement not reached" ); 139316179Sralph reached = 1; 139416179Sralph } 139516179Sralph p = optim(p); 139616179Sralph walkf( p, prtdcon ); 139716179Sralph locctr( PROG ); 139816179Sralph ecode( p ); 139916179Sralph tfree(p); 140016179Sralph } 140116179Sralph 140216179Sralph # ifdef STDPRTREE 140316179Sralph # ifndef ONEPASS 140416179Sralph 140516179Sralph prtree(p) register NODE *p; { 140616179Sralph 140716179Sralph register struct symtab *q; 140816179Sralph register ty; 140916179Sralph 141016179Sralph # ifdef MYPRTREE 141116179Sralph MYPRTREE(p); /* local action can be taken here; then return... */ 141216179Sralph #endif 141316179Sralph 141416179Sralph ty = optype(p->in.op); 141516179Sralph 141616179Sralph printf( "%d\t", p->in.op ); 141716179Sralph 141816179Sralph if( ty == LTYPE ) { 141916179Sralph printf( CONFMT, p->tn.lval ); 142016179Sralph printf( "\t" ); 142116179Sralph } 142216179Sralph if( ty != BITYPE ) { 142316179Sralph if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 142416179Sralph else printf( "%d\t", p->tn.rval ); 142516179Sralph } 142616179Sralph 142716179Sralph printf( "%o\t", p->in.type ); 142816179Sralph 142916179Sralph /* handle special cases */ 143016179Sralph 143116179Sralph switch( p->in.op ){ 143216179Sralph 143316179Sralph case NAME: 143416179Sralph case ICON: 143516179Sralph /* print external name */ 143616179Sralph if( p->tn.rval == NONAME ) printf( "\n" ); 143716179Sralph else if( p->tn.rval >= 0 ){ 143816179Sralph q = &stab[p->tn.rval]; 143916179Sralph printf( "%s\n", exname(q->sname) ); 144016179Sralph } 144116179Sralph else { /* label */ 144216179Sralph printf( LABFMT, -p->tn.rval ); 144316179Sralph } 144416179Sralph break; 144516179Sralph 144616179Sralph case STARG: 144716179Sralph case STASG: 144816179Sralph case STCALL: 144916179Sralph case UNARY STCALL: 145016179Sralph /* print out size */ 145116179Sralph /* use lhs size, in order to avoid hassles with the structure `.' operator */ 145216179Sralph 145316179Sralph /* note: p->in.left not a field... */ 145416179Sralph printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 145516179Sralph printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 145616179Sralph break; 145716179Sralph 145816179Sralph default: 145916179Sralph printf( "\n" ); 146016179Sralph } 146116179Sralph 146216179Sralph if( ty != LTYPE ) prtree( p->in.left ); 146316179Sralph if( ty == BITYPE ) prtree( p->in.right ); 146416179Sralph 146516179Sralph } 146616179Sralph 146716179Sralph # else 146816179Sralph 146916179Sralph p2tree(p) register NODE *p; { 147016179Sralph register ty; 147116179Sralph 147216179Sralph # ifdef MYP2TREE 147316179Sralph MYP2TREE(p); /* local action can be taken here; then return... */ 147416179Sralph # endif 147516179Sralph 147616179Sralph ty = optype(p->in.op); 147716179Sralph 147816179Sralph switch( p->in.op ){ 147916179Sralph 148016179Sralph case NAME: 148116179Sralph case ICON: 148216179Sralph #ifndef FLEXNAMES 148316179Sralph if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 148416179Sralph #else 148516179Sralph if( p->tn.rval == NONAME ) p->in.name = ""; 148616179Sralph #endif 148716179Sralph else if( p->tn.rval >= 0 ){ /* copy name from exname */ 148816179Sralph register char *cp; 148916179Sralph register i; 149016179Sralph cp = exname( stab[p->tn.rval].sname ); 149116179Sralph #ifndef FLEXNAMES 149216179Sralph for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 149316179Sralph #else 149416179Sralph p->in.name = tstr(cp); 149516179Sralph #endif 149616179Sralph } 149716179Sralph #ifndef FLEXNAMES 149816179Sralph else sprintf( p->in.name, LABFMT, -p->tn.rval ); 149916179Sralph #else 150016179Sralph else { 150116179Sralph char temp[32]; 150216179Sralph sprintf( temp, LABFMT, -p->tn.rval ); 150316179Sralph p->in.name = tstr(temp); 150416179Sralph } 150516179Sralph #endif 150616179Sralph break; 150716179Sralph 150816179Sralph case STARG: 150916179Sralph case STASG: 151016179Sralph case STCALL: 151116179Sralph case UNARY STCALL: 151216179Sralph /* set up size parameters */ 151316179Sralph p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 151416179Sralph p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 151516179Sralph break; 151616179Sralph 151716179Sralph case REG: 151816179Sralph rbusy( p->tn.rval, p->in.type ); 151916179Sralph default: 152016179Sralph #ifndef FLEXNAMES 152116179Sralph p->in.name[0] = '\0'; 152216179Sralph #else 152316179Sralph p->in.name = ""; 152416179Sralph #endif 152516179Sralph } 152616179Sralph 152716179Sralph p->in.rall = NOPREF; 152816179Sralph 152916179Sralph if( ty != LTYPE ) p2tree( p->in.left ); 153016179Sralph if( ty == BITYPE ) p2tree( p->in.right ); 153116179Sralph } 153216179Sralph 153316179Sralph # endif 153416179Sralph # endif 1535