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