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