|
|
1.1 root 1: #include "gencode.h"
2: #define NDNUM 800
3: mnod myt[NDNUM];
4: extern mnod *svq;
5: int ntree;
6: char *regnames[] = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
7: "r9", "r10", "r11", "r12", "r13", "r14", "r15"};
8: char *frameptr = "fp";
9: char *argptr = "ap";
10: #define CHARCHAR 'b'
11: #define SHORTCHAR 'w'
12: #define LONGCHAR 'l'
13: #define FLOATCHAR 'f'
14: #define DOUBLECHAR 'd'
15:
16: mnod *
17: gimmemnod()
18: { mnod *p;
19: p = myt + ntree++;
20: if(ntree > NDNUM)
21: cerror("out of temporary trees");
22: return(p);
23: }
24:
25: mnod *
26: tempnode(p, flag)
27: mnod *p;
28: { mnod *x, *q;
29: int n;
30: extern int minrvar;
31: if(p->op == Conv)
32: q = p; /* Conv to double of float, versus (CMP double double) */
33: else
34: q = (flag & RIGHT)? p->right: p->left;
35: x = gimmemnod();
36: x->type = q->type;
37: n = incrsize(q) == 8? 2: 1;
38: if(!(flag & ASADDR) && regvar >= REGVAR - 1 + n) {
39: x->op = Reg;
40: x->rval = regvar + 1 - n;
41: x->lval = 1; /* SCRATCH marker !!!!! */
42: regvar -= n;
43: if(minrvar > regvar)
44: minrvar = regvar; /* in case current routine recursive */
45: return(x);
46: }
47: x->op = Auto;
48: x->lval = gimmetemp(n);
49: /* scratch marker? */
50: return(x);
51: }
52: ret
53: alloctmp(p)
54: mnod *p;
55: { ret s;
56: sprintf(buf, "%d(%s)", gimmetemp(incrsize(p) == 8? 2: 1), frameptr);
57: done(s, CANINDIR|SCRATCH, 0);
58: }
59:
60: ret
61: allocreg(p, regmask)
62: mnod *p;
63: { int i, n;
64: ret s;
65: mnod *x;
66: if(p->type == Tdouble)
67: n = 2;
68: else
69: n = 1;
70: for(i = 0; i < REGVAR; i++) {
71: if(!(regmask & (1 << i)))
72: continue;
73: if(n == 2 & !(regmask & (1 << (1+i))))
74: continue;
75: sprintx(buf, "%s", regnames[i]);
76: regmask = (1 << i);
77: if(n == 2)
78: regmask |= (1 << (i+1));
79: done(s, SCRATCH|ISREG, regmask);
80: }
81: x = tempnode(p, 0);
82: if(x->op == Reg) {
83: sprintx(buf, "%s", regnames[x->rval]);
84: done(s, SCRATCH|ISREG, 0);
85: }
86: sprintx(buf, "%d(%s)", x->lval, frameptr);
87: done(s, SCRATCH|CANINDIR, 0);
88: }
89:
90: isfloat(p)
91: mnod *p;
92: {
93: return(p->type == Tfloat || p->type == Tdouble);
94: }
95:
96: childtype(p)
97: mnod *p;
98: {
99: return(type(p->left));
100: }
101:
102: char typearr[] = {LONGCHAR, CHARCHAR, CHARCHAR, SHORTCHAR, SHORTCHAR,
103: LONGCHAR, LONGCHAR, LONGCHAR, LONGCHAR,
104: FLOATCHAR, DOUBLECHAR, '?', '?'};
105: type(p)
106: mnod *p;
107: {
108: return(typearr[p->type]);
109: }
110:
111: int shiftarr[] = {2, 0, 0, 1, 1, 2, 2, 2, 2, 2, 3, -99, 0};
112: shiftsize(p)
113: mnod *p;
114: {
115: return(shiftarr[p->type]);
116: }
117:
118: int incrarr[] = {4, 1, 1, 2, 2, 4, 4, 4, 4, 4, 8, -99, 0};
119: incrsize(p)
120: mnod *p;
121: {
122: return(incrarr[p->type]);
123: }
124:
125: int unsarr[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0};
126: isunsigned(p)
127: mnod *p;
128: {
129: return(unsarr[p->type]);
130: }
131:
132: mnod *
133: copymnod(p)
134: mnod *p;
135: { mnod *a, *b, *c;
136: c = gimmemnod();
137: switch(p->op) {
138: case Andeq: case And: case Cmp: case Comop: case Decr:
139: case Diveq: case Div: case Xoreq: case Xor:
140: case Incr: case Lseq: case Ls: case Minuseq: case Minus:
141: case Modeq: case Mod: case Muleq: case Mul: case Oreq:
142: case Or: case Pluseq: case Plus: case Rseq: case Rs:
143: case Asg: case Cm:
144: case Call: case Stcall:
145: case Stasg:
146: a = copymnod(p->left);
147: b = copymnod(p->right);
148: *c = *p;
149: c->left = a;
150: c->right = b;
151: return(c);
152: case Compl: case Conv: case Genbr: case Genlab:
153: case Genubr: case Star: case Addr: case Ucall:
154: case Uminus: case Ustcall: case Init: case Funarg:
155: case Fld:case Starg:
156: a = copymnod(p->left);
157: *c = *p;
158: c->left = a;
159: return(c);
160: case Auto: case Reg: case Name: case Param: case Icon:
161: case Snode: case Rnode: case Qnode:
162: *c = *p;
163: return(c);
164: default:
165: cerror("unk mnod in copymnod");
166: }
167: }
168:
169: /* rewrit A op B into (T = A, T) op B or A op (T = B, T) */
170: totemp(p, flag)
171: mnod *p;
172: { mnod *a, *b, *c;
173: a = gimmemnod();
174: b = tempnode(p, flag);
175: c = gimmemnod();
176: if(flag & LEFT)
177: *a = *p->left;
178: else
179: *a = *p->right;
180: a->op = Asg;
181: a->left = b;
182: if(flag & LEFT)
183: a->right = p->left;
184: else
185: a->right = p->right;
186: c->op = Comop;
187: c->left = a;
188: c->right = b;
189: c->type = a->type;
190: if(flag & LEFT)
191: p->left = c;
192: else
193: p->right = c;
194: }
195:
196: funargs(p, regmask)
197: mnod *p;
198: { ret s, t;
199: int i;
200: switch(p->op) {
201: case Cm: /* order depends on way stack grows */
202: #ifdef LTORARGS
203: i = funargs(p->left, regmask);
204: i |= funargs(p->right, regmask);
205: #else
206: i = funargs(p->right, regmask);
207: i |= funargs(p->left, regmask);
208: #endif
209: return(i);
210: case Funarg:
211: t = tostack();
212: s = doit(p->left, VALUE|TOSTACK, t, regmask);
213: return(s.flag & FAIL);
214: case Starg:
215: /* this has to have same cases as STASG */
216: if(regmask != REGMASK)
217: return(FAILX);
218: s = doit(p->left, (ASADDR|VALUE|FSTASG), 0, regmask);
219: /* this generates expensive code for small structures */
220: i = p->stsize / 8;
221: if(p->left->op == Stasg) {
222: if(i != 4 && i != 8) {
223: pr("#\tsubl2\t$%d,sp\n", i);
224: pr("#\tsubl2\t$%d,r3\n", i);
225: pr("#\tmovc3\t$%d,(r3),(sp)\n", p->stsize/8);
226: return(0);
227: }
228: }
229: if(i == 4)
230: pr("#\tpushl\t%s\n", str(s));
231: else if(i == 8)
232: pr("#\tmovq\t%s,-(sp)\n", str(s));
233: else {
234: pr("#\tsubl2\t$%d,sp\n", i);
235: pr("#\tmovc3\t$%d,%s,(sp)\n", p->stsize/8, str(s));
236: }
237: return(s.flag & FAIL);
238: }
239: }
240: ret
241: specialreg(p, regmask)
242: mnod *p;
243: { ret s;
244: int n, i;
245: n = p->type == Tdouble? 2: 1;
246: i = 1;
247: if(n == 2)
248: i = 3;
249: sprintx(buf, "%s", regnames[0]);
250: if(i & ~regmask)
251: pr("#\specialreg not free\n");
252: done(s, SCRATCH|ISREG, i);
253: }
254: /* these guys rewrite a1 = a2 = ... an = x
255: * as t = x; an = t; an-1 = an */
256: mnod *
257: fromtemp(p, temp)
258: mnod *p, *temp;
259: { mnod *q;
260: q = gimmemnod();
261: *q = *p;
262: q->left = p;
263: q->op = Asg;
264: q->right = temp;
265: return(q);
266: }
267:
268: mnod *
269: to(p, temp)
270: mnod *p, *temp;
271: { mnod *q;
272: q = gimmemnod();
273: *q = *p;
274: q->right = p;
275: q->op = Asg;
276: q->left = temp;
277: return(q);
278: }
279:
280: mnod *
281: commnod(a, p)
282: mnod *a, *p;
283: { mnod *q;
284: q = gimmemnod();
285: *q = *p;
286: q->op = Comop;
287: q->right = p;
288: q->left = a;
289: return(q);
290: }
291:
292: asgwrite(p)
293: mnod *p;
294: { mnod *q, *a, *temp;
295: debugpr("#REWRITEasgwrite ");
296: temp = tempnode(p, 0);
297: a = fromtemp(p->left, temp);
298: for(q = p->right; q->op == Asg; q = q->right)
299: a = commnod(fromtemp(q->left, temp), a);
300: a = commnod(to(q, temp), a);
301: *p = *a;
302: }
303:
304: lsconv(p)
305: mnod *p;
306: { mnod *lft, *right;
307: debugpr("#REWRITElsconv ");
308: lft = gimmemnod();
309: right = gimmemnod();
310: lft->op = right->op = Conv;
311: lft->type = right->type = Tlong;
312: lft->left = p->left;
313: right->left = p->right;
314: if(p->left->op != Icon) /* Icon are longs anyway (see RS) */
315: p->left = lft;
316: p->right = right;
317: }
318: /* only some ops have to be rewritten (addb and addl are the same at the bottom) */
319: rewriteasgop(p)
320: mnod *p;
321: { mnod *a, *newop;
322: if(p->left->op != Conv)
323: return(0);
324: if(p->left->left->op == Star)
325: longjmp(back, awfulstar(p));
326: debugpr("#REWRITE rewriteasgop ");
327: newop = gimmemnod();
328: *newop = *p;
329: switch(p->op) {
330: case Diveq:
331: newop->op = Div;
332: break;
333: case Lseq:
334: newop->op = Ls;
335: break;
336: case Modeq:
337: newop->op = Mod;
338: break;
339: case Rseq:
340: newop->op = Rs;
341: break;
342: case Pluseq:
343: if(!isfloat(p->left))
344: return(0);
345: newop->op = Plus;
346: break;
347: case Minuseq:
348: if(!isfloat(p->left))
349: return(0);
350: newop->op = Minus;
351: break;
352: case Muleq:
353: if(!isfloat(p->left))
354: return(0);
355: newop->op = Mul;
356: break;
357:
358: default:
359: cerror("codegen: rewriting asgop");
360: }
361: a = gimmemnod();
362: *a = *p->left->left;
363: p->op = Asg;
364: p->left = a;
365: p->right = newop;
366: return(1);
367: }
368:
369: rewriteconv(p) /* uns to float or double */
370: mnod *p;
371: { mnod *a;
372: debugpr("#REWRITEconv ");
373: a = gimmemnod();
374: *a = *p;
375: a->type = Tlong;
376: p->left = a;
377: }
378:
379: /* =(FLD(*(A)),B) -> ,(=(T,A), =(FLD(*(T)),B) */
380: fldstar(p)
381: mnod *p;
382: { mnod *A, *B, *T, *newtop;
383: debugpr("#REWRITE fldstar ");write(2, "fldstar\n", 8);
384: A = p->left->left->left;
385: B = p->right;
386: T = tempnode(A, 0);
387: newtop = gimmemnod();
388: newtop->op = Comop;
389: newtop->type = p->type;
390: newtop->left = gimmemnod();
391: newtop->left->op = Asg;
392: newtop->left->type = A->type;
393: newtop->left->left = T;
394: newtop->left->right = A;
395: newtop->right = gimmemnod();
396: *newtop->right = *p;
397: p->left->left->left = T;
398: *p = *newtop;
399: }
400:
401: mediumstar(p)
402: mnod *p;
403: { mnod *newtop, *tmp, *x, *y;
404: debugpr("#REWRITE mediumstar ");
405: newtop = gimmemnod();
406: newtop->op = Comop;
407: newtop->type = p->type;
408: x = gimmemnod();
409: x->op = Asg;
410: x->type = Tpoint;
411: x->right = p->left->left;
412: newtop->left = x;
413: tmp = tempnode(newtop, 0);
414: tmp->type = Tpoint;
415: x->left = tmp;
416: y = gimmemnod();
417: y->op = Comop;
418: y->type = p->type;
419: x = gimmemnod();
420: *x = *p;
421: newtop->right = y;
422: y->left = x;
423: y->right = x->left;
424: x->left->left = tmp;
425: *p = *newtop;
426: return(1);
427: }
428:
429: awfulstar(p)
430: mnod *p;
431: { mnod *newtop, *doleft, *x, *op, *equals;
432: debugpr("#REWRITE awfulstar ");
433: newtop = gimmemnod();
434: newtop->op = Comop;
435: newtop->type = p->type;
436: doleft = gimmemnod();
437: doleft->op = Asg;
438: doleft->type = Tpoint;
439: doleft->right = p->left->left->left;
440: x = tempnode(doleft, RIGHT);
441: doleft->left = x;
442: op = gimmemnod();
443: *op = *p;
444: op->op += 1; /* cheap hack */
445: op->left->left->left = x; /* so it's a dag, but x is harmless */
446: equals = gimmemnod();
447: *equals = *p;
448: equals->right = op;
449: equals->left = p->left->left;
450: equals->op = Asg;
451: *p = *newtop;
452: p->left = doleft;
453: p->right = equals;
454: return(1);
455: }
456: rewritefld(p)
457: mnod *p;
458: { mnod *q, *tmp, *left, *comop;
459: debugpr("#REWRITEfld ");
460: if((q = p->left->left)->op != Star) {
461: rewfld(p);
462: return;
463: }
464: q = q->left;
465: tmp = tempnode(q, 0);
466: left = gimmemnod();
467: left->type = q->type;
468: left->op = Asg;
469: left->left = tmp;
470: left->right = gimmemnod();
471: left->right = copymnod(q);
472: *q = *tmp;
473: comop = gimmemnod();
474: comop->op = Comop;
475: comop->left = left;
476: comop->right = copymnod(p);
477: *p = *comop;
478: rewfld(p->right);
479: longjmp(back, 1);
480: }
481: rewfld(p)
482: mnod *p;
483: { mnod *x, *y, *z;
484: x = gimmemnod();
485: *x = *copymnod(p);
486: y = gimmemnod();
487: *y = *copymnod(p);
488: z = gimmemnod();
489: *z = *p;
490: z->left = x;
491: x->op = Asg;
492: x->right = y;
493: if(p->op == Decr || p->op == Minuseq)
494: z->op = Plus;
495: else
496: z->op = Minus;
497: if(p->op == Decr)
498: y->op = Minus;
499: else if(p->op == Incr)
500: y->op = Plus;
501: else
502: y->op += 1; /* cheap hack */
503: if(p->op == Decr || p->op == Incr)
504: *p = *z;
505: else
506: *p = *x;
507: }
508: /* not int = (...? int exprs) have a bogus tree */
509: extracheck(p)
510: mnod *p;
511: { mnod *a;
512: if(p->right->op != Genlab && p->right->op != Comop)
513: return;
514: debugpr("#REWRITE extracheck ");
515: a = gimmemnod();
516: *a = *p;
517: a->left = p->right;
518: a->op = Conv;
519: p->right = a;
520: }
521:
522: starasg(p)
523: mnod *p;
524: { mnod *tmp, *asg, *x;
525: debugpr("#REWRITE starasg ");
526: tmp = tempnode(p->left->left, 0);
527: x = gimmemnod();
528: *x = *p;
529: asg = gimmemnod();
530: *asg = *p->left->left;
531: asg->op = Asg;
532: asg->left = tmp;
533: asg->right = p->left->left;
534: x->left->left = tmp;
535: p->op = Comop;
536: p->left = asg;
537: p->right = x;
538: }
539: /* *A op= B => (T=A, *T op= B) if T has Incr or Asg */
540: fixuns(p)
541: mnod *p;
542: { mnod *tmp, *asg, *new;
543: if(!sideffects(p->left->left))
544: return(0);
545: debugpr("#REWRITE fixuns");
546: tmp = tempnode(p->left->left, 0);
547: asg = gimmemnod();
548: asg->type = tmp->type;
549: asg->op = Asg;
550: asg->left = tmp;
551: asg->right = p->left->left;
552: new = gimmemnod();
553: *new = *p;
554: new->left->left = tmp;
555: p->op = Comop;
556: p->left = asg;
557: p->right = new;
558: return(1);
559: }
560:
561: stasgrewrite(p)
562: mnod *p;
563: { mnod *qa, *qb, *n, *left, *right;
564: debugpr("#REWRITE starasgrewrite ");
565: totemp(p, RIGHT);
566: longjmp(back, 1);
567: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.