|
|
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 turns %d into %d\n",p-node,x-node); ! 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 CONV: ! 399: /* someday, make pvconvert and sconvert the same */ ! 400: return( ISPTR(p->tn.type)?pvconvert(p):sconvert(p) ); ! 401: case ASG PLUS: ! 402: case ASG MINUS: ! 403: case ASG AND: ! 404: case ASG OR: ! 405: case ASG ER: ! 406: case ASG LS: ! 407: case ASG RS: ! 408: case ASG MUL: ! 409: case ASG DIV: ! 410: case ASG MOD: ! 411: /* if conversion ops on the lhs, transfer them to the rhs */ ! 412: t = l->in.type; ! 413: ! 414: /* (CONV A) op= B into A op= (CONV B) ! 415: ** this only holds if the result depends only on the ! 416: ** low order part of B (e.g., that part of B that ! 417: ** is the width of A ! 418: ** this is not true for /=, %=, or floats */ ! 419: ! 420: if( l->tn.op == CONV && t!=FLOAT && t!=DOUBLE ! 421: && o!=ASG DIV && o != ASG MOD ) ! 422: { ! 423: p->in.left = l->in.left; ! 424: l->tn.op = FREE; ! 425: l = l->in.left; ! 426: r = makety( r, p->in.type, p->fn.cdim, p->fn.csiz ); ! 427: p->in.right = doptim( r ); ! 428: } ! 429: if( !nncon(r) ) break; /* no more optimization */ ! 430: /* get rid of 0 ops that don't change anything... */ ! 431: if( !r->tn.lval && (o==ASG PLUS || o==ASG MINUS || o==ASG OR || ! 432: o==ASG ER || o==ASG LS || o==ASG RS) ) ! 433: { ! 434: /* the answer is the lhs */ ! 435: goto bless; ! 436: } ! 437: if( r->tn.lval == 1 && (o==ASG MUL || o==ASG DIV) ) ! 438: { ! 439: /* the answer is the lhs */ ! 440: goto bless; ! 441: } ! 442: if( (i = ispow2( r->tn.lval ))>=0 && o==ASG MUL ) ! 443: { ! 444: o = p->in.op = ASG LS; ! 445: r->tn.lval = i; ! 446: } ! 447: break; ! 448: case LS: ! 449: case RS: ! 450: if( !nncon(r) || r->tn.lval ) ! 451: break; /* do nothing */ ! 452: goto bless; /* shifts by 0 */ ! 453: case FORTCALL: ! 454: p->in.right = fortarg( r ); ! 455: break; ! 456: case UNARY AND: ! 457: switch( l->tn.op ) ! 458: { ! 459: case STAR: ! 460: /* fake up to use setuleft */ ! 461: l->tn.op = FREE; ! 462: l=l->in.left; ! 463: goto setuleft; ! 464: case VAUTO: ! 465: case VPARAM: ! 466: case TEMP: ! 467: /* the next two lines come from short structs */ ! 468: case CALL: ! 469: case UNARY CALL: ! 470: break; ! 471: ! 472: case RNODE: ! 473: # ifdef ARGSRET ! 474: /* RNODE disappears if structure simple */ ! 475: if( simpstr( p->fn.cdim, p->fn.csiz ) == STRTY ) ! 476: { ! 477: /* complicated: make it look like first arg */ ! 478: l->tn.op = VPARAM; ! 479: l->tn.lval = BITOOR(ARGINIT); ! 480: l->tn.rval = NONAME; ! 481: } ! 482: break; ! 483: #else ! 484: # ifdef STATSRET ! 485: /* simple structures will disappear */ ! 486: if( simpstr( p->fn.cdim, p->fn.csiz ) != STRTY ) break; ! 487: /* otherwise, make & RNODE into ICON for static area */ ! 488: l->tn.rval = -strftn; ! 489: # else ! 490: break; /* & of RNODE is just fine */ ! 491: #endif ! 492: #endif ! 493: case NAME: ! 494: # ifdef ANDABLE ! 495: if( !ANDABLE(l) ) return(p); ! 496: # endif ! 497: l->tn.op = ICON; ! 498: setuleft: ! 499: /* set the type of lhs with the type of the top */ ! 500: l->in.type = p->in.type; ! 501: l->fn.cdim = p->fn.cdim; ! 502: l->fn.csiz = p->fn.csiz; ! 503: p->in.op = FREE; ! 504: REPORT(l); ! 505: return( l ); ! 506: default: ! 507: cerror( "& error" ); ! 508: } ! 509: break; ! 510: case STCALL: ! 511: case UNARY STCALL: ! 512: /* use l in case return type overwritten */ ! 513: t = simpstr( l->fn.cdim, l->fn.csiz ); ! 514: if( t != STRTY ) ! 515: { ! 516: /* take some care to keep the types OK */ ! 517: /* the type of the return might well have been ! 518: ** overwritten by (say) a structure reference ! 519: */ ! 520: /* MAY NOT BE QUITE RIGHT IF TWO FLAVORS OF PTR */ ! 521: l = p; ! 522: p->tn.type = DECREF( p->tn.type ); ! 523: p = buildtree( UNARY AND, l, NIL ); ! 524: if( o == STCALL ) l->tn.op = CALL; ! 525: else l->tn.op = UNARY CALL; ! 526: l->fn.type = l->fn.csiz = t; ! 527: l->fn.cdim = 0; ! 528: } ! 529: break; ! 530: case STAR: ! 531: if( p->tn.type == STRTY || p->tn.type == UNIONTY ) ! 532: { ! 533: p->tn.op = FREE; ! 534: REPORT(l); ! 535: return( l ); ! 536: } ! 537: if( l->tn.op == UNARY AND && !callop(l->in.left->tn.op) ) ! 538: { ! 539: /* & of call used in structure optimization */ ! 540: /* fake up to use setuleft */ ! 541: l->tn.op = FREE; ! 542: l = l->in.left; ! 543: goto setuleft; ! 544: } ! 545: if( l->tn.op != ICON ) break; ! 546: l->tn.op = NAME; ! 547: goto setuleft; ! 548: case MINUS: ! 549: if( !nncon(r) ) break; ! 550: r->tn.lval = - r->tn.lval; ! 551: o = p->in.op = PLUS; ! 552: case MUL: ! 553: case PLUS: ! 554: case AND: ! 555: case OR: ! 556: case ER: ! 557: /* commutative ops; for now, just collect constants */ ! 558: /* someday, do it right */ ! 559: if( o==r->tn.op || nncon(l) || ( ISCON(l) && !ISCON(r) ) ) ! 560: { ! 561: /* make ops tower to the left, not the right */ ! 562: /* also, put constants on the right */ ! 563: sp = l; ! 564: l = p->in.left = r; ! 565: r = p->in.right = sp; ! 566: } ! 567: /* do (A + C1) + C2, etc. */ ! 568: /* the number of special cases is horrifying */ ! 569: /* many bugs have been found here; this code is very cautious */ ! 570: /* (A + C1) + C2, where C2 can be a ptr, C1 not */ ! 571: if( o==PLUS && l->tn.op==PLUS && ISCON(r) && ! 572: nncon(l->in.right) ) ! 573: { ! 574: p->in.left = l->in.left; ! 575: l->tn.op = FREE; ! 576: l = l->in.right; ! 577: r->tn.lval += l->tn.lval; ! 578: l->tn.op = FREE; ! 579: return( doptim( p ) ); ! 580: } ! 581: /* (A + C1) + C2, where C1 can be a ptr, C2 not */ ! 582: if( o==PLUS && l->tn.op==PLUS && nncon(r) && ! 583: ISCON(l->in.right) ) ! 584: { ! 585: l->in.right->tn.lval += r->tn.lval; ! 586: goto bless; /* return l as the result */ ! 587: } ! 588: /* (A - C1) + C2, where C2 can be a ptr, C1 not */ ! 589: if( o==PLUS && l->tn.op==MINUS && ISCON(r) && ! 590: nncon(l->in.right) ) ! 591: { ! 592: p->in.left = l->in.left; ! 593: l->tn.op = FREE; ! 594: l = l->in.right; ! 595: r->tn.lval -= l->tn.lval; ! 596: l->tn.op = FREE; ! 597: return( doptim( p ) ); ! 598: } ! 599: /* (&A)+C */ ! 600: if( o==PLUS && l->tn.op == UNARY AND && ISCON(r) ) ! 601: { ! 602: switch( l->in.left->tn.op ) ! 603: { ! 604: case NAME: ! 605: case VPARAM: ! 606: case VAUTO: ! 607: l->in.left->tn.lval += r->tn.lval; ! 608: goto bless; ! 609: } ! 610: } ! 611: /* change muls to shifts */ ! 612: if( o==MUL && nncon(r) && (i=ispow2(r->tn.lval))>=0) ! 613: { ! 614: if( i == 0 ) ! 615: { ! 616: /* multiplication by 1 */ ! 617: bless: ! 618: /* return l, with the type of p */ ! 619: l = makety( l, p->tn.type, p->fn.cdim, ! 620: p->fn.csiz ); ! 621: r->tn.op = FREE; ! 622: p->tn.op = FREE; ! 623: /* if a conversion op was added, optimize */ ! 624: l = doptim( l ); ! 625: #ifndef NODBG ! 626: if( opdebug ) ! 627: { ! 628: printf( "optim replaces op1 (%d) by:\n", ! 629: p-node ); ! 630: eprint(l); ! 631: } ! 632: #endif ! 633: return( l ); ! 634: } ! 635: o = p->in.op = LS; ! 636: r->tn.lval = i; ! 637: } ! 638: /* change +'s of negative consts back to - */ ! 639: if( o==PLUS && nncon(r) && r->tn.lval<0 ) ! 640: { ! 641: r->tn.lval = -r->tn.lval; ! 642: o = p->in.op = MINUS; ! 643: } ! 644: if( nncon(r) && !r->tn.lval && (o==PLUS||o==MINUS) ) ! 645: { ! 646: /* get rid of add or subtract of 0 */ ! 647: goto bless; ! 648: } ! 649: # ifdef PTRLEFT ! 650: if( o==PLUS && ISPTR(p->tn.type) && ISPTR(r->tn.type) ! 651: # ifdef CONSRIGHT ! 652: && r->tn.op != ICON ! 653: # endif ! 654: ) ! 655: { ! 656: sp = l; ! 657: p->in.left = r; ! 658: p->in.right = sp; ! 659: } ! 660: # endif ! 661: # ifdef PTRRIGHT ! 662: if( o==PLUS && ISPTR(p->tn.type) && ISPTR(l->tn.type) ! 663: # ifdef CONSRIGHT ! 664: && r->tn.op != ICON ! 665: # endif ! 666: ) ! 667: { ! 668: sp = l; ! 669: p->in.left = r; ! 670: p->in.right = sp; ! 671: } ! 672: # endif ! 673: break; ! 674: case DIV: ! 675: if( nncon( r ) && r->tn.lval == 1 ) goto bless; ! 676: break; ! 677: case EQ: ! 678: case NE: ! 679: case LT: ! 680: case LE: ! 681: case GT: ! 682: case GE: ! 683: case ULT: ! 684: case ULE: ! 685: case UGT: ! 686: case UGE: ! 687: if( ISCON(l) && !ISCON(r) ) ! 688: { ! 689: /* exchange operands */ ! 690: p->in.op = revrel[p->in.op - EQ ]; ! 691: sp = l; ! 692: l = p->in.left = r; ! 693: r = p->in.right = sp; ! 694: } ! 695: break; ! 696: case STASG: ! 697: if( (t=simpstr( p->fn.cdim, p->fn.csiz ) ) != STRTY ) ! 698: { ! 699: /* rewrite = as simpler */ ! 700: if( ISPTR(r->tn.type) ) ! 701: { ! 702: r = buildtree( STAR, r, NIL ); ! 703: r->fn.type = r->fn.csiz = t; ! 704: r->fn.cdim = 0; ! 705: p->in.right = r = doptim( r ); ! 706: } ! 707: l = buildtree( STAR, l, NIL ); ! 708: l->fn.type = l->fn.csiz = t; ! 709: l->fn.cdim = 0; ! 710: p->in.left = l = doptim( l ); ! 711: p->fn.type = p->fn.csiz = t; ! 712: p->fn.cdim = 0; ! 713: p->fn.op = ASSIGN; ! 714: return( p ); ! 715: } ! 716: case STARG: ! 717: if( (t=simpstr( p->fn.cdim, p->fn.csiz ) ) != STRTY ) ! 718: { ! 719: /* rewrite as simpler */ ! 720: if( ISPTR(l->fn.type) ) ! 721: { ! 722: l = buildtree( STAR, l, NIL ); ! 723: l->fn.type = l->fn.csiz = t; ! 724: l->fn.cdim = 0; ! 725: p->in.left = l = doptim( l ); ! 726: } ! 727: p->fn.type = p->fn.csiz = (t==LONG ? LONG : INT); ! 728: p->fn.cdim = 0; ! 729: p->fn.op = FUNARG; ! 730: return( p ); ! 731: } ! 732: # ifdef ENDSTRUCT ! 733: p->in.left = aadjust( l, p->stn.stsize ); ! 734: # endif ! 735: break; ! 736: } ! 737: return(p); ! 738: } ! 739: ! 740: NODE * ! 741: optim( p ) ! 742: register NODE *p; ! 743: { ! 744: switch( optype( p->tn.op ) ) ! 745: { ! 746: case BITYPE: ! 747: p->in.right = optim( p->in.right ); ! 748: /* FALLTHRU */ ! 749: case UTYPE: ! 750: p->in.left = optim( p->in.left ); ! 751: } ! 752: return( doptim( p ) ); ! 753: } ! 754: ! 755: ispow2( c ) ! 756: register CONSZ c; ! 757: { ! 758: register i; ! 759: if( c <= 0 || (c&(c-1)) ) return(-1); ! 760: for( i=0; c>1; ++i) c >>= 1; ! 761: return(i); ! 762: } ! 763: ! 764: nncon( p ) ! 765: register NODE *p; ! 766: { ! 767: /* is p a constant without a name */ ! 768: return( p->tn.op == ICON && p->tn.rval == NONAME && !ISPTR(p->tn.type)); ! 769: } ! 770: ! 771: /* some routines for debugging and tree transformation */ ! 772: #ifndef MYOFFCON ! 773: NODE * ! 774: offcon( off, t, d, s ) ! 775: OFFSZ off; ! 776: TWORD t; ! 777: { ! 778: /* return a node, for structure references, which is suitable for ! 779: ** being added to a pointer of type t, in order to be off bits offset ! 780: ** into a structure ! 781: */ ! 782: register NODE *p; ! 783: ! 784: /* t, d, and s are the type, dimension offset, and size offset */ ! 785: /* in general they may be necessary for offcon */ ! 786: p = bcon(0); ! 787: p->tn.lval = BITOOR(off); ! 788: p->fn.type = p->fn.csiz = PTRTYPE; ! 789: return(p); ! 790: } ! 791: # endif ! 792: ! 793: bccode() ! 794: { ! 795: /* called just before executing code */ ! 796: /* beware: called several times if there is auto. initialization */ ! 797: /*# ifdef SDB ! 798: /* static bcclev; ! 799: /* if( blevel != bcclev ) ! 800: /* { ! 801: /* bcclev = blevel; ! 802: /* pstab( S_LBRAC, blevel-1 ); ! 803: /* } ! 804: /*# endif ! 805: /**/ ! 806: # ifdef MYBCCODE ! 807: MYBCCODE; ! 808: # endif ! 809: p2bbeg( autooff, regvar ); ! 810: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.