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