|
|
1.1 ! root 1: /* ! 2: * n1/mtree0.c ! 3: * Modify an expression. ! 4: * All machines. ! 5: * ! 6: * modify() calls modtree() which generally does left before right ! 7: * deepest first traversal, including constant folding and machine ! 8: * dependent modifications. modify() then walk()'s the tree with ! 9: * modswap() and modrneg() and finally calls modleaf() to insert ! 10: * leaf nodes where required. ! 11: * ! 12: * mflag: ! 13: * 0 < mflag - prints trees before and after modification ! 14: * unless in MINIT context, where you get after only. ! 15: * 1 < mflag - prints trees at end of modtree() ! 16: * 2 < mflag - prints trees at beginning of modtree() ! 17: * 8 < mflag - gets multiple intermediate trees. ! 18: */ ! 19: ! 20: #ifdef vax ! 21: #include "INC$LIB:cc1.h" ! 22: #else ! 23: #include "cc1.h" ! 24: #endif ! 25: ! 26: int modswap(); ! 27: int modrneg(); ! 28: ! 29: /* ! 30: * Tree modify. ! 31: */ ! 32: TREE * ! 33: modify(tp, c) ! 34: register TREE *tp; ! 35: { ! 36: #if !TINY ! 37: if (mflag > 0 && c != MINIT) ! 38: snapf("%W%E", "Before modify", tp); ! 39: #endif ! 40: tp = modtree(tp, c, NULL); ! 41: walk(tp, modswap); ! 42: walk(tp, modrneg); ! 43: #if !TINY ! 44: if (mflag > 8 && c != MINIT) ! 45: snapf("%W%E", "Before modleaf", tp); ! 46: #endif ! 47: tp = modleaf(tp, c, NULL); ! 48: #if !TINY ! 49: if (mflag > 0) ! 50: snapf("%W%E%W", "After modify", tp, NULL); ! 51: #endif ! 52: return tp; ! 53: } ! 54: ! 55: /* ! 56: * Tree modifier. ! 57: * This routine performs a number of machine independent things. ! 58: * Folding of constant expressions is done by the routine 'modfold()'. ! 59: * After all the machine independent things have been done, ! 60: * a call to 'modoper()' does machine-specific modifications. ! 61: */ ! 62: TREE * ! 63: modtree(tp, ac, ptp) ! 64: register TREE *tp; ! 65: TREE *ptp; ! 66: { ! 67: register TREE *lp; ! 68: register TREE *rp; ! 69: register TREE *tp1; ! 70: register int c; ! 71: register int left; ! 72: register int n; ! 73: register int op; ! 74: register int tt, ts; ! 75: ! 76: c = ac; ! 77: if (c==MINIT || c==MRETURN || c==MSWITCH) ! 78: c = MRVALUE; ! 79: #if !TINY ! 80: if (mflag > 2 && ac != MINIT) ! 81: snapf("%W%E", "modtree before modfold", tp); ! 82: #endif ! 83: again: ! 84: tp = modfold(tp); ! 85: #if !TINY ! 86: if (mflag > 8 && ac != MINIT) ! 87: snapf("%W%E", "modtree after modfold", tp); ! 88: #endif ! 89: op = tp->t_op; ! 90: if (isleaf(op)) ! 91: goto done; ! 92: lp = tp->t_lp; ! 93: rp = (op == FIELD) ? NULL : tp->t_rp; ! 94: tt = tp->t_type; ! 95: ts = tp->t_size; ! 96: /* ! 97: * Change '(reg = a) + b' into 'reg = a, reg + b'. ! 98: */ ! 99: if (isokasgn(op, lp)) { ! 100: lp = leftnode(COMMA, lp, lp->t_type, lp->t_size); ! 101: lp->t_rp = tp; ! 102: tp->t_lp = copynode(lp->t_lp->t_lp); ! 103: tp = lp; ! 104: goto again; ! 105: } ! 106: /* ! 107: * Now change 'b + (reg = a)' into 'reg = a, b + reg'. ! 108: */ ! 109: if (isokasgn(op, rp)) { ! 110: rp = leftnode(COMMA, rp, rp->t_type, rp->t_size); ! 111: rp->t_rp = tp; ! 112: tp->t_rp = copynode(rp->t_lp->t_lp); ! 113: tp = rp; ! 114: goto again; ! 115: } ! 116: switch (op) { ! 117: ! 118: case BLKMOVE: ! 119: tp->t_lp = modtree(lp, MRVALUE, tp); ! 120: tp->t_rp = modtree(rp, MRVALUE, tp); ! 121: break; ! 122: ! 123: case CALL: ! 124: tp = modcall(tp, c); ! 125: break; ! 126: ! 127: case FIELD: ! 128: tp->t_lp = modtree(lp, c, tp); ! 129: break; ! 130: ! 131: case QUEST: ! 132: tp->t_lp = modtree(lp, MFLOW, tp); ! 133: if (rp->t_op != COLON) ! 134: cbotch("no ':'"); ! 135: rp->t_lp = modtree(rp->t_lp, c, rp); ! 136: rp->t_rp = modtree(rp->t_rp, c, rp); ! 137: break; ! 138: ! 139: case COLON: ! 140: cbotch("misplaced ':'"); ! 141: tp->t_op = COMMA; ! 142: ! 143: case COMMA: ! 144: if (isfxcon(lp) || lp->t_op == DCON) { ! 145: tp = rp; ! 146: goto again; ! 147: } ! 148: tp->t_lp = modtree(lp, MEFFECT, tp); ! 149: tp->t_rp = modtree(rp, c, tp); ! 150: break; ! 151: ! 152: case NOT: ! 153: if (c != MFLOW) { ! 154: tp = modtruth(tp); ! 155: goto again; ! 156: } ! 157: lp = modtree(lp, MFLOW, tp); ! 158: goto unary; ! 159: ! 160: case COM: ! 161: case NEG: ! 162: lp = modtree(lp, (ac==MINIT?MINIT:MRVALUE), tp); ! 163: unary: ! 164: if (lp->t_op == op) { ! 165: lp = lp->t_lp; ! 166: lp->t_type = tt; ! 167: lp->t_size = ts; ! 168: tp = lp; ! 169: goto again; ! 170: } ! 171: tp->t_lp = lp; ! 172: break; ! 173: ! 174: case CONVERT: ! 175: case CAST: ! 176: /* Distribute conversion to last comma node. */ ! 177: if (lp->t_op==COMMA) { ! 178: rp = lp; ! 179: rp->t_type = tt; ! 180: while (rp->t_rp->t_op==COMMA) { ! 181: rp->t_type = tt; ! 182: rp = rp->t_rp; ! 183: } ! 184: tp->t_lp = rp->t_rp; ! 185: rp->t_rp = tp; ! 186: tp = lp; ! 187: goto again; ! 188: } ! 189: /* Distribute conversion to subtrees of COLON. */ ! 190: if (lp->t_op==QUEST) { ! 191: rp = lp; ! 192: rp->t_type = tt; ! 193: rp = rp->t_rp; ! 194: rp->t_type = tt; ! 195: tp->t_lp = rp->t_lp; ! 196: rp->t_lp = tp; ! 197: rp->t_rp = leftnode(tp->t_op, rp->t_rp, tt); ! 198: tp = lp; ! 199: goto again; ! 200: } ! 201: tp->t_lp = lp = modtree(lp, MRVALUE, tp); ! 202: /* modtree() may have changed the op of lp. */ ! 203: if (lp->t_op==COMMA || lp->t_op==QUEST) ! 204: goto again; ! 205: /* Ignore conversions to same type and size. */ ! 206: if (tt==lp->t_type && ts==lp->t_size) { ! 207: tp = lp; ! 208: goto again; ! 209: } ! 210: /* Ignore conversions like (type1)(type2)type1 if type2 is wider. */ ! 211: if (iswiden(lp) && tt==lp->t_lp->t_type && ts==lp->t_lp->t_size) { ! 212: tp = lp->t_lp; ! 213: goto again; ! 214: } ! 215: break; ! 216: ! 217: case OROR: ! 218: case ANDAND: ! 219: if (c != MFLOW) { ! 220: tp = modtruth(tp); ! 221: goto again; ! 222: } ! 223: tp->t_lp = modtree(lp, MFLOW, tp); ! 224: tp->t_rp = modtree(rp, MFLOW, tp); ! 225: break; ! 226: ! 227: case INCAFT: ! 228: case DECAFT: ! 229: if (c == MEFFECT) ! 230: tp->t_op += INCBEF-INCAFT; ! 231: ! 232: case INCBEF: ! 233: case DECBEF: ! 234: tp->t_lp = modtree(lp, MLADDR, tp); ! 235: if (isflt(tt)) { ! 236: tp->t_op = (op==INCBEF || op==INCAFT) ? AADD : ASUB; ! 237: if (op==INCAFT || op==DECAFT) { ! 238: tp->t_lp = copynode(tp); ! 239: tp->t_rp = leftnode(CONVERT, ivalnode((ival_t)1), F64); ! 240: tp->t_op = (op==INCAFT)?SUB:ADD; ! 241: } ! 242: goto again; ! 243: } ! 244: tp->t_rp = modtree(basenode(rp), MRADDR, tp); ! 245: break; ! 246: ! 247: case ADDR: ! 248: lp = modtree(lp, (ac==MINIT?MINIT:MLADDR), tp); ! 249: if (lp->t_op == STAR) { ! 250: lp = lp->t_lp; ! 251: if ( ! isblkp(lp->t_type)) { ! 252: lp->t_type = tt; ! 253: lp->t_size = ts; ! 254: } ! 255: tp = lp; ! 256: goto again; ! 257: } else if (lp->t_op == QUEST) { ! 258: /* Change '&(a?b:c)' to 'a?&b:&c'. */ ! 259: rp = lp->t_rp; /* COLON node */ ! 260: rp->t_lp = leftnode(ADDR, rp->t_lp, tt, ts); ! 261: rp->t_rp = leftnode(ADDR, rp->t_rp, tt, ts); ! 262: rp->t_type = lp->t_type = tt; ! 263: rp->t_size = lp->t_size = ts; ! 264: tp = lp; ! 265: goto again; ! 266: } else if (lp->t_op == COMMA) { ! 267: /* Change '&(a,b)' to 'a, &b'. */ ! 268: lp->t_rp = leftnode(ADDR, lp->t_rp, tt, ts); ! 269: lp->t_type = tt; ! 270: lp->t_size = ts; ! 271: tp = lp; ! 272: goto again; ! 273: } ! 274: tp->t_lp = lp; ! 275: break; ! 276: ! 277: case STAR: ! 278: lp = modtree(lp, (ac==MINIT?MINIT:MRADDR), tp); ! 279: if (lp->t_op == ADDR) { ! 280: lp = lp->t_lp; ! 281: if ( ! isblkp(lp->t_type)) { ! 282: lp->t_type = tt; ! 283: lp->t_size = ts; ! 284: } ! 285: tp = lp; ! 286: goto again; ! 287: } ! 288: tp->t_lp = lp; ! 289: break; ! 290: ! 291: case ASSIGN: ! 292: tp->t_lp = modtree(lp, MLADDR, tp); ! 293: tp->t_rp = modtree(rp, MRVALUE, tp); ! 294: break; ! 295: ! 296: case DIV: ! 297: case REM: ! 298: case ADIV: ! 299: case AREM: ! 300: lp = modtree(lp, lgoal(op), tp); ! 301: rp = modtree(rp, MRADDR, tp); ! 302: if (((n = ispow2(rp)) >= 0) && ((n==0) || isuns(tt))) { ! 303: if (op==DIV || op==ADIV) { ! 304: tp->t_op += SHR-DIV; ! 305: tp->t_lp = lp; ! 306: tp->t_rp = ivalnode((ival_t)n); ! 307: goto again; ! 308: } ! 309: else { ! 310: tp->t_op += AND-REM; ! 311: tp->t_lp = lp; ! 312: tp->t_rp = gvalnode(tt, ((long)01<<n)-1); ! 313: goto again; ! 314: } ! 315: } ! 316: tp->t_lp = lp; ! 317: tp->t_rp = rp; ! 318: break; ! 319: ! 320: case MUL: ! 321: case AMUL: ! 322: lp = modtree(lp, lgoal(op), tp); ! 323: rp = modtree(rp, MRADDR, tp); ! 324: if ((tp1=modmul(tp, lp, rp)) != NULL ! 325: || (op==MUL && (tp1=modmul(tp, rp, lp))!=NULL)) { ! 326: tp = tp1; ! 327: goto again; ! 328: } ! 329: tp->t_lp = lp; ! 330: tp->t_rp = rp; ! 331: break; ! 332: ! 333: case ADD: ! 334: case SUB: ! 335: case AND: ! 336: case OR: ! 337: case XOR: ! 338: case SHR: ! 339: case SHL: ! 340: lp = modtree(lp, (ac==MINIT?MINIT:MRVALUE), tp); ! 341: rp = modtree(rp, (ac==MINIT?MINIT:MRADDR), tp); ! 342: if (isnval(rp, 0)) { ! 343: if (op == AND) { ! 344: rp->t_type = tt; ! 345: rp->t_size = ts; ! 346: tp = rp; ! 347: goto again; ! 348: } ! 349: lp->t_type = tt; ! 350: lp->t_size = ts; ! 351: tp = lp; ! 352: goto again; ! 353: } ! 354: if (op == SUB ! 355: && rp->t_op == ICON ! 356: && (isuns(rp->t_type)==0 || rp->t_ival>=0)) { ! 357: tp->t_op += ADD-SUB; ! 358: tp->t_type = IVAL_T; /* Signed */ ! 359: rp->t_ival = -rp->t_ival; ! 360: amd(rp); ! 361: tp->t_lp = lp; ! 362: tp->t_rp = rp; ! 363: goto again; ! 364: } ! 365: tp->t_lp = lp; ! 366: tp->t_rp = rp; ! 367: break; ! 368: ! 369: case AADD: ! 370: case ASUB: ! 371: case AAND: ! 372: case AOR: ! 373: case AXOR: ! 374: case ASHL: ! 375: case ASHR: ! 376: lp = modtree(lp, MLADDR, tp); ! 377: rp = modtree(rp, MRADDR, tp); ! 378: if (isnval(rp, 0)) { ! 379: if (op == AAND) { ! 380: tp->t_op = ASSIGN; ! 381: tp->t_lp = lp; ! 382: tp->t_rp = rp; ! 383: goto again; ! 384: } ! 385: lp->t_type = tt; ! 386: lp->t_size = ts; ! 387: tp = lp; ! 388: goto again; ! 389: } ! 390: tp->t_lp = lp; ! 391: tp->t_rp = rp; ! 392: break; ! 393: ! 394: case EQ: ! 395: case NE: ! 396: case GT: ! 397: case LT: ! 398: case GE: ! 399: case LE: ! 400: case UGT: ! 401: case UGE: ! 402: case ULT: ! 403: case ULE: ! 404: if (c != MFLOW) { ! 405: tp = modtruth(tp); ! 406: goto again; ! 407: } ! 408: lp = modfold(lp); ! 409: rp = modfold(rp); ! 410: if ((left=isnval(lp, 0)) || isnval(rp, 0)) { ! 411: /* 0 on left or right, force to right. */ ! 412: if (left) { ! 413: tp->t_op = op = fliprel[op-EQ]; ! 414: tp1 = lp; ! 415: lp = rp; ! 416: rp = tp1; ! 417: } ! 418: if (op==EQ || op==NE) { ! 419: lp = modtree(lp, MFLOW, tp); ! 420: if (lp->t_op == QUEST) { ! 421: /* ! 422: * Change "(a ? b : c) op 0" ! 423: * to "a ? b op 0 : c op 0". ! 424: */ ! 425: tp = lp; /* QUEST */ ! 426: tp->t_type = tt; ! 427: tp->t_size = ts; ! 428: tp1 = tp->t_rp; /* COLON */ ! 429: tp1->t_lp = leftnode(op, tp1->t_lp, tt, ts); ! 430: tp1->t_lp->t_rp = rp; ! 431: tp1->t_rp = leftnode(op, tp1->t_rp, tt, ts); ! 432: tp1->t_rp->t_rp = ivalnode((ival_t)0); ! 433: goto again; ! 434: } ! 435: } else ! 436: lp = modtree(lp, MRVALUE, tp); ! 437: } else ! 438: lp = modtree(lp, MRVALUE, tp); ! 439: tp->t_lp = lp; ! 440: tp->t_rp = modtree(rp, MRADDR, tp); ! 441: break; ! 442: } ! 443: tp = modfold(tp); ! 444: done: ! 445: walk(tp, amd); ! 446: if ((tp1 = modoper(tp, ac, ptp)) != NULL) { ! 447: tp = tp1; ! 448: goto again; ! 449: } ! 450: #if !TINY ! 451: if (mflag > 1 && ac != MINIT) ! 452: snapf("%W%E", "modtree done", tp); ! 453: #endif ! 454: return tp; ! 455: } ! 456: ! 457: /* ! 458: * Modify multiply. ! 459: * Called from the modify case for MUL and AMUL. ! 460: * If MUL, called twice in both arrangements. ! 461: */ ! 462: TREE * ! 463: modmul(tp, lp, rp) ! 464: register TREE *tp, *lp, *rp; ! 465: { ! 466: register n; ! 467: ! 468: if (isnval(rp, 0)) { ! 469: if (tp->t_op == AMUL) { ! 470: tp->t_op = ASSIGN; ! 471: return tp; ! 472: } ! 473: rp->t_type = tp->t_type; ! 474: rp->t_size = tp->t_size; ! 475: return rp; ! 476: } ! 477: if ((n=ispow2(rp)) >= 0) { ! 478: tp->t_op += SHL-MUL; ! 479: tp->t_lp = lp; ! 480: tp->t_rp = ivalnode((ival_t)n); ! 481: return tp; ! 482: } ! 483: return NULL; ! 484: } ! 485: ! 486: /* ! 487: * This routine fabricates a fake question colon pair ! 488: * to get the correct return value for !, &&, || and relational ops ! 489: * in non flow contexts. ! 490: */ ! 491: TREE * ! 492: modtruth(tp) ! 493: register TREE *tp; ! 494: { ! 495: register TREE *tp1; ! 496: ! 497: tp1 = ivalnode((ival_t)1); ! 498: tp1 = leftnode(COLON, tp1, TRUTH); ! 499: tp1->t_rp = ivalnode((ival_t)0); ! 500: tp = leftnode(QUEST, tp, TRUTH); ! 501: tp->t_rp = tp1; ! 502: return tp; ! 503: } ! 504: ! 505: /* ! 506: * Find left subgoal. ! 507: * This permits '+' and '+=' to share a lot of code. ! 508: */ ! 509: lgoal(op) ! 510: register op; ! 511: { ! 512: return (op>=AADD && op<=ASHR) ? MLADDR : MRVALUE; ! 513: } ! 514: ! 515: /* ! 516: * Look for '+' of a negative constant and make it into a subtract. ! 517: * Machines tend to have 'dec' instructions for small numbers. ! 518: */ ! 519: modrneg(tp, ptp) ! 520: register TREE *tp; ! 521: TREE *ptp; ! 522: { ! 523: register TREE *rp; ! 524: ! 525: if (tp->t_op==ADD || tp->t_op==AADD) { ! 526: rp = tp->t_rp; ! 527: if (rp->t_op==ICON && !isuns(rp->t_type) && rp->t_ival<0) { ! 528: tp->t_op += SUB-ADD; ! 529: rp->t_ival = -rp->t_ival; ! 530: amd(rp); ! 531: } ! 532: } ! 533: } ! 534: ! 535: /* ! 536: * Check assignment transformation for legality. ! 537: */ ! 538: isokasgn(op, tp) ! 539: register op; ! 540: register TREE *tp; ! 541: { ! 542: register top; ! 543: ! 544: if (op!=ASSIGN && (op<ADD || op>SHR)) ! 545: return 0; ! 546: if (tp == NULL) ! 547: return 0; ! 548: top = tp->t_op; ! 549: if (top!=ASSIGN && (top<AADD || top>ASHR)) ! 550: return 0; ! 551: return isokareg(tp, op); ! 552: } ! 553: ! 554: /* ! 555: * If the tree is a constant power of two, return the log ! 556: * base two of the number. ! 557: * If not, return -1. ! 558: */ ! 559: ispow2(tp) ! 560: register TREE *tp; ! 561: { ! 562: register i; ! 563: register long n; ! 564: ! 565: if (!isfxcon(tp)) ! 566: return -1; ! 567: n = grabnval(tp); ! 568: if (n<1 || (n&(n-1))!=0) ! 569: return -1; ! 570: i = 0; ! 571: while ((n&01) == 0) { ! 572: ++i; ! 573: n >>= 1; ! 574: } ! 575: return i; ! 576: } ! 577: ! 578: /* end of n1/mtree0.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.