|
|
1.1 root 1: /*
2: * C compiler.
3: * Pattern selection.
4: */
5: #ifdef vax
6: #include "INC$LIB:cc1.h"
7: #else
8: #include "cc1.h"
9: #endif
10:
11: #if !TINY
12: #define consnap(x, p) if (sflag>x) snapf(p)
13: #define consnapv(x, p, v) if (sflag>x) snapf(p, v)
14: #else
15: #define consnap(x, p) /* consnap */
16: #define consnapv(x, p, v) /* consnapv */
17: #endif
18:
19: /*
20: * Code selection.
21: * This routine is a near duplicate of output().
22: * This routine must succeed or a nomatch fatal error will result.
23: */
24: select(tp, c, r)
25: register TREE *tp;
26: {
27: register TREE *ap;
28: register op;
29: register TREE *xp;
30: int flag;
31: int rel;
32: int r1;
33:
34: #if !TINY
35: if (sflag > 1) {
36: snapf("select(%P, %C, ", tp, c);
37: snapf(c<MFLOW ? "%R" : c<MEQ ? "%d" : "L%d", r);
38: snapf(") %A\n", tp->t_op);
39: }
40: #endif
41: /* Process a few operators by hand */
42: op = tp->t_op;
43: if (op == COMMA) {
44: if (code1(&tp->t_lp, MEFFECT, ANYR) == 0
45: || code1(&tp->t_rp, c, r) == 0)
46: return (0);
47: tp->t_used = tp->t_lp->t_used | tp->t_rp->t_used;
48: tp->t_treg = tp->t_rp->t_treg;
49: tp->t_rreg = tp->t_rp->t_rreg;
50: return (1);
51: }
52: if (op == QUEST) {
53: if (code1(&tp->t_lp, MFLOW, 0) == 0)
54: return (0);
55: ap = tp->t_rp;
56: if (code1(&ap->t_lp, c, r) == 0)
57: return (0);
58: ap->t_rreg = NONE;
59: if (c==MLVALUE || c==MRVALUE) {
60: r = ap->t_lp->t_rreg;
61: ap->t_rreg = r;
62: }
63: if (code1(&ap->t_rp, c, r) == 0)
64: return (0);
65: ap->t_treg = NONE;
66: ap->t_used = ap->t_lp->t_used | ap->t_rp->t_used;
67: tp->t_rreg = ap->t_rreg;
68: tp->t_treg = NONE;
69: tp->t_used = tp->t_lp->t_used | ap->t_used;
70: return (1);
71: }
72: /* Conditionals may be unravelled to generate simpler code.
73: * 'r' is true or false depending on which condition should goto 'l'. */
74: if (c == MFLOW) {
75: if (op == NOT) {
76: if (code1(&tp->t_lp, c, !r) == 0)
77: return(0);
78: tp->t_used = tp->t_lp->t_used;
79: return(1);
80: }
81: if (op == LEAF) {
82: ap = tp->t_lp;
83: if (ap->t_op==ICON || ap->t_op==LCON)
84: return (1);
85: }
86: if (op==ANDAND || op==OROR) {
87: r1 = r;
88: if ((op==OROR) != r)
89: r1 = !r1;
90: if (code1(&tp->t_lp, MFLOW, r1) == 0
91: || code1(&tp->t_rp, MFLOW, r) == 0)
92: return (0);
93: tp->t_used = tp->t_lp->t_used | tp->t_rp->t_used;
94: tp->t_rreg = NONE;
95: tp->t_treg = NONE;
96: return (1);
97: }
98: rel = NE;
99: flag = 0;
100: if (isrelop(op)) {
101: rel = op;
102: if (isnval(tp->t_rp, 0) && tp->t_lp->t_op != QUEST) {
103: if (rel == ULE)
104: rel = EQ;
105: else if (rel == UGT)
106: rel = NE;
107: ap = tp->t_lp;
108: flag = 1;
109: while ((op = ap->t_op) == COMMA)
110: ap = ap->t_rp;
111: if (isrelop(op) || isflow(op)) {
112: switch (rel) {
113: case EQ:
114: case LE:
115: case ULE:
116: r = !r;
117: case NE:
118: case GT:
119: case UGT:
120: if (code1(&tp->t_lp, c, r) == 0)
121: return(0);
122: tp->t_used = tp->t_lp->t_used;
123: return(1);
124: }
125: }
126: }
127: }
128: if (r == 0)
129: rel = otherel[rel-EQ];
130: c = MEQ + rel - EQ;
131: r = ANYR;
132: if (flag) {
133: if (code1(&tp->t_lp, c, r) == 0)
134: return (0);
135: tp->t_used = tp->t_lp->t_used;
136: return (1);
137: }
138: }
139: if (op == CALL) {
140: #if 0
141: if (c != pertype[tp->t_type].p_frcxt
142: && (c==MRVALUE || c==MLVALUE))
143: return (0);
144: #endif
145: tp->t_used = FNUSED;
146: if (tp->t_rp != NULL) {
147: if (selargs(&tp->t_rp) == 0)
148: return (0);
149: tp->t_used |= tp->t_rp->t_used;
150: }
151: ap = tp->t_lp;
152: if (!isadr(ap->t_flag)) {
153: #if ICALLS
154: /* Does the machine allow
155: * an extra level of indirection
156: * on calls? */
157: if (ap->t_op != STAR)
158: cbotch("call no star");
159: xp = ap->t_lp;
160: if (!isadr(xp->t_flag)) {
161: if (!isofs(xp->t_flag))
162: store(ap, 0);
163: else {
164: xp = findoffs(xp);
165: if (select(xp, MLVALUE, ANYL) == 0)
166: return (0);
167: tp->t_used |= xp->t_used;
168: }
169: }
170: #else
171: if (!isofs(ap->t_flag))
172: cbotch("call not ofs");
173: ap = findoffs(ap);
174: if (select(ap, MLVALUE, ANYL) == 0)
175: return (0);
176: tp->t_used |= ap->t_used;
177: #endif
178: }
179: tp->t_treg = NONE;
180: tp->t_rreg = pertype[tp->t_type].p_frreg;
181: if ((c!=MLVALUE&&c!=MRVALUE)||(isrealreg(r)&&r!=tp->t_rreg))
182: selfix(tp, c, r);
183: return (1);
184: }
185: /* Everything not previously dispatched by hand
186: * must be found in the code tables by seltree */
187: if (seltree(tp, c, r)) {
188: if ((c==MLVALUE||c==MRVALUE) && isrealreg(r) && r!=tp->t_rreg)
189: selfix(tp, c, r);
190: return (1);
191: }
192: /* RVALUE patterns can be fixed up into anything */
193: if (c != MRVALUE && seltree(tp, MRVALUE, ANYR)) {
194: selfix(tp, c, r);
195: return (1);
196: }
197: #if 0
198: /* The m68000 needed this, maybe it won't next time */
199: if (c != MLVALUE && seltree(tp, MLVALUE, ANYL)) {
200: if (c != MEFFECT)
201: selfix(tp, c, r);
202: return (1);
203: }
204: #endif
205: /* FAILURE is a fatal error */
206: return (0);
207: }
208:
209: /*
210: * If the selector cannot find a template that will satisfy the context or the
211: * requested register, an MRVALUE case will do if the result is 'fixed up'.
212: * A FIXUP tree node tells the output part of the coder that a fixup is
213: * needed at this point in the tree.
214: * Context mismatch FIXUP's are generally benign:
215: * they either push a register onto the stack as a function argument,
216: * or test a register and generate a conditional branch.
217: * Register mismatch FIXUP's appear to be caused
218: * by table errors or overzealous node coercion
219: * and should to be avoided at all costs;
220: * they often lead to shuffling values back and forth between registers.
221: * The typical culprit is a code table pattern
222: * which specifies both a node register and an ADR subnode
223: * rather than a TREG subnode shared with the node register.
224: * seltree() coerces the ADR node into the wrong register
225: * and the fixup copies it to the requested reg.
226: */
227: selfix(tp, c, r)
228: register TREE *tp;
229: {
230: register TREE *ap;
231: TREE rnode;
232:
233: #if !TINY
234: if (sflag > 1) {
235: snapf("selfix(%P, %C, ", tp, c);
236: snapf(c<MFLOW ? "%R" : c<MEQ ? "%d" : "L%d", r);
237: snapf(") %A\n", tp->t_op);
238: }
239: #endif
240: ap = copynode(tp);
241: fixtoptype(tp);
242: rnode.t_op = REG;
243: rnode.t_type = tp->t_type;
244: rnode.t_size = tp->t_size;
245: rnode.t_reg = tp->t_rreg;
246: tp->t_op = FIXUP;
247: tp->t_lp = &rnode;
248: tp->t_rp = NULL;
249: walk(tp, amd);
250: #if !TINY
251: rnode.t_treg = NONE;
252: rnode.t_rreg = NONE;
253: rnode.t_used = 0;
254: rnode.t_patp = NULL;
255: if (sflag > 2) snapf("%W%E%W", "Selfix", tp, NULL);
256: #endif
257: if (select(tp, c, r) == 0)
258: cbotch("node will not fix");
259: tp->t_lp = ap;
260: tp->t_used = ap->t_used;
261: if (isrealreg(r))
262: setused(tp, r);
263: }
264:
265: /*
266: * Add register 'r' to the used set of the tree node pointed to by 'tp'.
267: */
268: setused(tp, r)
269: TREE *tp;
270: {
271: tp->t_used |= reg[r].r_phys;
272: }
273:
274: /*
275: * Run down the (possibly null)
276: * argument list of a function, making
277: * the required recursive calls to the
278: * walker and/or the code selector.
279: * If the node is a BLK pointer,
280: * it the address of a structure argument and
281: * must get special treatment.
282: */
283: selargs(tpp)
284: register TREE **tpp;
285: {
286: register TREE *tp;
287:
288: if ((tp = *tpp) == NULL)
289: return (1);
290: if (tp->t_op == ARGLST) {
291: if (selargs(&tp->t_lp)==0)
292: return (0);
293: if (selargs(&tp->t_rp)==0)
294: return (0);
295: tp->t_used = 0;
296: if (tp->t_lp != NULL)
297: tp->t_used |= tp->t_lp->t_used;
298: if (tp->t_rp != NULL)
299: tp->t_used |= tp->t_rp->t_used;
300: return (1);
301: }
302: if (isblkp(tp->t_type))
303: return (code1(tpp, MBLARG, MBLREG));
304: return (code1(tpp, MFNARG, ANYR));
305: }
306:
307: /*
308: * Set up an address in an rvalue context.
309: * This routine knows how to pool
310: * constants on demand, how to use registers
311: * as indexing temporaries and as plain old
312: * value temporaries, and how to give up and
313: * put a value into memory.
314: * If the top operator is one of the leaf
315: * nodes the register used in the setup of an
316: * offset address is not made busy.
317: * It is marked used by the tree.
318: * These trees are more like a TREG than a RHS
319: * in their use of a register.
320: */
321: selrv(ttp, flag, didstorep)
322: TREE *ttp;
323: int *didstorep;
324: {
325: register TREE *tp, *ap;
326: register op, leaf;
327: int lab, r;
328:
329: leaf = 1;
330: tp = ttp;
331: op = tp->t_op;
332: if (op==CONVERT || op==CAST || op==FIXUP || op==LEAF)
333: leaf = 2;
334: #if !TINY
335: if (sflag > 1)
336: snapf("selrv(%P, %d, ...) leaf=%d\n", tp, flag, leaf);
337: #endif
338: tp = flag ? tp->t_rp : tp->t_lp;
339: /* Pool constants into memory */
340: if ((tp->t_flag&T_IMM) != 0) {
341: for (ap=tp; ap->t_op==LEAF; ap=ap->t_lp)
342: ;
343: pool(ap);
344: walk(tp, amd);
345: return;
346: }
347: /* The tree is offset addressible,
348: * load the offset node into an index reg */
349: if (isofs(tp->t_flag)) {
350: ap = findoffs(tp);
351: consnapv(2, "Rv offs %P\n", ap);
352: if ((r = rallo(ap, ttp->t_used, leaf)) >= 0) {
353: consnapv(2, "Offs %R\n", r);
354: if (leaf == 1)
355: setbusy(r);
356: if (select(ap, MLVALUE, r)) {
357: ttp->t_used |= ap->t_used;
358: return;
359: }
360: if (leaf == 1)
361: clrbusy(r);
362: }
363: }
364: /* Try to load the tree into a register */
365: if ((r = rallo(tp, ttp->t_used, 0)) >= 0) {
366: setbusy(r);
367: if (select(tp, MRVALUE, r)) {
368: tp->t_flag = 0;
369: ttp->t_used |= tp->t_used;
370: return;
371: }
372: clrbusy(r);
373: }
374: /* Store the tree into a stack temporary */
375: store(ttp, flag);
376: walk(tp, amd);
377: *didstorep = 1;
378: }
379:
380: /*
381: * This function sets up a left context subtree in an addressing context.
382: * The 'index' argument is a preferred register; if negative,
383: * then indirection is legal.
384: * This routine is the pits, comparable
385: * in pittiness to the part of output()
386: * responsible for undoing this madness.
387: */
388: sellv(ttp, index, flag, didstorep)
389: TREE *ttp;
390: int *didstorep;
391: {
392: register TREE *tp, *tp1, *tp2;
393: int newindex;
394:
395: tp = flag ? ttp->t_rp : ttp->t_lp;
396: #if !TINY
397: if (sflag > 1)
398: snapf("sellv(%P, %R, %d, ...)\n", tp, index, flag);
399: #endif
400: if (tp->t_op == FIELD) {
401: tp->t_used = ttp->t_used;
402: sellv(tp, index, 0, didstorep);
403: ttp->t_used |= tp->t_used;
404: return;
405: }
406: if (!isofs(tp->t_flag))
407: cbotch("sellv: not an ofs");
408: /* If we can indirect through a stack temporary,
409: * we still try first to do it in a register,
410: * but we give up with much less grief. */
411: if (index < 0) {
412: tp1 = findoffs(tp);
413: consnapv(2, "Lv offs %P\n", tp1);
414: if ((index = rallo(tp1, ttp->t_used, 1)) >= 0) {
415: consnapv(2, "Index %R\n", index);
416: setbusy(index);
417: if (select(tp1, MLVALUE, index)) {
418: tp->t_used |= tp1->t_used;
419: ttp->t_used |= tp1->t_used;
420: return;
421: }
422: clrbusy(index);
423: }
424: /* The store puts a stack temp under tp
425: * which must have tp->t_op == STAR */
426: store(tp, 0);
427: walk(tp, amd);
428: *didstorep = 1;
429: return;
430: }
431: /* We cannot indirect through a temp,
432: * so we may have to fake it. */
433: tp2 = findoffs(tp);
434: consnapv(2, "Offs %P\n", tp2);
435: for (tp1 = tp; tp1->t_lp != tp2; tp1 = tp1->t_lp);
436: /* If the offset is not directly addressible
437: * then we will have to generate code to load
438: * it into the index register. */
439: if (!isadr(tp2->t_flag)) {
440: /* If the preferred index is useable
441: * then attempt to use it */
442: if ((ttp->t_used®[index].r_phys) == 0) {
443: if (select(tp2, MLVALUE, index)) {
444: tp->t_used |= tp2->t_used;
445: ttp->t_used |= tp2->t_used;
446: return;
447: }
448: }
449: /* Since the preferred index is already used,
450: * try to use another one. */
451: if ((newindex = rallo(tp2, ttp->t_used, 1)) >= 0) {
452: setbusy(newindex);
453: if (select(tp2, MLVALUE, newindex)) {
454: ttp->t_used |= tp2->t_used;
455: tp->t_used |= tp2->t_used;
456: return;
457: }
458: clrbusy(newindex);
459: }
460: /* We can't do it ourselves, but an index has been
461: * reserved to load from a stack temp, so give up
462: * and store the offset. */
463: store(tp1, 0);
464: walk(tp, amd);
465: *didstorep = 1;
466: }
467: /* tp2 either was addressible to begin with,
468: * or was just made into an addressible temp */
469: tp2 = tp1->t_lp;
470: if (tp2->t_op != LEAF) {
471: tp2 = leafnode(tp2);
472: tp2->t_flag = tp1->t_lp->t_flag;
473: tp1->t_lp = tp2;
474: }
475: /* Select the addressible offset node
476: * into an index register */
477: if (select(tp2, MLVALUE, index) == 0)
478: cbotch("sellv");
479: /* This flag is for the benefit of output() */
480: tp->t_flag |= T_INDIR;
481: tp->t_used |= tp2->t_used;
482: ttp->t_used |= tp2->t_used;
483: }
484:
485: /*
486: * Store a subtree of the node pointed to by 'ttp'.
487: * The 'flag' argument tells which subtree;
488: * true means store the right side.
489: * Then rewrite the subtree to refer to the storage location.
490: */
491: store(ttp, flag)
492: TREE *ttp;
493: {
494: register TREE *ap;
495: register TREE *tp;
496: register int sideflag;
497:
498: if (nstorelist >= NSTORE)
499: cbotch("more than %d stores", NSTORE);
500: sideflag = MRADDR;
501: if (ttp->t_op>=INCBEF && ttp->t_op<=DECAFT) {
502: if (flag != 0)
503: cbotch("store");
504: tp = copynode(ttp);
505: sideflag = MRVALUE;
506: } else if (flag != 0)
507: tp = ttp->t_rp;
508: else
509: tp = ttp->t_lp;
510: ap = tempnode(tp, 1);
511: if (sideflag == MRVALUE)
512: ap = leafnode(ap);
513: walk(ap, amd);
514: if (sideflag == MRVALUE)
515: *ttp = *ap;
516: else if (flag != 0)
517: ttp->t_rp = ap;
518: else
519: ttp->t_lp = ap;
520: amd(ttp);
521: ap = tempnode(tp, 0);
522: ap = leftnode(ASSIGN, ap, ap->t_type, ap->t_size);
523: while (tp->t_op == LEAF)
524: tp = tp->t_lp;
525: if (tp->t_type != ap->t_type)
526: tp = leftnode(CONVERT, tp, ap->t_type, ap->t_size);
527: else if ((tp->t_flag&T_LEAF) != 0)
528: tp = leafnode(tp);
529: ap->t_rp = ripout(tp, 0);
530: fixtoptype(ap);
531: walk(ap, amd);
532: storelist[nstorelist++] = ap;
533: }
534:
535: /*
536: * Return true if the top of the argument tree is a conversion of some type
537: * and the conversion makes the data wider (e.g. int to long).
538: */
539: iswiden(tp)
540: register TREE *tp;
541: {
542: register TREE *lp;
543:
544: if (tp->t_op!=CONVERT && tp->t_op!=CAST)
545: return (0);
546: lp = tp->t_lp;
547: if (wtype[tp->t_type] < wtype[lp->t_type])
548: return (0);
549: return (1);
550: }
551:
552: /*
553: * This routine determines if a pattern and a set of expression flags mismatch,
554: * and a call to 'sellv' or 'selrv' is needed.
555: * Also used by output().
556: */
557: selmiss(pflag, eflag)
558: FLAG pflag;
559: FLAG eflag;
560: {
561: if ((pflag&eflag&~T_OFS) == 0)
562: return (1);
563: return (0);
564: }
565:
566: /*
567: * Remove any fix nodes which may have been generated
568: * before a temp was substituted for an expression by store.
569: */
570: TREE *
571: ripout(tp, flag)
572: register TREE *tp;
573: {
574: register op;
575:
576: op = tp->t_op;
577: if (!isleaf(op)) {
578: tp->t_lp = ripout(tp->t_lp, flag);
579: if (op!=FIELD && tp->t_rp!=NULL)
580: tp->t_rp = ripout(tp->t_rp, flag);
581: }
582: if (op==FIXUP || (op==LEAF && flag!=0))
583: tp = tp->t_lp;
584: return (tp);
585: }
586:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.