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