|
|
1.1 ! root 1: /* ! 2: * The routines in this file ! 3: * are a portable associative tree ! 4: * reorderer and constant expression ! 5: * folder. They may not be general ! 6: * enough for all machines. ! 7: */ ! 8: #ifdef vax ! 9: #include "INC$LIB:cc1.h" ! 10: #else ! 11: #include "cc1.h" ! 12: #endif ! 13: ! 14: #define NLNODE 20 ! 15: #define NONODE 20 ! 16: ! 17: static char cltc[] = "associative expression too complex"; ! 18: TREE *fold1(); ! 19: TREE *foldaddr(); ! 20: ! 21: /* ! 22: * Fancy folder. ! 23: * Gathers up all the constants that ! 24: * in can, by digging through the ! 25: * subtrees of commutative/associative ! 26: * operations. Simpler things are ! 27: * done for operations that are not quite ! 28: * so friendly. ! 29: * Returns a pointer to the new ! 30: * tree. ! 31: */ ! 32: TREE * ! 33: modfold(tp) ! 34: register TREE *tp; ! 35: { ! 36: register TREE *lp, **rp; ! 37: int i, nl, nn, op, cop; ! 38: lval_t c1; ! 39: TREE *leaves[NLNODE], *onodes[NONODE]; ! 40: ! 41: op = tp->t_op; ! 42: if (op==NEG && tp->t_lp->t_op==DCON) { ! 43: tp = tp->t_lp; ! 44: #if IEEE|DECVAX ! 45: tp->t_dval[DVALIS] ^= DVALMS; ! 46: #else ! 47: #if MCFFP ! 48: if ((((int)tp->t_dval[3])&0377) != 0) ! 49: tp->t_dval[3] ^= 0200; ! 50: #else ! 51: dvalneg((char *)tp->t_dval); ! 52: #endif ! 53: #endif ! 54: return (tp); ! 55: } ! 56: if (isleaf(op) || isflt(tp->t_type)) ! 57: return (tp); ! 58: if (op==CONVERT || op==CAST) { ! 59: lp = tp->t_lp; ! 60: if ((cop=lp->t_op)==ICON || cop==LCON) { ! 61: c1 = grabnval(lp); ! 62: if (islong(tp->t_type)) ! 63: lp = lvalnode(c1); else ! 64: lp = ivalnode((int) c1); ! 65: lp->t_type = tp->t_type; ! 66: lp->t_size = tp->t_size; ! 67: return (lp); ! 68: } ! 69: } ! 70: if (op!=ADD && op!=MUL && op!=AND && op!=OR && op!=XOR) { ! 71: lp = fold1(op, tp->t_lp, tp->t_rp); ! 72: if (lp != NULL) ! 73: return (lp); ! 74: return (tp); ! 75: } ! 76: nn = nl = 0; ! 77: cluster(tp, op, tp->t_type, &nn, &nl, onodes, leaves); ! 78: rp = &leaves[--nl]; ! 79: for (i = nl; i > 0; ) { ! 80: lp = fold1(op, rp[0], rp[-1]); ! 81: if (lp == NULL) ! 82: break; ! 83: --nl; ! 84: --rp; ! 85: rp[0] = lp; ! 86: --i; ! 87: } ! 88: tp = rp[0]; ! 89: if (op==ADD || op==OR || op==XOR) { ! 90: if (nl>0 && isnval(tp, 0)) ! 91: --nl; ! 92: if (nl <= 0) ! 93: return (leaves[0]); ! 94: } ! 95: if (op==MUL || op==AND) { ! 96: if (isnval(tp, 0)) ! 97: return (tp); ! 98: if (op==MUL && nl>0 && isnval(tp, 1)) ! 99: --nl; ! 100: } ! 101: if (nl <= 0) ! 102: return (leaves[0]); ! 103: rp = &leaves[0]; ! 104: tp = leaves[0]; ! 105: for (i=0; i<nl; ++i) { ! 106: lp = onodes[i]; ! 107: lp->t_rp = *++rp; ! 108: lp->t_lp = tp; ! 109: tp = lp; ! 110: if (op==ADD && isblkp(tp->t_type)==0) ! 111: fixaddtype(tp); ! 112: } ! 113: return (tp); ! 114: } ! 115: ! 116: /* ! 117: * Collect up an associative ! 118: * operator cluster. Pack it into the ! 119: * supplied buffers. ! 120: */ ! 121: cluster(tp, op, type, ann, anl, onodes, leaves) ! 122: register TREE *tp; ! 123: int *ann, *anl; ! 124: register TREE *onodes[], *leaves[]; ! 125: { ! 126: register i, nl; ! 127: int nn; ! 128: TREE *xp; ! 129: ! 130: if (tp->t_op==op && tp->t_type==type) { ! 131: nn = *ann; ! 132: if ((*ann)++ >= NONODE) ! 133: cfatal(cltc); ! 134: onodes[nn] = tp; ! 135: cluster(tp->t_lp, op, type, ann, anl, onodes, leaves); ! 136: cluster(tp->t_rp, op, type, ann, anl, onodes, leaves); ! 137: return; ! 138: } ! 139: nl = *anl; ! 140: if ((*anl)++ >= NLNODE) ! 141: cfatal(cltc); ! 142: if (isncon(tp->t_op)) { ! 143: leaves[nl] = tp; ! 144: return; ! 145: } ! 146: for (i = nl; i > 0; ) { ! 147: xp = leaves[i-1]; ! 148: if (tp->t_op==ADDR && !isncon(xp->t_op)) ! 149: break; ! 150: if (tp->t_op==STAR && xp->t_op==STAR) ! 151: break; ! 152: leaves[i] = xp; ! 153: --i; ! 154: } ! 155: leaves[i] = tp; ! 156: } ! 157: ! 158: /* ! 159: * Fold an operation. ! 160: * Return a pointer to the folded ! 161: * tree, or NULL if no fold is ! 162: * possible. ! 163: */ ! 164: TREE * ! 165: fold1(op, lp, rp) ! 166: TREE *lp, *rp; ! 167: { ! 168: register TREE *fp; ! 169: register sop, lrf; ! 170: register tt; ! 171: lval_t c1, c2; ! 172: ! 173: if ((fp = foldaddr(op, lp, rp)) != NULL) ! 174: return (fp); ! 175: lrf = 0; ! 176: if ((sop=lp->t_op)!=ICON && sop!=LCON) ! 177: return (NULL); ! 178: c1 = grabnval(lp); ! 179: tt = lp->t_type; ! 180: if (sop == LCON) ! 181: ++lrf; ! 182: if (op == QUEST) { ! 183: return (c1 ? rp->t_lp : rp->t_rp); ! 184: } ! 185: if (rp != NULL) { ! 186: if ((sop=rp->t_op)!=ICON && sop!=LCON) ! 187: return (NULL); ! 188: c2 = grabnval(rp); ! 189: if (rp->t_type > tt) ! 190: tt = rp->t_type; ! 191: if (sop == LCON) ! 192: ++lrf; ! 193: } ! 194: switch (op) { ! 195: ! 196: case COM: ! 197: c1 = ~c1; ! 198: break; ! 199: ! 200: case NOT: ! 201: c1 = !c1; ! 202: break; ! 203: ! 204: case NEG: ! 205: c1 = -c1; ! 206: break; ! 207: ! 208: case ADD: ! 209: c1 += c2; ! 210: break; ! 211: ! 212: case SUB: ! 213: c1 -= c2; ! 214: break; ! 215: ! 216: case MUL: ! 217: c1 *= c2; ! 218: break; ! 219: ! 220: case DIV: ! 221: if (c2 == 0) ! 222: return (NULL); ! 223: c1 /= c2; ! 224: break; ! 225: ! 226: case REM: ! 227: if (c2 == 0) ! 228: return (NULL); ! 229: c1 %= c2; ! 230: break; ! 231: ! 232: case AND: ! 233: c1 &= c2; ! 234: break; ! 235: ! 236: case OR: ! 237: c1 |= c2; ! 238: break; ! 239: ! 240: case XOR: ! 241: c1 ^= c2; ! 242: break; ! 243: ! 244: case SHL: ! 245: c1 <<= c2; ! 246: break; ! 247: ! 248: case SHR: ! 249: c1 >>= c2; ! 250: break; ! 251: ! 252: case EQ: ! 253: c1 = c1==c2; ! 254: break; ! 255: ! 256: case NE: ! 257: c1 = c1!=c2; ! 258: break; ! 259: ! 260: case LT: ! 261: c1 = c1<c2; ! 262: break; ! 263: ! 264: case LE: ! 265: c1 = c1<=c2; ! 266: break; ! 267: ! 268: case GT: ! 269: c1 = c1>c2; ! 270: break; ! 271: ! 272: case GE: ! 273: c1 = c1>=c2; ! 274: break; ! 275: ! 276: case ANDAND: ! 277: c1 = (c1 && c2); ! 278: break; ! 279: ! 280: case OROR: ! 281: c1 = (c1 || c2); ! 282: break; ! 283: ! 284: default: ! 285: return (NULL); ! 286: } ! 287: if (lrf && op!=ANDAND && op!=OROR && !isrelop(op)) ! 288: fp = lvalnode(c1); ! 289: else ! 290: fp = ivalnode((int) c1); ! 291: fp->t_type = tt; ! 292: return (fp); ! 293: } ! 294: ! 295: /* ! 296: * Fold things that look like ! 297: * `&array[constant]' where the array ! 298: * is an external or a static. ! 299: */ ! 300: TREE * ! 301: foldaddr(op, lp, rp) ! 302: register TREE *lp, *rp; ! 303: { ! 304: register TREE *xp; ! 305: long val; ! 306: ! 307: if (op==ADD || op==SUB) { ! 308: if (lp->t_op==ADDR ! 309: && (rp->t_op==LCON || rp->t_op==ICON)) { ! 310: xp = lp->t_lp; ! 311: if (xp->t_op==LID || xp->t_op==GID) { ! 312: val = grabnval(rp); ! 313: if (op == ADD) ! 314: xp->t_offs += val; ! 315: else ! 316: xp->t_offs -= val; ! 317: return (lp); ! 318: } ! 319: } ! 320: if (op==ADD && rp->t_op==ADDR ! 321: && (lp->t_op==LCON || lp->t_op==ICON)) { ! 322: xp = rp->t_lp; ! 323: if (xp->t_op==LID || xp->t_op==GID) { ! 324: xp->t_offs += grabnval(lp); ! 325: return (rp); ! 326: } ! 327: } ! 328: } ! 329: return (NULL); ! 330: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.