|
|
1.1 root 1: /* C compiler: machine-independent back-end support routines */
2:
3: #include "c.h"
4:
5: unsigned freemask[3];
6: int savebase[3];
7: unsigned savemask[3];
8: unsigned tempmask[3];
9: unsigned usedmask[3];
10: unsigned eemask[3];
11: unsigned tmask[3];
12: unsigned vmask[3];
13:
14: char **asmstr[MAXINTS];
15: int nregsets;
16: Node last;
17: int maxoffset;
18: int ncalls;
19: int offset;
20: int argoffset;
21: int argbuildsize;
22: int bflag, dflag, kflag, pflag, rflag;
23: char **opcodes;
24: Symbol regs;
25: Symbol regvars;
26: Symbol rmap[8];
27: int dalign, salign;
28: int genx = 2;
29:
30: static int cseg;
31: static Node curhead;
32:
33: dclproto(static Node *findxnext,(Node));
34: dclproto(static void freereg,(Symbol));
35: dclproto(static void genreload,(Node*, Symbol, int, Symbol));
36: dclproto(static void genreloads,(Node, Symbol, int, Symbol));
37: dclproto(static Symbol genspill,(Symbol, int, Node *));
38: dclproto(static Symbol getreg,(Symbol, Node, unsigned, int));
39: dclproto(static void linearize,(Node, Node *, Node));
40: dclproto(static Node *lin1,(Node, Node *));
41: dclproto(static Symbol mkreg,(char *, int, int, int, int, Symbol));
42: dclproto(static void mvregvar,(Symbol, unsigned));
43: dclproto(static int ntob,(Symbol));
44: dclproto(static int overlaps,(Symbol, Symbol));
45: dclproto(static void ralloc,(Node));
46: dclproto(static int rmember,(Regnode, Symbol));
47: dclproto(static Symbol spillee,(Symbol, Node, unsigned));
48: dclproto(static void spillr,(Symbol, Node));
49: dclproto(static int uses,(Node, Symbol));
50:
51: /* aset - record that p and any right ADD+P descendants are address calculations */
52: int aset(p, n) Node p; {
53: p = p->kids[n];
54: p->x.loadaddr = 1;
55: while (p->op == ADD+P) {
56: p = p->kids[1];
57: p->x.loadaddr = 1;
58: }
59: return 1;
60: }
61:
62: /* bitcount - count number of 1 bits in mask */
63: int bitcount(mask) unsigned mask; {
64: unsigned i, n = 0;
65:
66: for (i = 1; i; i <<= 1)
67: if (mask&i)
68: n++;
69: return n;
70: }
71:
72: /* blkcopy - emit code to copy size bytes from sreg+soff to dreg+doff using tmp regs */
73: void blkcopy(dreg, doff, sreg, soff, size, tmp) int tmp[]; {
74: if (size <= 0)
75: return;
76: else if (size <= 1) {
77: blkunroll(1, dreg, doff, sreg, soff, size, tmp);
78: } else if (size <= 3) {
79: blkunroll(2, dreg, doff, sreg, soff, 2, tmp);
80: blkcopy(dreg, doff+(size&~(2-1)), sreg, soff+(size&~(2-1)), size&(2-1), tmp);
81: } else if (size <= 16) {
82: blkunroll(4, dreg, doff, sreg, soff, size&~(4-1), tmp);
83: blkcopy(dreg, doff+(size&~(4-1)), sreg, soff+(size&~(4-1)), size&(4-1), tmp);
84: } else
85: (*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
86: }
87:
88: /* blkunroll - blkcopy as an unrolled loop using k-byte chunks */
89: void blkunroll(k, dreg, doff, sreg, soff, size, tmp) int tmp[]; {
90: int i;
91:
92: assert(IR->x.maxunalignedload);
93: if ((salign < k || dalign < k) && k > IR->x.maxunalignedload)
94: k = IR->x.maxunalignedload;
95: (*IR->x.blkfetch)(k, soff, sreg, tmp[0]);
96: for (i = k; i <= size - k; i += k) {
97: (*IR->x.blkfetch)(k, i+soff, sreg, tmp[(i&k)==k]);
98: (*IR->x.blkstore)(k, i+doff-k, dreg, tmp[(i&k)!=k]);
99: }
100: (*IR->x.blkstore)(k, i+doff-k, dreg, tmp[((i-k)&k)==k]);
101: }
102:
103: /* blockbeg - begin a compound statement */
104: void blockbeg(e) Env *e; {
105: int i;
106:
107: e->off = offset;
108: for (i = 0; i < nregsets; i++)
109: e->freemask[i] = freemask[i];
110: }
111:
112: /* blockend - end a compound statement */
113: void blockend(e) Env *e; {
114: int i;
115:
116: if (offset > maxoffset)
117: maxoffset = offset;
118: offset = e->off;
119: for (i = 0; i < nregsets; i++)
120: freemask[i] = e->freemask[i];
121: }
122:
123: /* docall - finalize a call */
124: void docall(p) Node p; {
125: if (argoffset > argbuildsize)
126: argbuildsize = argoffset;
127: p->syms[0] = intconst(argoffset);
128: argoffset = 0;
129: }
130:
131: /* dumpregs - trace register allocation */
132: void dumpregs(msg, a, b) char *a, *b, *msg; {
133: int i;
134:
135: fprint(2, msg, a, b);
136: for (i = 0; i < nregsets; i++)
137: fprint(2, "(free[%d]=%x)\n", i, freemask[i]);
138: }
139:
140: /* dumptree1 - emit debugging image of dag p, indented n, with kid# k */
141: void dumptree1(p, op, k, n) Node p; {
142: int i;
143: char *s;
144: extern char **opcodes;
145:
146: if (dflag == 0 || p == 0)
147: return;
148: for (i = 0; i < n; i++)
149: fprint(2, " ");
150: if (k < 0)
151: fprint(2, "(root=%x ", p);
152: else
153: fprint(2, "(kid%d=%x ", k, p);
154: s = opname(op);
155: if (*s >= '0' && *s <= '9')
156: s = opcodes[op];
157: fprint(2, "op=%s ", s);
158: for (i = 0; i < MAXINTS; i++)
159: if (p->x.ints[i])
160: fprint(2, "I%d=%s ", i, asmstr[i][p->x.ints[i]]);
161: for (i = 0; i < MAXSYMS; i++)
162: if (p->syms[i])
163: fprint(2, "S%d=%s ", i, p->syms[i]->x.name);
164: fprint(2, "count=%d)\n", p->count);
165: if (p->x.registered == 0)
166: for (i = 0; i < MAXKIDS; i++)
167: if (p->kids[i])
168: dumptree1(p->kids[i], p->kids[i]->op, i, n+1);
169: if (k == -1)
170: fprint(2, "\n");
171: }
172:
173: void export(p) Symbol p; {
174: if (!bflag)
175: print(IR->x.exportfmt, p->x.name);
176: }
177:
178: /* findxnext - return the address of the pointer to p in the linearized chain */
179: static Node *findxnext(p) Node p; {
180: Node *q;
181:
182: for (q = &curhead; *q; q = &(*q)->x.next)
183: if (*q == p)
184: return q;
185: assert(0);
186: return 0;
187: }
188:
189: /* freereg - free register p */
190: static void freereg(p) Symbol p; {
191: assert(p->x.regnode);
192: p->x.regnode->count = 0;
193: freemask[p->x.regnode->regset] |= p->x.regnode->mask;
194: debug(rflag, dumpregs("(freeing %s)\n", p->x.name, 0));
195: }
196:
197: /* freeregvars - free register variables */
198: void freeregvars() {
199: Symbol p;
200:
201: for (p = regvars; p; p = p->x.nextregvar) {
202: Regnode r = p->x.regvar->x.regnode;
203: usedmask[r->regset] |= r->mask;
204: freereg(p->x.regvar);
205: }
206: }
207:
208: /* gen - drive nodelist from front end through all back-end phases */
209: Node gen(nodelist) Node nodelist; {
210: int i;
211: Node p, q = 0;
212:
213: curhead = nodelist;
214: last = 0;
215: for (p = nodelist; p; p = p->link) {
216: switch (generic(p->op)) {
217: case CALL:
218: p->x.sideeffect = 1;
219: p->x.iscall = 1;
220: p->x.args = q;
221: q = 0;
222: (*IR->x.docall)(p);
223: break;
224: case ARG:
225: p->x.isarg = 1;
226: p->x.args = q;
227: q = p;
228: (*IR->x.doarg)(p);
229: /* fall through */
230: case ASGN: case JUMP: case LABEL: case RET:
231: case EQ: case GE: case GT: case LE: case LT: case NE:
232: assert(p->count == 0);
233: p->x.sideeffect = 1;
234: break;
235: case INDIR:
236: p->x.unavailable = 1;
237: assert(p->count);
238: break;
239: case DIV: case MOD: case MUL:
240: if (IR->mulops_are_calls && (optype(p->op) == I || optype(p->op) == U))
241: break;
242: /* else fall through */
243: default:
244: assert(0);
245: }
246: (*IR->x.rewrite)(p);
247: last = p;
248: debug(dflag, fprint(2, "(last=%x)\n", last));
249: }
250: last = 0;
251: linearize(curhead, &curhead, 0);
252: for (p = curhead; p; p = p->x.next) {
253: assert(p->x.sideeffect || p->count);
254: if (p->x.registered == 0) {
255: if (p->x.iscall)
256: for (q = p->x.args; q; q = q->x.args)
257: if (q->syms[RX] && q->syms[RX]->x.regnode)
258: freereg(q->syms[RX]);
259: ralloc(p);
260: if (p->x.isarg && p->syms[RX] && p->syms[RX]->x.regnode)
261: p->syms[RX]->x.regnode->count = -1;
262: else if (p->x.listed && p->count == 0 && p->syms[RX] && p->syms[RX]->x.regnode && p->syms[RX]->x.regnode->count >= 0)
263: freereg(p->syms[RX]);
264: last = p;
265: } else
266: last = 0;
267: }
268: for (i = 0; i < nregsets; i++) {
269: freemask[i] |= tempmask[i];
270: tempmask[i] = 0;
271: }
272: return curhead;
273: }
274:
275: /* genascii - emit ascii string str */
276: void genascii(ascii, byte, len, str) char *ascii, *byte, *str; {
277: char *s = str;
278: int m, n;
279:
280: for (n = 5, m = 9; s < str + len; s++) {
281: if (*s == '"' || *s == '\\')
282: m += 2;
283: else
284: m += *s < ' ' || *s >= 0177 ? 4 : 1;
285: n += *s < 10 ? 2 : *s < 100 ? 3 : 4;
286: }
287: s = str;
288: if (ascii == 0 || n < m) {
289: print("%s %d", byte, (*s++)&0xff);
290: for (n = 0; s < str + len; n++)
291: if (n > 10) {
292: n = 0;
293: print("\n%s %d", byte, (*s++)&0xff);
294: } else
295: print(",%d", (*s++)&0xff);
296: outs("\n");
297: } else {
298: n = 0;
299: print("%s \"", ascii);
300: for (s = str; s < str + len; s++) {
301: if (n >= 64) {
302: print("\"\n%s \"", ascii);
303: n = 0;
304: }
305: if (*s == '"' || *s == '\\') {
306: print("\\%c", *s);
307: n += 2;
308: } else if (*s >= ' ' && *s < 0177) {
309: *bp++ = *s;
310: n += 1;
311: } else {
312: print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7);
313: n += 4;
314: }
315: }
316: outs("\"\n");
317: }
318: }
319:
320: /* genreload - make *pp use reloads instead of r */
321: static void genreload(pp, temp, ty, r) Node *pp; Symbol r, temp; {
322: int i;
323: Node p = *pp;
324:
325: for (i = 0; i < MAXKIDS; i++)
326: if (p->kids[i] && p->kids[i]->syms[RX] == r && p->kids[i]->x.registered) {
327: Symbol target = p->kids[i]->x.rtarget;
328: p->kids[i] = newnode(INDIR + ty, newnode(ADDRL+P, 0, 0, temp), 0, 0);
329: p->kids[i]->count = 1;
330: (*IR->x.rewrite)(p->kids[i]);
331: if (target)
332: rtarget(p, i, target);
333: (*IR->x.rewrite)(p);
334: linearize(p->kids[i], pp, *pp);
335: if (p->kids[i])
336: pp = &p->kids[i]->x.next;
337: }
338: }
339:
340: /* genreloads - make the nodes after dot use reloads instead of r */
341: static void genreloads(dot, temp, ty, r) Node dot; Symbol r, temp; {
342: Node p, *pp;
343:
344: if (IR->x.twoop && dot->x.zap0) {
345: pp = findxnext(dot);
346: genreload(pp, temp, ty, r);
347: for (p = *pp; p != dot; p = p->x.next)
348: ralloc(*pp);
349: }
350: for (pp = &dot->x.next; dot = *pp; pp = &dot->x.next)
351: genreload(pp, temp, ty, r);
352: }
353:
354: /* genspill - generate code to spill r and return the temp used */
355: static Symbol genspill(r, ty, last) Symbol r; Node *last; {
356: Node p, q;
357: Symbol s, tmp;
358: static struct symbol z;
359: unsigned i, savemask[(sizeof freemask)/(sizeof freemask[0])];
360:
361: for (i = 0; i < nregsets; i++) {
362: savemask[i] = vmask[i];
363: vmask[i] &= ~usedmask[i];
364: }
365: tmp = newtemp(REGISTER, ty);
366: for (i = 0; i < nregsets; i++)
367: vmask[i] = savemask[i];
368: debug(rflag, fprint(2, "(spilling %s to symbol %s=%s)\n", r->x.name, tmp->name, tmp->x.name));
369: s = (Symbol) talloc(sizeof *s);
370: *s = z;
371: s->sclass = REGISTER;
372: s->x.name = r->x.name;
373: symeaddr(s) = symeaddr(r);
374: s->x.regvar = r;
375: q = newnode(ADDRL+P, 0, 0, s);
376: q = newnode(INDIR + ty, q, 0, 0);
377: p = newnode(ADDRL+P, 0, 0, tmp);
378: p = newnode(ASGN + ty, p, q, 0);
379: p->x.sideeffect = 1;
380: (*IR->x.rewrite)(p);
381: q = *last;
382: linearize(p, last, q);
383: for (p = *last; p != q; p = p->x.next)
384: ralloc(p);
385: return tmp;
386: }
387:
388: /* getint - return value of signed integer constant */
389: int getint(p) Symbol p; {
390: switch (ttob(p->type)) {
391: case C: return p->u.c.v.sc;
392: case S: return p->u.c.v.ss;
393: default: return p->u.c.v.i;
394: }
395: }
396:
397: /* getreg - assign a register from set rs to node p */
398: static Symbol getreg(rs, p, rmask, count) Symbol rs; Node p; unsigned rmask; {
399: Regnode rn;
400: Symbol r;
401:
402: if (rs->x.regnode->link == 0)
403: rmask = -1;
404: for (r = rs; r; r = rn->link) {
405: rn = r->x.regnode;
406: assert(rn);
407: if ((rn->mask&~(freemask[rn->regset]&rmask)) == 0) {
408: freemask[rn->regset] &= ~rn->mask;
409: r->x.regnode->node = p;
410: r->x.regnode->count = count;
411: return r;
412: }
413: }
414: if (p == 0) /* register variable */
415: return 0;
416: r = spillee(rs, p, rmask);
417: spill(r->x.regnode->mask, r->x.regnode->regset, p);
418: r = getreg(rs, p, rmask, count);
419: assert(r);
420: return r;
421: }
422:
423: /* getregnode - return regnode for register variable or codegen temp */
424: Regnode getregnode(p) Symbol p; {
425: assert(p);
426: if (p->x.regvar) {
427: assert(!p->x.regnode);
428: assert(p->x.regvar->x.regnode);
429: return p->x.regvar->x.regnode;
430: } else {
431: assert(p->x.regnode);
432: return p->x.regnode;
433: }
434: }
435:
436: /* getregset - return index of the register set to which p's been allocated */
437: int getregset(p) Symbol p; {
438: if (p->sclass == REGISTER) {
439: assert(p->x.regvar);
440: return getregnode(p)->regset;
441: } else
442: return -1;
443: }
444:
445: /* getregvar - assign variable p to a register if possible */
446: int getregvar(p, reglist) Symbol p, reglist; {
447: Symbol reg;
448:
449: assert(p && p->type);
450: if (reglist && isscalar(p->type) && isregvar(p) && (reg = getreg(reglist, 0, vmask[reglist->x.regnode->regset], -1))) {
451: p->x.regvar = reg;
452: p->x.name = reg->x.name;
453: symeaddr(p) = symeaddr(reg);
454: p->x.nextregvar = regvars;
455: regvars = p;
456: debug(rflag, dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name));
457: if (p->temporary)
458: tempmask[reg->x.regnode->regset] |= reg->x.regnode->mask;
459: return 1;
460: } else {
461: p->sclass = AUTO;
462: return 0;
463: }
464: }
465:
466: /* getunsigned - return value of unsigned integer constant */
467: unsigned getunsigned(p) Symbol p; {
468: switch (ttob(p->type)) {
469: case C: return p->u.c.v.uc;
470: case S: return p->u.c.v.us;
471: default: return p->u.c.v.u;
472: }
473: }
474:
475: /* initfunc - common function initialization */
476: void initfunc(a, b, c) {
477: int i;
478:
479: offset = b;
480: maxoffset = 0;
481: argbuildsize = c;
482: ncalls = a;
483: regvars = 0;
484: for (i = 0; i < nregsets; i++) {
485: usedmask[i] = 0;
486: freemask[i] = -1;
487: }
488: }
489:
490: /* linearize - linearize nodelist p */
491: static void linearize(p, last, next) Node *last, next, p; {
492: for (; p; p = p->link)
493: if (p->x.sideeffect || p->count > 0) {
494: last = lin1(p, last);
495: p->x.listed = 1;
496: }
497: *last = next;
498: }
499:
500: /* lin1 - linearize dag p */
501: static Node *lin1(p, last) Node p, *last; {
502: int i;
503:
504: if (p->x.linearized)
505: return last;
506: for (i = 0; i < MAXKIDS; i++)
507: if (p->kids[i])
508: last = lin1(p->kids[i], last);
509: p->x.linearized = 1;
510: *last = p;
511: debug(rflag, fprint(2, "(listing %x)\n", p));
512: return &p->x.next;
513: }
514:
515: /* lop - p->syms[i] &= mask */
516: int lop(p, i, size) Node p; {
517: unsigned before = getunsigned(p->syms[i]);
518: unsigned after = before&((1<<size) - 1);
519:
520: if (before == after)
521: return 0;
522: else {
523: Value v;
524: v.u = after;
525: p->syms[i] = constant(p->syms[i]->type, v);
526: return 1;
527: }
528: }
529:
530: /* mkactual - make next frame offset */
531: int mkactual(prealign, size, postalign) {
532: int n = roundup(argoffset, prealign);
533: argoffset = roundup(n + size, postalign);
534: return n;
535: }
536:
537: /* mkauto - make next local */
538: int mkauto(p, align) Symbol p; {
539: offset = roundup(offset + p->type->size, align);
540: p->x.offset = -offset;
541: return -offset;
542: }
543:
544: /* mkreg - create register s with given mask, regset, and link */
545: static Symbol mkreg(s, n, mask, regset, regtype, link) char *s; Symbol link; {
546: static struct symbol zs;
547: static struct regnode zr;
548: Symbol q = (Symbol)alloc(sizeof *q);
549:
550: *q = zs;
551: q->x.name = string(s);
552: symeaddr(q) = atoi(s);
553: q->x.regnode = (Regnode)alloc(sizeof *q->x.regnode);
554: *q->x.regnode = zr;
555: q->x.regnode->regnum = n;
556: q->x.regnode->mask = mask;
557: q->x.regnode->link = link;
558: q->x.regnode->regset = regset;
559: q->x.regnode->regtype = regtype;
560: q->x.regnode->next = regs;
561: regs = q;
562: return q;
563: }
564:
565: /* mkregs - create registers lo to hi by inc with given mask and type */
566: Symbol mkregs(fmt, lo, hi, inc, mask, regset, regtype, p) char *fmt; Symbol p; {
567: for (; lo*inc <= hi*inc; lo += inc)
568: p = mkreg(stringf(fmt, lo), lo, mask << lo, regset, regtype, p);
569: return p;
570: }
571:
572: /* mvregvar - move register variable */
573: static void mvregvar(p, mask) Symbol p; unsigned mask; {
574: Symbol reg;
575:
576: if (reg = getreg(rmap[ttob(p->type)], 0, ~mask, -1)) {
577: freereg(p->x.regvar);
578: p->x.regvar = reg;
579: p->x.name = reg->x.name;
580: symeaddr(p) = symeaddr(reg);
581: debug(rflag, dumpregs("(moving register variable %s to %s)\n", p->name, p->x.name));
582: }
583: }
584:
585: /* mvregvars - move register variables to reduce callee saves */
586: void mvregvars() {
587: Symbol p;
588:
589: if (ncalls == 0) {
590: unsigned i, mask[(sizeof usedmask)/(sizeof usedmask[0])];
591: for (i = 0; i < nregsets; i++)
592: mask[i] = usedmask[i] | eemask[i];
593: for (p = regvars; p; p = p->x.nextregvar) {
594: Regnode r = p->x.regvar->x.regnode;
595: mask[r->regset] |= r->mask;
596: }
597: for (p = regvars; p; p = p->x.nextregvar) {
598: Regnode r = p->x.regvar->x.regnode;
599: if (r->mask&eemask[r->regset])
600: mvregvar(p, mask[r->regset]);
601: }
602: }
603: freeregvars();
604: }
605:
606: /* ntob - infer type suffix from register set for register p */
607: static int ntob(p) Symbol p; {
608: Regnode r = getregnode(p);
609: assert(r->regtype);
610: return r->regtype;
611: }
612:
613: /* overlaps - do registers x and y overlap? */
614: static int overlaps(x, y) Symbol x, y; {
615: Regnode rx = getregnode(x), ry = getregnode(y);
616: return rx->regset == ry->regset && rx->mask&ry->mask;
617: }
618:
619: /* parseflags - parse back end flags */
620: void parseflags(argc, argv) char *argv[]; {
621: for (++argv; --argc > 0; ++argv)
622: if (strcmp(*argv, "-d") == 0)
623: dflag++;
624: else if (strcmp(*argv, "-p") == 0 || strcmp(*argv, "-pg") == 0)
625: pflag++;
626: else if (strcmp(*argv, "-r") == 0)
627: rflag++;
628: else if (strcmp(*argv, "-k") == 0)
629: kflag++;
630: }
631:
632: void progend() {}
633:
634: /* ralloc - assign registers for p */
635: static void ralloc(p) Node p; {
636: Symbol s;
637: int i, n;
638:
639: assert(p && p->x.registered == 0);
640: n = IR->x.twoop && p->x.zap0 ? 1 : MAXKIDS;
641: for (i = 0; i < n; i++)
642: if (p->kids[i]) {
643: assert(p->kids[i]->x.registered);
644: s = p->kids[i]->syms[RX];
645: if (s == 0) {
646: debug(rflag, fprint(2, "(%x->kids[%d]=%x has no register allocated)\n", p, i, p->kids[i]));
647: assert(s);
648: }
649: if (s->x.regnode && s->x.regnode->count >= 0 && --s->x.regnode->count == 0)
650: freereg(s);
651: }
652: s = p->syms[RX];
653: if (s && s->x.regnode) {
654: p->syms[RX] = getreg(s, p, tmask[s->x.regnode->regset], p->count);
655: usedmask[p->syms[RX]->x.regnode->regset] |= p->syms[RX]->x.regnode->mask;
656: debug(rflag, dumpregs("(allocating %s to node %x)\n", p->syms[RX]->x.name, (char *) p));
657: }
658: for (i = n; i < MAXKIDS; i++)
659: if (p->kids[i]) {
660: assert(p->kids[i]->x.registered);
661: s = p->kids[i]->syms[RX];
662: assert(s);
663: if (s->x.regnode && s->x.regnode->count >= 0 && --s->x.regnode->count == 0)
664: freereg(s);
665: }
666: p->x.registered = 1;
667: (*IR->x.final)(p);
668: }
669:
670: /* range - does signed k fit in n bits? */
671: int range(k, n) {
672: return k >= -(1<<(n - 1)) && k < (1<<(n - 1));
673: }
674:
675: /* regchain - does this binary instruction overwrite its left operand? */
676: regchain(a) Node a; {
677: return a->kids[0] == 0 || a->kids[0]->syms[RX] == a->syms[RX];
678: }
679:
680: /* regloc - return "id" for p's register */
681: unsigned regloc(p) Symbol p; {
682: assert(p && p->sclass == REGISTER && p->x.regvar && p->x.regvar->x.regnode);
683: return p->x.regvar->x.regnode->regset<<8 | p->x.regvar->x.regnode->regnum;
684: }
685:
686: /* rmcopy - remove the register-to-register copy in node a? */
687: int rmcopy(a) Node a; {
688: return !isregvar(a->syms[RX]) && !a->x.unavailable;
689: }
690:
691: /* rmember - is regnode r in register class s? */
692: static int rmember(r, s) Regnode r; Symbol s; {
693: assert(r && s->x.regnode);
694: for (; s; s = s->x.regnode->link)
695: if (r->regset == s->x.regnode->regset && r->mask == s->x.regnode->mask)
696: return 1;
697: return 0;
698: }
699:
700: /* rtarget - evaluate p->kids[n] into register r */
701: void rtarget(p, n, r) Node p; Symbol r; {
702: Node q;
703: Regnode regnode;
704: Symbol s;
705:
706: assert(p && r);
707: q = p->kids[n];
708: assert(q && r);
709: regnode = getregnode(r);
710: assert(r->x.regvar || regnode->link == 0);
711: s = q->syms[RX];
712: assert(s);
713: if (!isregvar(s) && rmember(regnode, s)) {
714: debug(rflag, fprint(2, "(targeting %x to %s)\n", q, r->x.name));
715: q->syms[RX] = q->x.rtarget = r;
716: } else {
717: debug(rflag, fprint(2, "(moving %x to %s)\n", q, r->x.name));
718: q->count--;
719: p->kids[n] = q = newnode(LOAD + ntob(q->syms[RX]), q, 0, q->syms[0]?q->syms[0]:p->syms[0]);
720: q->count++;
721: q->syms[RX] = q->x.rtarget = r;
722: (*IR->x.rewrite)(q);
723: }
724: }
725:
726: /* setseg - switch to logical segment n (1..5) */
727: void setseg(n) {
728: assert(n >= 0 && n < sizeof IR->x.segnames/sizeof IR->x.segnames[0]);
729: cseg = n;
730: if (IR->x.segnames[n-1])
731: print("%s\n", IR->x.segnames[n-1]);
732: }
733:
734: /* spacen - allocate n bytes of space in the current segment */
735: void spacen(n, prefix) char *prefix; {
736: if (cseg != BSS)
737: print("%s ", prefix);
738: print("%d\n", n);
739: }
740:
741: /* spill - spill all busy registers in regset n that overlap mask */
742: void spill(mask, n, dot) unsigned mask; Node dot; {
743: Symbol r;
744:
745: if (mask&~freemask[n])
746: for (r = regs; r; r = r->x.regnode->next)
747: if (n == r->x.regnode->regset && mask&r->x.regnode->mask && r->x.regnode->count)
748: spillr(r, dot);
749: usedmask[n] |= mask;
750: }
751:
752: /* spillee - identify most-distantly-used register in register class r */
753: static Symbol spillee(r, dot, rmask) Node dot; Symbol r; unsigned rmask; {
754: int bestdist = -1;
755: Symbol bestreg = 0;
756:
757: for (; r; r = r->x.regnode->link)
758: if ((r->x.regnode->mask&~rmask) == 0 && r->x.regnode->count >= 0) {
759: Node q;
760: int dist = 0;
761: for (q = dot; q && !uses(q, r); q = q->x.next)
762: dist++;
763: if (q && dist > bestdist) { /* no local use => reg vbl */
764: bestdist = dist;
765: bestreg = r;
766: }
767: }
768: assert(bestreg);
769: return bestreg;
770: }
771:
772: /* spillr - spill register r */
773: static void spillr(r, dot) Symbol r; Node dot; {
774: int ty = ntob(r);
775: if (r->x.regnode->count < 0) {
776: Node p = newnode(LOAD+ty,
777: newnode(INDIR+ty,
778: newnode(ADDRL+P, 0, 0,
779: genspill(r, ty, findxnext(dot))), 0, 0), 0, 0);
780: p->syms[RX] = r;
781: p->x.sideeffect = 1;
782: (*IR->x.rewrite)(p);
783: linearize(p, &dot->x.next, dot->x.next);
784: p->x.registered = 1;
785: } else if (dot->x.registered && r == dot->syms[RX]) {
786: /* dot can't have set it yet, so no spill is needed */
787: } else {
788: genreloads(dot, genspill(r, ty, &r->x.regnode->node->x.next), ty, r);
789: freereg(r);
790: }
791: }
792:
793: /* uses - does node p read register r? */
794: static int uses(p, r) Node p; Symbol r; {
795: int i;
796:
797: for (i = 0; i < MAXKIDS; i++)
798: if (
799: p->kids[i] &&
800: p->kids[i]->x.registered &&
801: overlaps(r, p->kids[i]->syms[RX])
802: )
803: return 1;
804: return 0;
805: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.