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