|
|
1.1 ! root 1: /* @(#) optim.c: 1.3 1/12/84 */ ! 2: ! 3: # include "mfile1.h" ! 4: ! 5: # define ISCON(p) (p->in.op==ICON) ! 6: ! 7: int opdebug = 0; ! 8: NODE *doptim(); ! 9: ! 10: NODE * ! 11: aadjust( p, adj ) ! 12: register NODE *p; ! 13: register adj; ! 14: { ! 15: /* try to adjust p by adj bits */ ! 16: register NODE *q; ! 17: adj = BITOOR(adj); ! 18: switch( p->tn.op ) ! 19: { ! 20: case ICON: ! 21: p->tn.lval += adj; ! 22: return( p ); ! 23: default: ! 24: /* construct a + node */ ! 25: mkplus: ! 26: return( block( PLUS, p, bcon(adj), p->fn.type, ! 27: p->fn.cdim, p->fn.csiz ) ); ! 28: case PLUS: ! 29: q = p->in.right; ! 30: if( q->tn.op != ICON ) goto mkplus; ! 31: q->tn.lval += adj; ! 32: return( p ); ! 33: case MINUS: ! 34: q = p->in.right; ! 35: if( q->tn.op != ICON ) goto mkplus; ! 36: q->tn.lval -= adj; ! 37: return( p ); ! 38: } ! 39: } ! 40: ! 41: adjust( p, adj ) ! 42: register NODE *p; ! 43: register adj; ! 44: { ! 45: /* handle adjustment of scalars by adj bits */ ! 46: ! 47: switch( p->tn.op ) ! 48: { ! 49: case NAME: ! 50: case VAUTO: ! 51: case VPARAM: ! 52: p->tn.lval += BITOOR(adj); ! 53: return( 1 ); ! 54: case STAR: ! 55: p->in.left = aadjust( p->in.left, adj ); ! 56: return( 1 ); ! 57: default: ! 58: return( 0 ); ! 59: } ! 60: } ! 61: ! 62: # ifdef NOSIMPSTR ! 63: # ifndef MYSIMPSTR ! 64: simpstr( d, s ) ! 65: { ! 66: return( STRTY ); ! 67: } ! 68: # endif ! 69: # else ! 70: TWORD ! 71: simpstr( d, s ) ! 72: { ! 73: /* return STRTY if not, and CHAR, INT, SHORT, or LONG if simple */ ! 74: register sz, al; ! 75: ! 76: sz = tsize( STRTY, d, s ); ! 77: al = talign( STRTY, s ); ! 78: if( sz == SZINT /*&& !( al % ALINT)*/ ) return( INT ); ! 79: else if( sz == SZCHAR /*&& !( al % ALCHAR)*/ ) return( CHAR ); ! 80: else if( sz == SZLONG /*&& !( al % ALLONG)*/ ) return( LONG ); ! 81: else if( sz == SZSHORT /*&& !( al % ALSHORT)*/ ) return( SHORT ); ! 82: return( STRTY ); ! 83: } ! 84: # endif ! 85: ! 86: tydown( p ) ! 87: NODE *p; ! 88: { ! 89: /* reflect the type of p downwards, as appropriate */ ! 90: /* the type is typically getting smaller */ ! 91: /* returns 1 if it makes a real change */ ! 92: ! 93: TWORD t; ! 94: NODE *l, *r; ! 95: int flag; ! 96: ! 97: #ifndef NODBG ! 98: if( opdebug ) ! 99: { ! 100: printf( "tydown(%d) called with:\n", p-node ); ! 101: eprint( p ); ! 102: } ! 103: #endif ! 104: t = p->tn.type; ! 105: if( ISPTR(t) || ISARY(t) ) return(0); ! 106: ! 107: /* work these types down into the tree */ ! 108: ! 109: flag = 0; ! 110: ! 111: switch( p->tn.op ) ! 112: { ! 113: ! 114: case AND: ! 115: case OR: ! 116: case PLUS: ! 117: case MINUS: ! 118: case ER: ! 119: case COMOP: ! 120: #ifndef NODBG ! 121: if( opdebug ) ! 122: { ! 123: printf( "tydown:\n" ); ! 124: eprint( p ); ! 125: } ! 126: #endif ! 127: r = p->in.right; ! 128: if( bigsize(r->tn.type) > bigsize(p->tn.type ) ) ! 129: { ! 130: r = makety( r, t, 0, (int) t ); ! 131: tydown( r ); ! 132: p->in.right = doptim( r ); ! 133: #ifndef NODBG ! 134: if( opdebug ) ! 135: { ! 136: printf( "tydown(%d), after doptim(R):\n", ! 137: p-node ); ! 138: eprint(p); ! 139: } ! 140: #endif ! 141: flag = 1; ! 142: } ! 143: if( p->tn.op == COMOP ) return( flag ); ! 144: /* FALLTHRU */ ! 145: ! 146: case UNARY MINUS: ! 147: case COMPL: ! 148: l = p->in.left; ! 149: if( bigsize(l->tn.type) > bigsize(p->tn.type ) ) ! 150: { ! 151: l = makety( l, t, 0, (int) t ); ! 152: tydown( l ); ! 153: p->in.left = doptim( l ); ! 154: #ifndef NODBG ! 155: if( opdebug ) ! 156: { ! 157: printf( "tydown(%d), after doptim(L):\n", ! 158: p-node ); ! 159: eprint(p); ! 160: } ! 161: #endif ! 162: flag = 1; ! 163: } ! 164: return(flag); ! 165: } ! 166: return( 0 ); /* no change */ ! 167: } ! 168: ! 169: # ifndef MYCONVERT ! 170: NODE * ! 171: sconvert( p ) ! 172: register NODE *p; ! 173: { ! 174: register TWORD t, lt; ! 175: register NODE *l; ! 176: register o; ! 177: ! 178: /* optimize CONV nodes */ ! 179: /* the unsigned-ness is ignored */ ! 180: /* if the CONV involves floats or doubles, retain unless null */ ! 181: /* if the CONV makes things bigger, retain */ ! 182: /* if the CONV keeps things the same size, just paint the type */ ! 183: /* if the CONV makes things smaller, adjust the addressing with ! 184: ** memory references, and paint the new type ! 185: */ ! 186: /* if a pointer is being converted, convert as if it were PTRTYPE */ ! 187: /* finally, if CONV converts a constant, do it in place */ ! 188: again: ! 189: #ifndef NODBG ! 190: if( opdebug ) ! 191: { ! 192: printf( "sconvert(%d) called:\n", p-node ); ! 193: eprint( p ); ! 194: } ! 195: #endif ! 196: if( p->tn.op != CONV ) cerror( "sconvert" ); ! 197: l = p->in.left; ! 198: t = p->tn.type; ! 199: lt = l->tn.type; ! 200: o = l->tn.op; ! 201: ! 202: if( o == FCON ) ! 203: { ! 204: /* for a floating point const, paint type, ! 205: ** round when it is output */ ! 206: if( t == FLOAT || t == DOUBLE ) goto paint; ! 207: /* otherwise, convert it to long and treat as long conversion */ ! 208: l->tn.op = ICON; ! 209: l->tn.lval = l->fpn.dval; /* MACHINE-DEPENDENT CONVERSION */ ! 210: l->tn.rval = NONAME; ! 211: goto icon; ! 212: } ! 213: ! 214: if( o==CONV && cbigger( l ) ) ! 215: { ! 216: merge: ! 217: p->in.left = l->in.left; ! 218: l->tn.op = FREE; ! 219: tydown( p ); ! 220: goto again; ! 221: } ! 222: if( t == lt && (t == DOUBLE || t == FLOAT) ) ! 223: goto paint; /* float over float, double over double */ ! 224: if( t==FLOAT || t==DOUBLE || t == VOID ! 225: || lt==FLOAT || lt==DOUBLE ) return( p ); ! 226: ! 227: if( ISUNSIGNED(t) ) t = DEUNSIGN(t); ! 228: if( ISUNSIGNED(lt) ) lt = DEUNSIGN(lt); ! 229: if( ISPTR(lt) ) ! 230: # ifdef MEMONLY ! 231: if( o==STAR || o==NAME || o==VAUTO || o==VPARAM ) ! 232: # endif ! 233: lt = PTRTYPE; ! 234: if( t == lt ) goto paint; ! 235: if( ISPTR(lt) || ISARY(lt) ) return(p); ! 236: ! 237: if( o == ICON ) ! 238: { ! 239: icon: ! 240: l->tn.lval = ccast( l->tn.lval, p->tn.type ); ! 241: paint: ! 242: l->tn.type = p->tn.type; ! 243: l->fn.csiz = p->fn.csiz; ! 244: l->fn.cdim = p->fn.cdim; ! 245: p->tn.op = FREE; ! 246: if( tydown(l) ) ! 247: { ! 248: l = doptim(l); ! 249: } ! 250: return( l ); ! 251: } ! 252: if( cbigger(p) ) return( p ); ! 253: /* p makes things smaller */ ! 254: if( o==CONV ) ! 255: { ! 256: /* two conversions in a row: the second makes things smaller */ ! 257: /* make them into one */ ! 258: goto merge; ! 259: } ! 260: if( o==STAR || o==NAME || o==VAUTO || o==VPARAM ) ! 261: { ! 262: /* memory reference: determine the adjustment */ ! 263: # ifdef RTOLBYTES ! 264: # ifdef LOWINT ! 265: if( lt == LONG ) if( !adjust( l, LOWINT )) cerror( "adj" ); ! 266: # endif ! 267: # else ! 268: register adj = 0; ! 269: if( lt == LONG ) adj = SZLONG; ! 270: else if( lt == INT ) adj = SZINT; ! 271: else if( lt == SHORT ) adj = SZSHORT; ! 272: else cerror( "sconv:lt 0%o", lt ); ! 273: if( t == INT ) adj -= SZINT; ! 274: else if( t == SHORT ) adj -= SZSHORT; ! 275: else if( t == CHAR ) adj -= SZCHAR; ! 276: else cerror( "sconv:t 0%o", t ); ! 277: # ifdef LOWINT ! 278: if( lt == LONG ) adj += LOWINT; ! 279: # endif ! 280: if( adj ) if( !adjust( l, adj ) ) cerror( "adj1" ); ! 281: # endif ! 282: } ! 283: ! 284: /* other cases are where it is computed into a reg; */ ! 285: /* simply paint the type */ ! 286: /* must avoid clobbering the type for assignment nodes */ ! 287: /* however, we must copy (e.g., apply the CONV) for register vars */ ! 288: /* also, can't paint type over fields */ ! 289: if( o == REG || asgop(o) || o == FLD ) return( p ); ! 290: goto paint; ! 291: } ! 292: # endif ! 293: ! 294: NODE * ! 295: pvconvert( p ) ! 296: register NODE *p; ! 297: { ! 298: /* p is a CONV node; convert */ ! 299: /* this does something only when the descendent is not a ptr */ ! 300: register NODE *l; ! 301: register int o; ! 302: l = p->in.left; ! 303: if( ISPTR( l->tn.type ) ) return( clocal(p) ); ! 304: # ifdef MEMONLY ! 305: o = l->tn.op; ! 306: if( o==STAR || o==NAME || o==VAUTO || o==VPARAM || o==ICON ) ! 307: # endif ! 308: { ! 309: /* optimize this reference */ ! 310: /* sconvert and optimize to PTRTYPE */ ! 311: l = makety( l, PTRTYPE, 0, PTRTYPE ); ! 312: if( l->tn.op == CONV ) l = sconvert( l ); ! 313: l->tn.type = p->tn.type; ! 314: l->fn.cdim = p->fn.cdim; ! 315: l->fn.csiz = p->fn.csiz; ! 316: p->tn.op = FREE; ! 317: p = l; ! 318: } ! 319: return( clocal(p) ); ! 320: } ! 321: ! 322: NODE * ! 323: fortarg( p ) ! 324: register NODE *p; ! 325: { ! 326: /* fortran function arguments */ ! 327: ! 328: if( p->in.op == CM ) ! 329: { ! 330: p->in.left = fortarg( p->in.left ); ! 331: p->in.right = fortarg( p->in.right ); ! 332: return(p); ! 333: } ! 334: while( ISPTR(p->in.type) ) ! 335: { ! 336: p = buildtree( STAR, p, NIL ); ! 337: } ! 338: return( optim(p) ); ! 339: } ! 340: ! 341: /* mapping relationals when the sides are reversed */ ! 342: short revrel[] = ! 343: { ! 344: EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT ! 345: }; ! 346: ! 347: #ifndef NODBG ! 348: #define REPORT(x) if(opdebug){printf( "optim did\n"); eprint(x);} ! 349: #else ! 350: # define REPORT(x) ! 351: #endif ! 352: NODE * ! 353: doptim(p) ! 354: register NODE *p; ! 355: { ! 356: /* local optimizations, most of which are machine independent */ ! 357: /* doptim is called for each node by optim; it assumes that ! 358: ** the children of p are already optimized ! 359: */ ! 360: /* p is not a leaf */ ! 361: register NODE *l, *r, *sp; ! 362: register o, i; ! 363: register TWORD t; ! 364: ! 365: #ifndef NODBG ! 366: if( opdebug ) ! 367: { ! 368: printf( "doptim called on:\n" ); ! 369: eprint(p); ! 370: } ! 371: #endif ! 372: ! 373: if( (t=BTYPE(p->in.type))==ENUMTY || t==MOETY ) econvert(p); ! 374: switch( optype( o = p->tn.op ) ) ! 375: { ! 376: case BITYPE: ! 377: r = p->in.right; ! 378: /* FALLTHRU */ ! 379: case UTYPE: ! 380: l = p->in.left; ! 381: break; ! 382: case LTYPE: ! 383: /* nothing more to do (after doing the enum stuff) */ ! 384: return( p ); ! 385: } ! 386: sp = conval( p ); ! 387: /* return only if conval did something */ ! 388: if( sp != p ) return( doptim(sp) ); ! 389: #ifndef NODBG ! 390: if( opdebug ) ! 391: { ! 392: printf( "doptim works on:\n" ); ! 393: eprint(p); ! 394: } ! 395: #endif ! 396: switch(o) ! 397: { ! 398: case COMOP: /* maybe simpstr changed the type of the right */ ! 399: if(p->in.type != r->in.type) { ! 400: p->in.type = r->in.type; ! 401: /* anything else? */ ! 402: REPORT(p); ! 403: } ! 404: return(p); ! 405: case CONV: ! 406: /* someday, make pvconvert and sconvert the same */ ! 407: return( ISPTR(p->tn.type)?pvconvert(p):sconvert(p) ); ! 408: case ASG PLUS: ! 409: case ASG MINUS: ! 410: case ASG AND: ! 411: case ASG OR: ! 412: case ASG ER: ! 413: case ASG LS: ! 414: case ASG RS: ! 415: case ASG MUL: ! 416: case ASG DIV: ! 417: case ASG MOD: ! 418: /* if conversion ops on the lhs, transfer them to the rhs */ ! 419: t = l->in.type; ! 420: ! 421: /* (CONV A) op= B into A op= (CONV B) ! 422: ** this only holds if the result depends only on the ! 423: ** low order part of B (e.g., that part of B that ! 424: ** is the width of A ! 425: ** this is not true for /=, %=, or floats */ ! 426: ! 427: if( l->tn.op == CONV && t!=FLOAT && t!=DOUBLE ! 428: && o!=ASG DIV && o != ASG MOD ) ! 429: { ! 430: p->in.left = l->in.left; ! 431: l->tn.op = FREE; ! 432: l = l->in.left; ! 433: r = makety( r, p->in.type, p->fn.cdim, p->fn.csiz ); ! 434: p->in.right = doptim( r ); ! 435: } ! 436: if( !nncon(r) ) break; /* no more optimization */ ! 437: /* get rid of 0 ops that don't change anything... */ ! 438: if( !r->tn.lval && (o==ASG PLUS || o==ASG MINUS || o==ASG OR || ! 439: o==ASG ER || o==ASG LS || o==ASG RS) ) ! 440: { ! 441: /* the answer is the lhs */ ! 442: goto bless; ! 443: } ! 444: if( r->tn.lval == 1 && (o==ASG MUL || o==ASG DIV) ) ! 445: { ! 446: /* the answer is the lhs */ ! 447: goto bless; ! 448: } ! 449: if( (i = ispow2( r->tn.lval ))>=0 && o==ASG MUL ) ! 450: { ! 451: o = p->in.op = ASG LS; ! 452: r->tn.lval = i; ! 453: } ! 454: break; ! 455: case LS: ! 456: case RS: ! 457: if( !nncon(r) || r->tn.lval ) ! 458: break; /* do nothing */ ! 459: goto bless; /* shifts by 0 */ ! 460: case FORTCALL: ! 461: p->in.right = fortarg( r ); ! 462: break; ! 463: case UNARY AND: ! 464: switch( l->tn.op ) ! 465: { ! 466: case STAR: ! 467: /* fake up to use setuleft */ ! 468: l->tn.op = FREE; ! 469: l=l->in.left; ! 470: goto setuleft; ! 471: case VAUTO: ! 472: case VPARAM: ! 473: case TEMP: ! 474: /* the next two lines come from short structs */ ! 475: case CALL: ! 476: case UNARY CALL: ! 477: break; ! 478: ! 479: case RNODE: ! 480: # ifdef ARGSRET ! 481: /* RNODE disappears if structure simple */ ! 482: if( simpstr( p->fn.cdim, p->fn.csiz ) == STRTY ) ! 483: { ! 484: /* complicated: make it look like first arg */ ! 485: l->tn.op = VPARAM; ! 486: l->tn.lval = BITOOR(ARGINIT); ! 487: l->tn.rval = NONAME; ! 488: } ! 489: break; ! 490: #else ! 491: # ifdef STATSRET ! 492: /* simple structures will disappear */ ! 493: if( simpstr( p->fn.cdim, p->fn.csiz ) != STRTY ) break; ! 494: /* otherwise, make & RNODE into ICON for static area */ ! 495: l->tn.rval = -strftn; ! 496: # else ! 497: break; /* & of RNODE is just fine */ ! 498: #endif ! 499: #endif ! 500: case NAME: ! 501: # ifdef ANDABLE ! 502: if( !ANDABLE(l) ) return(p); ! 503: # endif ! 504: l->tn.op = ICON; ! 505: setuleft: ! 506: /* set the type of lhs with the type of the top */ ! 507: l->in.type = p->in.type; ! 508: l->fn.cdim = p->fn.cdim; ! 509: l->fn.csiz = p->fn.csiz; ! 510: p->in.op = FREE; ! 511: REPORT(l); ! 512: return( l ); ! 513: default: ! 514: cerror( "& error" ); ! 515: } ! 516: break; ! 517: case STCALL: ! 518: case UNARY STCALL: ! 519: /* use l in case return type overwritten */ ! 520: t = simpstr( l->fn.cdim, l->fn.csiz ); ! 521: if( t != STRTY ) ! 522: { ! 523: /* take some care to keep the types OK */ ! 524: /* the type of the return might well have been ! 525: ** overwritten by (say) a structure reference ! 526: */ ! 527: /* MAY NOT BE QUITE RIGHT IF TWO FLAVORS OF PTR */ ! 528: l = p; ! 529: p->tn.type = DECREF( p->tn.type ); ! 530: p = buildtree( UNARY AND, l, NIL ); ! 531: if( o == STCALL ) l->tn.op = CALL; ! 532: else l->tn.op = UNARY CALL; ! 533: l->fn.type = l->fn.csiz = t; ! 534: l->fn.cdim = 0; ! 535: } ! 536: break; ! 537: case STAR: ! 538: if( p->tn.type == STRTY || p->tn.type == UNIONTY ) ! 539: { ! 540: p->tn.op = FREE; ! 541: REPORT(l); ! 542: return( l ); ! 543: } ! 544: if( l->tn.op == UNARY AND && !callop(l->in.left->tn.op) ) ! 545: { ! 546: /* & of call used in structure optimization */ ! 547: /* fake up to use setuleft */ ! 548: l->tn.op = FREE; ! 549: l = l->in.left; ! 550: goto setuleft; ! 551: } ! 552: if( l->tn.op != ICON ) break; ! 553: l->tn.op = NAME; ! 554: goto setuleft; ! 555: case MINUS: ! 556: if( !nncon(r) ) break; ! 557: r->tn.lval = - r->tn.lval; ! 558: o = p->in.op = PLUS; ! 559: case MUL: ! 560: case PLUS: ! 561: case AND: ! 562: case OR: ! 563: case ER: ! 564: /* commutative ops; for now, just collect constants */ ! 565: /* someday, do it right */ ! 566: if( o==r->tn.op || nncon(l) || ( ISCON(l) && !ISCON(r) ) ) ! 567: { ! 568: /* make ops tower to the left, not the right */ ! 569: /* also, put constants on the right */ ! 570: sp = l; ! 571: l = p->in.left = r; ! 572: r = p->in.right = sp; ! 573: } ! 574: /* do (A + C1) + C2, etc. */ ! 575: /* the number of special cases is horrifying */ ! 576: /* many bugs have been found here; this code is very cautious */ ! 577: /* (A + C1) + C2, where C2 can be a ptr, C1 not */ ! 578: if( o==PLUS && l->tn.op==PLUS && ISCON(r) && ! 579: nncon(l->in.right) ) ! 580: { ! 581: p->in.left = l->in.left; ! 582: l->tn.op = FREE; ! 583: l = l->in.right; ! 584: r->tn.lval += l->tn.lval; ! 585: l->tn.op = FREE; ! 586: return( doptim( p ) ); ! 587: } ! 588: /* (A + C1) + C2, where C1 can be a ptr, C2 not */ ! 589: if( o==PLUS && l->tn.op==PLUS && nncon(r) && ! 590: ISCON(l->in.right) ) ! 591: { ! 592: l->in.right->tn.lval += r->tn.lval; ! 593: goto bless; /* return l as the result */ ! 594: } ! 595: /* (A - C1) + C2, where C2 can be a ptr, C1 not */ ! 596: if( o==PLUS && l->tn.op==MINUS && ISCON(r) && ! 597: nncon(l->in.right) ) ! 598: { ! 599: p->in.left = l->in.left; ! 600: l->tn.op = FREE; ! 601: l = l->in.right; ! 602: r->tn.lval -= l->tn.lval; ! 603: l->tn.op = FREE; ! 604: return( doptim( p ) ); ! 605: } ! 606: /* (&A)+C */ ! 607: if( o==PLUS && l->tn.op == UNARY AND && ISCON(r) ) ! 608: { ! 609: switch( l->in.left->tn.op ) ! 610: { ! 611: case NAME: ! 612: case VPARAM: ! 613: case VAUTO: ! 614: l->in.left->tn.lval += r->tn.lval; ! 615: goto bless; ! 616: } ! 617: } ! 618: /* change muls to shifts */ ! 619: if( o==MUL && nncon(r) && (i=ispow2(r->tn.lval))>=0) ! 620: { ! 621: if( i == 0 ) ! 622: { ! 623: /* multiplication by 1 */ ! 624: bless: ! 625: /* return l, with the type of p */ ! 626: l = makety( l, p->tn.type, p->fn.cdim, ! 627: p->fn.csiz ); ! 628: r->tn.op = FREE; ! 629: p->tn.op = FREE; ! 630: /* if a conversion op was added, optimize */ ! 631: l = doptim( l ); ! 632: #ifndef NODBG ! 633: if( opdebug ) ! 634: { ! 635: printf( "optim replaces op1 (%d) by:\n", ! 636: p-node ); ! 637: eprint(l); ! 638: } ! 639: #endif ! 640: return( l ); ! 641: } ! 642: o = p->in.op = LS; ! 643: r->tn.lval = i; ! 644: } ! 645: /* change +'s of negative consts back to - */ ! 646: if( o==PLUS && nncon(r) && r->tn.lval<0 ) ! 647: { ! 648: r->tn.lval = -r->tn.lval; ! 649: o = p->in.op = MINUS; ! 650: } ! 651: if( nncon(r) && !r->tn.lval && (o==PLUS||o==MINUS) ) ! 652: { ! 653: /* get rid of add or subtract of 0 */ ! 654: goto bless; ! 655: } ! 656: # ifdef PTRLEFT ! 657: if( o==PLUS && ISPTR(p->tn.type) && ISPTR(r->tn.type) ! 658: # ifdef CONSRIGHT ! 659: && r->tn.op != ICON ! 660: # endif ! 661: ) ! 662: { ! 663: sp = l; ! 664: p->in.left = r; ! 665: p->in.right = sp; ! 666: } ! 667: # endif ! 668: # ifdef PTRRIGHT ! 669: if( o==PLUS && ISPTR(p->tn.type) && ISPTR(l->tn.type) ! 670: # ifdef CONSRIGHT ! 671: && r->tn.op != ICON ! 672: # endif ! 673: ) ! 674: { ! 675: sp = l; ! 676: p->in.left = r; ! 677: p->in.right = sp; ! 678: } ! 679: # endif ! 680: break; ! 681: case DIV: ! 682: if( nncon( r ) && r->tn.lval == 1 ) goto bless; ! 683: break; ! 684: case EQ: ! 685: case NE: ! 686: case LT: ! 687: case LE: ! 688: case GT: ! 689: case GE: ! 690: case ULT: ! 691: case ULE: ! 692: case UGT: ! 693: case UGE: ! 694: if( ISCON(l) && !ISCON(r) ) ! 695: { ! 696: /* exchange operands */ ! 697: p->in.op = revrel[p->in.op - EQ ]; ! 698: sp = l; ! 699: l = p->in.left = r; ! 700: r = p->in.right = sp; ! 701: } ! 702: break; ! 703: case STASG: ! 704: if( (t=simpstr( p->fn.cdim, p->fn.csiz ) ) != STRTY ) ! 705: { ! 706: /* rewrite = as simpler */ ! 707: if( ISPTR(r->tn.type) ) ! 708: { ! 709: r = buildtree( STAR, r, NIL ); ! 710: r->fn.type = r->fn.csiz = t; ! 711: r->fn.cdim = 0; ! 712: p->in.right = r = doptim( r ); ! 713: } ! 714: l = buildtree( STAR, l, NIL ); ! 715: l->fn.type = l->fn.csiz = t; ! 716: l->fn.cdim = 0; ! 717: p->in.left = l = doptim( l ); ! 718: p->fn.type = p->fn.csiz = t; ! 719: p->fn.cdim = 0; ! 720: p->fn.op = ASSIGN; ! 721: return( p ); ! 722: } ! 723: case STARG: ! 724: if( (t=simpstr( p->fn.cdim, p->fn.csiz ) ) != STRTY ) ! 725: { ! 726: /* rewrite as simpler */ ! 727: if( ISPTR(l->fn.type) ) ! 728: { ! 729: l = buildtree( STAR, l, NIL ); ! 730: l->fn.type = l->fn.csiz = t; ! 731: l->fn.cdim = 0; ! 732: p->in.left = l = doptim( l ); ! 733: } ! 734: p->fn.type = p->fn.csiz = (t==LONG ? LONG : INT); ! 735: p->fn.cdim = 0; ! 736: p->fn.op = FUNARG; ! 737: return( p ); ! 738: } ! 739: # ifdef ENDSTRUCT ! 740: p->in.left = aadjust( l, p->stn.stsize ); ! 741: # endif ! 742: break; ! 743: } ! 744: return(p); ! 745: } ! 746: ! 747: NODE * ! 748: optim( p ) ! 749: register NODE *p; ! 750: { ! 751: switch( optype( p->tn.op ) ) ! 752: { ! 753: case BITYPE: ! 754: p->in.right = optim( p->in.right ); ! 755: /* FALLTHRU */ ! 756: case UTYPE: ! 757: p->in.left = optim( p->in.left ); ! 758: } ! 759: return( doptim( p ) ); ! 760: } ! 761: ! 762: ispow2( c ) ! 763: register CONSZ c; ! 764: { ! 765: register i; ! 766: if( c <= 0 || (c&(c-1)) ) return(-1); ! 767: for( i=0; c>1; ++i) c >>= 1; ! 768: return(i); ! 769: } ! 770: ! 771: nncon( p ) ! 772: register NODE *p; ! 773: { ! 774: /* is p a constant without a name */ ! 775: return( p->tn.op == ICON && p->tn.rval == NONAME && !ISPTR(p->tn.type)); ! 776: } ! 777: ! 778: /* some routines for debugging and tree transformation */ ! 779: #ifndef MYOFFCON ! 780: NODE * ! 781: offcon( off, t, d, s ) ! 782: OFFSZ off; ! 783: TWORD t; ! 784: { ! 785: /* return a node, for structure references, which is suitable for ! 786: ** being added to a pointer of type t, in order to be off bits offset ! 787: ** into a structure ! 788: */ ! 789: register NODE *p; ! 790: ! 791: /* t, d, and s are the type, dimension offset, and size offset */ ! 792: /* in general they may be necessary for offcon */ ! 793: p = bcon(0); ! 794: p->tn.lval = BITOOR(off); ! 795: p->fn.type = p->fn.csiz = PTRTYPE; ! 796: return(p); ! 797: } ! 798: # endif ! 799: ! 800: bccode() ! 801: { ! 802: /* called just before executing code */ ! 803: /* beware: called several times if there is auto. initialization */ ! 804: # ifdef MYBCCODE ! 805: MYBCCODE; ! 806: # endif ! 807: p2bbeg( autooff, regvar ); ! 808: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.