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