|
|
1.1 root 1: #include "gencode.h"
2: #define NDNUM 400
3: NODE myt[NDNUM];
4: int ntree;
5: extern int bothdebug, nosharp;
6: #if M32 == 1
7: char *regnames[] = {"%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
8: "%r8", "%fp", "%ap", "%r11", "%sp", "%r13", "%r14", "%pc"};
9: char *frameptr = "%fp";
10: char *argptr = "%ap";
11: char *jeq = "je";
12: char *jne = "jne";
13: char *jgt = "jg";
14: char *jge = "jge";
15: char *jlt = "jl";
16: char *jle = "jle";
17: char *jugt = "jgu";
18: char *juge = "jgeu";
19: char *jult = "jlu";
20: char *jule = "jleu";
21: #define CHARCHAR 'b'
22: #define SHORTCHAR 'h'
23: #define LONGCHAR 'w'
24: #define FLOATCHAR 's'
25: #define DOUBLECHAR 'd'
26: #else if VAX == 1
27: char *regnames[] = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
28: "r9", "r10", "r11", "r12", "r13", "r14", "r15"};
29: char *frameptr = "fp";
30: char *argptr = "ap";
31: char *jeq = "jeql";
32: char *jne = "jneq";
33: char *jgt = "jgtr";
34: char *jge = "jgeq";
35: char *jlt = "jlss";
36: char *jle = "jleq";
37: char *jugt = "jgtru";
38: char *juge = "jgequ";
39: char *jult = "jlssu";
40: char *jule = "jlequ";
41: #define CHARCHAR 'b'
42: #define SHORTCHAR 'w'
43: #define LONGCHAR 'l'
44: #define FLOATCHAR 'f'
45: #define DOUBLECHAR 'd'
46: #endif
47: char *bufend = (char *)bufs + sizeof(bufs);
48: pr(fmt, list)
49: char *fmt; long list;
50: {
51: char *sprintxl();
52: nosharp = !bothdebug;
53: prptr = sprintxl(prptr, fmt, &list);
54: if(prptr > prbuf + sizeof(prbuf))
55: cerror("prbuf overflow");
56: nosharp = 0;
57: }
58:
59: outpr()
60: {
61: *prptr = 0;
62: printbuf(prbuf, prptr-prbuf);
63: }
64: NODE *
65: gimmenode()
66: { NODE *p;
67: p = myt + ntree++;
68: if(ntree > NDNUM)
69: cerror("out of temporary trees");
70: return(p);
71: }
72:
73: NODE *
74: tempnode(p, flag)
75: NODE *p;
76: { NODE *x, *q = p->in.left;
77: int n;
78: extern int minrvar;
79: if(p->in.op == CONV)
80: q = p; /* CONV to double of float, versus (CMP double double) */
81: x = gimmenode();
82: x->in.type = q->in.type;
83: n = incrsize(q) == 8? 2: 1;
84: if(!(flag & ASADDR) && regvar >= REGVAR - 1 + n) {
85: x->in.op = REG;
86: x->tn.rval = regvar + 1 - n;
87: x->tn.lval = 1; /* SCRATCH marker !!!!! */
88: regvar -= n;
89: if(minrvar > regvar)
90: minrvar = regvar; /* in case current routine recursive */
91: return(x);
92: }
93: x->in.op = VAUTO;
94: x->tn.lval = gimmetemp(n);
95: /* scratch marker? */
96: return(x);
97: }
98: ret
99: alloctmp(p)
100: NODE *p;
101: { ret s;
102: sprintf(buf, "%d(%s)", gimmetemp(incrsize(p) == 8? 2: 1), frameptr);
103: done(s, CANINDIR|SCRATCH, 0);
104: }
105: ret
106: checksize(p, s, regmask)
107: NODE *p;
108: ret s;
109: { ret t;
110: if(p->in.type != TDOUBLE)
111: return(s);
112: regmask |= s.regmask;
113: t = allocreg(p, regmask);
114: return(t);
115: }
116:
117: ret
118: allocreg(p, regmask)
119: NODE *p;
120: { int i, n;
121: ret s;
122: NODE *x;
123: if(p->in.type == TDOUBLE)
124: n = 2;
125: else
126: n = 1;
127: for(i = 0; i < REGVAR; i++) {
128: if(!(regmask & (1 << i)))
129: continue;
130: if(n == 2 & !(regmask & (1 << (1+i))))
131: continue;
132: sprintx(buf, "%s", regnames[i]);
133: regmask = (1 << i);
134: if(n == 2)
135: regmask |= (1 << (i+1));
136: done(s, SCRATCH|ISREG, regmask);
137: }
138: x = tempnode(p, 0);
139: if(x->in.op == REG) {
140: sprintx(buf, "%s", regnames[x->tn.rval]);
141: done(s, SCRATCH|ISREG, 0);
142: }
143: sprintx(buf, "%d(%s)", x->tn.lval, frameptr);
144: done(s, SCRATCH|CANINDIR, 0);
145: }
146:
147: gimmetemp(n)
148: {
149: if(VAX)
150: return(freetemp(n)/8 - maxboff/SZCHAR);
151: else
152: return(freetemp(n)/8 + maxboff/SZCHAR);
153: }
154:
155: isfloat(p)
156: NODE *p;
157: {
158: return(p->in.type == TFLOAT || p->in.type == TDOUBLE);
159: }
160:
161: childtype(p)
162: NODE *p;
163: {
164: return(type(p->in.left));
165: }
166:
167: type(p)
168: NODE *p;
169: { int n = p->in.type;
170: switch(n) {
171: default:
172: return('?');
173: case TCHAR: case TUCHAR:
174: return(CHARCHAR);
175: case TSHORT: case TUSHORT:
176: return(SHORTCHAR);
177: case TINT: case TUNSIGNED: case TLONG: case TULONG:
178: case TPOINT: case TSTRUCT:
179: return(LONGCHAR);
180: case TFLOAT:
181: return(FLOATCHAR);
182: case TDOUBLE:
183: return(DOUBLECHAR);
184: }
185: }
186:
187: shiftsize(p)
188: NODE *p;
189: {
190: switch(p->in.type) {
191: default:
192: return(0); /* 0 can't occur in an ICON under shift */
193: case TCHAR: case TUCHAR:
194: return(0);
195: case TSHORT: case TUSHORT:
196: return(1);
197: case TINT: case TUNSIGNED: case TLONG: case TULONG: case TPOINT:
198: case TFLOAT:
199: return(2);
200: case TDOUBLE:
201: return(3);
202: }
203: }
204:
205: incrsize(p)
206: NODE *p;
207: {
208: switch(p->in.type) {
209: default:
210: return(0); /* 0 can't occur in an icon under incrop */
211: case TCHAR: case TUCHAR:
212: return(1);
213: case TSHORT: case TUSHORT:
214: return(2);
215: case TINT: case TUNSIGNED: case TLONG: case TULONG: case TPOINT:
216: case TFLOAT:
217: return(4);
218: case TDOUBLE:
219: return(8);
220: }
221: }
222:
223: isunsigned(p)
224: NODE *p;
225: {
226: switch(p->in.type) {
227: #if VAX==1
228: case TCHAR:
229: #endif
230: case TSHORT: case TINT: case TLONG: case TFLOAT: case TDOUBLE:
231: return(0);
232: #if M32==1
233: case TCHAR:
234: #endif
235: default:
236: return(1);
237: }
238: }
239:
240: NODE *
241: copytree(p)
242: NODE *p;
243: { NODE *a, *b, *c;
244: switch(p->in.op) {
245: case ASG AND: case AND: case CALL: case CMP: case COMOP:
246: case DECR: case ASG DIV: case DIV: case ASG ER: case ER:
247: case INCR: case ASG LS: case LS: case ASG MINUS: case MINUS:
248: case ASG MOD: case MOD: case ASG MUL: case MUL: case ASG OR:
249: case OR: case ASG PLUS: case PLUS: case ASG RS: case RS:
250: case STASG: case STCALL: case ASSIGN: case CM:
251: a = copytree(p->in.left);
252: b = copytree(p->in.right);
253: c = gimmenode();
254: *c = *p;
255: c->in.left = a;
256: c->in.right = b;
257: return(c);
258: case COMPL: case CONV: case FLD: case GENBR: case GENLAB:
259: case GENUBR: case STAR: case UNARY AND: case UNARY CALL:
260: case UNARY MINUS: case UNARY STCALL: case INIT: case FUNARG:
261: case STARG:
262: a = copytree(p->in.left);
263: c = gimmenode();
264: *c = *p;
265: c->in.left = a;
266: return(c);
267: case VAUTO: case REG: case NAME: case VPARAM: case ICON:
268: case SNODE: case RNODE: case QNODE:
269: c = gimmenode();
270: *c = *p;
271: return(c);
272: default:
273: cerror("unk node in copytree");
274: }
275: }
276: /* rewrit A op B into (T = A, T) op B or A op (T = B, T) */
277: totemp(p, flag)
278: NODE *p;
279: { NODE *a, *b, *c;
280: a = gimmenode();
281: b = tempnode(p, flag);
282: c = gimmenode();
283: if(flag & LEFT)
284: *a = *p->in.left;
285: else
286: *a = *p->in.right;
287: a->in.op = ASSIGN;
288: a->in.left = b;
289: if(flag & LEFT)
290: a->in.right = p->in.left;
291: else
292: a->in.right = p->in.right;
293: c->in.op = COMOP;
294: c->in.left = a;
295: c->in.right = b;
296: c->in.type = a->in.type;
297: if(flag & LEFT)
298: p->in.left = c;
299: else
300: p->in.right = c;
301: }
302:
303: funargs(p, regmask)
304: NODE *p;
305: { ret s, t;
306: int i;
307: switch(p->in.op) {
308: case CM: /* order depends on way stack grows */
309: #ifdef LTORARGS
310: i = funargs(p->in.left, regmask);
311: i |= funargs(p->in.right, regmask);
312: #else
313: i = funargs(p->in.right, regmask);
314: i |= funargs(p->in.left, regmask);
315: #endif
316: return(i);
317: case FUNARG:
318: #if VAX==1
319: t = tostack();
320: s = doit(p->in.left, VALUE|TOSTACK, t, regmask);
321: #else if M32==1
322: s = doit(p->in.left, VALUE|TOSTACK, 0, regmask);
323: #endif
324: return(s.flag & FAIL);
325: case STARG:
326: /* this has to have same cases as STASG */
327: if(regmask != REGMASK)
328: return(FAILX);
329: s = doit(p->in.left, VAX?(ASADDR|VALUE):VALUE, 0, regmask);
330: /* this generates expensive code for small structures */
331: i = p->stn.stsize / 8;
332: if(p->in.left->in.op == STASG) {
333: if(VAX && i != 4 && i != 8) {
334: pr("#\tsubl2\t$%d,sp\n", i);
335: pr("#\tsubl2\t$%d,r3\n", i);
336: pr("#\tmovc3\t$%d,(r3),(sp)\n", p->stn.stsize/8);
337: return(0);
338: }
339: else if(M32 && i >= 7 * 4) {
340: pr("#\taddw2\t&%d,%%sp\n", i);
341: pr("#\tsubw2\t&%d,%%r0\n", i/4);
342: goto moveit;
343: }
344: }
345: if(VAX) {
346: if(i == 4)
347: pr("#\tpushl\t%s\n", str(s));
348: else if(i == 8)
349: pr("#\tmovq\t%s,-(sp)\n", str(s));
350: else {
351: pr("#\tsubl2\t$%d,sp\n", i);
352: pr("#\tmovc3\t$%d,%s,(sp)\n", p->stn.stsize/8, str(s));
353: }
354: }
355: else if(M32) {
356: pr("#\taddw2\t&%d,%%sp\n", i);
357: if(strcmp(str(s), "%r0"))
358: pr("#\tmovw\t%s,%r0\n", str(s));
359: moveit:
360: pr("#\tmovaw\t-%d(%%sp),%r1\n", p->stn.stsize/8);
361: i = p->stn.stsize/32;
362: if(i >= 7) {
363: pr("#\tmovw\t&%d,%%r2\n", i);
364: pr("#\tMOVBLW\n");
365: }
366: else
367: while(--i >= 0)
368: pr("#\tmovw\t%d(%r0),%d(%r1)\n", 4*i, 4*i);
369: }
370: return(s.flag & FAIL);
371: }
372: }
373:
374: strshift(s, n)
375: char *s;
376: { int i, j;
377: i = strlen(s);
378: if(n > 0)
379: for(j = i; j >= 0; j--)
380: s[j + n] = s[j];
381: else
382: for(j = -n; j <= i; j++)
383: s[j + n] = s[j];
384: }
385:
386: ret
387: tostack()
388: { ret s;
389: sprintx(buf, "-(sp)");
390: done(s, 0, 0);
391: }
392:
393: ret
394: specialreg(p, regmask)
395: NODE *p;
396: { ret s;
397: int n, i;
398: n = p ->in.type == TDOUBLE? 2: 1;
399: i = 1;
400: if(n == 2)
401: i = 3;
402: sprintx(buf, "%s", regnames[0]);
403: if(i & ~regmask)
404: pr("#\specialreg not free\n");
405: done(s, SCRATCH|ISREG, i);
406: }
407: /* these guys rewrite a1 = a2 = ... an = x
408: * as t = x; an = t; an-1 = an */
409: NODE *
410: fromtemp(p, temp)
411: NODE *p, *temp;
412: { NODE *q;
413: q = gimmenode();
414: *q = *p;
415: q->in.left = p;
416: q->in.op = ASSIGN;
417: q->in.right = temp;
418: return(q);
419: }
420:
421: NODE *
422: to(p, temp)
423: NODE *p, *temp;
424: { NODE *q;
425: q = gimmenode();
426: *q = *p;
427: q->in.right = p;
428: q->in.op = ASSIGN;
429: q->in.left = temp;
430: return(q);
431: }
432:
433: NODE *
434: comnode(a, p)
435: NODE *a, *p;
436: { NODE *q;
437: q = gimmenode();
438: *q = *p;
439: q->in.op = COMOP;
440: q->in.right = p;
441: q->in.left = a;
442: return(q);
443: }
444:
445: asgwrite(p)
446: NODE *p;
447: { NODE *q, *a, *temp;
448: temp = tempnode(p, 0);
449: a = fromtemp(p->in.left, temp);
450: for(q = p->in.right; q->in.op == ASSIGN; q = q->in.right)
451: a = comnode(fromtemp(q->in.left, temp), a);
452: a = comnode(to(q, temp), a);
453: *p = *a;
454: }
455:
456: char *
457: genjmp(n)
458: {
459: switch(n) {
460: default:
461: return("jweird");
462: case EQ:
463: return(jeq);
464: case NE:
465: return(jne);
466: case GT:
467: return(jgt);
468: case GE:
469: return(jge);
470: case LT:
471: return(jlt);
472: case LE:
473: return(jle);
474: case UGT:
475: return(jugt);
476: case UGE:
477: return(juge);
478: case ULT:
479: return(jult);
480: case ULE:
481: return(jule);
482: }
483: }
484:
485: lsconv(p)
486: NODE *p;
487: { NODE *lft, *right;
488: lft = gimmenode();
489: right = gimmenode();
490: lft->in.op = right->in.op = CONV;
491: lft->in.type = right->in.type = TLONG;
492: lft->in.left = p->in.left;
493: right->in.left = p->in.right;
494: if(p->in.left->in.op != ICON) /* ICONS are longs anyway (see RS) */
495: p->in.left = lft;
496: p->in.right = right;
497: }
498: /* only some ops have to be rewritten (addb and addl are the same at the bottom) */
499: rewriteasgop(p)
500: NODE *p;
501: { NODE *a, *newop;
502: if(p->in.left->in.op != CONV)
503: return(0);
504: if(p->in.left->in.left->in.op == STAR)
505: longjmp(back, awfulstar(p));
506: newop = gimmenode();
507: *newop = *p;
508: switch(p->in.op) {
509: case ASG DIV:
510: newop->in.op = DIV;
511: break;
512: case ASG LS:
513: newop->in.op = LS;
514: break;
515: case ASG MOD:
516: newop->in.op = MOD;
517: break;
518: case ASG RS:
519: newop->in.op = RS;
520: break;
521: case ASG PLUS:
522: if(incrsize(p->in.left) != 8)
523: return(0);
524: newop->in.op = PLUS;
525: break;
526: case ASG MINUS:
527: if(incrsize(p->in.left) != 8)
528: return(0);
529: newop->in.op = MINUS;
530: break;
531: case ASG MUL:
532: if(incrsize(p->in.left) != 8)
533: return(0);
534: newop->in.op = MUL;
535: break;
536:
537: default:
538: cerror("codegen: rewriting asgop");
539: }
540: a = gimmenode();
541: *a = *p->in.left->in.left;
542: p->in.op = ASSIGN;
543: p->in.left = a;
544: p->in.right = newop;
545: return(1);
546: }
547:
548: rewriteconv(p) /* uns to float or double */
549: NODE *p;
550: { NODE *a;
551: a = gimmenode();
552: *a = *p;
553: a->in.type = TLONG;
554: p->in.left = a;
555: }
556:
557: mediumstar(p)
558: NODE *p;
559: { NODE *newtop, *tmp, *x, *y;
560: newtop = gimmenode();
561: newtop->in.op = COMOP;
562: newtop->in.type = p->in.type;
563: x = gimmenode();
564: x->in.op = ASSIGN;
565: x->in.type = TPOINT;
566: x->in.right = p->in.left->in.left;
567: newtop->in.left = x;
568: tmp = tempnode(newtop, 0);
569: tmp->in.type = TPOINT;
570: x->in.left = tmp;
571: y = gimmenode();
572: y->in.op = COMOP;
573: y->in.type = p->in.type;
574: x = gimmenode();
575: *x = *p;
576: newtop->in.right = y;
577: y->in.left = x;
578: y->in.right = x->in.left;
579: x->in.left->in.left = tmp;
580: *p = *newtop;
581: return(1);
582: }
583:
584: awfulstar(p)
585: NODE *p;
586: { NODE *newtop, *doleft, *x, *op, *equals;
587: newtop = gimmenode();
588: newtop->in.op = COMOP;
589: newtop->in.type = p->in.type;
590: doleft = gimmenode();
591: doleft->in.op = ASSIGN;
592: doleft->in.type = TPOINT;
593: doleft->in.right = p->in.left->in.left->in.left;
594: x = tempnode(doleft, 0);
595: doleft->in.left = x;
596: op = gimmenode();
597: *op = *p;
598: op->in.op -= (ASG 0); /* crap for crap */
599: op->in.left->in.left->in.left = x; /* so it's a dag, but x is harmless */
600: equals = gimmenode();
601: *equals = *p;
602: equals->in.right = op;
603: equals->in.left = p->in.left->in.left;
604: equals->in.op = ASSIGN;
605: *p = *newtop;
606: p->in.left = doleft;
607: p->in.right = equals;
608: return(1);
609: }
610: rewritefld(p)
611: NODE *p;
612: { NODE *q, *tmp, *left, *comop;
613: if((q = p->in.left->in.left)->in.op != STAR) {
614: rewfld(p);
615: return;
616: }
617: q = q->in.left;
618: tmp = tempnode(q, 0);
619: left = gimmenode();
620: left->in.type = q->in.type;
621: left->in.op = ASSIGN;
622: left->in.left = tmp;
623: left->in.right = gimmenode();
624: left->in.right = copytree(q);
625: *q = *tmp;
626: comop = gimmenode();
627: comop->in.op = COMOP;
628: comop->in.left = left;
629: comop->in.right = copytree(p);
630: *p = *comop;
631: rewfld(p->in.right);
632: longjmp(back, 1);
633: }
634: rewfld(p)
635: NODE *p;
636: { NODE *x, *y, *z;
637: x = gimmenode();
638: *x = *copytree(p);
639: y = gimmenode();
640: *y = *copytree(p);
641: z = gimmenode();
642: *z = *p;
643: z->in.left = x;
644: x->in.op = ASSIGN;
645: x->in.right = y;
646: if(p->in.op == DECR || p->in.op == ASG MINUS)
647: z->in.op = PLUS;
648: else
649: z->in.op = MINUS;
650: if(p->in.op == DECR)
651: y->in.op = MINUS;
652: else if(p->in.op == INCR)
653: y->in.op = PLUS;
654: else
655: y->in.op -= (ASG 0); /* good grief */
656: if(p->in.op == DECR || p->in.op == INCR)
657: *p = *z;
658: else
659: *p = *x;
660: }
661:
662: ret
663: indirit(s)
664: ret s;
665: {
666: if(s.flag & ISREG) {
667: strcat(str(s), ")");
668: strshift(str(s), 1);
669: str(s)[0] = '(';
670: return(s);
671: }
672: if(s.flag & CANINDIR) {
673: strshift(str(s), 1);
674: str(s)[0] = '*';
675: return(s);
676: }
677: if(VAX && str(s)[0] == '(') { /* (r3)[r11] */
678: strshift(str(s), 1);
679: str(s)[0] = '*';
680: return(s);
681: }
682: if(VAX && str(s)[0] == '$') { /* an icon for structure returns */
683: strshift(str(s), -1);
684: return(s);
685: }
686: s.flag = FAIL;
687: return(s);
688: }
689: /* not int = (...? int exprs) have a bogus tree */
690: extracheck(p)
691: NODE *p;
692: { NODE *a;
693: if(p->in.right->in.op != GENLAB)
694: return;
695: a = gimmenode();
696: *a = *p;
697: a->in.left = p->in.right;
698: a->in.op = CONV;
699: p->in.right = a;
700: }
701:
702: starasg(p)
703: NODE *p;
704: { NODE *tmp, *asg, *x;
705: tmp = tempnode(p->in.left->in.left, 0);
706: x = gimmenode();
707: *x = *p;
708: asg = gimmenode();
709: *asg = *p->in.left->in.left;
710: asg->in.op = ASSIGN;
711: asg->in.left = tmp;
712: asg->in.right = p->in.left->in.left;
713: x->in.left->in.left = tmp;
714: p->in.op = COMOP;
715: p->in.left = asg;
716: p->in.right = x;
717: }
718: stasgrewrite(p)
719: NODE *p;
720: { NODE *qa, *qb, *n, *left, *right;
721: if(VAX) {
722: totemp(p, RIGHT);
723: longjmp(back, 1);
724: }
725: if(M32) {
726: qa = tempnode(p->in.right, 0);
727: qb = tempnode(p->in.left, 0);
728: right = to(p->in.right, qa);
729: left = to(p->in.left, qb);
730: p->in.right = qa;
731: p->in.left = qb;
732: qa = gimmenode();
733: qb = gimmenode();
734: qa->in.op = qb->in.op = COMOP;
735: qa->in.left = left;
736: qa->in.right = qb;
737: qb->in.left = right;
738: n = gimmenode();
739: *n = *p;
740: qb->in.right = n;
741: *p = *qa;
742: longjmp(back, 1);
743: }
744: }
745: ret
746: simpler(a, b) /* returns b (as dest) preferentially */
747: ret a, b;
748: {
749: if(b.flag & ISREG)
750: return(b);
751: if(a.flag & ISREG)
752: return(a);
753: if(b.flag & SCRATCH)
754: return(b);
755: if(a.flag & SCRATCH)
756: return(a);
757: if(!(b.flag & INDEX))
758: return(b);
759: if(!(a.flag & INDEX))
760: return(a);
761: /* disallow *p++ = *q++ but not p[i]=q[i]*/
762: if(!index(str(b), '-') && !index(str(b), '+'))
763: return(b);
764: if(!index(str(a), '-') && !index(str(a), '+'))
765: return(a);
766: b.flag |= USED;
767: return(b);
768: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.