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