|
|
1.1 root 1: /* C compiler: dag processing */
2:
3: #include "c.h"
4: #define NBUCKETS 020
5:
6: struct code codehead = { Start };
7: Code codelist = &codehead; /* list of code nodes for current function */
8: int nodecount; /* # of available nodes in hash table */
9:
10: static struct dag { /* dags: */
11: struct node node; /* the node itself */
12: struct dag *hlink; /* next dag on hash chain */
13: } *buckets[NBUCKETS]; /* hash table */
14: static Node nodelist; /* node list */
15: dclproto(static struct dag *dagnode,(int, Node, Node, Symbol));
16: dclproto(static void fixup,(Node));
17: dclproto(static int haskid,(Node, Node));
18: dclproto(static Node labelnode,(int));
19: dclproto(static Node list,(Node));
20: dclproto(static void reset,(void));
21: dclproto(static void remove,(Node));
22: dclproto(static void trash,(Node));
23: dclproto(static void typestab,(Symbol, Generic));
24: dclproto(static Node undag,(Node));
25: dclproto(static Node undag1,(Node, Node));
26:
27: /* addlocal - add local p to list of locals for the current block */
28: void addlocal(p) Symbol p; {
29: if (!p->defined) {
30: code(Local)->u.var = p;
31: p->defined = 1;
32: p->scope = level;
33: }
34: }
35:
36: /* btot - map operator op or suffix op into a representative type */
37: Type btot(op) int op; {
38: switch (optype(op)) {
39: case F: return floattype;
40: case D: return doubletype;
41: case C: return chartype;
42: case S: return shorttype;
43: case I: return inttype;
44: case U: return unsignedtype;
45: case P: return voidptype;
46: default: assert(0);
47: }
48: return 0;
49: }
50:
51: /* code - allocate a code node of kind and append to the code list */
52: Code code(kind) {
53: Code cp;
54:
55: if (kind > Label) {
56: for (cp = codelist; cp->kind < Label; )
57: cp = cp->prev;
58: if (cp->kind == Jump)
59: warning("unreachable code\n");
60: }
61: cp = (Code)talloc(sizeof *cp);
62: cp->kind = kind;
63: cp->prev = codelist;
64: cp->next = 0;
65: codelist->next = cp;
66: return codelist = cp;
67: }
68:
69: /* dagnode - allocate a dag with the given fields */
70: static struct dag *dagnode(op, l, r, sym) Node l, r; Symbol sym; {
71: register struct dag *p = (struct dag *) talloc(sizeof *p);
72:
73: BZERO(p, struct dag);
74: p->node.op = op;
75: if (p->node.kids[0] = l)
76: ++l->count;
77: if (p->node.kids[1] = r)
78: ++r->count;
79: p->node.syms[0] = sym;
80: return p;
81: }
82:
83: /* emitcode - emit code for the current function */
84: void emitcode() {
85: Code bp, cp;
86: Coordinate save;
87:
88: save = src;
89: for (bp = 0, cp = &codehead; errcnt <= 0 && cp; cp = cp->next)
90: switch (cp->kind) {
91: case Blockbeg:
92: cp->u.block.prev = bp;
93: bp = cp;
94: if (glevel && IR->stabblock) {
95: (*IR->stabblock)('{', bp->u.block.level - LOCAL, bp->u.block.locals);
96: swtoseg(CODE);
97: }
98: break;
99: case Blockend:
100: if (glevel && IR->stabblock) {
101: foreach(bp->u.block.identifiers, bp->u.block.level, typestab, (Generic)0);
102: foreach(bp->u.block.types, bp->u.block.level, typestab, (Generic)0);
103: (*IR->stabblock)('}', bp->u.block.level - LOCAL, bp->u.block.locals);
104: swtoseg(CODE);
105: }
106: bp = bp->u.block.prev;
107: break;
108: case Local:
109: if (glevel && IR->stabsym) {
110: (*IR->stabsym)(cp->u.var);
111: swtoseg(CODE);
112: }
113: break;
114: case Defpoint:
115: src = cp->u.point.src;
116: if (glevel && IR->stabline) {
117: (*IR->stabline)(&cp->u.point.src);
118: swtoseg(CODE);
119: }
120: break;
121: case Jump:
122: if (cp->u.node == 0)
123: break;
124: /* else fall thru */
125: case Gen: case Label:
126: (*IR->emit)(cp->u.node);
127: break;
128: case Switch: {
129: int i, k = cp->u.swtch.values[0];
130: for (i = 0; i < cp->u.swtch.size; i++) {
131: while (k++ < cp->u.swtch.values[i])
132: (*IR->defaddress)(cp->u.swtch.deflab->u.l.equatedto);
133: (*IR->defaddress)(cp->u.swtch.labels[i]->u.l.equatedto);
134: }
135: break;
136: }
137: }
138: src = save;
139: }
140:
141: /* fixup - re-aim equated labels to the true label */
142: static void fixup(p) Node p; {
143: for ( ; p; p = p->link)
144: switch (generic(p->op)) {
145: case JUMP:
146: if (p->kids[0]->op == ADDRG+P)
147: p->kids[0]->syms[0] = p->kids[0]->syms[0]->u.l.equatedto;
148: break;
149: case LABEL:
150: case EQ: case GE: case GT: case LE: case LT: case NE:
151: assert(p->syms[0]);
152: p->syms[0] = p->syms[0]->u.l.equatedto;
153: }
154: }
155:
156: /* gencode - generate code for the current function */
157: void gencode(caller, callee) Symbol caller[], callee[]; {
158: int i;
159: Code bp, cp;
160: Symbol p, q;
161: Coordinate save;
162:
163: save = src;
164: cp = codehead.next->next;
165: codelist = codehead.next;
166: for (i = 0; (p = callee[i]) && (q = caller[i]); i++)
167: if (p->sclass != q->sclass || p->type != q->type) {
168: walk(asgn(p, idnode(q)), 0, 0);
169: if (glevel && IR->stabsym) {
170: (*IR->stabsym)(p);
171: (*IR->stabsym)(q);
172: swtoseg(CODE);
173: }
174: } else if (glevel && IR->stabsym) {
175: (*IR->stabsym)(p);
176: swtoseg(CODE);
177: }
178: codelist->next = cp;
179: cp->prev = codelist;
180: for (bp = 0, cp = &codehead; errcnt <= 0 && cp; cp = cp->next)
181: switch (cp->kind) {
182: case Start: case Switch:
183: break;
184: case Defpoint:
185: src = cp->u.point.src;
186: break;
187: case Blockbeg: {
188: Symbol *p = cp->u.block.locals;
189: cp->u.block.prev = bp;
190: bp = cp;
191: (*IR->blockbeg)(&bp->u.block.x);
192: for ( ; *p; p++)
193: if ((*p)->ref || glevel)
194: (*IR->local)(*p);
195: break;
196: }
197: case Blockend:
198: (*IR->blockend)(&bp->u.block.x);
199: bp = bp->u.block.prev;
200: break;
201: case Local:
202: assert(cp->u.var->scope == bp->u.block.level);
203: (*IR->local)(cp->u.var);
204: break;
205: case Address:
206: (*IR->address)(cp->u.addr.sym, cp->u.addr.base, cp->u.addr.offset);
207: break;
208: case Jump:
209: if (cp->u.node == 0)
210: break;
211: /* else fall thru */
212: case Gen: case Label:
213: fixup(cp->u.node);
214: if (IR->no_dag)
215: cp->u.node = undag(cp->u.node);
216: cp->u.node = (*IR->gen)(cp->u.node);
217: break;
218: default:assert(0);
219: }
220: src = save;
221: }
222:
223: /* haskid - does p appear as an operand in t? */
224: static int haskid(p, t) Node p, t; {
225: if (t == 0)
226: return 0;
227: else if (p == t)
228: return 1;
229: else
230: return haskid(p, t->kids[0]) || haskid(p, t->kids[1]);
231: }
232:
233: /* labelnode - list and return a LABEL node for label lab */
234: static Node labelnode(lab) {
235: assert(lab);
236: if (islabel(nodelist)) {
237: equatelab(findlabel(lab), nodelist->syms[0]);
238: return nodelist;
239: }
240: return list(newnode(LABEL+V, 0, 0, findlabel(lab)));
241: }
242:
243: /* list - list node p unless it's already listed; return p */
244: static Node list(p) Node p; {
245: if (p && p->link == 0) {
246: if (nodelist) {
247: p->link = nodelist->link;
248: nodelist->link = p;
249: } else
250: p->link = p;
251: nodelist = p;
252: #ifdef DAGCHECK
253: { extern void type_checker(Node); type_checker(p); }
254: #endif
255: }
256: return p;
257: }
258:
259: /* listnodes - walk tree tp, building and listing dag nodes in execution order */
260: Node listnodes(tp, tlab, flab) Tree tp; {
261: Opcode op;
262: Node p, l, r;
263:
264: if (tp == 0)
265: return 0;
266: if (tp->node)
267: return tp->node;
268: op = generic(tp->op);
269: switch (op) {
270: case AND:
271: if (flab) {
272: listnodes(tp->kids[0], 0, flab);
273: r = listnodes(tp->kids[1], 0, flab);
274: } else {
275: listnodes(tp->kids[0], 0, flab = genlabel(1));
276: listnodes(tp->kids[1], tlab, 0);
277: r = labelnode(flab);
278: }
279: trash(0);
280: return r;
281: case NOT:
282: return listnodes(tp->kids[0], flab, tlab);
283: case OR:
284: if (tlab) {
285: listnodes(tp->kids[0], tlab, 0);
286: r = listnodes(tp->kids[1], tlab, 0);
287: } else {
288: listnodes(tp->kids[0], tlab = genlabel(1), 0);
289: listnodes(tp->kids[1], 0, flab);
290: r = labelnode(tlab);
291: }
292: trash(0);
293: return r;
294: case COND: {
295: Tree q;
296: assert(tlab == 0 && flab == 0);
297: if (tp->u.sym)
298: addlocal(tp->u.sym);
299: trash(0);
300: listnodes(tp->kids[0], 0, flab = genlabel(2));
301: trash(0);
302: if (q = tp->kids[1]) {
303: assert(q->op == RIGHT);
304: listnodes(q->kids[0], 0, 0);
305: if (islabel(nodelist)) {
306: equatelab(nodelist->syms[0], findlabel(flab + 1));
307: remove(nodelist);
308: }
309: trash(0);
310: }
311: if (q && q->kids[1]) {
312: list(jump(flab + 1));
313: labelnode(flab);
314: listnodes(q->kids[1], 0, 0);
315: if (islabel(nodelist)) {
316: equatelab(nodelist->syms[0], findlabel(flab + 1));
317: remove(nodelist);
318: }
319: } else
320: labelnode(flab);
321: p = labelnode(flab + 1);
322: trash(0);
323: if (tp->u.sym) {
324: Tree t = idnode(tp->u.sym);
325: tp->u.sym->ref = 0; /* undo idnode's setting ref */
326: p = listnodes(t, 0, 0);
327: }
328: break;
329: }
330: case CNST: {
331: Type ty = unqual(tp->type);
332: assert(op == CNST+S || ty->u.sym);
333: if (op == CNST+S || ty->u.sym->addressed)
334: p = listnodes(cvtconst(tp), tlab, flab);
335: else if (tlab == 0 && flab == 0)
336: p = node(tp->op, 0, 0, constant(ty, tp->u.v));
337: else {
338: assert(ty == inttype);
339: if (tlab && tp->u.v.i != 0)
340: p = list(jump(tlab));
341: else if (flab && tp->u.v.i == 0)
342: p = list(jump(flab));
343: else
344: p = 0;
345: }
346: break;
347: }
348: case RIGHT:
349: if (tp->kids[0] && generic(tp->kids[0]->op) == INDIR
350: && tp->kids[1] && generic(tp->kids[1]->op) == ASGN
351: && tp->kids[0]->kids[0] == tp->kids[1]->kids[0]) { /* e++ */
352: p = listnodes(tp->kids[0], 0, 0);
353: if (nodelist) {
354: Node t;
355: for (t = nodelist; ; t = t->link)
356: if (haskid(p, t->link)) {
357: p->link = t->link;
358: t->link = p;
359: break;
360: } else if (t->link == nodelist) {
361: list(p);
362: break;
363: }
364: } else
365: list(p);
366: listnodes(tp->kids[1], 0, 0);
367: } else if (tp->kids[1]) {
368: if (tp->kids[0] && generic(tp->kids[0]->op) == CNST)
369: tp->kids[0] = 0;
370: listnodes(tp->kids[0], 0, 0);
371: p = listnodes(tp->kids[1], tlab, flab);
372: } else
373: p = listnodes(tp->kids[0], tlab, flab);
374: break;
375: case JUMP:
376: assert(tlab == 0 && flab == 0);
377: assert(tp->u.sym == 0);
378: assert(tp->kids[0]);
379: l = listnodes(tp->kids[0], 0, 0);
380: p = newnode(JUMP+V, l, 0, 0);
381: trash(0);
382: list(p);
383: break;
384: case CALL:
385: assert(tlab == 0 && flab == 0);
386: l = listnodes(tp->kids[0], 0, 0); /* arguments, function name */
387: r = listnodes(tp->kids[1], 0, 0);
388: p = newnode(tp->op, l, r, 0);
389: p->syms[0] = (Symbol)talloc(sizeof *p->syms[0]);
390: BZERO(p->syms[0], struct symbol);
391: if (isptr(tp->kids[0]->type) && isfunc(tp->kids[0]->type->type))
392: p->syms[0]->type = tp->kids[0]->type->type;
393: else
394: p->syms[0]->type = func(voidtype, 0, 1);
395: trash(0);
396: list(p);
397: cfunc->u.f.ncalls++;
398: break;
399: case ARG:
400: assert(tlab == 0 && flab == 0);
401: if (IR->left_to_right)
402: listnodes(tp->kids[1], 0, 0);
403: l = listnodes(tp->kids[0], 0, 0);
404: p = newnode(tp->op, l, 0, 0);
405: p->syms[0] = intconst(tp->type->size);
406: p->syms[1] = intconst(tp->type->align);
407: list(p);
408: if (!IR->left_to_right)
409: listnodes(tp->kids[1], 0, 0);
410: return 0;
411: case EQ: case NE: case GT: case GE: case LE: case LT: {
412: int lab;
413: assert(tp->u.sym == 0);
414: assert(errcnt || tlab || flab);
415: if (lab = flab) {
416: assert(tlab == 0);
417: switch (op) {
418: case EQ: op = NE + optype(tp->op); break;
419: case NE: op = EQ + optype(tp->op); break;
420: case GT: op = LE + optype(tp->op); break;
421: case LT: op = GE + optype(tp->op); break;
422: case GE: op = LT + optype(tp->op); break;
423: case LE: op = GT + optype(tp->op); break;
424: }
425: } else if (lab = tlab)
426: op = tp->op;
427: l = listnodes(tp->kids[0], 0, 0);
428: r = listnodes(tp->kids[1], 0, 0);
429: p = newnode(op, l, r, findlabel(lab));
430: p->syms[0]->ref++;
431: list(p);
432: break;
433: }
434: case ASGN:
435: assert(tlab == 0 && flab == 0);
436: if (tp->kids[0]->op == FIELD) {
437: Tree x = tp->kids[0]->kids[0];
438: Field p = tp->kids[0]->u.field;
439: assert(generic(x->op) == INDIR);
440: trash(0);
441: l = listnodes(lvalue(x), 0, 0);
442: if (fieldsize(p) < 8*p->type->size) {
443: unsigned int fmask = fieldmask(p);
444: unsigned int mask = fmask<<fieldright(p);
445: Tree q = tp->kids[1];
446: if (q->op == CNST+I && q->u.v.i == 0
447: || q->op == CNST+U && q->u.v.u == 0)
448: q = bitnode(BAND, x, constnode(~mask, unsignedtype));
449: else if (q->op == CNST+I && (q->u.v.i&fmask) == fmask
450: || q->op == CNST+U && (q->u.v.u&fmask) == fmask)
451: q = bitnode(BOR, x, constnode(mask, unsignedtype));
452: else
453: q = bitnode(BOR,
454: bitnode(BAND, x, constnode(~mask, unsignedtype)),
455: bitnode(BAND, shnode(LSH, cast(q, unsignedtype),
456: constnode(fieldright(p), inttype)),
457: constnode(mask, unsignedtype)));
458: r = listnodes(q, 0, 0);
459: } else
460: r = listnodes(tp->kids[1], 0, 0);
461: } else {
462: l = listnodes(tp->kids[0], 0, 0);
463: r = listnodes(tp->kids[1], 0, 0);
464: }
465: trash(isaddrop(tp->kids[0]->op) && !tp->kids[0]->u.sym->computed ? l : 0);
466: p = newnode(tp->op, l, r, 0);
467: p->syms[0] = intconst(tp->kids[1]->type->size);
468: p->syms[1] = intconst(tp->kids[1]->type->align);
469: list(p);
470: p = listnodes(tp->kids[1], 0, 0);
471: break;
472: case BAND:
473: assert(tlab == 0 && flab == 0);
474: l = listnodes(tp->kids[0], 0, 0);
475: if (IR->compl_band)
476: r = listnodes(cast(
477: simplify(BCOM+U, unsignedtype,
478: cast(tp->kids[1], unsignedtype), 0),
479: tp->kids[1]->type), 0, 0);
480: else
481: r = listnodes(tp->kids[1], 0, 0);
482: p = node(tp->op, l, r, 0);
483: break;
484: case RSH:
485: assert(tlab == 0 && flab == 0);
486: l = listnodes(tp->kids[0], 0, 0);
487: if (IR->compl_band && tp->op == RSH+I)
488: r = listnodes(simplify(NEG+I, inttype, tp->kids[1], 0), 0, 0);
489: else
490: r = listnodes(tp->kids[1], 0, 0);
491: p = node(tp->op, l, r, 0);
492: break;
493: case ADD: case SUB: case DIV: case MUL: case MOD:
494: case BOR: case BXOR: case LSH:
495: assert(tlab == 0 && flab == 0);
496: l = listnodes(tp->kids[0], 0, 0);
497: r = listnodes(tp->kids[1], 0, 0);
498: p = node(tp->op, l, r, 0);
499: if (IR->mulops_are_calls &&
500: (p->op == DIV+I || p->op == MOD+I || p->op == MUL+I
501: || p->op == DIV+U || p->op == MOD+U || p->op == MUL+U))
502: list(p);
503: break;
504: case RET:
505: assert(tlab == 0 && flab == 0);
506: l = listnodes(tp->kids[0], 0, 0);
507: p = newnode(tp->op, l, 0, 0);
508: list(p);
509: break;
510: case CVC: case CVD: case CVF: case CVI:
511: case CVP: case CVS: case CVU: case NEG: case BCOM:
512: assert(tlab == 0 && flab == 0);
513: l = listnodes(tp->kids[0], 0, 0);
514: p = node(tp->op, l, 0, 0);
515: break;
516: case INDIR: {
517: Type ty = tp->kids[0]->type;
518: if (isptr(ty))
519: ty = unqual(ty)->type;
520: assert(tlab == 0 && flab == 0);
521: l = listnodes(tp->kids[0], 0, 0);
522: if (isvolatile(ty) || (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields))
523: p = newnode(tp->op, l, 0, 0);
524: else
525: p = node(tp->op, l, 0, 0);
526: break;
527: }
528: case FIELD: {
529: Tree q;
530: assert(tlab == 0 && flab == 0);
531: q = shnode(RSH,
532: shnode(LSH, tp->kids[0],
533: constnode(fieldleft(tp->u.field), inttype)),
534: constnode(8*tp->type->size - fieldsize(tp->u.field), inttype));
535: p = listnodes(q, 0, 0);
536: break;
537: }
538: case ADDRL:
539: assert(tlab == 0 && flab == 0);
540: if (tp->u.sym->temporary) {
541: addlocal(tp->u.sym);
542: release(tp->u.sym);
543: }
544: p = node(tp->op, 0, 0, tp->u.sym);
545: break;
546: case ADDRG: case ADDRF:
547: assert(tlab == 0 && flab == 0);
548: if (tp->u.sym->scope == LABELS)
549: tp->u.sym->ref++;
550: p = node(tp->op, 0, 0, tp->u.sym);
551: break;
552: default:assert(0);
553: }
554: return tp->node = p;
555: }
556:
557: /* jump - return tree for a jump to lab */
558: Node jump(lab) {
559: Symbol p = findlabel(lab);
560:
561: p->ref++;
562: return newnode(JUMP+V, node(ADDRG+P, 0, 0, p), 0, 0);
563: }
564:
565: /* newnode - allocate a node with the given fields */
566: Node newnode(op, l, r, sym) Node l, r; Symbol sym; {
567: return &dagnode(op, l, r, sym)->node;
568: }
569:
570: /* node - search for a node with the given fields, or allocate it */
571: Node node(op, l, r, sym) Node l, r; Symbol sym; {
572: int i = (opindex(op)^((unsigned)sym>>2))&(NBUCKETS-1);
573: register struct dag *p;
574:
575: for (p = buckets[i]; p; p = p->hlink)
576: if (p->node.op == op && p->node.syms[0] == sym
577: && p->node.kids[0] == l && p->node.kids[1] == r)
578: return &p->node;
579: p = dagnode(op, l, r, sym);
580: p->hlink = buckets[i];
581: buckets[i] = p;
582: ++nodecount;
583: return &p->node;
584: }
585:
586: dclproto(static void printdag1,(Node, int, int));
587: dclproto(static void printnode,(Node, int, int));
588:
589: /* printdag - print dag p on fd, or the node list if p == 0 */
590: void printdag(p, fd) Node p; {
591: printed(0);
592: if (p == 0) {
593: if (p = nodelist)
594: do {
595: p = p->link;
596: printdag1(p, fd, 0);
597: } while (p != nodelist);
598: } else if (*printed(nodeid((Tree)p)))
599: fprint(fd, "node'%d printed above\n", nodeid((Tree)p));
600: else
601: printdag1(p, fd, 0);
602: }
603:
604: /* printdag1 - recursively print dag p */
605: static void printdag1(p, fd, lev) Node p; {
606: int id, i;
607:
608: if (p == 0 || *printed(id = nodeid((Tree)p)))
609: return;
610: *printed(id) = 1;
611: for (i = 0; i < MAXKIDS; i++)
612: printdag1(p->kids[i], fd, lev + 1);
613: printnode(p, fd, lev);
614: }
615:
616: /* printnode - print fields of dag p */
617: static void printnode(p, fd, lev) Node p; {
618: if (p) {
619: int i, id = nodeid((Tree)p);
620: fprint(fd, "%c%d%s", lev == 0 ? '\'' : '#', id,
621: &" "[id < 10 ? 0 : id < 100 ? 1 : 2]);
622: fprint(fd, "%s count=%d", opname(p->op), p->count);
623: for (i = 0; i < MAXKIDS && p->kids[i]; i++)
624: fprint(fd, " #%d", nodeid((Tree)p->kids[i]));
625: for (i = 0; i < MAXSYMS && p->syms[i]; i++)
626: fprint(fd, " %s", p->syms[i]->name);
627: fprint(fd, "\n");
628: }
629: }
630:
631: /* remove - remove node p from the node list */
632: static void remove(p) Node p; {
633: if (nodelist) {
634: Node q = nodelist;
635: for ( ; q->link != p && q->link != nodelist; q = q->link)
636: ;
637: assert(q->link == p);
638: q->link = p->link;
639: if (p == nodelist)
640: nodelist = q;
641: }
642: }
643:
644: /* reset - clear the dag */
645: static void reset() {
646: BZERO(buckets, struct dag *[NBUCKETS]);
647: nodecount = 0;
648: }
649:
650: /* trash - preclude future links to rvalue of p or all values */
651: static void trash(p) Node p; {
652: if (p) {
653: register int i;
654: register struct dag *q, **r;
655: for (i = 0; i < NBUCKETS; i++)
656: for (r = &buckets[i]; q = *r; )
657: if (generic(q->node.op) == INDIR && (!isaddrop(q->node.kids[0]->op)
658: || q->node.kids[0]->syms[0] == p->syms[0])) {
659: *r = q->hlink;
660: --nodecount;
661: } else
662: r = &q->hlink;
663: } else if (nodecount > 0)
664: reset();
665: }
666:
667: /* typestab - emit stab entries for p */
668: static void typestab(p, cl) Symbol p; Generic cl; {
669: if (!isfunc(p->type) && (p->sclass == EXTERN || p->sclass == STATIC) && IR->stabsym)
670: (*IR->stabsym)(p);
671: else if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
672: (*IR->stabtype)(p);
673: }
674:
675: #define iscall(p) (generic((p)->op) == CALL || IR->mulops_are_calls \
676: && ((p)->op == DIV+I || (p)->op == MOD+I || (p)->op == MUL+I \
677: || (p)->op == DIV+U || (p)->op == MOD+U || (p)->op == MUL+U))
678:
679: /* undag - replace multiply-referenced nodes in nodelist by temporaries, return new nodelist */
680: static Node undag(nodelist) Node nodelist; {
681: Node p, pred;
682: struct node head;
683:
684: head.link = nodelist;
685: for (pred = &head; p = pred->link; ) {
686: /*
687: * succ is p's successor,
688: * pred is p's predecessor, and
689: * p->link == pred;
690: * undag1(x, p) adds predecessors and maintains p->link == p->link->link.
691: */
692: Node succ = p->link;
693: p->link = pred;
694: if (generic(p->op) == INDIR) {
695: assert(p->count >= 1);
696: undag1(p, p);
697: /*
698: * remove p from the node list,
699: * setting pred to the last node inserted (if any).
700: */
701: pred = p->link;
702: pred->link = succ;
703: p->link = 0;
704: } else if (iscall(p) && p->count >= 1) {
705: Node q;
706: undag1(p, p);
707: /*
708: * p->link is p's predecessor,
709: * which is the ASGN of p to a temporary.
710: */
711: assert(p->link && generic(p->link->op) == ASGN && p->link->kids[1] == p);
712: /*
713: * remove p from the node list,
714: * setting pred to the ASGN node.
715: */
716: pred = p->link;
717: pred->link = succ;
718: /*
719: * re-insert p into the node list
720: * immediately before its predecessor;
721: * this places the CALL node before the ASGN node.
722: * /
723: for (q = &head; q && q->link != pred; q = q->link)
724: ;
725: assert(q);
726: q->link = p;
727: p->link = pred; */
728: p->link = 0;
729: } else {
730: assert(p->count == 0);
731: undag1(p, p);
732: /*
733: * reestablish p's successor, and
734: * advance pred so that pred->link == succ
735: */
736: p->link = succ;
737: pred = p;
738: }
739: }
740: rmtemps(0, LOCAL);
741: return head.link;
742: }
743:
744: /* undag1 - return a reference to the temporary holding value of p, or p */
745: static Node undag1(p, root) Node p, root; {
746: Node e;
747:
748: if (p == 0)
749: ;
750: else if (p->syms[2]) {
751: e = newnode(INDIR + (isunsigned(p->syms[2]->type) ? I : ttob(p->syms[2]->type)),
752: newnode(ADDRL+P, 0, 0, p->syms[2]), 0, 0);
753: e->count = 1;
754: if (--p->count == 1) {
755: /* fprint(2, "releasing %s from ", p->syms[2]->name); printnode(p, 2, 1);
756: release(p->syms[2]); */
757: p->syms[2] = 0;
758: }
759: p = e;
760: } else if (p->count <= 1 && !iscall(p)
761: || p->count == 0 && iscall(p)) {
762: p->kids[0] = undag1(p->kids[0], root);
763: p->kids[1] = undag1(p->kids[1], root);
764: } else if (p->op == ADDRL+P || p->op == ADDRF+P) {
765: assert(p != root);
766: p = newnode(p->op, 0, 0, p->syms[0]);
767: p->count = 1;
768: } else if (generic(p->op) == INDIR
769: && (p->kids[0]->op == ADDRL+P || p->kids[0]->op == ADDRF+P)
770: && p->kids[0]->syms[0]->sclass == REGISTER && p != root) {
771: p = newnode(p->op,
772: newnode(p->kids[0]->op, 0, 0, p->kids[0]->syms[0]), 0, 0);
773: p->count = 1;
774: } else if (p->op == INDIR+B) {
775: --p->count;
776: p = newnode(p->op, p->kids[0], 0, 0);
777: p->count = 1;
778: p->kids[0] = undag1(p->kids[0], root);
779: } else {
780: p->syms[2] = temporary(REGISTER, btot(p->op));
781: /* fprint(2, "allocating %s to ", p->syms[2]->name); printnode(p, 2, 1); */
782: if (!p->syms[2]->defined) {
783: p->syms[2]->scope = LOCAL;
784: p->syms[2]->ref = 1;
785: (*IR->local)(p->syms[2]);
786: p->syms[2]->defined = 1;
787: }
788: p->kids[0] = undag1(p->kids[0], root);
789: p->kids[1] = undag1(p->kids[1], root);
790: e = newnode(ASGN + (isunsigned(p->syms[2]->type) ? I : ttob(p->syms[2]->type)),
791: newnode(ADDRL+P, 0, 0, p->syms[2]), p, 0);
792: e->syms[0] = intconst(p->syms[2]->type->size);
793: e->syms[1] = intconst(p->syms[2]->type->align);
794: /*
795: * root->link is the root's predecessor;
796: * point the root's predecessor to the ASGN,
797: * make the ASGN the root's new predecessor,
798: * and make root the ASGN's successor.
799: */
800: root->link = root->link->link = e;
801: e->link = root;
802: if (p != root)
803: p = undag1(p, root); /* returns reference to the temporary */
804: }
805: return p;
806: }
807:
808: /* walk - list tree tp, generate code for current node list, reset node list */
809: void walk(tp, tlab, flab) Tree tp; {
810: listnodes(tp, tlab, flab);
811: if (nodelist) {
812: trash(0);
813: code(Gen);
814: codelist->u.node = nodelist->link;
815: nodelist->link = 0;
816: nodelist = 0;
817: rmtemps(REGISTER, 0);
818: }
819: reset();
820: ntree = 0;
821: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.