|
|
1.1 ! root 1: /* ! 2: * n1/mtree1.c ! 3: * A portable associative tree reorderer and constant expression folder. ! 4: * This may not be general enough for all machines. ! 5: */ ! 6: ! 7: #ifdef vax ! 8: #include "INC$LIB:cc1.h" ! 9: #else ! 10: #include "cc1.h" ! 11: #endif ! 12: ! 13: #if _I386 ! 14: #define NLNODE 128 ! 15: #define NONODE 128 ! 16: #else ! 17: #define NLNODE 20 ! 18: #define NONODE 20 ! 19: #endif ! 20: ! 21: static char cltc[] = "associative expression too complex"; ! 22: TREE *fold1(); ! 23: TREE *foldaddr(); ! 24: ! 25: /* ! 26: * Fancy folder. ! 27: * This gathers up all the constants that it can ! 28: * by digging through the subtrees of commutative/associative operations. ! 29: * Simpler things are done for operations that are not quite so friendly. ! 30: * Returns a pointer to the new 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 = constcvt(tp->t_type, grabnval(lp)); ! 62: if (islong(tp->t_type)) ! 63: lp = lvalnode(c1); else ! 64: lp = ivalnode((ival_t) 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 operator cluster. ! 118: * Pack it into the supplied buffers. ! 119: */ ! 120: cluster(tp, op, type, ann, anl, onodes, leaves) ! 121: register TREE *tp; ! 122: int *ann, *anl; ! 123: register TREE *onodes[], *leaves[]; ! 124: { ! 125: register i, nl; ! 126: int nn; ! 127: TREE *xp; ! 128: ! 129: if (tp->t_op==op && tp->t_type==type) { ! 130: nn = *ann; ! 131: if ((*ann)++ >= NONODE) ! 132: cfatal(cltc); ! 133: onodes[nn] = tp; ! 134: cluster(tp->t_lp, op, type, ann, anl, onodes, leaves); ! 135: cluster(tp->t_rp, op, type, ann, anl, onodes, leaves); ! 136: return; ! 137: } ! 138: nl = *anl; ! 139: if ((*anl)++ >= NLNODE) ! 140: cfatal(cltc); ! 141: if (isncon(tp->t_op)) { ! 142: leaves[nl] = tp; ! 143: return; ! 144: } ! 145: for (i = nl; i > 0; ) { ! 146: xp = leaves[i-1]; ! 147: if (tp->t_op==ADDR && !isncon(xp->t_op)) ! 148: break; ! 149: if (tp->t_op==STAR && xp->t_op==STAR) ! 150: break; ! 151: leaves[i] = xp; ! 152: --i; ! 153: } ! 154: leaves[i] = tp; ! 155: } ! 156: ! 157: /* ! 158: * Fold an operation. ! 159: * Return a pointer to the folded tree, ! 160: * or NULL if no fold is possible. ! 161: * FIX_ME This should pay attention to unsigned types like n0/fold.c/fold0(). ! 162: */ ! 163: TREE * ! 164: fold1(op, lp, rp) int op; TREE *lp, *rp; ! 165: { ! 166: register TREE *fp; ! 167: register int sop, lflag, tt, bool; ! 168: lval_t lv, rv; ! 169: ! 170: if ((fp = foldaddr(op, lp, rp)) != NULL) ! 171: return fp; ! 172: if ((sop = lp->t_op)!=ICON && sop!=LCON) ! 173: return NULL; ! 174: lv = grabnval(lp); ! 175: tt = lp->t_type; ! 176: lflag = (sop == LCON); ! 177: if (op == QUEST) ! 178: return (lv) ? rp->t_lp : rp->t_rp; ! 179: if (rp != NULL) { ! 180: if ((sop = rp->t_op)!=ICON && sop!=LCON) ! 181: return NULL; ! 182: rv = grabnval(rp); ! 183: if (rp->t_type > tt) ! 184: tt = rp->t_type; ! 185: if (sop == LCON) ! 186: ++lflag; ! 187: } ! 188: bool = -1; ! 189: ! 190: /* Perform the folding, result to lv or bool. */ ! 191: switch (op) { ! 192: ! 193: case COM: lv = ~lv; break; ! 194: case NEG: lv = -lv; break; ! 195: case ADD: lv += rv; break; ! 196: case SUB: lv -= rv; break; ! 197: case MUL: lv *= rv; break; ! 198: case AND: lv &= rv; break; ! 199: case OR: lv |= rv; break; ! 200: case XOR: lv ^= rv; break; ! 201: case SHL: lv <<= rv; break; ! 202: case SHR: lv >>= rv; break; ! 203: ! 204: case DIV: ! 205: if (rv == 0) ! 206: return NULL; ! 207: lv /= rv; ! 208: break; ! 209: ! 210: case REM: ! 211: if (rv == 0) ! 212: return NULL; ! 213: lv %= rv; ! 214: break; ! 215: ! 216: case NOT: bool = !lv; break; ! 217: case EQ: bool = lv == rv; break; ! 218: case NE: bool = lv != rv; break; ! 219: case LT: bool = lv < rv; break; ! 220: case LE: bool = lv <= rv; break; ! 221: case GT: bool = lv > rv; break; ! 222: case GE: bool = lv >= rv; break; ! 223: case ANDAND: bool = (lv && rv); break; ! 224: case OROR: bool = (lv || rv); break; ! 225: ! 226: default: ! 227: return NULL; ! 228: } ! 229: ! 230: if (bool != -1) ! 231: fp = ivalnode((ival_t)bool); ! 232: else if (lflag) ! 233: fp = lvalnode(lv); ! 234: else ! 235: fp = ivalnode((ival_t) lv); ! 236: fp->t_type = tt; ! 237: return fp; ! 238: } ! 239: ! 240: /* ! 241: * Fold things that look like '&array[constant]' ! 242: * where the array is an external or a static. ! 243: */ ! 244: TREE * ! 245: foldaddr(op, lp, rp) ! 246: register TREE *lp, *rp; ! 247: { ! 248: register TREE *xp; ! 249: long val; ! 250: ! 251: if (op==ADD || op==SUB) { ! 252: if (lp->t_op==ADDR ! 253: && (rp->t_op==LCON || rp->t_op==ICON)) { ! 254: xp = lp->t_lp; ! 255: if (xp->t_op==LID || xp->t_op==GID) { ! 256: val = grabnval(rp); ! 257: if (op == ADD) ! 258: xp->t_offs += val; ! 259: else ! 260: xp->t_offs -= val; ! 261: return lp; ! 262: } ! 263: } ! 264: if (op==ADD && rp->t_op==ADDR ! 265: && (lp->t_op==LCON || lp->t_op==ICON)) { ! 266: xp = rp->t_lp; ! 267: if (xp->t_op==LID || xp->t_op==GID) { ! 268: xp->t_offs += grabnval(lp); ! 269: return rp; ! 270: } ! 271: } ! 272: } ! 273: return NULL; ! 274: } ! 275: ! 276: /* end of n1/mtree1.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.