|
|
1.1 root 1: #
2: /*
3:
4: C compiler, part 2
5:
6:
7: */
8:
9: #include "c1.h"
10:
11: #define dbprint(op) /* */
12: #ifdef DEBUG
13: #define dbprint(op) printf(" / %s", opntab[op])
14: #endif
15:
16: char maprel[] = { EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
17: LESS, GREATQP, GREATP, LESSEQP, LESSP
18: };
19:
20: char notrel[] = { NEQUAL, EQUAL, GREAT, GREATEQ, LESS,
21: LESSEQ, GREATP, GREATQP, LESSP, LESSEQP
22: };
23:
24: struct tconst czero = { CON, INT, 0};
25: struct tconst cone = { CON, INT, 1};
26:
27: struct tname sfuncr = { NAME, STRUCT, STATIC, 0, 0, 0 };
28:
29: struct table *cregtab;
30:
31: int nreg = 3;
32: int isn = 10000;
33:
34: main(argc, argv)
35: char *argv[];
36: {
37:
38: if (argc<4) {
39: error("Arg count");
40: exit(1);
41: }
42: if (freopen(argv[1], "r", stdin)==NULL) {
43: error("Missing temp file");
44: exit(1);
45: }
46: if ((freopen(argv[3], "w", stdout)) == NULL) {
47: error("Can't create %s", argv[3]);
48: exit(1);
49: }
50: funcbase = curbase = coremax = sbrk(0);
51: getree();
52: /*
53: * If any floating-point instructions
54: * were used, generate a reference that
55: * pulls in the floating-point part of printf.
56: */
57: if (nfloat)
58: printf(".globl fltused\n");
59: /*
60: * tack on the string file.
61: */
62: printf(".globl\n.data\n");
63: if (*argv[2] != '-') {
64: if (freopen(argv[2], "r", stdin)==NULL) {
65: error("Missing temp file");
66: exit(1);
67: }
68: getree();
69: }
70: if (totspace >= (unsigned)56000) {
71: error("Warning: possibly too much data");
72: nerror--;
73: }
74: exit(nerror!=0);
75: }
76:
77: /*
78: * Given a tree, a code table, and a
79: * count of available registers, find the code table
80: * for the appropriate operator such that the operands
81: * are of the right type and the number of registers
82: * required is not too large.
83: * Return a ptr to the table entry or 0 if none found.
84: */
85: struct optab *
86: match(tree, table, nrleft, nocvt)
87: union tree *tree;
88: struct table *table;
89: {
90: #define NOCVL 1
91: #define NOCVR 2
92: int op, d1, d2, dope;
93: union tree *p2;
94: register union tree *p1;
95: register struct optab *opt;
96:
97: if (tree==NULL)
98: return(NULL);
99: if (table==lsptab)
100: table = sptab;
101: if ((op = tree->t.op)==0)
102: return(0);
103: dope = opdope[op];
104: if ((dope&LEAF) == 0)
105: p1 = tree->t.tr1;
106: else
107: p1 = tree;
108: d1 = dcalc(p1, nrleft);
109: if ((dope&BINARY)!=0) {
110: p2 = tree->t.tr2;
111: /*
112: * If a subtree starts off with a conversion operator,
113: * try for a match with the conversion eliminated.
114: * E.g. int = double can be done without generating
115: * the converted int in a register by
116: * movf double,fr0; movfi fr0,int .
117: */
118: if (opdope[p2->t.op]&CNVRT && (nocvt&NOCVR)==0
119: && (opdope[p2->t.tr1->t.op]&CNVRT)==0) {
120: tree->t.tr2 = p2->t.tr1;
121: if (opt = match(tree, table, nrleft, NOCVL))
122: return(opt);
123: tree->t.tr2 = p2;
124: } else if (opdope[p1->t.op]&CNVRT && (nocvt&NOCVL)==0
125: && (opdope[p1->t.tr1->t.op]&CNVRT)==0) {
126: tree->t.tr1 = p1->t.tr1;
127: if (opt = match(tree, table, nrleft, NOCVR))
128: return(opt);
129: tree->t.tr1 = p1;
130: }
131: d2 = dcalc(p2, nrleft);
132: }
133: for (; table->tabop!=op; table++)
134: if (table->tabop==0)
135: return(0);
136: for (opt = table->tabp; opt->tabdeg1!=0; opt++) {
137: if (d1 > (opt->tabdeg1&077)
138: || (opt->tabdeg1 >= 0100 && (p1->t.op != STAR)))
139: continue;
140: if (notcompat(p1, opt->tabtyp1, opt->tabdeg1, op))
141: continue;
142: if ((opdope[op]&BINARY)!=0 && p2!=0) {
143: if (d2 > (opt->tabdeg2&077)
144: || (opt->tabdeg2 >= 0100) && (p2->t.op != STAR) )
145: continue;
146: if (notcompat(p2,opt->tabtyp2, opt->tabdeg2, 0))
147: continue;
148: if ((opt->tabdeg2&077)==20 && xdcalc(p2,nrleft)>20)
149: continue;
150: }
151: return(opt);
152: }
153: return(0);
154: }
155:
156: /*
157: * Given a tree, a code table, and a register,
158: * produce code to evaluate the tree with the appropriate table.
159: * Registers reg and upcan be used.
160: * If there is a value, it is desired that it appear in reg.
161: * The routine returns the register in which the value actually appears.
162: * This routine must work or there is an error.
163: * If the table called for is cctab, sptab, or efftab,
164: * and tree can't be done using the called-for table,
165: * another try is made.
166: * If the tree can't be compiled using cctab, regtab is
167: * used and a "tst" instruction is produced.
168: * If the tree can't be compiled using sptab,
169: * regtab is used and the register is pushed on the stack.
170: * If the tree can't be compiled using efftab,
171: * just use regtab.
172: * Regtab must succeed or an "op not found" error results.
173: *
174: * A number of special cases are recognized, and
175: * there is an interaction with the optimizer routines.
176: */
177: rcexpr(atree, atable, reg)
178: union tree *atree;
179: struct table *atable;
180: {
181: register r;
182: int modf, nargs, recurf;
183: register union tree *tree;
184: register struct table *table;
185:
186: table = atable;
187: recurf = 0;
188: if (reg<0) {
189: recurf++;
190: reg = ~reg;
191: if (reg>=020) {
192: reg -= 020;
193: recurf++;
194: }
195: }
196: again:
197: if((tree=atree)==0)
198: return(0);
199: if (tree->t.type==VOID) {
200: if (table!=efftab)
201: error("Illegal use of void");
202: tree->t.type = INT;
203: }
204: if (opdope[tree->t.op]&RELAT && tree->t.tr2->t.op==CON
205: && tree->t.tr2->c.value==0
206: && table==cctab)
207: tree = atree = tree->t.tr1;
208: /*
209: * fieldselect(...) : in efftab mode,
210: * ignore the select, otherwise
211: * do the shift and mask.
212: */
213: if (tree->t.op == FSELT) {
214: if (table==efftab)
215: atree = tree = tree->t.tr1;
216: else {
217: tree->t.op = FSEL;
218: atree = tree = optim(tree);
219: }
220: }
221: switch (tree->t.op) {
222:
223: /*
224: * Structure assignments
225: */
226: case STRASG:
227: strasg(tree);
228: return(0);
229:
230: /*
231: * An initializing expression
232: */
233: case INIT:
234: tree = optim(tree);
235: doinit(tree->t.type, tree->t.tr1);
236: return(0);
237:
238: /*
239: * Put the value of an expression in r0,
240: * for a switch or a return
241: */
242: case RFORCE:
243: tree = tree->t.tr1;
244: if((r=rcexpr(tree, regtab, reg)) != 0)
245: movreg(r, 0, tree);
246: return(0);
247:
248: /*
249: * sequential execution
250: */
251: case SEQNC:
252: r = nstack;
253: rcexpr(tree->t.tr1, efftab, reg);
254: nstack = r;
255: atree = tree = tree->t.tr2;
256: goto again;
257:
258: /*
259: * In the generated &~ operator,
260: * fiddle things so a PDP-11 "bit"
261: * instruction will be produced when cctab is used.
262: */
263: case ANDN:
264: if (table==cctab) {
265: tree->t.op = TAND;
266: tree->t.tr2 = optim(tnode(COMPL, tree->t.type, tree->t.tr2, TNULL));
267: }
268: break;
269:
270: /*
271: * Handle a subroutine call. It has to be done
272: * here because if cexpr got called twice, the
273: * arguments might be compiled twice.
274: * There is also some fiddling so the
275: * first argument, in favorable circumstances,
276: * goes to (sp) instead of -(sp), reducing
277: * the amount of stack-popping.
278: */
279: case CALL:
280: r = 0;
281: nargs = 0;
282: modf = 0;
283: if (tree->t.tr1->t.op!=NAME || tree->t.tr1->n.class!=EXTERN) {
284: nargs++;
285: nstack++;
286: }
287: tree = tree->t.tr2;
288: if(tree->t.op) {
289: while (tree->t.op==COMMA) {
290: r += comarg(tree->t.tr2, &modf);
291: tree = tree->t.tr1;
292: nargs++;
293: }
294: r += comarg(tree, &modf);
295: nargs++;
296: }
297: tree = atree;
298: tree->t.op = CALL2;
299: if (modf && tree->t.tr1->t.op==NAME
300: && tree->t.tr1->n.class==EXTERN)
301: tree->t.op = CALL1;
302: if (cexpr(tree, regtab, reg)<0)
303: error("compiler botch: call");
304: popstk(r);
305: nstack -= nargs;
306: if (table==efftab || table==regtab)
307: return(0);
308: r = 0;
309: goto fixup;
310:
311: /*
312: * Longs need special treatment.
313: */
314: case ASLSH:
315: case LSHIFT:
316: if (tree->t.type==LONG) {
317: if (tree->t.tr2->t.op==ITOL)
318: tree->t.tr2 = tree->t.tr2->t.tr1;
319: else
320: tree->t.tr2 = optim(tnode(LTOI,INT,tree->t.tr2,TNULL));
321: if (tree->t.op==ASLSH)
322: tree->t.op = ASLSHL;
323: else
324: tree->t.op = LLSHIFT;
325: }
326: break;
327:
328: /*
329: * Try to change * to shift.
330: */
331: case TIMES:
332: case ASTIMES:
333: tree = pow2(tree);
334: }
335: /*
336: * Try to find postfix ++ and -- operators that can be
337: * pulled out and done after the rest of the expression
338: */
339: if (table!=cctab && table!=cregtab && recurf<2
340: && (opdope[tree->t.op]&LEAF)==0) {
341: if (r=delay(&atree, table, reg)) {
342: tree = atree;
343: table = efftab;
344: reg = r-1;
345: }
346: }
347: /*
348: * Basically, try to reorder the computation
349: * so reg = x+y is done as reg = x; reg += y
350: */
351: if (recurf==0 && reorder(&atree, table, reg)) {
352: if (table==cctab && atree->t.op==NAME)
353: return(reg);
354: }
355: tree = atree;
356: if (table==efftab && tree->t.op==NAME)
357: return(reg);
358: if ((r=cexpr(tree, table, reg))>=0) {
359: if (table==cregtab && (tree->t.op==INCAFT
360: || tree->t.op==DECAFT || tree->t.op==TIMES))
361: goto fixup;
362: return(r);
363: }
364: if (table!=regtab && (table!=cctab||(opdope[tree->t.op]&RELAT)==0)) {
365: if((r=cexpr(tree, regtab, reg))>=0) {
366: fixup:
367: modf = isfloat(tree);
368: dbprint(tree->t.op);
369: if (table==sptab || table==lsptab) {
370: if (tree->t.type==LONG) {
371: printf("mov\tr%d,-(sp)\n",r+1);
372: nstack++;
373: }
374: printf("mov%s r%d,%s(sp)\n", modf=='f'?"f":"", r,
375: table==sptab? "-":"");
376: nstack++;
377: }
378: if (table==cctab || table==cregtab)
379: printf("tst%s r%d\n", modf=='f'?"f":"", r);
380: return(r);
381: }
382: }
383: /*
384: * Special grace for unsigned chars as right operands
385: */
386: if (opdope[tree->t.op]&BINARY && tree->t.tr2->t.type==UNCHAR) {
387: tree->t.tr2 = tnode(LOAD, UNSIGN, tree->t.tr2, TNULL);
388: return(rcexpr(tree, table, reg));
389: }
390: /*
391: * There's a last chance for this operator
392: */
393: if (tree->t.op==LTOI) {
394: r = rcexpr(tree->t.tr1, regtab, reg);
395: if (r >= 0) {
396: r++;
397: goto fixup;
398: }
399: }
400: if (tree->t.type == STRUCT)
401: error("Illegal operation on structure");
402: else if (tree->t.op>0 && tree->t.op<RFORCE && opntab[tree->t.op])
403: error("No code table for op: %s", opntab[tree->t.op]);
404: else
405: error("No code table for op %d", tree->t.op);
406: return(reg);
407: }
408:
409: /*
410: * Try to compile the tree with the code table using
411: * registers areg and up. If successful,
412: * return the register where the value actually ended up.
413: * If unsuccessful, return -1.
414: *
415: * Most of the work is the macro-expansion of the
416: * code table.
417: */
418: cexpr(tree, table, areg)
419: register union tree *tree;
420: struct table *table;
421: {
422: int c, r;
423: register union tree *p, *p1;
424: struct table *ctable;
425: union tree *p2;
426: char *string;
427: int reg, reg1, rreg, flag, opd;
428: struct optab *opt;
429:
430: reg = areg;
431: p1 = tree->t.tr2;
432: c = tree->t.op;
433: opd = opdope[c];
434: /*
435: * When the value of a relational or a logical expression is
436: * desired, more work must be done.
437: */
438: if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) {
439: cbranch(tree, c=isn++, 1, reg);
440: rcexpr((union tree *)&czero, table, reg);
441: branch(isn, 0, 0);
442: label(c);
443: rcexpr((union tree *)&cone, table, reg);
444: label(isn++);
445: return(reg);
446: }
447: if(c==QUEST) {
448: if (table==cctab)
449: return(-1);
450: cbranch(tree->t.tr1, c=isn++, 0, reg);
451: flag = nstack;
452: rreg = rcexpr(p1->t.tr1, table, reg);
453: nstack = flag;
454: branch(r=isn++, 0, 0);
455: label(c);
456: reg = rcexpr(p1->t.tr2, table, rreg);
457: if (rreg!=reg)
458: movreg(reg, rreg, tree->t.tr2);
459: label(r);
460: return(rreg);
461: }
462: reg = oddreg(tree, reg);
463: reg1 = reg+1;
464: /*
465: * long values take 2 registers.
466: */
467: if ((tree->t.type==LONG||opd&RELAT&&tree->t.tr1->t.type==LONG)
468: && tree->t.op!=ITOL)
469: reg1++;
470: /*
471: * Leaves of the expression tree
472: */
473: if ((r = chkleaf(tree, table, reg)) >= 0)
474: return(r);
475: /*
476: * x + (-1) is better done as x-1.
477: */
478: if (tree->t.op==PLUS||tree->t.op==ASPLUS) {
479: if ((p1=tree->t.tr2)->t.op==CON && p1->c.value==-1) {
480: p1->c.value = -p1->c.value;
481: tree->t.op += (MINUS-PLUS);
482: }
483: }
484: /*
485: * Because of a peculiarity of the PDP11 table
486: * char = *intreg++ and *--intreg cannot go through.
487: */
488: if (tree->t.tr2 && (tree->t.tr2->t.op==AUTOI||tree->t.tr2->t.op==AUTOD)
489: && (tree->t.tr1->t.type==CHAR || tree->t.tr1->t.type==UNCHAR)
490: && tree->t.tr2->t.type!=CHAR && tree->t.tr2->t.type!=UNCHAR)
491: tree->t.tr2 = tnode(LOAD, tree->t.tr2->t.type, tree->t.tr2, TNULL);
492: if (table==cregtab)
493: table = regtab;
494: /*
495: * The following peculiar code depends on the fact that
496: * if you just want the codition codes set, efftab
497: * will generate the right code unless the operator is
498: * a shift or
499: * postfix ++ or --. Unravelled, if the table is
500: * cctab and the operator is not special, try first
501: * for efftab; if the table isn't, if the operator is,
502: * or the first match fails, try to match
503: * with the table actually asked for.
504: */
505: /*
506: * Account for longs and oddregs; below is really
507: * r = nreg - reg - (reg-areg) - (reg1-reg-1);
508: */
509: r = nreg - reg + areg - reg1 + 1;
510: if (table!=cctab || c==INCAFT || c==DECAFT || tree->t.type==LONG
511: || c==ASRSH || c==ASLSH || c==ASULSH || tree->t.tr1->t.type==UNCHAR
512: || (opt = match(tree, efftab, r, 0)) == 0)
513: if ((opt=match(tree, table, r, 0))==0)
514: return(-1);
515: string = opt->tabstring;
516: p1 = tree->t.tr1;
517: if (p1->t.op==FCON && p1->f.value>0) {
518: /* nonportable */
519: printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p1->f.value,
520: ((unsigned short *)&(p1->f.fvalue))[0],
521: ((unsigned short *)&(p1->f.fvalue))[1],
522: ((unsigned short *)&(p1->f.fvalue))[2],
523: ((unsigned short *)&(p1->f.fvalue))[3] );
524: p1->c.value = -p1->c.value;
525: }
526: p2 = 0;
527: if (opdope[tree->t.op]&BINARY) {
528: p2 = tree->t.tr2;
529: if (p2->t.op==FCON && p2->f.value>0) {
530: /* nonportable */
531: printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p2->f.value,
532: ((unsigned short *)&(p2->f.fvalue))[0],
533: ((unsigned short *)&(p2->f.fvalue))[1],
534: ((unsigned short *)&(p2->f.fvalue))[2],
535: ((unsigned short *)&(p2->f.fvalue))[3] );
536: p2->f.value = -p2->f.value;
537: }
538: }
539: loop:
540: /*
541: * The 0200 bit asks for a tab.
542: */
543: if ((c = *string++) & 0200) {
544: c &= 0177;
545: putchar('\t');
546: }
547: switch (c) {
548:
549: case '\n':
550: dbprint(tree->t.op);
551: break;
552:
553: case '\0':
554: if (!isfloat(tree))
555: if (tree->t.op==DIVIDE||tree->t.op==ASDIV)
556: reg--;
557: if (table==regtab && (opdope[tree->t.op]&ASSGOP)) {
558: if (tree->t.tr1->t.type==CHAR)
559: printf("movb r%d,r%d\n", reg, reg);
560: }
561: return(reg);
562:
563: /* A1 */
564: case 'A':
565: p = p1;
566: goto adr;
567:
568: /* A2 */
569: case 'B':
570: p = p2;
571: goto adr;
572:
573: adr:
574: c = 0;
575: while (*string=='\'') {
576: c++;
577: string++;
578: }
579: if (*string=='+') {
580: c = 100;
581: string++;
582: }
583: pname(p, c);
584: goto loop;
585:
586: /* I */
587: case 'M':
588: if ((c = *string)=='\'')
589: string++;
590: else
591: c = 0;
592: prins(tree->t.op, c, instab);
593: goto loop;
594:
595: /* B1 */
596: case 'C':
597: if ((opd&LEAF) != 0)
598: p = tree;
599: else
600: p = p1;
601: goto pbyte;
602:
603: /* BF */
604: case 'P':
605: p = tree;
606: goto pb1;
607:
608: /* B2 */
609: case 'D':
610: p = p2;
611: pbyte:
612: if (p->t.type==CHAR || p->t.type==UNCHAR)
613: putchar('b');
614: pb1:
615: if (isfloat(p))
616: putchar('f');
617: goto loop;
618:
619: /* BE */
620: case 'L':
621: if (p1->t.type==CHAR || p2->t.type==CHAR
622: || p1->t.type==UNCHAR || p2->t.type==UNCHAR)
623: putchar('b');
624: p = tree;
625: goto pb1;
626:
627: /* F */
628: case 'G':
629: p = p1;
630: flag = 01;
631: goto subtre;
632:
633: /* S */
634: case 'K':
635: p = p2;
636: flag = 02;
637: goto subtre;
638:
639: /* H */
640: case 'H':
641: p = tree;
642: flag = 04;
643:
644: subtre:
645: ctable = regtab;
646: if (flag&04)
647: ctable = cregtab;
648: c = *string++ - 'A';
649: if (*string=='!') {
650: string++;
651: c |= 020; /* force right register */
652: }
653: if (*string=='?') {
654: string++;
655: c |= 040; /* force condition codes */
656: }
657: if ((c&02)!=0)
658: ctable = sptab;
659: if ((c&04)!=0)
660: ctable = cctab;
661: if ((flag&01) && ctable==regtab && (c&01)==0
662: && ((c&040)||tree->t.op==DIVIDE||tree->t.op==MOD
663: || tree->t.op==ASDIV||tree->t.op==ASMOD||tree->t.op==ITOL))
664: ctable = cregtab;
665: if ((c&01)!=0) {
666: p = p->t.tr1;
667: if(collcon(p) && ctable!=sptab) {
668: if (p->t.op==STAR)
669: p = p->t.tr1;
670: p = p->t.tr1;
671: }
672: }
673: if (table==lsptab && ctable==sptab)
674: ctable = lsptab;
675: if (c&010)
676: r = reg1;
677: else
678: if (opdope[p->t.op]&LEAF || p->t.degree < 2)
679: r = reg;
680: else
681: r = areg;
682: rreg = rcexpr(p, ctable, r);
683: if (ctable!=regtab && ctable!=cregtab)
684: goto loop;
685: if (c&010) {
686: if (c&020 && rreg!=reg1)
687: movreg(rreg, reg1, p);
688: else
689: reg1 = rreg;
690: } else if (rreg!=reg)
691: if ((c&020)==0 && oddreg(tree, 0)==0 && tree->t.type!=LONG
692: && (flag&04
693: || flag&01&&xdcalc(p2,nreg-rreg-1)<=(opt->tabdeg2&077)
694: || flag&02&&xdcalc(p1,nreg-rreg-1)<=(opt->tabdeg1&077))) {
695: reg = rreg;
696: reg1 = rreg+1;
697: } else
698: movreg(rreg, reg, p);
699: goto loop;
700:
701: /* R */
702: case 'I':
703: r = reg;
704: if (*string=='-') {
705: string++;
706: r--;
707: }
708: goto preg;
709:
710: /* R1 */
711: case 'J':
712: r = reg1;
713: preg:
714: if (*string=='+') {
715: string++;
716: r++;
717: }
718: if (r>nreg || r>=4 && tree->t.type==DOUBLE) {
719: if (regpanic)
720: error("Register overflow: simplify expression");
721: else
722: longjmp(jmpbuf, 1);
723: }
724: printf("r%d", r);
725: goto loop;
726:
727: case '-': /* check -(sp) */
728: if (*string=='(') {
729: nstack++;
730: if (table!=lsptab)
731: putchar('-');
732: goto loop;
733: }
734: break;
735:
736: case ')': /* check (sp)+ */
737: putchar(')');
738: if (*string=='+')
739: nstack--;
740: goto loop;
741:
742: /* #1 */
743: case '#':
744: p = p1->t.tr1;
745: goto nmbr;
746:
747: /* #2 */
748: case '"':
749: p = p2->t.tr1;
750:
751: nmbr:
752: if(collcon(p)) {
753: if (p->t.op==STAR) {
754: printf("*");
755: p = p->t.tr1;
756: }
757: if ((p = p->t.tr2)->t.op == CON) {
758: if (p->c.value)
759: psoct(p->c.value);
760: } else if (p->t.op==AMPER)
761: pname(p->t.tr1, 0);
762: }
763: goto loop;
764:
765: /*
766: * Certain adjustments for / %
767: */
768: case 'T':
769: c = reg-1;
770: if (uns(p1) || uns(p2)) {
771: printf("clr r%d\n", c);
772: goto loop;
773: }
774: if (dcalc(p1, 5)>12 && !match(p1, cctab, 10, 0))
775: printf("tst r%d\n", reg);
776: printf("sxt r%d\n", c);
777: goto loop;
778:
779: case 'V': /* adc sbc, clr, or sxt as required for longs */
780: switch(tree->t.op) {
781: case PLUS:
782: case ASPLUS:
783: case INCBEF:
784: case INCAFT:
785: printf("adc");
786: break;
787:
788: case MINUS:
789: case ASMINUS:
790: case NEG:
791: case DECBEF:
792: case DECAFT:
793: printf("sbc");
794: break;
795:
796: case ASSIGN:
797: p = tree->t.tr2;
798: goto lcasev;
799:
800: case ASDIV:
801: case ASMOD:
802: case ASULSH:
803: p = tree->t.tr1;
804: lcasev:
805: if (p->t.type!=LONG) {
806: if (uns(p) || uns(tree->t.tr2))
807: printf("clr");
808: else
809: printf("sxt");
810: goto loop;
811: }
812: default:
813: while ((c = *string++)!='\n' && c!='\0');
814: break;
815: }
816: goto loop;
817:
818: /*
819: * Mask used in field assignments
820: */
821: case 'Z':
822: printf("$%o", UNS(tree->F.mask));
823: goto loop;
824:
825: /*
826: * Relational on long values.
827: * Might bug out early. E.g.,
828: * (long<0) can be determined with only 1 test.
829: */
830: case 'X':
831: if (xlongrel(*string++ - '0'))
832: return(reg);
833: goto loop;
834: }
835: putchar(c);
836: goto loop;
837: }
838:
839: /*
840: * This routine just calls sreorder (below)
841: * on the subtrees and then on the tree itself.
842: * It returns non-zero if anything changed.
843: */
844: reorder(treep, table, reg)
845: union tree **treep;
846: struct table *table;
847: {
848: register r, o;
849: register union tree *p;
850:
851: p = *treep;
852: o = p->t.op;
853: if (opdope[o]&LEAF||o==LOGOR||o==LOGAND||o==SEQNC||o==QUEST||o==COLON)
854: return(0);
855: while(sreorder(&p->t.tr1, regtab, reg, 1))
856: ;
857: if (opdope[o]&BINARY)
858: while(sreorder(&p->t.tr2, regtab, reg, 1))
859: ;
860: r = 0;
861: if (table!=cctab)
862: while (sreorder(treep, table, reg, 0))
863: r++;
864: *treep = optim(*treep);
865: return(r);
866: }
867:
868: /*
869: * Basically this routine carries out two kinds of optimization.
870: * First, it observes that "x + (reg = y)" where actually
871: * the = is any assignment op is better done as "reg=y; x+reg".
872: * In this case rcexpr is called to do the first part and the
873: * tree is modified so the name of the register
874: * replaces the assignment.
875: * Moreover, expressions like "reg = x+y" are best done as
876: * "reg = x; reg += y" (so long as "reg" and "y" are not the same!).
877: */
878: sreorder(treep, table, reg, recurf)
879: union tree **treep;
880: struct table *table;
881: {
882: register union tree *p, *p1;
883:
884: p = *treep;
885: if (opdope[p->t.op]&LEAF)
886: return(0);
887: if (p->t.op==PLUS && recurf)
888: if (reorder(&p->t.tr2, table, reg))
889: *treep = p = optim(p);
890: if ((p1 = p->t.tr1)==TNULL)
891: return(0);
892: if (p->t.op==STAR || p->t.op==PLUS) {
893: if (recurf && reorder(&p->t.tr1, table, reg)) {
894: *treep = p = optim(p);
895: if (opdope[p->t.op]&LEAF)
896: return(0);
897: }
898: p1 = p->t.tr1;
899: }
900: if (p1->t.op==NAME) switch(p->t.op) {
901: case ASLSH:
902: case ASRSH:
903: case ASSIGN:
904: if (p1->n.class != REG || p1->n.type==CHAR
905: || isfloat(p->t.tr2))
906: return(0);
907: if (p->t.op==ASSIGN) switch (p->t.tr2->t.op) {
908: case RSHIFT:
909: if (p->t.type==UNSIGN)
910: return(0);
911: goto caseGEN;
912: case TIMES:
913: if (!ispow2(p->t.tr2))
914: break;
915: p->t.tr2 = pow2(p->t.tr2);
916: case PLUS:
917: case MINUS:
918: case AND:
919: case ANDN:
920: case OR:
921: case EXOR:
922: case LSHIFT:
923: caseGEN:
924: p1 = p->t.tr2->t.tr2;
925: if (xdcalc(p1, 16) > 12
926: || p1->t.op==NAME
927: &&(p1->n.nloc==p->t.tr1->n.nloc
928: || p1->n.regno==p->t.tr1->n.nloc))
929: return(0);
930: p1 = p->t.tr2;
931: p->t.tr2 = p1->t.tr1;
932: if (p1->t.tr1->t.op!=NAME
933: || p1->t.tr1->n.class!=REG
934: || p1->t.tr1->n.nloc!=p->t.tr1->n.nloc)
935: rcexpr(p, efftab, reg);
936: p->t.tr2 = p1->t.tr2;
937: p->t.op = p1->t.op + ASPLUS - PLUS;
938: *treep = p;
939: return(1);
940: }
941: goto OK;
942:
943: case ASTIMES:
944: if (!ispow2(p))
945: return(0);
946: case ASPLUS:
947: case ASMINUS:
948: case ASAND:
949: case ASANDN:
950: case ASOR:
951: case ASXOR:
952: case INCBEF:
953: case DECBEF:
954: OK:
955: if (table==cctab||table==cregtab)
956: reg += 020;
957: rcexpr(optim(p), efftab, ~reg);
958: *treep = p1;
959: return(1);
960: }
961: return(0);
962: }
963:
964: /*
965: * Delay handles postfix ++ and --
966: * It observes that "x + y++" is better
967: * treated as "x + y; y++".
968: * If the operator is ++ or -- itself,
969: * it calls rcexpr to load the operand, letting
970: * the calling instance of rcexpr to do the
971: * ++ using efftab.
972: * Otherwise it uses sdelay to search for inc/dec
973: * among the operands.
974: */
975: delay(treep, table, reg)
976: union tree **treep;
977: struct table *table;
978: {
979: register union tree *p, *p1;
980: register r;
981:
982: p = *treep;
983: if ((p->t.op==INCAFT||p->t.op==DECAFT)
984: && p->t.tr1->t.op==NAME) {
985: return(1+rcexpr(paint(p->t.tr1, p->t.type), table, reg));
986: }
987: p1 = 0;
988: if (opdope[p->t.op]&BINARY) {
989: if (p->t.op==LOGAND || p->t.op==LOGOR
990: || p->t.op==QUEST || p->t.op==COLON || p->t.op==SEQNC)
991: return(0);
992: }
993: p1 = sdelay(&p->t.tr2);
994: if (p1==0)
995: p1 = sdelay(&p->t.tr1);
996: if (p1) {
997: r = rcexpr(optim(p), table, reg);
998: *treep = p1;
999: return(r+1);
1000: }
1001: return(0);
1002: }
1003:
1004: union tree *
1005: sdelay(ap)
1006: union tree **ap;
1007: {
1008: register union tree *p, *p1;
1009:
1010: if ((p = *ap)==TNULL)
1011: return(TNULL);
1012: if ((p->t.op==INCAFT||p->t.op==DECAFT) && p->t.tr1->t.op==NAME) {
1013: *ap = paint(ncopy(p->t.tr1), p->t.type);
1014: return(p);
1015: }
1016: if (p->t.op==STAR || p->t.op==PLUS)
1017: if (p1=sdelay(&p->t.tr1))
1018: return(p1);
1019: if (p->t.op==PLUS)
1020: return(sdelay(&p->t.tr2));
1021: return(0);
1022: }
1023:
1024: /*
1025: * Propagate possible implicit type-changing operation
1026: */
1027: union tree *
1028: paint(tp, type)
1029: register union tree *tp;
1030: register type;
1031: {
1032:
1033: if (tp->t.type==type)
1034: return(tp);
1035: if (tp->t.type==CHAR && type==INT)
1036: return(tp);
1037: if (tp->t.type==CHAR || tp->t.type==UNCHAR)
1038: return(optim(tnode(LOAD, type, tp, TNULL)));
1039: tp->t.type = type;
1040: if (tp->t.op==AMPER && type&XTYPE)
1041: tp->t.tr1 = paint(tp->t.tr1, decref(type));
1042: else if (tp->t.op==STAR)
1043: tp->t.tr1 = paint(tp->t.tr1, incref(type));
1044: else if (tp->t.op==ASSIGN) {
1045: paint(tp->t.tr1, type);
1046: paint(tp->t.tr2, type);
1047: }
1048: return(tp);
1049: }
1050:
1051: /*
1052: * Copy a tree node for a register variable.
1053: * Used by sdelay because if *reg-- is turned
1054: * into *reg; reg-- the *reg will in turn
1055: * be changed to some offset class, accidentally
1056: * modifying the reg--.
1057: */
1058: union tree *
1059: ncopy(p)
1060: register union tree *p;
1061: {
1062: register union tree *q;
1063:
1064: q = getblk(sizeof(struct xtname));
1065: q->n.op = p->n.op;
1066: q->n.type = p->n.type;
1067: q->n.class = p->n.class;
1068: q->n.regno = p->n.regno;
1069: q->n.offset = p->n.offset;
1070: if (q->n.class==EXTERN || q->n.class==XOFFS)
1071: strncpy(q->x.name, p->x.name, NCPS);
1072: else
1073: q->n.nloc = p->n.nloc;
1074: return(q);
1075: }
1076:
1077: /*
1078: * If the tree can be immediately loaded into a register,
1079: * produce code to do so and return success.
1080: */
1081: chkleaf(tree, table, reg)
1082: register union tree *tree;
1083: struct table *table;
1084: {
1085: struct tnode lbuf;
1086:
1087: if (tree->t.op!=STAR && dcalc(tree, nreg-reg) > 12)
1088: return(-1);
1089: lbuf.op = LOAD;
1090: lbuf.type = tree->t.type;
1091: lbuf.degree = tree->t.degree;
1092: lbuf.tr1 = tree;
1093: return(rcexpr((union tree *)&lbuf, table, reg));
1094: }
1095:
1096: /*
1097: * Compile a function argument.
1098: * If the stack is currently empty, put it in (sp)
1099: * rather than -(sp); this will save a pop.
1100: * Return the number of bytes pushed,
1101: * for future popping.
1102: */
1103: comarg(tree, flagp)
1104: register union tree *tree;
1105: int *flagp;
1106: {
1107: register retval;
1108: int i;
1109: int size;
1110:
1111: if (tree->t.op==STRASG) {
1112: size = tree->F.mask;
1113: tree = tree->t.tr1;
1114: tree = strfunc(tree);
1115: if (size <= sizeof(short)) {
1116: paint(tree, INT);
1117: goto normal;
1118: }
1119: if (size <= sizeof(long)) {
1120: paint(tree, LONG);
1121: goto normal;
1122: }
1123: if (tree->t.op!=NAME && tree->t.op!=STAR) {
1124: error("Unimplemented structure assignment");
1125: return(0);
1126: }
1127: tree = tnode(AMPER, STRUCT+PTR, tree, TNULL);
1128: tree = tnode(PLUS, STRUCT+PTR, tree, tconst(size, INT));
1129: tree = optim(tree);
1130: retval = rcexpr(tree, regtab, 0);
1131: size >>= 1;
1132: if (size <= 5) {
1133: for (i=0; i<size; i++)
1134: printf("mov -(r%d),-(sp)\n", retval);
1135: } else {
1136: if (retval!=0)
1137: printf("mov r%d,r0\n", retval);
1138: printf("mov $%o,r1\n", UNS(size));
1139: printf("L%d:mov -(r0),-(sp)\ndec\tr1\njne\tL%d\n", isn, isn);
1140: isn++;
1141: }
1142: nstack++;
1143: return(size*2);
1144: }
1145: normal:
1146: if (nstack || isfloat(tree) || tree->t.type==LONG) {
1147: rcexpr(tree, sptab, 0);
1148: retval = arlength(tree->t.type);
1149: } else {
1150: (*flagp)++;
1151: rcexpr(tree, lsptab, 0);
1152: retval = 0;
1153: }
1154: return(retval);
1155: }
1156:
1157: union tree *
1158: strfunc(tp)
1159: register union tree *tp;
1160: {
1161: if (tp->t.op != CALL)
1162: return(tp);
1163: paint(tp, STRUCT+PTR);
1164: return(tnode(STAR, STRUCT, tp, TNULL));
1165: }
1166:
1167: /*
1168: * Compile an initializing expression
1169: */
1170: doinit(type, tree)
1171: register type;
1172: register union tree *tree;
1173: {
1174: float sfval;
1175: double fval;
1176: long lval;
1177:
1178: if (type==CHAR || type==UNCHAR) {
1179: printf(".byte ");
1180: if (tree->t.type&XTYPE)
1181: goto illinit;
1182: type = INT;
1183: }
1184: if (type&XTYPE)
1185: type = INT;
1186: switch (type) {
1187: case INT:
1188: case UNSIGN:
1189: if (tree->t.op==FTOI) {
1190: if (tree->t.tr1->t.op!=FCON && tree->t.tr1->t.op!=SFCON)
1191: goto illinit;
1192: tree = tree->t.tr1;
1193: tree->c.value = tree->f.fvalue;
1194: tree->t.op = CON;
1195: } else if (tree->t.op==LTOI) {
1196: if (tree->t.tr1->t.op!=LCON)
1197: goto illinit;
1198: tree = tree->t.tr1;
1199: lval = tree->l.lvalue;
1200: tree->t.op = CON;
1201: tree->c.value = lval;
1202: }
1203: if (tree->t.op == CON)
1204: printf("%o\n", UNS(tree->c.value));
1205: else if (tree->t.op==AMPER) {
1206: pname(tree->t.tr1, 0);
1207: putchar('\n');
1208: } else
1209: goto illinit;
1210: return;
1211:
1212: case DOUBLE:
1213: case FLOAT:
1214: if (tree->t.op==ITOF) {
1215: if (tree->t.tr1->t.op==CON) {
1216: fval = tree->t.tr1->c.value;
1217: } else
1218: goto illinit;
1219: } else if (tree->t.op==FCON || tree->t.op==SFCON)
1220: fval = tree->f.fvalue;
1221: else if (tree->t.op==LTOF) {
1222: if (tree->t.tr1->t.op!=LCON)
1223: goto illinit;
1224: fval = tree->t.tr1->l.lvalue;
1225: } else
1226: goto illinit;
1227: if (type==FLOAT) {
1228: sfval = fval;
1229: /* nonportable */
1230: printf("%o; %o\n",
1231: ((unsigned short *)&sfval)[0],
1232: ((unsigned short *)&sfval)[1] );
1233: } else
1234: printf("%o; %o; %o; %o\n",
1235: ((unsigned short *)&fval)[0],
1236: ((unsigned short *)&fval)[1],
1237: ((unsigned short *)&fval)[2],
1238: ((unsigned short *)&fval)[3] );
1239: return;
1240:
1241: case LONG:
1242: if (tree->t.op==FTOL) {
1243: tree = tree->t.tr1;
1244: if (tree->t.op==SFCON)
1245: tree->t.op = FCON;
1246: if (tree->t.op!= FCON)
1247: goto illinit;
1248: lval = tree->f.fvalue;
1249: } else if (tree->t.op==ITOL) {
1250: if (tree->t.tr1->t.op != CON)
1251: goto illinit;
1252: if (uns(tree->t.tr1))
1253: lval = (unsigned)tree->t.tr1->c.value;
1254: else
1255: lval = tree->t.tr1->c.value;
1256: } else if (tree->t.op==LCON)
1257: lval = tree->l.lvalue;
1258: else
1259: goto illinit;
1260: /* nonportable */
1261: printf("%o; %o\n", UNS((lval>>16)), UNS(lval));
1262: return;
1263: }
1264: illinit:
1265: error("Illegal initialization");
1266: }
1267:
1268: movreg(r0, r1, tree)
1269: union tree *tree;
1270: {
1271: register char *s;
1272: char c;
1273:
1274: if (r0==r1)
1275: return;
1276: if (tree->t.type==LONG) {
1277: if (r0>=nreg || r1>=nreg) {
1278: error("register overflow: compiler error");
1279: }
1280: s = "mov r%d,r%d\nmov r%d,r%d\n";
1281: if (r0 < r1)
1282: printf(s, r0+1,r1+1,r0,r1);
1283: else
1284: printf(s, r0,r1,r0+1,r1+1);
1285: return;
1286: }
1287: c = isfloat(tree);
1288: printf("mov%.1s r%d,r%d\n", &c, r0, r1);
1289: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.