|
|
1.1 root 1: /*
2: * The routines in this file perform code output.
3: * That is, they walk down a selected tree,
4: * expanding the code patterns and filling in the blanks.
5: */
6:
7: #ifdef vax
8: #include "INC$LIB:cc1.h"
9: #else
10: #include "cc1.h"
11: #endif
12:
13: /*
14: * Code output.
15: * All registers have been set up by selection.
16: * A pointer to the selected macro has been stashed in the tree.
17: * Walk down the tree, putting out the required code.
18: * It would be nice if select and this guy could be one routine.
19: */
20: output(tp, c, s, n)
21: register TREE *tp;
22: {
23: register TREE *ap;
24: register op;
25: int lab0, lab1, rel;
26:
27: again:
28: #if !TINY
29: if (oflag > 1)
30: snapf("output(%P, %C, %d, L%d); %A\n",
31: tp, c, s, n, tp->t_op);
32: #endif
33: if ((op=tp->t_op) == COMMA) {
34: output(tp->t_lp, MEFFECT, 0, 0);
35: tp = tp->t_rp;
36: goto again;
37: }
38: if (op == QUEST) {
39: lab0 = newlab();
40: lab1 = newlab();
41: output(tp->t_lp, MFLOW, 0, lab0);
42: ap = tp->t_rp;
43: output(ap->t_lp, c, s, n);
44: genubr(lab1);
45: genlab(lab0);
46: output(ap->t_rp, c, s, n);
47: genlab(lab1);
48: return;
49: }
50: if (c == MFLOW) {
51: if (op == NOT) {
52: s = !s;
53: tp = tp->t_lp;
54: goto again;
55: }
56: if (op == LEAF) {
57: ap = tp->t_lp;
58: if (ap->t_op==ICON || ap->t_op==LCON) {
59: if ((grabnval(ap)!=0) == s)
60: genubr(n);
61: return;
62: }
63: }
64: if (op==ANDAND || op==OROR) {
65: if ((op==OROR) == s) {
66: output(tp->t_lp, MFLOW, s, n);
67: output(tp->t_rp, MFLOW, s, n);
68: return;
69: }
70: lab0 = newlab();
71: output(tp->t_lp, MFLOW, !s, lab0);
72: output(tp->t_rp, MFLOW, s, n);
73: genlab(lab0);
74: return;
75: }
76: rel = NE;
77: if (isrelop(op)) {
78: rel = op;
79: if (isnval(tp->t_rp, 0)
80: && tp->t_lp->t_op != QUEST) {
81: if (rel == ULE)
82: rel = EQ;
83: else if (rel == UGT)
84: rel = NE;
85: tp = tp->t_lp;
86: ap = tp;
87: while ((op=ap->t_op) == COMMA)
88: ap = ap->t_rp;
89: if (isrelop(op) || isflow(op)) {
90: switch (rel) {
91:
92: case EQ:
93: case LE:
94: case ULE:
95: s = !s;
96: case NE:
97: case GT:
98: case UGT:
99: goto again;
100: }
101: }
102: }
103: }
104: if (s == 0)
105: rel = otherel[rel-EQ];
106: while ((op=tp->t_op) == COMMA) {
107: output(tp->t_lp, MEFFECT, 0, 0);
108: tp = tp->t_rp;
109: }
110: c = MEQ + rel - EQ;
111: }
112: if (op == CALL) {
113: outcall(tp, c, n);
114: return;
115: }
116: if (op == FIXUP) {
117: output(tp->t_lp, MRVALUE, 0, 0);
118: tp->t_lp->t_op = REG;
119: tp->t_lp->t_reg = tp->t_lp->t_rreg;
120: walk(tp, amd);
121: }
122: outtree(tp, c, n);
123: }
124:
125: /*
126: * This routine does the general cases of code output.
127: * It generates code to output the subgoals,
128: * then expands the code macro for this node.
129: */
130: outtree(tp, cxt, lab)
131: register TREE *tp;
132: {
133: register TREE *lp, *rp;
134: PAT *patp;
135: FLAG lflag, rflag, lpflag, rpflag;
136: TREE *ap;
137: int op; /* Tree operator */
138: int lab0, lab1; /* Manufactured labels */
139: unsigned char *mp; /* Macro pointer */
140: int c; /* Current macro byte */
141: int false; /* Conditional macro state */
142: int opcode; /* Machine operation */
143: int opv; /* Opcode size variant */
144: int naddr; /* Number of addresses output */
145: int nse; /* Side effect flag */
146: int star; /* Indirection of computed address */
147: int npfx; /* Number of prefix bytes */
148: unsigned char pfx[8]; /* Prefix bytes */
149: int label; /* jump label */
150: MASK mask; /* Bit field mask */
151: TREE node; /* Automatic node */
152:
153: /*
154: * Gather flags and types from the tree node.
155: * If the left operand is a FIELD,
156: * pull off the field and make up the appropriate mask.
157: */
158: #if !TINY
159: snapfix(&node);
160: if (oflag > 1) {
161: snapf("outtree(%P, %C, L%d);\n", tp, cxt, lab);
162: if (oflag > 2)
163: snapf("%W%E%W", "Outtree", tp, NULL);
164: }
165: #endif
166: if ((patp=tp->t_patp) == NULL) {
167: #if !TINY
168: printf("tp = ");
169: psnap((char *) tp);
170: printf("\n");
171: #endif
172: cbotch("no patp");
173: }
174: if ((lp=tp->t_lp)->t_op == FIELD) {
175: mask = ((MASK)01<<lp->t_width) - 1;
176: mask = mask << lp->t_base;
177: lp = lp->t_lp;
178: }
179: lflag = lp->t_flag;
180: lpflag = 0;
181: if (patp->p_lflag != 0)
182: lpflag = flagcache[patp->p_lflag-1];
183: rflag = rpflag = 0;
184: if ((rp=tp->t_rp) != NULL) {
185: rflag = rp->t_flag;
186: if (patp->p_rflag != 0)
187: rpflag = flagcache[patp->p_rflag-1];
188: }
189: /*
190: * Perform output for any subgoals.
191: * This code is similar to that in select,
192: * but works in exactly the reverse order.
193: */
194: if (selmiss(lpflag, lflag)
195: && islvadr(lpflag) && !isadr(lflag) && !isind(lflag))
196: outofs(lp);
197: if (selmiss(rpflag, rflag)
198: && islvadr(rpflag) && !isadr(rflag) && !isind(rflag))
199: outofs(rp);
200: if (selmiss(lpflag, lflag) && isrvadr(lpflag) && !isadr(lflag)) {
201: ap = lp;
202: if (isofs(lflag))
203: ap = findoffs(lp);
204: output(ap, MLVALUE, 0, 0);
205: ap->t_op = REG;
206: ap->t_reg = ap->t_rreg;
207: walk(lp, amd);
208: }
209: if (selmiss(rpflag, rflag) && isrvadr(rpflag) && !isadr(rflag)) {
210: ap = rp;
211: if (isofs(rflag))
212: ap = findoffs(rp);
213: output(ap, MLVALUE, 0, 0);
214: ap->t_op = REG;
215: ap->t_reg = ap->t_rreg;
216: walk(rp, amd);
217: }
218: /* BUG - these are not reversed, but maybe another bug, too */
219: if ((rpflag&T_TREG) != 0) {
220: output(rp, MRVALUE, 0, 0);
221: rp->t_op = REG;
222: rp->t_reg = rp->t_rreg;
223: amd(rp, NULL);
224: }
225: if ((lpflag&T_TREG) != 0) {
226: output(lp, MRVALUE, 0, 0);
227: lp->t_op = REG;
228: lp->t_reg = lp->t_rreg;
229: amd(lp, NULL);
230: }
231: if (isind(lflag))
232: outofs(lp);
233: if (isind(rflag))
234: outofs(rp);
235: /*
236: * Expand the code macro.
237: * Handle prefix bytes,
238: * the no side effect flag byte,
239: * the op variant prefix,
240: * jumps to other parts of the table,
241: * and conditional macros.
242: */
243: #if !TINY
244: if (isvariant(VTPROF)) {
245: bput(DLABEL);
246: bput(DC_LINE);
247: iput(patp->p_fline);
248: sput(namecache[patp->p_fname]);
249: bput(DT_NONE);
250: iput(0);
251: }
252: #endif
253: op = tp->t_op;
254: lab0 = lab1 = -1;
255: false = naddr = opv = nse = npfx = star = 0;
256: mp = patp->p_macro;
257: while ((c = *mp++) != M_END) {
258: /* Unsatisfied conditions ignore everything but goto's */
259: if (false) {
260: if (c == M_ENDIF) {
261: false = 0;
262: continue;
263: }
264: if (c != M_JMP1 && c != M_JMPB && c != M_JMP2)
265: continue;
266: }
267: switch (c) {
268:
269: case M_JMP1:
270: label = mp[0];
271: jump:
272: mp = macros + label;
273: continue;
274:
275: case M_JMPB:
276: label = mp - macros - 1 - mp[0];
277: goto jump;
278:
279: case M_JMP2:
280: label = mp[0] + (mp[1] << 8);
281: goto jump;
282:
283: case M_IFV: /* Value context conditional */
284: false = (cxt!=MLVALUE && cxt!=MRVALUE);
285: continue;
286:
287: case M_IFE: /* Effect context conditional */
288: false = (cxt != MEFFECT);
289: continue;
290:
291: case M_IFR: /* Relational context condtional */
292: false = (cxt < MEQ);
293: continue;
294:
295: case M_ENDIF: /* End of conditional */
296: continue;
297:
298: case M_TN: /* Adjust the opcode according */
299: case M_TL: /* to the type of the base, left, */
300: case M_TR: /* or right node via maptype(...) */
301: opv = c;
302: continue;
303:
304: case M_OP0: /* Use the opcode table to select */
305: case M_OP1: /* one of three variations of opcode */
306: case M_OP2:
307: opcode = optab[op-MIOBASE][c-M_OP0];
308: outop:
309: opcode = maptype(opv, opcode, tp);
310: bput(CODE);
311: bput(opcode);
312: naddr = opv = 0;
313: continue;
314:
315: case M_CALL:
316: outopcall(0);
317: continue;
318:
319: default: /* This should be a machine opcode */
320: if (c < M_ORG) {
321: opcode = mapcode(c, tp);
322: goto outop;
323: }
324: cbotch("bad macro %d", c);
325: /* NOTREACHED */
326:
327: case M_NSE: /* Set no side effect flag for genadr */
328: nse++;
329: continue;
330:
331: case M_HI: /* Set part of address prefix for genadr */
332: case M_LO:
333: pfx[npfx++] = c;
334: continue;
335:
336: case M_STAR: /* Indicate indirection of address */
337: star += 1;
338: continue;
339:
340: case M_AN: /* Output address form of base node */
341: ap = tp;
342: outadr:
343: if (star)
344: genstar(ap, nse, npfx, pfx);
345: else
346: genadr(ap, nse, npfx, pfx);
347: nse = npfx = star = 0;
348: naddr += 1;
349: continue;
350:
351: case M_AL: /* Output address form of left node */
352: ap = lp;
353: goto outadr;
354:
355: case M_AR: /* Output address form of right node */
356: ap = rp;
357: goto outadr;
358:
359: case M_R: /* Output node register */
360: node.t_reg = tp->t_treg;
361: node.t_type = tp->t_type;
362: outreg:
363: node.t_op = REG;
364: ap = &node;
365: goto outadr;
366:
367: case M_RL: /* Output left temp register */
368: node.t_reg = lp->t_rreg;
369: node.t_type = lp->t_type;
370: goto outreg;
371:
372: case M_RR: /* Output right temp register */
373: node.t_reg = rp->t_rreg;
374: node.t_type = rp->t_type;
375: goto outreg;
376:
377: case M_REGNO: /* Literal register from tables */
378: node.t_op = REG;
379: node.t_reg = *mp++;
380: ap = &node;
381: goto outadr;
382:
383: case M_ICON: /* Literal ival_t constant */
384: c = *mp++;
385: node.t_ival = ivalcache[c-1];
386: outival:
387: node.t_op = ICON;
388: node.t_type = IVAL_T;
389: ap = &node;
390: goto outadr;
391:
392: case M_SIZE: /* Size of block object */
393: node.t_ival = tp->t_size;
394: goto outival;
395:
396: case M_SSIZE: /* Size of block object on stack */
397: node.t_ival = mapssize(tp->t_size);
398: goto outival;
399:
400: case M_LCON: /* Literal lval_t constant */
401: c = *mp++;
402: node.t_lval = lvalcache[c-1];
403: outlval:
404: node.t_op = LCON;
405: node.t_type = LVAL_T;
406: ap = &node;
407: goto outadr;
408:
409: case M_EMASK: /* Field extraction mask */
410: node.t_lval = (lval_t) mask;
411: goto outlval;
412:
413: case M_CMASK: /* Field clear mask */
414: node.t_lval = (lval_t) ~mask;
415: goto outlval;
416:
417: case M_GID: /* Literal global identifier */
418: c = *mp++;
419: node.t_op = GID;
420: node.t_sp = gidpool(gidcache[c-1]);
421: node.t_seg = SANY;
422: node.t_offs = 0;
423: ap = &node;
424: goto outadr;
425:
426: #if BITS
427: case M_BITL: /* Bit number of left node */
428: node.t_ival = getbit(lp);
429: goto outival;
430:
431: case M_BITR: /* Bit number of right node */
432: node.t_ival = getbit(rp);
433: goto outival;
434: #endif
435:
436: case M_TOS: /* Generate top of stack address */
437: gentos(opcode, naddr++);
438: continue;
439:
440: case M_LAB0: /* Generated label #0 */
441: if (lab0 < 0)
442: lab0 = newlab();
443: node.t_label = lab0;
444: outlid:
445: node.t_op = LID;
446: node.t_seg = SANY;
447: node.t_offs = 0;
448: ap = &node;
449: goto outadr;
450:
451: case M_LAB1: /* Generated label #1 */
452: if (lab1 < 0)
453: lab1 = newlab();
454: node.t_label = lab1;
455: goto outlid;
456:
457: case M_DLAB0: /* Define label #0 */
458: if (lab0 < 0)
459: lab0 = newlab();
460: bput(LLABEL);
461: iput(lab0);
462: continue;
463:
464: case M_DLAB1: /* Define label #1 */
465: if (lab1 < 0)
466: lab1 = newlab();
467: bput(LLABEL);
468: iput(lab1);
469: continue;
470:
471: case M_LAB: /* The label associated with the tree */
472: node.t_label = lab;
473: goto outlid;
474:
475: case M_REL0:
476: case M_REL1:
477: bput(CODE);
478: bput(optab[cxt-MEQ+EQ-MIOBASE][c-M_REL0]);
479: naddr = 0;
480: continue;
481:
482: #if LONGREL
483: case M_LREL0:
484: case M_LREL1:
485: case M_LREL2:
486: bput(CODE);
487: opcode = cxt-MEQ+EQ;
488: if (c == M_LREL2) {
489: if (opcode>=GT && opcode<=LT)
490: opcode += UGT-GT;
491: bput(optab[opcode-MIOBASE][0]);
492: naddr = 0;
493: continue;
494: }
495: if (c == M_LREL1)
496: opcode = fliprel[opcode-EQ];
497: bput(optab[opcode-MIOBASE][2]);
498: naddr = 0;
499: continue;
500: #endif
501:
502: }
503: }
504: }
505:
506: /*
507: * Given a pointer to an offset type tree,
508: * dig up the subtree that gets loaded into the base register
509: * and make a recursive call to generate the code that does the load.
510: */
511: outofs(tp)
512: TREE *tp;
513: {
514: register TREE *ap;
515:
516: ap = findoffs(tp);
517: output(ap, MLVALUE, 0, 0);
518: ap->t_op = REG;
519: ap->t_reg = ap->t_rreg;
520: walk(tp, amd);
521: }
522:
523: #if BITS
524: /*
525: * Figure out and output a bit number.
526: * The argument must be flagged as a bit thing.
527: */
528: getbit(tp)
529: register TREE *tp;
530: {
531: register ival_t half;
532:
533: if ((tp->t_flag&(T_UOBS|T_LOBS|T_UOBC|T_LOBC)) == 0)
534: cbotch("bad bit");
535: {
536: register op;
537:
538: while ((op=tp->t_op) == LEAF)
539: tp = tp->t_lp;
540: if (op == ICON)
541: half = tp->t_ival;
542: else if ((tp->t_flag&(T_UOBS|T_UOBC)) != 0)
543: half = upper(tp->t_lval);
544: else
545: half = lower(tp->t_lval);
546: }
547: if ((tp->t_flag&(T_UOBC|T_LOBC)) != 0)
548: half = ~half;
549: {
550: register bitnum;
551:
552: bitnum = 0;
553: while ((half&01) == 0) {
554: half >>= 1;
555: ++bitnum;
556: }
557: return (bitnum);
558: }
559: }
560: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.