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