1*16179Sralph static char *sccsid ="@(#)trees.c 4.1 (Berkeley) 03/14/84"; 2*16179Sralph # include "mfile1" 3*16179Sralph 4*16179Sralph /* corrections when in violation of lint */ 5*16179Sralph 6*16179Sralph /* some special actions, used in finding the type of nodes */ 7*16179Sralph # define NCVT 01 8*16179Sralph # define PUN 02 9*16179Sralph # define TYPL 04 10*16179Sralph # define TYPR 010 11*16179Sralph # define TYMATCH 040 12*16179Sralph # define LVAL 0100 13*16179Sralph # define CVTO 0200 14*16179Sralph # define CVTL 0400 15*16179Sralph # define CVTR 01000 16*16179Sralph # define PTMATCH 02000 17*16179Sralph # define OTHER 04000 18*16179Sralph # define NCVTR 010000 19*16179Sralph 20*16179Sralph /* node conventions: 21*16179Sralph 22*16179Sralph NAME: rval>0 is stab index for external 23*16179Sralph rval<0 is -inlabel number 24*16179Sralph lval is offset in bits 25*16179Sralph ICON: lval has the value 26*16179Sralph rval has the STAB index, or - label number, 27*16179Sralph if a name whose address is in the constant 28*16179Sralph rval = NONAME means no name 29*16179Sralph REG: rval is reg. identification cookie 30*16179Sralph 31*16179Sralph */ 32*16179Sralph 33*16179Sralph int bdebug = 0; 34*16179Sralph extern ddebug; 35*16179Sralph 36*16179Sralph NODE * 37*16179Sralph buildtree( o, l, r ) register NODE *l, *r; { 38*16179Sralph register NODE *p, *q; 39*16179Sralph register actions; 40*16179Sralph register opty; 41*16179Sralph register struct symtab *sp; 42*16179Sralph register NODE *lr, *ll; 43*16179Sralph int i; 44*16179Sralph extern int eprint(); 45*16179Sralph 46*16179Sralph # ifndef BUG1 47*16179Sralph if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r ); 48*16179Sralph # endif 49*16179Sralph opty = optype(o); 50*16179Sralph 51*16179Sralph /* check for constants */ 52*16179Sralph 53*16179Sralph if( opty == UTYPE && l->in.op == ICON ){ 54*16179Sralph 55*16179Sralph switch( o ){ 56*16179Sralph 57*16179Sralph case NOT: 58*16179Sralph if( hflag ) werror( "constant argument to NOT" ); 59*16179Sralph case UNARY MINUS: 60*16179Sralph case COMPL: 61*16179Sralph if( conval( l, o, l ) ) return(l); 62*16179Sralph break; 63*16179Sralph 64*16179Sralph } 65*16179Sralph } 66*16179Sralph 67*16179Sralph else if( o==UNARY MINUS && l->in.op==FCON ){ 68*16179Sralph l->fpn.dval = -l->fpn.dval; 69*16179Sralph return(l); 70*16179Sralph } 71*16179Sralph 72*16179Sralph else if( o==QUEST && l->in.op==ICON ) { 73*16179Sralph l->in.op = FREE; 74*16179Sralph r->in.op = FREE; 75*16179Sralph if( l->tn.lval ){ 76*16179Sralph tfree( r->in.right ); 77*16179Sralph return( r->in.left ); 78*16179Sralph } 79*16179Sralph else { 80*16179Sralph tfree( r->in.left ); 81*16179Sralph return( r->in.right ); 82*16179Sralph } 83*16179Sralph } 84*16179Sralph 85*16179Sralph else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn; 86*16179Sralph 87*16179Sralph else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){ 88*16179Sralph 89*16179Sralph switch( o ){ 90*16179Sralph 91*16179Sralph case ULT: 92*16179Sralph case UGT: 93*16179Sralph case ULE: 94*16179Sralph case UGE: 95*16179Sralph case LT: 96*16179Sralph case GT: 97*16179Sralph case LE: 98*16179Sralph case GE: 99*16179Sralph case EQ: 100*16179Sralph case NE: 101*16179Sralph case ANDAND: 102*16179Sralph case OROR: 103*16179Sralph case CBRANCH: 104*16179Sralph 105*16179Sralph ccwarn: 106*16179Sralph if( hflag ) werror( "constant in conditional context" ); 107*16179Sralph 108*16179Sralph case PLUS: 109*16179Sralph case MINUS: 110*16179Sralph case MUL: 111*16179Sralph case DIV: 112*16179Sralph case MOD: 113*16179Sralph case AND: 114*16179Sralph case OR: 115*16179Sralph case ER: 116*16179Sralph case LS: 117*16179Sralph case RS: 118*16179Sralph if( conval( l, o, r ) ) { 119*16179Sralph r->in.op = FREE; 120*16179Sralph return(l); 121*16179Sralph } 122*16179Sralph break; 123*16179Sralph } 124*16179Sralph } 125*16179Sralph 126*16179Sralph else if( opty == BITYPE && (l->in.op==FCON||l->in.op==ICON) && 127*16179Sralph (r->in.op==FCON||r->in.op==ICON) ){ 128*16179Sralph switch(o){ 129*16179Sralph case PLUS: 130*16179Sralph case MINUS: 131*16179Sralph case MUL: 132*16179Sralph case DIV: 133*16179Sralph if( l->in.op == ICON ){ 134*16179Sralph l->fpn.dval = l->tn.lval; 135*16179Sralph } 136*16179Sralph if( r->in.op == ICON ){ 137*16179Sralph r->fpn.dval = r->tn.lval; 138*16179Sralph } 139*16179Sralph l->in.op = FCON; 140*16179Sralph l->in.type = l->fn.csiz = DOUBLE; 141*16179Sralph r->in.op = FREE; 142*16179Sralph switch(o){ 143*16179Sralph case PLUS: 144*16179Sralph l->fpn.dval += r->fpn.dval; 145*16179Sralph return(l); 146*16179Sralph case MINUS: 147*16179Sralph l->fpn.dval -= r->fpn.dval; 148*16179Sralph return(l); 149*16179Sralph case MUL: 150*16179Sralph l->fpn.dval *= r->fpn.dval; 151*16179Sralph return(l); 152*16179Sralph case DIV: 153*16179Sralph if( r->fpn.dval == 0 ) uerror( "division by 0." ); 154*16179Sralph else l->fpn.dval /= r->fpn.dval; 155*16179Sralph return(l); 156*16179Sralph } 157*16179Sralph } 158*16179Sralph } 159*16179Sralph 160*16179Sralph /* its real; we must make a new node */ 161*16179Sralph 162*16179Sralph p = block( o, l, r, INT, 0, INT ); 163*16179Sralph 164*16179Sralph actions = opact(p); 165*16179Sralph 166*16179Sralph if( actions&LVAL ){ /* check left descendent */ 167*16179Sralph if( notlval(p->in.left) ) { 168*16179Sralph uerror( "illegal lhs of assignment operator" ); 169*16179Sralph } 170*16179Sralph } 171*16179Sralph 172*16179Sralph if( actions & NCVTR ){ 173*16179Sralph p->in.left = pconvert( p->in.left ); 174*16179Sralph } 175*16179Sralph else if( !(actions & NCVT ) ){ 176*16179Sralph switch( opty ){ 177*16179Sralph 178*16179Sralph case BITYPE: 179*16179Sralph p->in.right = pconvert( p->in.right ); 180*16179Sralph case UTYPE: 181*16179Sralph p->in.left = pconvert( p->in.left ); 182*16179Sralph 183*16179Sralph } 184*16179Sralph } 185*16179Sralph 186*16179Sralph if( (actions&PUN) && (o!=CAST||cflag) ){ 187*16179Sralph chkpun(p); 188*16179Sralph } 189*16179Sralph 190*16179Sralph if( actions & (TYPL|TYPR) ){ 191*16179Sralph 192*16179Sralph q = (actions&TYPL) ? p->in.left : p->in.right; 193*16179Sralph 194*16179Sralph p->in.type = q->in.type; 195*16179Sralph p->fn.cdim = q->fn.cdim; 196*16179Sralph p->fn.csiz = q->fn.csiz; 197*16179Sralph } 198*16179Sralph 199*16179Sralph if( actions & CVTL ) p = convert( p, CVTL ); 200*16179Sralph if( actions & CVTR ) p = convert( p, CVTR ); 201*16179Sralph if( actions & TYMATCH ) p = tymatch(p); 202*16179Sralph if( actions & PTMATCH ) p = ptmatch(p); 203*16179Sralph 204*16179Sralph if( actions & OTHER ){ 205*16179Sralph l = p->in.left; 206*16179Sralph r = p->in.right; 207*16179Sralph 208*16179Sralph switch(o){ 209*16179Sralph 210*16179Sralph case NAME: 211*16179Sralph sp = &stab[idname]; 212*16179Sralph if( sp->stype == UNDEF ){ 213*16179Sralph #ifndef FLEXNAMES 214*16179Sralph uerror( "%.8s undefined", sp->sname ); 215*16179Sralph #else 216*16179Sralph uerror( "%s undefined", sp->sname ); 217*16179Sralph #endif 218*16179Sralph /* make p look reasonable */ 219*16179Sralph p->in.type = p->fn.cdim = p->fn.csiz = INT; 220*16179Sralph p->tn.rval = idname; 221*16179Sralph p->tn.lval = 0; 222*16179Sralph defid( p, SNULL ); 223*16179Sralph break; 224*16179Sralph } 225*16179Sralph p->in.type = sp->stype; 226*16179Sralph p->fn.cdim = sp->dimoff; 227*16179Sralph p->fn.csiz = sp->sizoff; 228*16179Sralph p->tn.lval = 0; 229*16179Sralph p->tn.rval = idname; 230*16179Sralph /* special case: MOETY is really an ICON... */ 231*16179Sralph if( p->in.type == MOETY ){ 232*16179Sralph p->tn.rval = NONAME; 233*16179Sralph p->tn.lval = sp->offset; 234*16179Sralph p->fn.cdim = 0; 235*16179Sralph p->in.type = ENUMTY; 236*16179Sralph p->in.op = ICON; 237*16179Sralph } 238*16179Sralph break; 239*16179Sralph 240*16179Sralph case ICON: 241*16179Sralph p->in.type = INT; 242*16179Sralph p->fn.cdim = 0; 243*16179Sralph p->fn.csiz = INT; 244*16179Sralph break; 245*16179Sralph 246*16179Sralph case STRING: 247*16179Sralph p->in.op = NAME; 248*16179Sralph p->in.type = CHAR+ARY; 249*16179Sralph p->tn.lval = 0; 250*16179Sralph p->tn.rval = NOLAB; 251*16179Sralph p->fn.cdim = curdim; 252*16179Sralph p->fn.csiz = CHAR; 253*16179Sralph break; 254*16179Sralph 255*16179Sralph case FCON: 256*16179Sralph p->tn.lval = 0; 257*16179Sralph p->tn.rval = 0; 258*16179Sralph p->in.type = DOUBLE; 259*16179Sralph p->fn.cdim = 0; 260*16179Sralph p->fn.csiz = DOUBLE; 261*16179Sralph break; 262*16179Sralph 263*16179Sralph case STREF: 264*16179Sralph /* p->x turned into *(p+offset) */ 265*16179Sralph /* rhs must be a name; check correctness */ 266*16179Sralph 267*16179Sralph i = r->tn.rval; 268*16179Sralph if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){ 269*16179Sralph uerror( "member of structure or union required" ); 270*16179Sralph }else 271*16179Sralph /* if this name is non-unique, find right one */ 272*16179Sralph if( stab[i].sflags & SNONUNIQ && 273*16179Sralph (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) && 274*16179Sralph (l->fn.csiz +1) >= 0 ){ 275*16179Sralph /* nonunique name && structure defined */ 276*16179Sralph char * memnam, * tabnam; 277*16179Sralph register k; 278*16179Sralph int j; 279*16179Sralph int memi; 280*16179Sralph j=dimtab[l->fn.csiz+1]; 281*16179Sralph for( ; (memi=dimtab[j]) >= 0; ++j ){ 282*16179Sralph tabnam = stab[memi].sname; 283*16179Sralph memnam = stab[i].sname; 284*16179Sralph # ifndef BUG1 285*16179Sralph if( ddebug>1 ){ 286*16179Sralph #ifndef FLEXNAMES 287*16179Sralph printf("member %.8s==%.8s?\n", 288*16179Sralph #else 289*16179Sralph printf("member %s==%s?\n", 290*16179Sralph #endif 291*16179Sralph memnam, tabnam); 292*16179Sralph } 293*16179Sralph # endif 294*16179Sralph if( stab[memi].sflags & SNONUNIQ ){ 295*16179Sralph #ifndef FLEXNAMES 296*16179Sralph for( k=0; k<NCHNAM; ++k ){ 297*16179Sralph if(*memnam++!=*tabnam) 298*16179Sralph goto next; 299*16179Sralph if(!*tabnam++) break; 300*16179Sralph } 301*16179Sralph #else 302*16179Sralph if (memnam != tabnam) 303*16179Sralph goto next; 304*16179Sralph #endif 305*16179Sralph r->tn.rval = i = memi; 306*16179Sralph break; 307*16179Sralph } 308*16179Sralph next: continue; 309*16179Sralph } 310*16179Sralph if( memi < 0 ) 311*16179Sralph #ifndef FLEXNAMES 312*16179Sralph uerror("illegal member use: %.8s", 313*16179Sralph #else 314*16179Sralph uerror("illegal member use: %s", 315*16179Sralph #endif 316*16179Sralph stab[i].sname); 317*16179Sralph } 318*16179Sralph else { 319*16179Sralph register j; 320*16179Sralph if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){ 321*16179Sralph if( stab[i].sflags & SNONUNIQ ){ 322*16179Sralph uerror( "nonunique name demands struct/union or struct/union pointer" ); 323*16179Sralph } 324*16179Sralph else werror( "struct/union or struct/union pointer required" ); 325*16179Sralph } 326*16179Sralph else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" ); 327*16179Sralph else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){ 328*16179Sralph #ifndef FLEXNAMES 329*16179Sralph werror( "illegal member use: %.8s", stab[i].sname ); 330*16179Sralph #else 331*16179Sralph werror( "illegal member use: %s", stab[i].sname ); 332*16179Sralph #endif 333*16179Sralph } 334*16179Sralph } 335*16179Sralph 336*16179Sralph p = stref( p ); 337*16179Sralph break; 338*16179Sralph 339*16179Sralph case UNARY MUL: 340*16179Sralph if( l->in.op == UNARY AND ){ 341*16179Sralph p->in.op = l->in.op = FREE; 342*16179Sralph p = l->in.left; 343*16179Sralph } 344*16179Sralph if( !ISPTR(l->in.type))uerror("illegal indirection"); 345*16179Sralph p->in.type = DECREF(l->in.type); 346*16179Sralph p->fn.cdim = l->fn.cdim; 347*16179Sralph p->fn.csiz = l->fn.csiz; 348*16179Sralph break; 349*16179Sralph 350*16179Sralph case UNARY AND: 351*16179Sralph switch( l->in.op ){ 352*16179Sralph 353*16179Sralph case UNARY MUL: 354*16179Sralph p->in.op = l->in.op = FREE; 355*16179Sralph p = l->in.left; 356*16179Sralph case NAME: 357*16179Sralph p->in.type = INCREF( l->in.type ); 358*16179Sralph p->fn.cdim = l->fn.cdim; 359*16179Sralph p->fn.csiz = l->fn.csiz; 360*16179Sralph break; 361*16179Sralph 362*16179Sralph case COMOP: 363*16179Sralph lr = buildtree( UNARY AND, l->in.right, NIL ); 364*16179Sralph p->in.op = l->in.op = FREE; 365*16179Sralph p = buildtree( COMOP, l->in.left, lr ); 366*16179Sralph break; 367*16179Sralph 368*16179Sralph case QUEST: 369*16179Sralph lr = buildtree( UNARY AND, l->in.right->in.right, NIL ); 370*16179Sralph ll = buildtree( UNARY AND, l->in.right->in.left, NIL ); 371*16179Sralph p->in.op = l->in.op = l->in.right->in.op = FREE; 372*16179Sralph p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) ); 373*16179Sralph break; 374*16179Sralph 375*16179Sralph # ifdef ADDROREG 376*16179Sralph case OREG: 377*16179Sralph /* OREG was built in clocal() 378*16179Sralph * for an auto or formal parameter 379*16179Sralph * now its address is being taken 380*16179Sralph * local code must unwind it 381*16179Sralph * back to PLUS/MINUS REG ICON 382*16179Sralph * according to local conventions 383*16179Sralph */ 384*16179Sralph { 385*16179Sralph extern NODE * addroreg(); 386*16179Sralph p->in.op = FREE; 387*16179Sralph p = addroreg( l ); 388*16179Sralph } 389*16179Sralph break; 390*16179Sralph 391*16179Sralph # endif 392*16179Sralph default: 393*16179Sralph uerror( "unacceptable operand of &" ); 394*16179Sralph break; 395*16179Sralph } 396*16179Sralph break; 397*16179Sralph 398*16179Sralph case LS: 399*16179Sralph case RS: 400*16179Sralph case ASG LS: 401*16179Sralph case ASG RS: 402*16179Sralph if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT) 403*16179Sralph p->in.right = makety(p->in.right, INT, 0, INT ); 404*16179Sralph break; 405*16179Sralph 406*16179Sralph case RETURN: 407*16179Sralph case ASSIGN: 408*16179Sralph case CAST: 409*16179Sralph /* structure assignment */ 410*16179Sralph /* take the addresses of the two sides; then make an 411*16179Sralph /* operator using STASG and 412*16179Sralph /* the addresses of left and right */ 413*16179Sralph 414*16179Sralph { 415*16179Sralph register TWORD t; 416*16179Sralph register d, s; 417*16179Sralph 418*16179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" ); 419*16179Sralph 420*16179Sralph r = buildtree( UNARY AND, r, NIL ); 421*16179Sralph t = r->in.type; 422*16179Sralph d = r->fn.cdim; 423*16179Sralph s = r->fn.csiz; 424*16179Sralph 425*16179Sralph l = block( STASG, l, r, t, d, s ); 426*16179Sralph 427*16179Sralph if( o == RETURN ){ 428*16179Sralph p->in.op = FREE; 429*16179Sralph p = l; 430*16179Sralph break; 431*16179Sralph } 432*16179Sralph 433*16179Sralph p->in.op = UNARY MUL; 434*16179Sralph p->in.left = l; 435*16179Sralph p->in.right = NIL; 436*16179Sralph break; 437*16179Sralph } 438*16179Sralph case COLON: 439*16179Sralph /* structure colon */ 440*16179Sralph 441*16179Sralph if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" ); 442*16179Sralph break; 443*16179Sralph 444*16179Sralph case CALL: 445*16179Sralph p->in.right = r = strargs( p->in.right ); 446*16179Sralph case UNARY CALL: 447*16179Sralph if( !ISPTR(l->in.type)) uerror("illegal function"); 448*16179Sralph p->in.type = DECREF(l->in.type); 449*16179Sralph if( !ISFTN(p->in.type)) uerror("illegal function"); 450*16179Sralph p->in.type = DECREF( p->in.type ); 451*16179Sralph p->fn.cdim = l->fn.cdim; 452*16179Sralph p->fn.csiz = l->fn.csiz; 453*16179Sralph if( l->in.op == UNARY AND && l->in.left->in.op == NAME && 454*16179Sralph l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME && 455*16179Sralph ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){ 456*16179Sralph p->in.op += (FORTCALL-CALL); 457*16179Sralph } 458*16179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 459*16179Sralph /* function returning structure */ 460*16179Sralph /* make function really return ptr to str., with * */ 461*16179Sralph 462*16179Sralph p->in.op += STCALL-CALL; 463*16179Sralph p->in.type = INCREF( p->in.type ); 464*16179Sralph p = buildtree( UNARY MUL, p, NIL ); 465*16179Sralph 466*16179Sralph } 467*16179Sralph break; 468*16179Sralph 469*16179Sralph default: 470*16179Sralph cerror( "other code %d", o ); 471*16179Sralph } 472*16179Sralph 473*16179Sralph } 474*16179Sralph 475*16179Sralph if( actions & CVTO ) p = oconvert(p); 476*16179Sralph p = clocal(p); 477*16179Sralph 478*16179Sralph # ifndef BUG1 479*16179Sralph if( bdebug ) fwalk( p, eprint, 0 ); 480*16179Sralph # endif 481*16179Sralph 482*16179Sralph return(p); 483*16179Sralph 484*16179Sralph } 485*16179Sralph 486*16179Sralph NODE * 487*16179Sralph strargs( p ) register NODE *p; { /* rewrite structure flavored arguments */ 488*16179Sralph 489*16179Sralph if( p->in.op == CM ){ 490*16179Sralph p->in.left = strargs( p->in.left ); 491*16179Sralph p->in.right = strargs( p->in.right ); 492*16179Sralph return( p ); 493*16179Sralph } 494*16179Sralph 495*16179Sralph if( p->in.type == STRTY || p->in.type == UNIONTY ){ 496*16179Sralph p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz ); 497*16179Sralph p->in.left = buildtree( UNARY AND, p->in.left, NIL ); 498*16179Sralph p = clocal(p); 499*16179Sralph } 500*16179Sralph return( p ); 501*16179Sralph } 502*16179Sralph 503*16179Sralph chkstr( i, j, type ) TWORD type; { 504*16179Sralph /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */ 505*16179Sralph /* i has been checked to contain a MOS or MOU */ 506*16179Sralph /* j is the index in dimtab of the members... */ 507*16179Sralph int k, kk; 508*16179Sralph 509*16179Sralph extern int ddebug; 510*16179Sralph 511*16179Sralph # ifndef BUG1 512*16179Sralph #ifndef FLEXNAMES 513*16179Sralph if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j ); 514*16179Sralph #else 515*16179Sralph if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j ); 516*16179Sralph #endif 517*16179Sralph # endif 518*16179Sralph if( (k = j) < 0 ) uerror( "undefined structure or union" ); 519*16179Sralph else { 520*16179Sralph for( ; (kk = dimtab[k] ) >= 0; ++k ){ 521*16179Sralph if( kk >= SYMTSZ ){ 522*16179Sralph cerror( "gummy structure" ); 523*16179Sralph return(1); 524*16179Sralph } 525*16179Sralph if( kk == i ) return( 1 ); 526*16179Sralph switch( stab[kk].stype ){ 527*16179Sralph 528*16179Sralph case STRTY: 529*16179Sralph case UNIONTY: 530*16179Sralph if( type == STRTY ) continue; /* no recursive looking for strs */ 531*16179Sralph if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){ 532*16179Sralph if( stab[kk].sname[0] == '$' ) return(0); /* $FAKE */ 533*16179Sralph werror( 534*16179Sralph #ifndef FLEXNAMES 535*16179Sralph "illegal member use: perhaps %.8s.%.8s?", 536*16179Sralph #else 537*16179Sralph "illegal member use: perhaps %s.%s?", 538*16179Sralph #endif 539*16179Sralph stab[kk].sname, stab[i].sname ); 540*16179Sralph return(1); 541*16179Sralph } 542*16179Sralph } 543*16179Sralph } 544*16179Sralph } 545*16179Sralph return( 0 ); 546*16179Sralph } 547*16179Sralph 548*16179Sralph conval( p, o, q ) register NODE *p, *q; { 549*16179Sralph /* apply the op o to the lval part of p; if binary, rhs is val */ 550*16179Sralph int i, u; 551*16179Sralph CONSZ val; 552*16179Sralph 553*16179Sralph val = q->tn.lval; 554*16179Sralph u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type); 555*16179Sralph if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE); 556*16179Sralph 557*16179Sralph if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0); 558*16179Sralph if( q->tn.rval != NONAME && o!=PLUS ) return(0); 559*16179Sralph if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0); 560*16179Sralph 561*16179Sralph switch( o ){ 562*16179Sralph 563*16179Sralph case PLUS: 564*16179Sralph p->tn.lval += val; 565*16179Sralph if( p->tn.rval == NONAME ){ 566*16179Sralph p->tn.rval = q->tn.rval; 567*16179Sralph p->in.type = q->in.type; 568*16179Sralph } 569*16179Sralph break; 570*16179Sralph case MINUS: 571*16179Sralph p->tn.lval -= val; 572*16179Sralph break; 573*16179Sralph case MUL: 574*16179Sralph p->tn.lval *= val; 575*16179Sralph break; 576*16179Sralph case DIV: 577*16179Sralph if( val == 0 ) uerror( "division by 0" ); 578*16179Sralph else p->tn.lval /= val; 579*16179Sralph break; 580*16179Sralph case MOD: 581*16179Sralph if( val == 0 ) uerror( "division by 0" ); 582*16179Sralph else p->tn.lval %= val; 583*16179Sralph break; 584*16179Sralph case AND: 585*16179Sralph p->tn.lval &= val; 586*16179Sralph break; 587*16179Sralph case OR: 588*16179Sralph p->tn.lval |= val; 589*16179Sralph break; 590*16179Sralph case ER: 591*16179Sralph p->tn.lval ^= val; 592*16179Sralph break; 593*16179Sralph case LS: 594*16179Sralph i = val; 595*16179Sralph p->tn.lval = p->tn.lval << i; 596*16179Sralph break; 597*16179Sralph case RS: 598*16179Sralph i = val; 599*16179Sralph p->tn.lval = p->tn.lval >> i; 600*16179Sralph break; 601*16179Sralph 602*16179Sralph case UNARY MINUS: 603*16179Sralph p->tn.lval = - p->tn.lval; 604*16179Sralph break; 605*16179Sralph case COMPL: 606*16179Sralph p->tn.lval = ~p->tn.lval; 607*16179Sralph break; 608*16179Sralph case NOT: 609*16179Sralph p->tn.lval = !p->tn.lval; 610*16179Sralph break; 611*16179Sralph case LT: 612*16179Sralph p->tn.lval = p->tn.lval < val; 613*16179Sralph break; 614*16179Sralph case LE: 615*16179Sralph p->tn.lval = p->tn.lval <= val; 616*16179Sralph break; 617*16179Sralph case GT: 618*16179Sralph p->tn.lval = p->tn.lval > val; 619*16179Sralph break; 620*16179Sralph case GE: 621*16179Sralph p->tn.lval = p->tn.lval >= val; 622*16179Sralph break; 623*16179Sralph case ULT: 624*16179Sralph p->tn.lval = (p->tn.lval-val)<0; 625*16179Sralph break; 626*16179Sralph case ULE: 627*16179Sralph p->tn.lval = (p->tn.lval-val)<=0; 628*16179Sralph break; 629*16179Sralph case UGE: 630*16179Sralph p->tn.lval = (p->tn.lval-val)>=0; 631*16179Sralph break; 632*16179Sralph case UGT: 633*16179Sralph p->tn.lval = (p->tn.lval-val)>0; 634*16179Sralph break; 635*16179Sralph case EQ: 636*16179Sralph p->tn.lval = p->tn.lval == val; 637*16179Sralph break; 638*16179Sralph case NE: 639*16179Sralph p->tn.lval = p->tn.lval != val; 640*16179Sralph break; 641*16179Sralph default: 642*16179Sralph return(0); 643*16179Sralph } 644*16179Sralph return(1); 645*16179Sralph } 646*16179Sralph 647*16179Sralph chkpun(p) register NODE *p; { 648*16179Sralph 649*16179Sralph /* checks p for the existance of a pun */ 650*16179Sralph 651*16179Sralph /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */ 652*16179Sralph 653*16179Sralph /* one case is when enumerations are used: this applies only to lint */ 654*16179Sralph /* in the other case, one operand is a pointer, the other integer type */ 655*16179Sralph /* we check that this integer is in fact a constant zero... */ 656*16179Sralph 657*16179Sralph /* in the case of ASSIGN, any assignment of pointer to integer is illegal */ 658*16179Sralph /* this falls out, because the LHS is never 0 */ 659*16179Sralph 660*16179Sralph register NODE *q; 661*16179Sralph register t1, t2; 662*16179Sralph register d1, d2; 663*16179Sralph 664*16179Sralph t1 = p->in.left->in.type; 665*16179Sralph t2 = p->in.right->in.type; 666*16179Sralph 667*16179Sralph if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */ 668*16179Sralph if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) { 669*16179Sralph uerror( "illegal comparison of enums" ); 670*16179Sralph return; 671*16179Sralph } 672*16179Sralph if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return; 673*16179Sralph werror( "enumeration type clash, operator %s", opst[p->in.op] ); 674*16179Sralph return; 675*16179Sralph } 676*16179Sralph 677*16179Sralph if( ISPTR(t1) || ISARY(t1) ) q = p->in.right; 678*16179Sralph else q = p->in.left; 679*16179Sralph 680*16179Sralph if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){ 681*16179Sralph if( q->in.op != ICON || q->tn.lval != 0 ){ 682*16179Sralph werror( "illegal combination of pointer and integer, op %s", 683*16179Sralph opst[p->in.op] ); 684*16179Sralph } 685*16179Sralph } 686*16179Sralph else { 687*16179Sralph d1 = p->in.left->fn.cdim; 688*16179Sralph d2 = p->in.right->fn.cdim; 689*16179Sralph for( ;; ){ 690*16179Sralph if( t1 == t2 ) {; 691*16179Sralph if( p->in.left->fn.csiz != p->in.right->fn.csiz ) { 692*16179Sralph werror( "illegal structure pointer combination" ); 693*16179Sralph } 694*16179Sralph return; 695*16179Sralph } 696*16179Sralph if( ISARY(t1) || ISPTR(t1) ){ 697*16179Sralph if( !ISARY(t2) && !ISPTR(t2) ) break; 698*16179Sralph if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){ 699*16179Sralph werror( "illegal array size combination" ); 700*16179Sralph return; 701*16179Sralph } 702*16179Sralph if( ISARY(t1) ) ++d1; 703*16179Sralph if( ISARY(t2) ) ++d2; 704*16179Sralph } 705*16179Sralph else break; 706*16179Sralph t1 = DECREF(t1); 707*16179Sralph t2 = DECREF(t2); 708*16179Sralph } 709*16179Sralph werror( "illegal pointer combination" ); 710*16179Sralph } 711*16179Sralph 712*16179Sralph } 713*16179Sralph 714*16179Sralph NODE * 715*16179Sralph stref( p ) register NODE *p; { 716*16179Sralph 717*16179Sralph TWORD t; 718*16179Sralph int d, s, dsc, align; 719*16179Sralph OFFSZ off; 720*16179Sralph register struct symtab *q; 721*16179Sralph 722*16179Sralph /* make p->x */ 723*16179Sralph /* this is also used to reference automatic variables */ 724*16179Sralph 725*16179Sralph q = &stab[p->in.right->tn.rval]; 726*16179Sralph p->in.right->in.op = FREE; 727*16179Sralph p->in.op = FREE; 728*16179Sralph p = pconvert( p->in.left ); 729*16179Sralph 730*16179Sralph /* make p look like ptr to x */ 731*16179Sralph 732*16179Sralph if( !ISPTR(p->in.type)){ 733*16179Sralph p->in.type = PTR+UNIONTY; 734*16179Sralph } 735*16179Sralph 736*16179Sralph t = INCREF( q->stype ); 737*16179Sralph d = q->dimoff; 738*16179Sralph s = q->sizoff; 739*16179Sralph 740*16179Sralph p = makety( p, t, d, s ); 741*16179Sralph 742*16179Sralph /* compute the offset to be added */ 743*16179Sralph 744*16179Sralph off = q->offset; 745*16179Sralph dsc = q->sclass; 746*16179Sralph 747*16179Sralph if( dsc & FIELD ) { /* normalize offset */ 748*16179Sralph align = ALINT; 749*16179Sralph s = INT; 750*16179Sralph off = (off/align)*align; 751*16179Sralph } 752*16179Sralph if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) ); 753*16179Sralph 754*16179Sralph p = buildtree( UNARY MUL, p, NIL ); 755*16179Sralph 756*16179Sralph /* if field, build field info */ 757*16179Sralph 758*16179Sralph if( dsc & FIELD ){ 759*16179Sralph p = block( FLD, p, NIL, q->stype, 0, q->sizoff ); 760*16179Sralph p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align ); 761*16179Sralph } 762*16179Sralph 763*16179Sralph return( clocal(p) ); 764*16179Sralph } 765*16179Sralph 766*16179Sralph notlval(p) register NODE *p; { 767*16179Sralph 768*16179Sralph /* return 0 if p an lvalue, 1 otherwise */ 769*16179Sralph 770*16179Sralph again: 771*16179Sralph 772*16179Sralph switch( p->in.op ){ 773*16179Sralph 774*16179Sralph case FLD: 775*16179Sralph p = p->in.left; 776*16179Sralph goto again; 777*16179Sralph 778*16179Sralph case UNARY MUL: 779*16179Sralph /* fix the &(a=b) bug, given that a and b are structures */ 780*16179Sralph if( p->in.left->in.op == STASG ) return( 1 ); 781*16179Sralph /* and the f().a bug, given that f returns a structure */ 782*16179Sralph if( p->in.left->in.op == UNARY STCALL || 783*16179Sralph p->in.left->in.op == STCALL ) return( 1 ); 784*16179Sralph case NAME: 785*16179Sralph case OREG: 786*16179Sralph if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1); 787*16179Sralph case REG: 788*16179Sralph return(0); 789*16179Sralph 790*16179Sralph default: 791*16179Sralph return(1); 792*16179Sralph 793*16179Sralph } 794*16179Sralph 795*16179Sralph } 796*16179Sralph 797*16179Sralph NODE * 798*16179Sralph bcon( i ){ /* make a constant node with value i */ 799*16179Sralph register NODE *p; 800*16179Sralph 801*16179Sralph p = block( ICON, NIL, NIL, INT, 0, INT ); 802*16179Sralph p->tn.lval = i; 803*16179Sralph p->tn.rval = NONAME; 804*16179Sralph return( clocal(p) ); 805*16179Sralph } 806*16179Sralph 807*16179Sralph NODE * 808*16179Sralph bpsize(p) register NODE *p; { 809*16179Sralph return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) ); 810*16179Sralph } 811*16179Sralph 812*16179Sralph OFFSZ 813*16179Sralph psize( p ) NODE *p; { 814*16179Sralph /* p is a node of type pointer; psize returns the 815*16179Sralph size of the thing pointed to */ 816*16179Sralph 817*16179Sralph if( !ISPTR(p->in.type) ){ 818*16179Sralph uerror( "pointer required"); 819*16179Sralph return( SZINT ); 820*16179Sralph } 821*16179Sralph /* note: no pointers to fields */ 822*16179Sralph return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) ); 823*16179Sralph } 824*16179Sralph 825*16179Sralph NODE * 826*16179Sralph convert( p, f ) register NODE *p; { 827*16179Sralph /* convert an operand of p 828*16179Sralph f is either CVTL or CVTR 829*16179Sralph operand has type int, and is converted by the size of the other side 830*16179Sralph */ 831*16179Sralph 832*16179Sralph register NODE *q, *r; 833*16179Sralph 834*16179Sralph q = (f==CVTL)?p->in.left:p->in.right; 835*16179Sralph 836*16179Sralph r = block( PMCONV, 837*16179Sralph q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT ); 838*16179Sralph r = clocal(r); 839*16179Sralph if( f == CVTL ) 840*16179Sralph p->in.left = r; 841*16179Sralph else 842*16179Sralph p->in.right = r; 843*16179Sralph return(p); 844*16179Sralph 845*16179Sralph } 846*16179Sralph 847*16179Sralph econvert( p ) register NODE *p; { 848*16179Sralph 849*16179Sralph /* change enums to ints, or appropriate types */ 850*16179Sralph 851*16179Sralph register TWORD ty; 852*16179Sralph 853*16179Sralph if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) { 854*16179Sralph if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR; 855*16179Sralph else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT; 856*16179Sralph else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT; 857*16179Sralph else ty = LONG; 858*16179Sralph ty = ctype( ty ); 859*16179Sralph p->fn.csiz = ty; 860*16179Sralph MODTYPE(p->in.type,ty); 861*16179Sralph if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT; 862*16179Sralph } 863*16179Sralph } 864*16179Sralph 865*16179Sralph NODE * 866*16179Sralph pconvert( p ) register NODE *p; { 867*16179Sralph 868*16179Sralph /* if p should be changed into a pointer, do so */ 869*16179Sralph 870*16179Sralph if( ISARY( p->in.type) ){ 871*16179Sralph p->in.type = DECREF( p->in.type ); 872*16179Sralph ++p->fn.cdim; 873*16179Sralph return( buildtree( UNARY AND, p, NIL ) ); 874*16179Sralph } 875*16179Sralph if( ISFTN( p->in.type) ) 876*16179Sralph return( buildtree( UNARY AND, p, NIL ) ); 877*16179Sralph 878*16179Sralph return( p ); 879*16179Sralph } 880*16179Sralph 881*16179Sralph NODE * 882*16179Sralph oconvert(p) register NODE *p; { 883*16179Sralph /* convert the result itself: used for pointer and unsigned */ 884*16179Sralph 885*16179Sralph switch(p->in.op) { 886*16179Sralph 887*16179Sralph case LE: 888*16179Sralph case LT: 889*16179Sralph case GE: 890*16179Sralph case GT: 891*16179Sralph if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) ) p->in.op += (ULE-LE); 892*16179Sralph case EQ: 893*16179Sralph case NE: 894*16179Sralph return( p ); 895*16179Sralph 896*16179Sralph case MINUS: 897*16179Sralph return( clocal( block( PVCONV, 898*16179Sralph p, bpsize(p->in.left), INT, 0, INT ) ) ); 899*16179Sralph } 900*16179Sralph 901*16179Sralph cerror( "illegal oconvert: %d", p->in.op ); 902*16179Sralph 903*16179Sralph return(p); 904*16179Sralph } 905*16179Sralph 906*16179Sralph NODE * 907*16179Sralph ptmatch(p) register NODE *p; { 908*16179Sralph 909*16179Sralph /* makes the operands of p agree; they are 910*16179Sralph either pointers or integers, by this time */ 911*16179Sralph /* with MINUS, the sizes must be the same */ 912*16179Sralph /* with COLON, the types must be the same */ 913*16179Sralph 914*16179Sralph TWORD t1, t2, t; 915*16179Sralph int o, d2, d, s2, s; 916*16179Sralph 917*16179Sralph o = p->in.op; 918*16179Sralph t = t1 = p->in.left->in.type; 919*16179Sralph t2 = p->in.right->in.type; 920*16179Sralph d = p->in.left->fn.cdim; 921*16179Sralph d2 = p->in.right->fn.cdim; 922*16179Sralph s = p->in.left->fn.csiz; 923*16179Sralph s2 = p->in.right->fn.csiz; 924*16179Sralph 925*16179Sralph switch( o ){ 926*16179Sralph 927*16179Sralph case ASSIGN: 928*16179Sralph case RETURN: 929*16179Sralph case CAST: 930*16179Sralph { break; } 931*16179Sralph 932*16179Sralph case MINUS: 933*16179Sralph { if( psize(p->in.left) != psize(p->in.right) ){ 934*16179Sralph uerror( "illegal pointer subtraction"); 935*16179Sralph } 936*16179Sralph break; 937*16179Sralph } 938*16179Sralph case COLON: 939*16179Sralph { if( t1 != t2 ) uerror( "illegal types in :"); 940*16179Sralph break; 941*16179Sralph } 942*16179Sralph default: /* must work harder: relationals or comparisons */ 943*16179Sralph 944*16179Sralph if( !ISPTR(t1) ){ 945*16179Sralph t = t2; 946*16179Sralph d = d2; 947*16179Sralph s = s2; 948*16179Sralph break; 949*16179Sralph } 950*16179Sralph if( !ISPTR(t2) ){ 951*16179Sralph break; 952*16179Sralph } 953*16179Sralph 954*16179Sralph /* both are pointers */ 955*16179Sralph if( talign(t2,s2) < talign(t,s) ){ 956*16179Sralph t = t2; 957*16179Sralph s = s2; 958*16179Sralph } 959*16179Sralph break; 960*16179Sralph } 961*16179Sralph 962*16179Sralph p->in.left = makety( p->in.left, t, d, s ); 963*16179Sralph p->in.right = makety( p->in.right, t, d, s ); 964*16179Sralph if( o!=MINUS && !logop(o) ){ 965*16179Sralph 966*16179Sralph p->in.type = t; 967*16179Sralph p->fn.cdim = d; 968*16179Sralph p->fn.csiz = s; 969*16179Sralph } 970*16179Sralph 971*16179Sralph return(clocal(p)); 972*16179Sralph } 973*16179Sralph 974*16179Sralph int tdebug = 0; 975*16179Sralph 976*16179Sralph NODE * 977*16179Sralph tymatch(p) register NODE *p; { 978*16179Sralph 979*16179Sralph /* satisfy the types of various arithmetic binary ops */ 980*16179Sralph 981*16179Sralph /* rules are: 982*16179Sralph if assignment, op, type of LHS 983*16179Sralph if any float or doubles, make double 984*16179Sralph if any longs, make long 985*16179Sralph otherwise, make int 986*16179Sralph if either operand is unsigned, the result is... 987*16179Sralph */ 988*16179Sralph 989*16179Sralph register TWORD t1, t2, t, tu; 990*16179Sralph register o, u; 991*16179Sralph 992*16179Sralph o = p->in.op; 993*16179Sralph 994*16179Sralph t1 = p->in.left->in.type; 995*16179Sralph t2 = p->in.right->in.type; 996*16179Sralph if( (t1==UNDEF || t2==UNDEF) && o!=CAST ) 997*16179Sralph uerror("void type illegal in expression"); 998*16179Sralph 999*16179Sralph u = 0; 1000*16179Sralph if( ISUNSIGNED(t1) ){ 1001*16179Sralph u = 1; 1002*16179Sralph t1 = DEUNSIGN(t1); 1003*16179Sralph } 1004*16179Sralph if( ISUNSIGNED(t2) ){ 1005*16179Sralph u = 1; 1006*16179Sralph t2 = DEUNSIGN(t2); 1007*16179Sralph } 1008*16179Sralph 1009*16179Sralph if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT; 1010*16179Sralph if( t2 == CHAR || t2 == SHORT ) t2 = INT; 1011*16179Sralph 1012*16179Sralph if( t1==DOUBLE || t1==FLOAT || t2==DOUBLE || t2==FLOAT ) t = DOUBLE; 1013*16179Sralph else if( t1==LONG || t2==LONG ) t = LONG; 1014*16179Sralph else t = INT; 1015*16179Sralph 1016*16179Sralph if( asgop(o) ){ 1017*16179Sralph tu = p->in.left->in.type; 1018*16179Sralph t = t1; 1019*16179Sralph } 1020*16179Sralph else { 1021*16179Sralph tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t; 1022*16179Sralph } 1023*16179Sralph 1024*16179Sralph /* because expressions have values that are at least as wide 1025*16179Sralph as INT or UNSIGNED, the only conversions needed 1026*16179Sralph are those involving FLOAT/DOUBLE, and those 1027*16179Sralph from LONG to INT and ULONG to UNSIGNED */ 1028*16179Sralph 1029*16179Sralph if( t != t1 ) p->in.left = makety( p->in.left, tu, 0, (int)tu ); 1030*16179Sralph 1031*16179Sralph if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); 1032*16179Sralph 1033*16179Sralph if( asgop(o) ){ 1034*16179Sralph p->in.type = p->in.left->in.type; 1035*16179Sralph p->fn.cdim = p->in.left->fn.cdim; 1036*16179Sralph p->fn.csiz = p->in.left->fn.csiz; 1037*16179Sralph } 1038*16179Sralph else if( !logop(o) ){ 1039*16179Sralph p->in.type = tu; 1040*16179Sralph p->fn.cdim = 0; 1041*16179Sralph p->fn.csiz = t; 1042*16179Sralph } 1043*16179Sralph 1044*16179Sralph # ifndef BUG1 1045*16179Sralph if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu ); 1046*16179Sralph # endif 1047*16179Sralph 1048*16179Sralph return(p); 1049*16179Sralph } 1050*16179Sralph 1051*16179Sralph NODE * 1052*16179Sralph makety( p, t, d, s ) register NODE *p; TWORD t; { 1053*16179Sralph /* make p into type t by inserting a conversion */ 1054*16179Sralph 1055*16179Sralph if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p); 1056*16179Sralph if( t == p->in.type ){ 1057*16179Sralph p->fn.cdim = d; 1058*16179Sralph p->fn.csiz = s; 1059*16179Sralph return( p ); 1060*16179Sralph } 1061*16179Sralph 1062*16179Sralph if( t & TMASK ){ 1063*16179Sralph /* non-simple type */ 1064*16179Sralph return( block( PCONV, p, NIL, t, d, s ) ); 1065*16179Sralph } 1066*16179Sralph 1067*16179Sralph if( p->in.op == ICON ){ 1068*16179Sralph if( t==DOUBLE||t==FLOAT ){ 1069*16179Sralph p->in.op = FCON; 1070*16179Sralph if( ISUNSIGNED(p->in.type) ){ 1071*16179Sralph p->fpn.dval = /* (unsigned CONSZ) */ p->tn.lval; 1072*16179Sralph } 1073*16179Sralph else { 1074*16179Sralph p->fpn.dval = p->tn.lval; 1075*16179Sralph } 1076*16179Sralph 1077*16179Sralph p->in.type = p->fn.csiz = t; 1078*16179Sralph return( clocal(p) ); 1079*16179Sralph } 1080*16179Sralph } 1081*16179Sralph 1082*16179Sralph return( block( SCONV, p, NIL, t, d, s ) ); 1083*16179Sralph 1084*16179Sralph } 1085*16179Sralph 1086*16179Sralph NODE * 1087*16179Sralph block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; { 1088*16179Sralph 1089*16179Sralph register NODE *p; 1090*16179Sralph 1091*16179Sralph p = talloc(); 1092*16179Sralph p->in.op = o; 1093*16179Sralph p->in.left = l; 1094*16179Sralph p->in.right = r; 1095*16179Sralph p->in.type = t; 1096*16179Sralph p->fn.cdim = d; 1097*16179Sralph p->fn.csiz = s; 1098*16179Sralph return(p); 1099*16179Sralph } 1100*16179Sralph 1101*16179Sralph icons(p) register NODE *p; { 1102*16179Sralph /* if p is an integer constant, return its value */ 1103*16179Sralph int val; 1104*16179Sralph 1105*16179Sralph if( p->in.op != ICON ){ 1106*16179Sralph uerror( "constant expected"); 1107*16179Sralph val = 1; 1108*16179Sralph } 1109*16179Sralph else { 1110*16179Sralph val = p->tn.lval; 1111*16179Sralph if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" ); 1112*16179Sralph } 1113*16179Sralph tfree( p ); 1114*16179Sralph return(val); 1115*16179Sralph } 1116*16179Sralph 1117*16179Sralph /* the intent of this table is to examine the 1118*16179Sralph operators, and to check them for 1119*16179Sralph correctness. 1120*16179Sralph 1121*16179Sralph The table is searched for the op and the 1122*16179Sralph modified type (where this is one of the 1123*16179Sralph types INT (includes char and short), LONG, 1124*16179Sralph DOUBLE (includes FLOAT), and POINTER 1125*16179Sralph 1126*16179Sralph The default action is to make the node type integer 1127*16179Sralph 1128*16179Sralph The actions taken include: 1129*16179Sralph PUN check for puns 1130*16179Sralph CVTL convert the left operand 1131*16179Sralph CVTR convert the right operand 1132*16179Sralph TYPL the type is determined by the left operand 1133*16179Sralph TYPR the type is determined by the right operand 1134*16179Sralph TYMATCH force type of left and right to match, by inserting conversions 1135*16179Sralph PTMATCH like TYMATCH, but for pointers 1136*16179Sralph LVAL left operand must be lval 1137*16179Sralph CVTO convert the op 1138*16179Sralph NCVT do not convert the operands 1139*16179Sralph OTHER handled by code 1140*16179Sralph NCVTR convert the left operand, not the right... 1141*16179Sralph 1142*16179Sralph */ 1143*16179Sralph 1144*16179Sralph # define MINT 01 /* integer */ 1145*16179Sralph # define MDBI 02 /* integer or double */ 1146*16179Sralph # define MSTR 04 /* structure */ 1147*16179Sralph # define MPTR 010 /* pointer */ 1148*16179Sralph # define MPTI 020 /* pointer or integer */ 1149*16179Sralph # define MENU 040 /* enumeration variable or member */ 1150*16179Sralph 1151*16179Sralph opact( p ) NODE *p; { 1152*16179Sralph 1153*16179Sralph register mt12, mt1, mt2, o; 1154*16179Sralph 1155*16179Sralph mt12 = 0; 1156*16179Sralph 1157*16179Sralph switch( optype(o=p->in.op) ){ 1158*16179Sralph 1159*16179Sralph case BITYPE: 1160*16179Sralph mt12=mt2 = moditype( p->in.right->in.type ); 1161*16179Sralph case UTYPE: 1162*16179Sralph mt12 &= (mt1 = moditype( p->in.left->in.type )); 1163*16179Sralph 1164*16179Sralph } 1165*16179Sralph 1166*16179Sralph switch( o ){ 1167*16179Sralph 1168*16179Sralph case NAME : 1169*16179Sralph case STRING : 1170*16179Sralph case ICON : 1171*16179Sralph case FCON : 1172*16179Sralph case CALL : 1173*16179Sralph case UNARY CALL: 1174*16179Sralph case UNARY MUL: 1175*16179Sralph { return( OTHER ); } 1176*16179Sralph case UNARY MINUS: 1177*16179Sralph if( mt1 & MDBI ) return( TYPL ); 1178*16179Sralph break; 1179*16179Sralph 1180*16179Sralph case COMPL: 1181*16179Sralph if( mt1 & MINT ) return( TYPL ); 1182*16179Sralph break; 1183*16179Sralph 1184*16179Sralph case UNARY AND: 1185*16179Sralph { return( NCVT+OTHER ); } 1186*16179Sralph case INIT: 1187*16179Sralph case CM: 1188*16179Sralph case NOT: 1189*16179Sralph case CBRANCH: 1190*16179Sralph case ANDAND: 1191*16179Sralph case OROR: 1192*16179Sralph return( 0 ); 1193*16179Sralph 1194*16179Sralph case MUL: 1195*16179Sralph case DIV: 1196*16179Sralph if( mt12 & MDBI ) return( TYMATCH ); 1197*16179Sralph break; 1198*16179Sralph 1199*16179Sralph case MOD: 1200*16179Sralph case AND: 1201*16179Sralph case OR: 1202*16179Sralph case ER: 1203*16179Sralph if( mt12 & MINT ) return( TYMATCH ); 1204*16179Sralph break; 1205*16179Sralph 1206*16179Sralph case LS: 1207*16179Sralph case RS: 1208*16179Sralph if( mt12 & MINT ) return( TYMATCH+OTHER ); 1209*16179Sralph break; 1210*16179Sralph 1211*16179Sralph case EQ: 1212*16179Sralph case NE: 1213*16179Sralph case LT: 1214*16179Sralph case LE: 1215*16179Sralph case GT: 1216*16179Sralph case GE: 1217*16179Sralph if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT ); 1218*16179Sralph if( mt12 & MDBI ) return( TYMATCH+CVTO ); 1219*16179Sralph else if( mt12 & MPTR ) return( PTMATCH+PUN ); 1220*16179Sralph else if( mt12 & MPTI ) return( PTMATCH+PUN ); 1221*16179Sralph else break; 1222*16179Sralph 1223*16179Sralph case QUEST: 1224*16179Sralph case COMOP: 1225*16179Sralph if( mt2&MENU ) return( TYPR+NCVTR ); 1226*16179Sralph return( TYPR ); 1227*16179Sralph 1228*16179Sralph case STREF: 1229*16179Sralph return( NCVTR+OTHER ); 1230*16179Sralph 1231*16179Sralph case FORCE: 1232*16179Sralph return( TYPL ); 1233*16179Sralph 1234*16179Sralph case COLON: 1235*16179Sralph if( mt12 & MENU ) return( NCVT+PUN+PTMATCH ); 1236*16179Sralph else if( mt12 & MDBI ) return( TYMATCH ); 1237*16179Sralph else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN ); 1238*16179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN ); 1239*16179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN ); 1240*16179Sralph else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER ); 1241*16179Sralph break; 1242*16179Sralph 1243*16179Sralph case ASSIGN: 1244*16179Sralph case RETURN: 1245*16179Sralph if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER ); 1246*16179Sralph case CAST: 1247*16179Sralph if(o==CAST && mt1==0)return(TYPL+TYMATCH); 1248*16179Sralph if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); 1249*16179Sralph else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); 1250*16179Sralph else if( mt12 == 0 ) break; 1251*16179Sralph else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); 1252*16179Sralph else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); 1253*16179Sralph break; 1254*16179Sralph 1255*16179Sralph case ASG LS: 1256*16179Sralph case ASG RS: 1257*16179Sralph if( mt12 & MINT ) return( TYPL+LVAL+OTHER ); 1258*16179Sralph break; 1259*16179Sralph 1260*16179Sralph case ASG MUL: 1261*16179Sralph case ASG DIV: 1262*16179Sralph if( mt12 & MDBI ) return( LVAL+TYMATCH ); 1263*16179Sralph break; 1264*16179Sralph 1265*16179Sralph case ASG MOD: 1266*16179Sralph case ASG AND: 1267*16179Sralph case ASG OR: 1268*16179Sralph case ASG ER: 1269*16179Sralph if( mt12 & MINT ) return( LVAL+TYMATCH ); 1270*16179Sralph break; 1271*16179Sralph 1272*16179Sralph case ASG PLUS: 1273*16179Sralph case ASG MINUS: 1274*16179Sralph case INCR: 1275*16179Sralph case DECR: 1276*16179Sralph if( mt12 & MDBI ) return( TYMATCH+LVAL ); 1277*16179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR ); 1278*16179Sralph break; 1279*16179Sralph 1280*16179Sralph case MINUS: 1281*16179Sralph if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN ); 1282*16179Sralph if( mt2 & MPTR ) break; 1283*16179Sralph case PLUS: 1284*16179Sralph if( mt12 & MDBI ) return( TYMATCH ); 1285*16179Sralph else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR ); 1286*16179Sralph else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL ); 1287*16179Sralph 1288*16179Sralph } 1289*16179Sralph uerror( "operands of %s have incompatible types", opst[o] ); 1290*16179Sralph return( NCVT ); 1291*16179Sralph } 1292*16179Sralph 1293*16179Sralph moditype( ty ) TWORD ty; { 1294*16179Sralph 1295*16179Sralph switch( ty ){ 1296*16179Sralph 1297*16179Sralph case TVOID: 1298*16179Sralph case UNDEF: 1299*16179Sralph return(0); /* type is void */ 1300*16179Sralph case ENUMTY: 1301*16179Sralph case MOETY: 1302*16179Sralph return( MENU ); 1303*16179Sralph 1304*16179Sralph case STRTY: 1305*16179Sralph case UNIONTY: 1306*16179Sralph return( MSTR ); 1307*16179Sralph 1308*16179Sralph case CHAR: 1309*16179Sralph case SHORT: 1310*16179Sralph case UCHAR: 1311*16179Sralph case USHORT: 1312*16179Sralph return( MINT|MPTI|MDBI ); 1313*16179Sralph case UNSIGNED: 1314*16179Sralph case ULONG: 1315*16179Sralph case INT: 1316*16179Sralph case LONG: 1317*16179Sralph return( MINT|MDBI|MPTI ); 1318*16179Sralph case FLOAT: 1319*16179Sralph case DOUBLE: 1320*16179Sralph return( MDBI ); 1321*16179Sralph default: 1322*16179Sralph return( MPTR|MPTI ); 1323*16179Sralph 1324*16179Sralph } 1325*16179Sralph } 1326*16179Sralph 1327*16179Sralph NODE * 1328*16179Sralph doszof( p ) register NODE *p; { 1329*16179Sralph /* do sizeof p */ 1330*16179Sralph int i; 1331*16179Sralph 1332*16179Sralph /* whatever is the meaning of this if it is a bitfield? */ 1333*16179Sralph i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR; 1334*16179Sralph 1335*16179Sralph tfree(p); 1336*16179Sralph if( i <= 0 ) werror( "sizeof returns 0" ); 1337*16179Sralph return( bcon( i ) ); 1338*16179Sralph } 1339*16179Sralph 1340*16179Sralph # ifndef BUG2 1341*16179Sralph eprint( p, down, a, b ) register NODE *p; int *a, *b; { 1342*16179Sralph register ty; 1343*16179Sralph 1344*16179Sralph *a = *b = down+1; 1345*16179Sralph while( down > 1 ){ 1346*16179Sralph printf( "\t" ); 1347*16179Sralph down -= 2; 1348*16179Sralph } 1349*16179Sralph if( down ) printf( " " ); 1350*16179Sralph 1351*16179Sralph ty = optype( p->in.op ); 1352*16179Sralph 1353*16179Sralph printf("%o) %s, ", p, opst[p->in.op] ); 1354*16179Sralph if( ty == LTYPE ){ 1355*16179Sralph printf( CONFMT, p->tn.lval ); 1356*16179Sralph printf( ", %d, ", p->tn.rval ); 1357*16179Sralph } 1358*16179Sralph tprint( p->in.type ); 1359*16179Sralph printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz ); 1360*16179Sralph } 1361*16179Sralph # endif 1362*16179Sralph 1363*16179Sralph prtdcon( p ) register NODE *p; { 1364*16179Sralph int i; 1365*16179Sralph 1366*16179Sralph if( p->in.op == FCON ){ 1367*16179Sralph locctr( DATA ); 1368*16179Sralph defalign( ALDOUBLE ); 1369*16179Sralph deflab( i = getlab() ); 1370*16179Sralph fincode( p->fpn.dval, SZDOUBLE ); 1371*16179Sralph p->tn.lval = 0; 1372*16179Sralph p->tn.rval = -i; 1373*16179Sralph p->in.type = DOUBLE; 1374*16179Sralph p->in.op = NAME; 1375*16179Sralph } 1376*16179Sralph } 1377*16179Sralph 1378*16179Sralph 1379*16179Sralph int edebug = 0; 1380*16179Sralph ecomp( p ) register NODE *p; { 1381*16179Sralph # ifndef BUG2 1382*16179Sralph if( edebug ) fwalk( p, eprint, 0 ); 1383*16179Sralph # endif 1384*16179Sralph if( !reached ){ 1385*16179Sralph werror( "statement not reached" ); 1386*16179Sralph reached = 1; 1387*16179Sralph } 1388*16179Sralph p = optim(p); 1389*16179Sralph walkf( p, prtdcon ); 1390*16179Sralph locctr( PROG ); 1391*16179Sralph ecode( p ); 1392*16179Sralph tfree(p); 1393*16179Sralph } 1394*16179Sralph 1395*16179Sralph # ifdef STDPRTREE 1396*16179Sralph # ifndef ONEPASS 1397*16179Sralph 1398*16179Sralph prtree(p) register NODE *p; { 1399*16179Sralph 1400*16179Sralph register struct symtab *q; 1401*16179Sralph register ty; 1402*16179Sralph 1403*16179Sralph # ifdef MYPRTREE 1404*16179Sralph MYPRTREE(p); /* local action can be taken here; then return... */ 1405*16179Sralph #endif 1406*16179Sralph 1407*16179Sralph ty = optype(p->in.op); 1408*16179Sralph 1409*16179Sralph printf( "%d\t", p->in.op ); 1410*16179Sralph 1411*16179Sralph if( ty == LTYPE ) { 1412*16179Sralph printf( CONFMT, p->tn.lval ); 1413*16179Sralph printf( "\t" ); 1414*16179Sralph } 1415*16179Sralph if( ty != BITYPE ) { 1416*16179Sralph if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" ); 1417*16179Sralph else printf( "%d\t", p->tn.rval ); 1418*16179Sralph } 1419*16179Sralph 1420*16179Sralph printf( "%o\t", p->in.type ); 1421*16179Sralph 1422*16179Sralph /* handle special cases */ 1423*16179Sralph 1424*16179Sralph switch( p->in.op ){ 1425*16179Sralph 1426*16179Sralph case NAME: 1427*16179Sralph case ICON: 1428*16179Sralph /* print external name */ 1429*16179Sralph if( p->tn.rval == NONAME ) printf( "\n" ); 1430*16179Sralph else if( p->tn.rval >= 0 ){ 1431*16179Sralph q = &stab[p->tn.rval]; 1432*16179Sralph printf( "%s\n", exname(q->sname) ); 1433*16179Sralph } 1434*16179Sralph else { /* label */ 1435*16179Sralph printf( LABFMT, -p->tn.rval ); 1436*16179Sralph } 1437*16179Sralph break; 1438*16179Sralph 1439*16179Sralph case STARG: 1440*16179Sralph case STASG: 1441*16179Sralph case STCALL: 1442*16179Sralph case UNARY STCALL: 1443*16179Sralph /* print out size */ 1444*16179Sralph /* use lhs size, in order to avoid hassles with the structure `.' operator */ 1445*16179Sralph 1446*16179Sralph /* note: p->in.left not a field... */ 1447*16179Sralph printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) ); 1448*16179Sralph printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) ); 1449*16179Sralph break; 1450*16179Sralph 1451*16179Sralph default: 1452*16179Sralph printf( "\n" ); 1453*16179Sralph } 1454*16179Sralph 1455*16179Sralph if( ty != LTYPE ) prtree( p->in.left ); 1456*16179Sralph if( ty == BITYPE ) prtree( p->in.right ); 1457*16179Sralph 1458*16179Sralph } 1459*16179Sralph 1460*16179Sralph # else 1461*16179Sralph 1462*16179Sralph p2tree(p) register NODE *p; { 1463*16179Sralph register ty; 1464*16179Sralph 1465*16179Sralph # ifdef MYP2TREE 1466*16179Sralph MYP2TREE(p); /* local action can be taken here; then return... */ 1467*16179Sralph # endif 1468*16179Sralph 1469*16179Sralph ty = optype(p->in.op); 1470*16179Sralph 1471*16179Sralph switch( p->in.op ){ 1472*16179Sralph 1473*16179Sralph case NAME: 1474*16179Sralph case ICON: 1475*16179Sralph #ifndef FLEXNAMES 1476*16179Sralph if( p->tn.rval == NONAME ) p->in.name[0] = '\0'; 1477*16179Sralph #else 1478*16179Sralph if( p->tn.rval == NONAME ) p->in.name = ""; 1479*16179Sralph #endif 1480*16179Sralph else if( p->tn.rval >= 0 ){ /* copy name from exname */ 1481*16179Sralph register char *cp; 1482*16179Sralph register i; 1483*16179Sralph cp = exname( stab[p->tn.rval].sname ); 1484*16179Sralph #ifndef FLEXNAMES 1485*16179Sralph for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++; 1486*16179Sralph #else 1487*16179Sralph p->in.name = tstr(cp); 1488*16179Sralph #endif 1489*16179Sralph } 1490*16179Sralph #ifndef FLEXNAMES 1491*16179Sralph else sprintf( p->in.name, LABFMT, -p->tn.rval ); 1492*16179Sralph #else 1493*16179Sralph else { 1494*16179Sralph char temp[32]; 1495*16179Sralph sprintf( temp, LABFMT, -p->tn.rval ); 1496*16179Sralph p->in.name = tstr(temp); 1497*16179Sralph } 1498*16179Sralph #endif 1499*16179Sralph break; 1500*16179Sralph 1501*16179Sralph case STARG: 1502*16179Sralph case STASG: 1503*16179Sralph case STCALL: 1504*16179Sralph case UNARY STCALL: 1505*16179Sralph /* set up size parameters */ 1506*16179Sralph p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR; 1507*16179Sralph p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR; 1508*16179Sralph break; 1509*16179Sralph 1510*16179Sralph case REG: 1511*16179Sralph rbusy( p->tn.rval, p->in.type ); 1512*16179Sralph default: 1513*16179Sralph #ifndef FLEXNAMES 1514*16179Sralph p->in.name[0] = '\0'; 1515*16179Sralph #else 1516*16179Sralph p->in.name = ""; 1517*16179Sralph #endif 1518*16179Sralph } 1519*16179Sralph 1520*16179Sralph p->in.rall = NOPREF; 1521*16179Sralph 1522*16179Sralph if( ty != LTYPE ) p2tree( p->in.left ); 1523*16179Sralph if( ty == BITYPE ) p2tree( p->in.right ); 1524*16179Sralph } 1525*16179Sralph 1526*16179Sralph # endif 1527*16179Sralph # endif 1528