|
|
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.