|
|
1.1 root 1: /*
2: * n1/mtree0.c
3: * Modify an expression.
4: * All machines.
5: *
6: * modify() calls modtree() which generally does left before right
7: * deepest first traversal, including constant folding and machine
8: * dependent modifications. modify() then walk()'s the tree with
9: * modswap() and modrneg() and finally calls modleaf() to insert
10: * leaf nodes where required.
11: *
12: * mflag:
13: * 0 < mflag - prints trees before and after modification
14: * unless in MINIT context, where you get after only.
15: * 1 < mflag - prints trees at end of modtree()
16: * 2 < mflag - prints trees at beginning of modtree()
17: * 8 < mflag - gets multiple intermediate trees.
18: */
19:
20: #ifdef vax
21: #include "INC$LIB:cc1.h"
22: #else
23: #include "cc1.h"
24: #endif
25:
26: int modswap();
27: int modrneg();
28:
29: /*
30: * Tree modify.
31: */
32: TREE *
33: modify(tp, c)
34: register TREE *tp;
35: {
36: #if !TINY
37: if (mflag > 0 && c != MINIT)
38: snapf("%W%E", "Before modify", tp);
39: #endif
40: tp = modtree(tp, c, NULL);
41: walk(tp, modswap);
42: walk(tp, modrneg);
43: #if !TINY
44: if (mflag > 8 && c != MINIT)
45: snapf("%W%E", "Before modleaf", tp);
46: #endif
47: tp = modleaf(tp, c, NULL);
48: #if !TINY
49: if (mflag > 0)
50: snapf("%W%E%W", "After modify", tp, NULL);
51: #endif
52: return tp;
53: }
54:
55: /*
56: * Tree modifier.
57: * This routine performs a number of machine independent things.
58: * Folding of constant expressions is done by the routine 'modfold()'.
59: * After all the machine independent things have been done,
60: * a call to 'modoper()' does machine-specific modifications.
61: */
62: TREE *
63: modtree(tp, ac, ptp)
64: register TREE *tp;
65: TREE *ptp;
66: {
67: register TREE *lp;
68: register TREE *rp;
69: register TREE *tp1;
70: register int c;
71: register int left;
72: register int n;
73: register int op;
74: register int tt, ts;
75:
76: c = ac;
77: if (c==MINIT || c==MRETURN || c==MSWITCH)
78: c = MRVALUE;
79: #if !TINY
80: if (mflag > 2 && ac != MINIT)
81: snapf("%W%E", "modtree before modfold", tp);
82: #endif
83: again:
84: tp = modfold(tp);
85: #if !TINY
86: if (mflag > 8 && ac != MINIT)
87: snapf("%W%E", "modtree after modfold", tp);
88: #endif
89: op = tp->t_op;
90: if (isleaf(op))
91: goto done;
92: lp = tp->t_lp;
93: rp = (op == FIELD) ? NULL : 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: tp->t_lp = lp = modtree(lp, MRVALUE, tp);
202: /* modtree() may have changed the op of lp. */
203: if (lp->t_op==COMMA || lp->t_op==QUEST)
204: goto again;
205: /* Ignore conversions to same type and size. */
206: if (tt==lp->t_type && ts==lp->t_size) {
207: tp = lp;
208: goto again;
209: }
210: /* Ignore conversions like (type1)(type2)type1 if type2 is wider. */
211: if (iswiden(lp) && tt==lp->t_lp->t_type && ts==lp->t_lp->t_size) {
212: tp = lp->t_lp;
213: goto again;
214: }
215: break;
216:
217: case OROR:
218: case ANDAND:
219: if (c != MFLOW) {
220: tp = modtruth(tp);
221: goto again;
222: }
223: tp->t_lp = modtree(lp, MFLOW, tp);
224: tp->t_rp = modtree(rp, MFLOW, tp);
225: break;
226:
227: case INCAFT:
228: case DECAFT:
229: if (c == MEFFECT)
230: tp->t_op += INCBEF-INCAFT;
231:
232: case INCBEF:
233: case DECBEF:
234: tp->t_lp = modtree(lp, MLADDR, tp);
235: if (isflt(tt)) {
236: tp->t_op = (op==INCBEF || op==INCAFT) ? AADD : ASUB;
237: if (op==INCAFT || op==DECAFT) {
238: tp->t_lp = copynode(tp);
239: tp->t_rp = leftnode(CONVERT, ivalnode((ival_t)1), F64);
240: tp->t_op = (op==INCAFT)?SUB:ADD;
241: }
242: goto again;
243: }
244: tp->t_rp = modtree(basenode(rp), MRADDR, tp);
245: break;
246:
247: case ADDR:
248: lp = modtree(lp, (ac==MINIT?MINIT:MLADDR), tp);
249: if (lp->t_op == STAR) {
250: lp = lp->t_lp;
251: if ( ! isblkp(lp->t_type)) {
252: lp->t_type = tt;
253: lp->t_size = ts;
254: }
255: tp = lp;
256: goto again;
257: } else if (lp->t_op == QUEST) {
258: /* Change '&(a?b:c)' to 'a?&b:&c'. */
259: rp = lp->t_rp; /* COLON node */
260: rp->t_lp = leftnode(ADDR, rp->t_lp, tt, ts);
261: rp->t_rp = leftnode(ADDR, rp->t_rp, tt, ts);
262: rp->t_type = lp->t_type = tt;
263: rp->t_size = lp->t_size = ts;
264: tp = lp;
265: goto again;
266: } else if (lp->t_op == COMMA) {
267: /* Change '&(a,b)' to 'a, &b'. */
268: lp->t_rp = leftnode(ADDR, lp->t_rp, tt, ts);
269: lp->t_type = tt;
270: lp->t_size = ts;
271: tp = lp;
272: goto again;
273: }
274: tp->t_lp = lp;
275: break;
276:
277: case STAR:
278: lp = modtree(lp, (ac==MINIT?MINIT:MRADDR), tp);
279: if (lp->t_op == ADDR) {
280: lp = lp->t_lp;
281: if ( ! isblkp(lp->t_type)) {
282: lp->t_type = tt;
283: lp->t_size = ts;
284: }
285: tp = lp;
286: goto again;
287: }
288: tp->t_lp = lp;
289: break;
290:
291: case ASSIGN:
292: tp->t_lp = modtree(lp, MLADDR, tp);
293: tp->t_rp = modtree(rp, MRVALUE, tp);
294: break;
295:
296: case DIV:
297: case REM:
298: case ADIV:
299: case AREM:
300: lp = modtree(lp, lgoal(op), tp);
301: rp = modtree(rp, MRADDR, tp);
302: if (((n = ispow2(rp)) >= 0) && ((n==0) || isuns(tt))) {
303: if (op==DIV || op==ADIV) {
304: tp->t_op += SHR-DIV;
305: tp->t_lp = lp;
306: tp->t_rp = ivalnode((ival_t)n);
307: goto again;
308: }
309: else {
310: tp->t_op += AND-REM;
311: tp->t_lp = lp;
312: tp->t_rp = gvalnode(tt, ((long)01<<n)-1);
313: goto again;
314: }
315: }
316: tp->t_lp = lp;
317: tp->t_rp = rp;
318: break;
319:
320: case MUL:
321: case AMUL:
322: lp = modtree(lp, lgoal(op), tp);
323: rp = modtree(rp, MRADDR, tp);
324: if ((tp1=modmul(tp, lp, rp)) != NULL
325: || (op==MUL && (tp1=modmul(tp, rp, lp))!=NULL)) {
326: tp = tp1;
327: goto again;
328: }
329: tp->t_lp = lp;
330: tp->t_rp = rp;
331: break;
332:
333: case ADD:
334: case SUB:
335: case AND:
336: case OR:
337: case XOR:
338: case SHR:
339: case SHL:
340: lp = modtree(lp, (ac==MINIT?MINIT:MRVALUE), tp);
341: rp = modtree(rp, (ac==MINIT?MINIT:MRADDR), tp);
342: if (isnval(rp, 0)) {
343: if (op == AND) {
344: rp->t_type = tt;
345: rp->t_size = ts;
346: tp = rp;
347: goto again;
348: }
349: lp->t_type = tt;
350: lp->t_size = ts;
351: tp = lp;
352: goto again;
353: }
354: if (op == SUB
355: && rp->t_op == ICON
356: && (isuns(rp->t_type)==0 || rp->t_ival>=0)) {
357: tp->t_op += ADD-SUB;
358: tp->t_type = IVAL_T; /* Signed */
359: rp->t_ival = -rp->t_ival;
360: amd(rp);
361: tp->t_lp = lp;
362: tp->t_rp = rp;
363: goto again;
364: }
365: tp->t_lp = lp;
366: tp->t_rp = rp;
367: break;
368:
369: case AADD:
370: case ASUB:
371: case AAND:
372: case AOR:
373: case AXOR:
374: case ASHL:
375: case ASHR:
376: lp = modtree(lp, MLADDR, tp);
377: rp = modtree(rp, MRADDR, tp);
378: if (isnval(rp, 0)) {
379: if (op == AAND) {
380: tp->t_op = ASSIGN;
381: tp->t_lp = lp;
382: tp->t_rp = rp;
383: goto again;
384: }
385: lp->t_type = tt;
386: lp->t_size = ts;
387: tp = lp;
388: goto again;
389: }
390: tp->t_lp = lp;
391: tp->t_rp = rp;
392: break;
393:
394: case EQ:
395: case NE:
396: case GT:
397: case LT:
398: case GE:
399: case LE:
400: case UGT:
401: case UGE:
402: case ULT:
403: case ULE:
404: if (c != MFLOW) {
405: tp = modtruth(tp);
406: goto again;
407: }
408: lp = modfold(lp);
409: rp = modfold(rp);
410: if ((left=isnval(lp, 0)) || isnval(rp, 0)) {
411: /* 0 on left or right, force to right. */
412: if (left) {
413: tp->t_op = op = fliprel[op-EQ];
414: tp1 = lp;
415: lp = rp;
416: rp = tp1;
417: }
418: if (op==EQ || op==NE) {
419: lp = modtree(lp, MFLOW, tp);
420: if (lp->t_op == QUEST) {
421: /*
422: * Change "(a ? b : c) op 0"
423: * to "a ? b op 0 : c op 0".
424: */
425: tp = lp; /* QUEST */
426: tp->t_type = tt;
427: tp->t_size = ts;
428: tp1 = tp->t_rp; /* COLON */
429: tp1->t_lp = leftnode(op, tp1->t_lp, tt, ts);
430: tp1->t_lp->t_rp = rp;
431: tp1->t_rp = leftnode(op, tp1->t_rp, tt, ts);
432: tp1->t_rp->t_rp = ivalnode((ival_t)0);
433: goto again;
434: }
435: } else
436: lp = modtree(lp, MRVALUE, tp);
437: } else
438: lp = modtree(lp, MRVALUE, tp);
439: tp->t_lp = lp;
440: tp->t_rp = modtree(rp, MRADDR, tp);
441: break;
442: }
443: tp = modfold(tp);
444: done:
445: walk(tp, amd);
446: if ((tp1 = modoper(tp, ac, ptp)) != NULL) {
447: tp = tp1;
448: goto again;
449: }
450: #if !TINY
451: if (mflag > 1 && ac != MINIT)
452: snapf("%W%E", "modtree done", tp);
453: #endif
454: return tp;
455: }
456:
457: /*
458: * Modify multiply.
459: * Called from the modify case for MUL and AMUL.
460: * If MUL, called twice in both arrangements.
461: */
462: TREE *
463: modmul(tp, lp, rp)
464: register TREE *tp, *lp, *rp;
465: {
466: register n;
467:
468: if (isnval(rp, 0)) {
469: if (tp->t_op == AMUL) {
470: tp->t_op = ASSIGN;
471: return tp;
472: }
473: rp->t_type = tp->t_type;
474: rp->t_size = tp->t_size;
475: return rp;
476: }
477: if ((n=ispow2(rp)) >= 0) {
478: tp->t_op += SHL-MUL;
479: tp->t_lp = lp;
480: tp->t_rp = ivalnode((ival_t)n);
481: return tp;
482: }
483: return NULL;
484: }
485:
486: /*
487: * This routine fabricates a fake question colon pair
488: * to get the correct return value for !, &&, || and relational ops
489: * in non flow contexts.
490: */
491: TREE *
492: modtruth(tp)
493: register TREE *tp;
494: {
495: register TREE *tp1;
496:
497: tp1 = ivalnode((ival_t)1);
498: tp1 = leftnode(COLON, tp1, TRUTH);
499: tp1->t_rp = ivalnode((ival_t)0);
500: tp = leftnode(QUEST, tp, TRUTH);
501: tp->t_rp = tp1;
502: return tp;
503: }
504:
505: /*
506: * Find left subgoal.
507: * This permits '+' and '+=' to share a lot of code.
508: */
509: lgoal(op)
510: register op;
511: {
512: return (op>=AADD && op<=ASHR) ? MLADDR : MRVALUE;
513: }
514:
515: /*
516: * Look for '+' of a negative constant and make it into a subtract.
517: * Machines tend to have 'dec' instructions for small numbers.
518: */
519: modrneg(tp, ptp)
520: register TREE *tp;
521: TREE *ptp;
522: {
523: register TREE *rp;
524:
525: if (tp->t_op==ADD || tp->t_op==AADD) {
526: rp = tp->t_rp;
527: if (rp->t_op==ICON && !isuns(rp->t_type) && rp->t_ival<0) {
528: tp->t_op += SUB-ADD;
529: rp->t_ival = -rp->t_ival;
530: amd(rp);
531: }
532: }
533: }
534:
535: /*
536: * Check assignment transformation for legality.
537: */
538: isokasgn(op, tp)
539: register op;
540: register TREE *tp;
541: {
542: register top;
543:
544: if (op!=ASSIGN && (op<ADD || op>SHR))
545: return 0;
546: if (tp == NULL)
547: return 0;
548: top = tp->t_op;
549: if (top!=ASSIGN && (top<AADD || top>ASHR))
550: return 0;
551: return isokareg(tp, op);
552: }
553:
554: /*
555: * If the tree is a constant power of two, return the log
556: * base two of the number.
557: * If not, return -1.
558: */
559: ispow2(tp)
560: register TREE *tp;
561: {
562: register i;
563: register long n;
564:
565: if (!isfxcon(tp))
566: return -1;
567: n = grabnval(tp);
568: if (n<1 || (n&(n-1))!=0)
569: return -1;
570: i = 0;
571: while ((n&01) == 0) {
572: ++i;
573: n >>= 1;
574: }
575: return i;
576: }
577:
578: /* end of n1/mtree0.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.