4 * (long)btodb(l) produced 'no code table error for op: >>(17) type: 6'
5 * allow both long and ulong at line ~341. 1996/6/19
8 #if !defined(lint) && defined(DOSCCS)
9 static char sccsid[] = "@(#)c10.c 2.1 (2.11BSD GTE) 10/4/94";
17 #define dbprint(op) fprintf(temp_fp[temp_fi], " / %s", opntab[op])
19 #define dbprint(op) /* */
22 char maprel[] = { EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
23 LESS, GREATQP, GREATP, LESSEQP, LESSP
26 char notrel[] = { NEQUAL, EQUAL, GREAT, GREATEQ, LESS,
27 LESSEQ, GREATP, GREATQP, LESSP, LESSEQP
30 struct cnode czero = { { CON, INT, (int *)NULL, (union str *)NULL }, 0};
31 struct cnode cone = { { CON, INT, (int *)NULL, (union str *)NULL }, 1};
33 struct locnnode sfuncr = { { { NAME, STRUCT, (int *)NULL, (union str *)NULL }, (struct nmlist *)NULL, STATIC/*nn_class*/, 0/*nn_regno*/, 0/*nn_offset*/ }, 0/*locnn_nloc*/ };
34 struct table *cregtab;
40 int main(argc, argv) int argc; char *argv[]; {
48 if (freopen(argv[1], "r", stdin)==NULL) {
49 error1("Missing temp file");
52 setbuf(stdin,buf1); /* sbrk problems */
53 if ((freopen(argv[3], "w", stdout)) == NULL) {
54 error1("Can't create %s", argv[3]);
57 setbuf(stdout,buf2); /* sbrk problems */
58 funcbase = curbase = coremax = sbrk(0);
61 * If any floating-point instructions
62 * were used, generate a reference that
63 * pulls in the floating-point part of printf.
66 fprintf(temp_fp[temp_fi], ".globl fltused\n");
68 * tack on the string file.
70 fprintf(temp_fp[temp_fi], ".globl\n.data\n");
71 if (*argv[2] != '-') {
72 if (freopen(argv[2], "r", stdin)==NULL) {
73 error1("Missing temp file");
76 setbuf(stdin,buf1); /* sbrk problems */
79 if (totspace >= (_UNSIGNED_INT)56000)
80 werror1("possibly too much data");
86 * Given a tree, a code table, and a
87 * count of available registers, find the code table
88 * for the appropriate operator such that the operands
89 * are of the right type and the number of registers
90 * required is not too large.
91 * Return a ptr to the table entry or 0 if none found.
93 struct optab *match(tree, table, nrleft, nocvt) struct node *tree; struct table *table; int nrleft; int nocvt; {
98 register struct node *p1;
99 register struct optab *opt;
105 if ((op = tree->n_op)==0)
108 if ((dope&LEAF) == 0)
109 p1 = ((struct tnode *)tree)->tn_tr1;
112 d1 = dcalc(p1, nrleft);
113 if ((dope&BINARY)!=0) {
114 #define ttree ((struct tnode *)tree)
117 * If a subttree starts off with a conversion operator,
118 * try for a match with the conversion eliminated.
119 * E.g. int = double can be done without generating
120 * the converted int in a register by
121 * movf double,fr0; movfi fr0,int .
123 if (opdope1[p2->n_op]&CNVRT && (nocvt&NOCVR)==0
124 && (opdope1[((struct tnode *)p2)->tn_tr1->n_op]&CNVRT)==0) {
125 ttree->tn_tr2 = ((struct tnode *)p2)->tn_tr1;
126 if (opt = match((struct node *)ttree, table, nrleft, NOCVL))
129 } else if (opdope1[p1->n_op]&CNVRT && (nocvt&NOCVL)==0
130 && (opdope1[((struct tnode *)p1)->tn_tr1->n_op]&CNVRT)==0) {
131 ttree->tn_tr1 = ((struct tnode *)p1)->tn_tr1;
132 if (opt = match((struct node *)ttree, table, nrleft, NOCVR))
136 d2 = dcalc(p2, nrleft);
139 for (; table->tabop!=op; table++)
142 for (opt = table->tabp; opt->tabdeg1!=0; opt++) {
143 if (d1 > (opt->tabdeg1&077)
144 || (opt->tabdeg1 >= 0100 && (p1->n_op != STAR)))
146 if (notcompat(p1, opt->tabtyp1, opt->tabdeg1, op))
148 if ((opdope1[op]&BINARY)!=0 && p2!=0) {
149 if (d2 > (opt->tabdeg2&077)
150 || (opt->tabdeg2 >= 0100) && (p2->n_op != STAR) )
152 if (notcompat(p2,opt->tabtyp2, opt->tabdeg2, 0))
154 if ((opt->tabdeg2&077)==20 && xdcalc(p2,nrleft)>20)
163 * Given a tree, a code table, and a register,
164 * produce code to evaluate the tree with the appropriate table.
165 * Registers reg and upcan be used.
166 * If there is a value, it is desired that it appear in reg.
167 * The routine returns the register in which the value actually appears.
168 * This routine must work or there is an error.
169 * If the table called for is cctab, sptab, or efftab,
170 * and tree can't be done using the called-for table,
171 * another try is made.
172 * If the tree can't be compiled using cctab, regtab is
173 * used and a "tst" instruction is produced.
174 * If the tree can't be compiled using sptab,
175 * regtab is used and the register is pushed on the stack.
176 * If the tree can't be compiled using efftab,
178 * Regtab must succeed or an "op not found" error results.
180 * A number of special cases are recognized, and
181 * there is an interaction with the optimizer routines.
183 int rcexpr1(atree, atable, reg) struct node *atree; struct table *atable; int reg; {
185 int modf, nargs, recurf;
186 register struct node *tree;
187 register struct table *table;
189 /*fprintf(stderr, "rcexpr1(0x%08x, 0x%08x, 0x%08x)\n", atree, atable, reg);*/
203 if (tree->n_type==VOID) {
205 error1("Illegal use of void");
208 if (opdope1[tree->n_op]&RELAT && ((struct tnode *)tree)->tn_tr2->n_op==CON
209 && ((struct cnode *)((struct tnode *)tree)->tn_tr2)->cn_value==0
211 tree = atree = ((struct tnode *)tree)->tn_tr1;
213 * fieldselect(...) : in efftab mode,
214 * ignore the select, otherwise
215 * do the shift and mask.
217 if (tree->n_op == FSELT) {
219 atree = tree = ((struct tnode *)tree)->tn_tr1;
222 atree = tree = optim(tree);
225 switch (tree->n_op) {
228 * Structure assignments
232 #define ttree ((struct tnode *)tree)
233 if (ttree->tn_type != STRUCT)
240 * An initializing expression
244 #define ttree ((struct tnode *)tree)
245 doinit(ttree->tn_type, ttree->tn_tr1);
250 * Put the value of an expression in r0,
251 * for a switch or a return
254 #define ttree ((struct tnode *)tree)
255 if (ttree->tn_type == STRUCT) {
260 tree = ((struct tnode *)tree)->tn_tr1;
261 if((r=rcexpr1(tree, regtab, reg)) != 0)
266 * sequential execution
269 #define ttree ((struct tnode *)tree)
271 rcexpr1(ttree->tn_tr1, efftab, reg);
274 atree = tree = ((struct tnode *)tree)->tn_tr2;
278 * In the generated &~ operator,
279 * fiddle things so a PDP-11 "bit"
280 * instruction will be produced when cctab is used.
283 #define ttree ((struct tnode *)tree)
286 ttree->tn_tr2 = optim((struct node *)tnode(COMPL, ttree->tn_type, ttree->tn_tr2, (struct node *)NULL));
292 * Handle a subroutine call. It has to be done
293 * here because if cexpr got called twice, the
294 * arguments might be compiled twice.
295 * There is also some fiddling so the
296 * first argument, in favorable circumstances,
297 * goes to (sp) instead of -(sp), reducing
298 * the amount of stack-popping.
306 * The following code would catch instances of foo(...) where
307 * "foo" was anything other than a simple name. In particular
308 * f(...), (fp(...))(...) and (ffp(...))(...) where "f" is a
309 * pointer to a function, "fp" is a function returning a
310 * pointer to a function and "ffp" is a pointer to a function
311 * returning a pointer to a function. The catch would among
312 * other things cause the (sp)/-(sp) stack optimization to
313 * stop working. The compiler has been tested in all these
314 * different cases with the catch commented out and all the
315 * code generated was correct. So what was it here for?
316 * If a strange error crops up, uncommenting the catch might
319 if (tree->tn_tr1->tn_op!=NAME || tree->tn_tr1->nn_class!=EXTERN) {
324 tree = ((struct tnode *)tree)->tn_tr2;
326 while (tree->n_op==COMMA) {
327 r += comarg(((struct tnode *)tree)->tn_tr2, &modf);
328 tree = ((struct tnode *)tree)->tn_tr1;
331 r += comarg(tree, &modf);
335 #define ttree ((struct tnode *)tree)
336 ttree->tn_op = CALL2;
337 if (modf && ttree->tn_tr1->n_op==NAME
338 && ((struct nnode *)ttree->tn_tr1)->nn_class==EXTERN)
339 ttree->tn_op = CALL1;
340 if (cexpr((struct node *)ttree, regtab, reg)<0)
341 error1("compiler botch: call");
344 if (table==efftab || table==regtab)
351 * Longs need special treatment.
353 case ASULSH: /* 18 */
355 #define ttree ((struct tnode *)tree)
356 if (ttree->tn_type != LONG && ttree->tn_type != UNLONG)
358 if (ttree->tn_tr2->n_op==ITOL)
359 ttree->tn_tr2 = ((struct tnode *)ttree->tn_tr2)->tn_tr1;
361 ttree->tn_tr2 = optim((struct node *)tnode(LTOI,INT,ttree->tn_tr2,(struct node *)NULL));
362 if (ttree->tn_op==ASULSH)
364 ttree->tn_op = UASLSHL;
365 ttree->tn_tr1 = (struct node *)tnode(AMPER, LONG+PTR, ttree->tn_tr1, (struct node *)NULL);
368 ttree->tn_op = ULLSHIFT;
374 #define ttree ((struct tnode *)tree)
375 if (ttree->tn_type==LONG || ttree->tn_type==UNLONG) {
376 if (ttree->tn_tr2->n_op==ITOL)
377 ttree->tn_tr2 = ((struct tnode *)ttree->tn_tr2)->tn_tr1;
379 ttree->tn_tr2 = optim((struct node *)tnode(LTOI,INT,ttree->tn_tr2,(struct node *)NULL));
380 if (ttree->tn_op==ASLSH)
381 ttree->tn_op = ASLSHL;
383 ttree->tn_op = LLSHIFT;
389 * Try to change * to shift.
393 tree = (struct node *)pow2((struct tnode *)tree);
396 * Try to find postfix ++ and -- operators that can be
397 * pulled out and done after the rest of the expression
399 /* delay() has to be able to assume input pointer is a tnode */
400 if (tree != atree) abort();
401 if (table!=cctab && table!=cregtab && recurf<2
402 && (opdope1[tree->n_op]&LEAF)==0) {
403 if (r=delay(&atree, table, reg)) {
410 * Basically, try to reorder the computation
411 * so reg = x+y is done as reg = x; reg += y
413 if (recurf==0 && reorder(&atree, table, reg)) {
414 if (table==cctab && atree->n_op==NAME)
418 if (table==efftab && tree->n_op==NAME)
420 if ((r=cexpr(tree, table, reg))>=0) {
421 if (table==cregtab && (tree->n_op==INCAFT
422 || tree->n_op==DECAFT || tree->n_op==TIMES))
426 if (table!=regtab && (table!=cctab||(opdope1[tree->n_op]&RELAT)==0)) {
427 if((r=cexpr(tree, regtab, reg))>=0) {
429 modf = isfloat(tree);
431 if (table==sptab || table==lsptab) {
432 if (tree->n_type==LONG || tree->n_type==UNLONG){
433 fprintf(temp_fp[temp_fi], "mov\tr%d,-(sp)\n",r+1);
436 fprintf(temp_fp[temp_fi], "mov%s r%d,%s(sp)\n", modf=='f'?"f":"", r,
437 table==sptab? "-":"");
440 if (table==cctab || table==cregtab)
441 fprintf(temp_fp[temp_fi], "tst%s r%d\n", modf=='f'?"f":"", r);
446 * Special grace for unsigned chars as right operands
448 if (opdope1[tree->n_op]&BINARY && ((struct tnode *)tree)->tn_tr2->n_type==UNCHAR) {
449 #define ttree ((struct tnode *)tree)
450 ttree->tn_tr2 = (struct node *)tnode(LOAD, UNSIGN, ttree->tn_tr2, (struct node *)NULL);
451 return(rcexpr1((struct node *)ttree, table, reg));
455 * There's a last chance for this operator
457 if (tree->n_op==LTOI) {
458 #define ttree ((struct tnode *)tree)
459 r = rcexpr1(ttree->tn_tr1, regtab, reg);
468 if (tree->n_type == STRUCT)
469 error1("Illegal operation on structure");
470 else if (r > 0 && r < UASLSHL && opntab[r])
471 error1("No code table for op: %s(%d) type: %d", opntab[r], r,
474 error1("No code table for op %d", r);
479 * Try to compile the tree with the code table using
480 * registers areg and up. If successful,
481 * return the register where the value actually ended up.
482 * If unsuccessful, return -1.
484 * Most of the work is the macro-expansion of the
487 int cexpr(tree, table, areg) register struct node *tree; struct table *table; int areg; {
489 register struct node *p, *p1;
490 struct table *ctable;
493 int reg, reg1, rreg, flag, opd;
500 * When the value of a relational or a logical expression is
501 * desired, more work must be done.
503 if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) {
504 cbranch1(tree, c=isn1++, 1, reg);
505 rcexpr1((struct node *)&czero, table, reg);
508 rcexpr1((struct node *)&cone, table, reg);
513 #define ttree ((struct tnode *)tree)
516 cbranch1(ttree->tn_tr1, c=isn1++, 0, reg);
518 rreg = rcexpr1(((struct tnode *)ttree->tn_tr2)->tn_tr1, table, reg);
520 branch1(r=isn1++, 0, 0);
522 reg = rcexpr1(((struct tnode *)ttree->tn_tr2)->tn_tr2, table, rreg);
524 movreg(reg, rreg, ttree->tn_tr2);
529 reg = oddreg(tree, reg);
532 * long values take 2 registers.
534 if ((tree->n_type==LONG||tree->n_type==UNLONG||opd&RELAT&&(((struct tnode *)tree)->tn_tr1->n_type==LONG||((struct tnode *)tree)->tn_tr1->n_type==UNLONG))
538 * Leaves of the expression tree
540 if ((r = chkleaf(tree, table, reg)) >= 0)
542 /* if chkleaf returns -1 then tree is a struct tnode */
543 #define ttree ((struct tnode *)tree)
545 * x + (-1) is better done as x-1.
547 if (ttree->tn_op==PLUS||ttree->tn_op==ASPLUS) {
548 if ((p1=ttree->tn_tr2)->n_op==CON && ((struct cnode *)p1)->cn_value==-1) {
549 #define cp1 ((struct cnode *)p1)
550 cp1->cn_value = -cp1->cn_value;
551 ttree->tn_op += (MINUS-PLUS);
556 * Because of a peculiarity of the PDP11 table
557 * char = *intreg++ and *--intreg cannot go through.
559 if (ttree->tn_tr2 && (ttree->tn_tr2->n_op==AUTOI||ttree->tn_tr2->n_op==AUTOD)
560 && (ttree->tn_tr1->n_type==CHAR || ttree->tn_tr1->n_type==UNCHAR)
561 && ttree->tn_tr2->n_type!=CHAR && ttree->tn_tr2->n_type!=UNCHAR)
562 ttree->tn_tr2 = (struct node *)tnode(LOAD, ttree->tn_tr2->n_type, ttree->tn_tr2, (struct node *)NULL);
564 * Another peculiarity of the PDP11 table manifested itself when
565 * amplifying the move3: table. The same case which optimizes
566 * u_char to char moves is used to move a u_char to a register. This
567 * is wrong, leading to sign extension. Rather than lose the ability
568 * to generate better code when moving a u_char to a char, a check
569 * is made here to prevent sign extension.
571 * If the opcode is assign, the destination is a register and the
572 * source is u_char then do a conversion.
574 * u_char handling in the compiler is a bit awkward, it would be nice
575 * if %aub in the tables had a more unique meaning.
577 if (ttree->tn_tr2 && ttree->tn_tr1->n_op == NAME
578 && ((struct nnode *)ttree->tn_tr1)->nn_class == REG && ttree->tn_op == ASSIGN
579 && ttree->tn_tr2->n_type == UNCHAR)
580 ttree->tn_tr2 = (struct node *)tnode(LOAD, UNSIGN, ttree->tn_tr2, (struct node *)NULL);
584 * The following peculiar code depends on the fact that
585 * if you just want the codition codes set, efftab
586 * will generate the right code unless the operator is
588 * postfix ++ or --. Unravelled, if the table is
589 * cctab and the operator is not special, try first
590 * for efftab; if the table isn't, if the operator is,
591 * or the first match fails, try to match
592 * with the table actually asked for.
595 * Account for longs and oddregs; below is really
596 * r = nreg - reg - (reg-areg) - (reg1-reg-1);
598 r = nreg - reg + areg - reg1 + 1;
599 if (table!=cctab || c==INCAFT || c==DECAFT || ttree->tn_type==LONG || ttree->tn_type==UNLONG
600 /* || c==ASRSH || c==ASLSH || c==ASULSH || ttree->tn_tr1->tn_type==UNCHAR */
601 || c==ASRSH || c==ASLSH || c==ASULSH
602 || (opt = match((struct node *)ttree, efftab, r, 0)) == 0)
603 if ((opt=match((struct node *)ttree, table, r, 0))==0)
605 string = opt->tabstring;
607 if (p1->n_op==FCON && ((struct fnode *)p1)->fn_value>0) {
608 #define fp1 ((struct fnode *)p1)
611 fprintf(temp_fp[temp_fi], ".data\nL%d:%o;%o;%o;%o\n.text\n", fp1->fn_value,
612 ((_UNSIGNED_INT *)&(fp1->fn_fvalue))[0],
613 ((_UNSIGNED_INT *)&(fp1->fn_fvalue))[1],
614 ((_UNSIGNED_INT *)&(fp1->fn_fvalue))[2],
615 ((_UNSIGNED_INT *)&(fp1->fn_fvalue))[3] );
617 fprintf(temp_fp[temp_fi], ".data\nL%d:%o;%o;%o;%o\n.text\n", fp1->fn_value,
618 (int)(fp1->fn_fvalue.h >> 16) & 0xffff,
619 (int)fp1->fn_fvalue.h & 0xffff,
620 (int)(fp1->fn_fvalue.l >> 16) & 0xffff,
621 (int)fp1->fn_fvalue.l & 0xffff );
623 fp1->fn_value = -fp1->fn_value; /* says flushed out */
627 if (opdope1[ttree->tn_op]&BINARY) {
629 if (p2->n_op==FCON && ((struct fnode *)p2)->fn_value>0) {
630 #define fp2 ((struct fnode *)p2)
633 fprintf(temp_fp[temp_fi], ".data\nL%d:%o;%o;%o;%o\n.text\n", fp2->fn_value,
634 ((_UNSIGNED_INT *)&(fp2->fn_fvalue))[0],
635 ((_UNSIGNED_INT *)&(fp2->fn_fvalue))[1],
636 ((_UNSIGNED_INT *)&(fp2->fn_fvalue))[2],
637 ((_UNSIGNED_INT *)&(fp2->fn_fvalue))[3] );
639 fprintf(temp_fp[temp_fi], ".data\nL%d:%o;%o;%o;%o\n.text\n", fp2->fn_value,
640 (int)(fp2->fn_fvalue.h >> 16) & 0xffff,
641 (int)fp2->fn_fvalue.h & 0xffff,
642 (int)(fp2->fn_fvalue.l >> 16) & 0xffff,
643 (int)fp2->fn_fvalue.l & 0xffff );
645 fp2->fn_value = -fp2->fn_value; /* says flushed out */
651 * The 0200 bit asks for a tab.
653 if ((c = *string++) & 0200) {
655 fputc('\t', temp_fp[temp_fi]) /*putchar('\t')*/;
660 dbprint(ttree->tn_op);
664 if (!isfloat((struct node *)ttree))
665 if (ttree->tn_op==DIVIDE||ttree->tn_op==ASDIV)
667 if (table==regtab && (opdope1[ttree->tn_op]&ASSGOP)) {
668 if (ttree->tn_tr1->n_type==CHAR)
669 fprintf(temp_fp[temp_fi], "movb r%d,r%d\n", reg, reg);
685 while (*string=='\'') {
698 if ((c = *string)=='\'')
702 prins(ttree->tn_op, c, instab, 0);
708 p = (struct node *)ttree;
715 p = (struct node *)ttree;
722 if (p->n_type==CHAR || p->n_type==UNCHAR)
723 fputc('b', temp_fp[temp_fi]);
726 fputc('f', temp_fp[temp_fi]);
731 if (p1->n_type==CHAR || p2->n_type==CHAR
732 || p1->n_type==UNCHAR || p2->n_type==UNCHAR)
733 fputc('b', temp_fp[temp_fi]);
734 p = (struct node *)ttree;
751 p = (struct node *)ttree;
761 c |= 020; /* force right register */
765 c |= 040; /* force condition codes */
771 if ((flag&01) && ctable==regtab && (c&01)==0
772 && ((c&040)||ttree->tn_op==DIVIDE||ttree->tn_op==MOD
773 || ttree->tn_op==ASDIV||ttree->tn_op==ASMOD||ttree->tn_op==ITOL))
776 /* previous code was accessing tn_tr1 without a type check */
777 if (opdope1[p->n_op] & LEAF) abort();
778 p = ((struct tnode *)p)->tn_tr1;
779 if(collcon(p) && ctable!=sptab) {
781 p = ((struct tnode *)p)->tn_tr1;
782 p = ((struct tnode *)p)->tn_tr1;
785 if (table==lsptab && ctable==sptab)
790 if (opdope1[p->n_op]&LEAF || ((struct tnode *)p)->tn_degree < 2)
794 rreg = rcexpr1(p, ctable, r);
795 if (ctable!=regtab && ctable!=cregtab)
798 if (c&020 && rreg!=reg1)
799 movreg(rreg, reg1, p);
802 } else if (rreg!=reg)
803 if ((c&020)==0 && oddreg((struct node *)ttree, 0)==0 && ttree->tn_type!=LONG
804 && ttree->tn_type!=UNLONG
806 || flag&01&&xdcalc(p2,nreg-rreg-1)<=(opt->tabdeg2&077)
807 || flag&02&&xdcalc(p1,nreg-rreg-1)<=(opt->tabdeg1&077))) {
811 movreg(rreg, reg, p);
831 if (r>nreg || r>=4 && ttree->tn_type==DOUBLE) {
833 error1("Register overflow: simplify expression");
836 fprintf(stderr, "warning: register overflow\n");
840 fprintf(temp_fp[temp_fi], "r%d", r);
843 case '-': /* check -(sp) */
847 fputc('-', temp_fp[temp_fi]);
852 case ')': /* check (sp)+ */
853 fputc(')', temp_fp[temp_fi]);
860 /* previous code was accessing tn_tr1 without a type check */
861 if (opdope1[p1->n_op] & LEAF) abort();
862 p = ((struct tnode *)p1)->tn_tr1;
867 /* previous code was accessing tn_tr1 without a type check */
868 if (opdope1[p2->n_op] & LEAF) abort();
869 p = ((struct tnode *)p2)->tn_tr1;
874 fprintf(temp_fp[temp_fi], "*");
875 p = ((struct tnode *)p)->tn_tr1;
877 if ((p = ((struct tnode *)p)->tn_tr2)->n_op == CON) {
878 #define cp ((struct cnode *)p)
882 } else if (p->n_op==AMPER)
883 pname(((struct tnode *)p)->tn_tr1, 0);
888 * Certain adjustments for / %
892 if (uns(p1) || uns(p2)) {
893 fprintf(temp_fp[temp_fi], "clr r%d\n", c);
896 if (dcalc(p1, 5)>12 && !match(p1, cctab, 10, 0))
897 fprintf(temp_fp[temp_fi], "tst r%d\n", reg);
898 fprintf(temp_fp[temp_fi], "sxt r%d\n", c);
901 case 'V': /* adc sbc, clr, or sxt as required for longs */
902 switch(ttree->tn_op) {
907 fprintf(temp_fp[temp_fi], "adc");
915 fprintf(temp_fp[temp_fi], "sbc");
927 if (p->n_type!=LONG && p->n_type!=UNLONG) {
928 if (uns(p) || uns(ttree->tn_tr2))
929 fprintf(temp_fp[temp_fi], "clr");
931 fprintf(temp_fp[temp_fi], "sxt");
935 /* no conversion needed, skip to end of line */
936 while ((c = *string++)!='\n' && c!='\0');
942 * Mask used in field assignments
945 /* previous code was accessing fa_mask without a type check */
946 if (ttree->tn_op != FSELA) abort();
947 fprintf(temp_fp[temp_fi], "$%o", UNS(((struct fasgn *)ttree)->fa_mask));
951 * Relational on long values.
952 * Might bug out early. E.g.,
953 * (long<0) can be determined with only 1 test.
956 if (xlongrel(*string++ - '0'))
960 fputc(c, temp_fp[temp_fi]);
966 * This routine just calls sreorder (below)
967 * on the subtrees and then on the tree itself.
968 * It returns non-zero if anything changed.
970 int reorder(treep, table, reg) struct node **treep; struct table *table; int reg; {
972 register struct node *p;
976 if (opdope1[o]&LEAF||o==LOGOR||o==LOGAND||o==SEQNC||o==QUEST||o==COLON)
978 #define tp ((struct tnode *)p)
979 while(sreorder(&tp->tn_tr1, regtab, reg, 1))
981 if (opdope1[o]&BINARY)
982 while(sreorder(&tp->tn_tr2, regtab, reg, 1))
986 while (sreorder(treep, table, reg, 0))
988 *treep = optim(*treep);
994 * Basically this routine carries out two kinds of optimization.
995 * First, it observes that "x + (reg = y)" where actually
996 * the = is any assignment op is better done as "reg=y; x+reg".
997 * In this case rcexpr is called to do the first part and the
998 * tree is modified so the name of the register
999 * replaces the assignment.
1000 * Moreover, expressions like "reg = x+y" are best done as
1001 * "reg = x; reg += y" (so long as "reg" and "y" are not the same!).
1003 int sreorder(treep, table, reg, recurf) struct node **treep; struct table *table; int reg; int recurf; {
1004 register struct node *p, *p1;
1007 if (opdope1[p->n_op]&LEAF)
1009 #define tp ((struct tnode *)p)
1010 if (tp->tn_op==PLUS && recurf)
1011 if (reorder(&tp->tn_tr2, table, reg))
1012 /* in this case optim() is guaranteed to return a struct tnode */
1014 *treep = p = optim((struct node *)tp);
1015 if (opdope1[p->n_op] & LEAF) abort();
1017 if ((p1 = tp->tn_tr1)==(struct node *)NULL)
1019 if (tp->tn_op==STAR || tp->tn_op==PLUS) {
1020 if (recurf && reorder(&tp->tn_tr1, table, reg)) {
1021 /* in this case optim() might not return a struct tnode */
1022 *treep = p = optim((struct node *)tp);
1023 if (opdope1[p->n_op]&LEAF)
1025 /* but it's a struct tnode, so continue accessing via tp */
1029 if (p1->n_op==NAME) switch(tp->tn_op) {
1033 if (((struct nnode *)p1)->nn_class != REG || ((struct nnode *)p1)->nn_type==CHAR
1034 || isfloat(tp->tn_tr2))
1036 if (tp->tn_op==ASSIGN) switch (tp->tn_tr2->n_op) {
1038 if (tp->tn_type==UNSIGN)
1042 if (!ispow2((struct tnode *)tp->tn_tr2))
1044 tp->tn_tr2 = (struct node *)pow2((struct tnode *)tp->tn_tr2);
1053 p1 = ((struct tnode *)tp->tn_tr2)->tn_tr2;
1054 /* here tp->tn_tr1 (former p1) is a locnnode of class REG, checked above */
1055 /* XXX formerly nn_class was not checked in the below, so random values of */
1056 /* nloc/name could (rarely) have caused the optimization not to be applied */
1057 if (xdcalc(p1, 16) > 12
1059 &&(((struct nnode *)p1)->nn_class == REG && ((struct locnnode *)p1)->locnn_nloc==((struct locnnode *)tp->tn_tr1)->locnn_nloc
1060 || (((struct nnode *)p1)->nn_class == OFFS || ((struct nnode *)p1)->nn_class == SOFFS || ((struct nnode *)p1)->nn_class == XOFFS) && ((struct nnode *)p1)->nn_regno==((struct locnnode *)tp->tn_tr1)->locnn_nloc))
1063 #define tp1 ((struct tnode *)p1)
1064 tp->tn_tr2 = tp1->tn_tr1;
1065 if (tp1->tn_tr1->n_op!=NAME
1066 || ((struct nnode *)tp1->tn_tr1)->nn_class!=REG
1067 || ((struct locnnode *)tp1->tn_tr1)->locnn_nloc!=((struct locnnode *)tp->tn_tr1)->locnn_nloc)
1068 rcexpr1((struct node *)tp, efftab, reg);
1069 tp->tn_tr2 = tp1->tn_tr2;
1070 tp->tn_op = tp1->tn_op + ASPLUS - PLUS;
1071 *treep = (struct node *)tp;
1089 if (table==cctab||table==cregtab)
1091 rcexpr1(optim((struct node *)tp), efftab, ~reg);
1100 * Delay handles postfix ++ and --
1101 * It observes that "x + y++" is better
1102 * treated as "x + y; y++".
1103 * If the operator is ++ or -- itself,
1104 * it calls rcexpr to load the operand, letting
1105 * the calling instance of rcexpr to do the
1107 * Otherwise it uses sdelay to search for inc/dec
1108 * among the operands.
1110 int delay(treep, table, reg) struct node **treep; struct table *table; int reg; {
1111 register struct tnode *p;
1112 register struct node *p1;
1115 p = (struct tnode *)*treep;
1116 if ((p->tn_op==INCAFT||p->tn_op==DECAFT)
1117 && p->tn_tr1->n_op==NAME) {
1118 r = ((struct nnode *)p->tn_tr1)->nn_class;
1119 if (r == EXTERN || r == OFFS || r == STATIC &&
1120 p->tn_tr1->n_type == UNCHAR)
1121 return(1+rcexpr1(p->tn_tr1, table, reg));
1123 return(1+rcexpr1(paint(p->tn_tr1, p->tn_type), table,reg));
1127 * typo fix, original code.
1128 * if (opdope1[p->tn_op]&BINARY) {
1129 * if (p->tn_op==LOGAND || p->tn_op==LOGOR
1130 * || p->tn_op==QUEST || p->tn_op==COLON || p->tn_op==SEQNC)
1133 * p1 = sdelay(&p->tn_tr2);
1135 * p1 = sdelay(&p->tn_tr1);
1137 if (opdope1[p->tn_op]&BINARY) {
1138 if (p->tn_op==LOGAND || p->tn_op==LOGOR
1139 || p->tn_op==QUEST || p->tn_op==COLON || p->tn_op==SEQNC)
1141 p1 = sdelay(&p->tn_tr2);
1144 p1 = sdelay(&p->tn_tr1);
1146 r = rcexpr1(optim((struct node *)p), table, reg);
1153 struct node *sdelay(ap) struct node **ap; {
1154 register struct node *p, *p1;
1156 if ((p = *ap)==(struct node *)NULL)
1157 return((struct node *)NULL);
1158 if ((p->n_op==INCAFT||p->n_op==DECAFT) && ((struct tnode *)p)->tn_tr1->n_op==NAME) {
1159 #define tp ((struct tnode *)p)
1160 *ap = paint((struct node *)ncopy((struct nnode *)tp->tn_tr1), tp->tn_type);
1161 return((struct node *)tp);
1164 if (p->n_op==STAR || p->n_op==PLUS)
1165 if (p1=sdelay(&((struct tnode *)p)->tn_tr1))
1168 return(sdelay(&((struct tnode *)p)->tn_tr2));
1173 * Propagate possible implicit type-changing operation
1175 struct node *paint(tp, type) register struct node *tp; register int type; {
1177 if (tp->n_type==type)
1179 if (tp->n_type==CHAR && type==INT)
1181 if (tp->n_type==CHAR || tp->n_type==UNCHAR)
1182 return(optim((struct node *)tnode(LOAD, type, tp, (struct node *)NULL)));
1184 if (tp->n_op==AMPER && type&XTYPE)
1185 #define ttp ((struct tnode *)tp)
1186 ttp->tn_tr1 = paint(ttp->tn_tr1, decref1(type));
1188 else if (tp->n_op==STAR)
1189 #define ttp ((struct tnode *)tp)
1190 ttp->tn_tr1 = paint(ttp->tn_tr1, incref1(type));
1192 else if (tp->n_op==ASSIGN) {
1193 #define ttp ((struct tnode *)tp)
1194 /* previous code was not saving back return value from paint() ??? */
1196 paint(ttp->tn_tr1, type);
1197 if (temp != ttp->tn_tr1) fprintf(stderr, "warning: possible paint() issue\n");
1199 paint(ttp->tn_tr2, type);
1200 if (temp != ttp->tn_tr2) fprintf(stderr, "warning: possible paint() issue\n");
1207 * Copy a tree node for a register variable.
1208 * Used by sdelay because if *reg-- is turned
1209 * into *reg; reg-- the *reg will in turn
1210 * be changed to some offset class, accidentally
1211 * modifying the reg--.
1213 struct nnode *ncopy(p) register struct nnode *p; {
1216 if (p->nn_class==EXTERN || p->nn_class==XOFFS) {
1217 #define extp ((struct extnnode *)p)
1218 #define extq (*(struct extnnode **)&q)
1219 extq = (struct extnnode *)getblk(sizeof(struct extnnode));
1220 extq->extnn_name = extp->extnn_name;
1225 #define locp ((struct locnnode *)p)
1226 #define locq (*(struct locnnode **)&q)
1227 locq = (struct locnnode *)getblk(sizeof(struct locnnode));
1228 locq->locnn_nloc = locp->locnn_nloc;
1232 q->nn_op = p->nn_op;
1233 q->nn_type = p->nn_type;
1234 q->nn_class = p->nn_class;
1235 q->nn_regno = p->nn_regno;
1236 q->nn_offset = p->nn_offset;
1241 * If the tree can be immediately loaded into a register,
1242 * produce code to do so and return success.
1244 int chkleaf(tree, table, reg) register struct node *tree; struct table *table; int reg; {
1247 if (tree->n_op!=STAR && dcalc(tree, nreg-reg) > 12)
1249 /* if dcalc() returns 0 then either tree == NULL or tree is a struct tnode */
1250 #define ttree ((struct tnode *)tree)
1252 lbuf.tn_type = ttree->tn_type;
1253 lbuf.tn_degree = ttree->tn_degree;
1255 /* can't have garbage in lbuf.tr2, cexpr() will deref it if non-NULL */
1256 lbuf.tn_tr2 = (struct node *)NULL;
1257 return(rcexpr1((struct node *)&lbuf, table, reg));
1261 * Compile a function argument.
1262 * If the stack is currently empty, put it in (sp)
1263 * rather than -(sp); this will save a pop.
1264 * Return the number of bytes pushed,
1265 * for future popping.
1267 int comarg(tree, flagp) register struct node *tree; int *flagp; {
1268 register int retval;
1272 if (/*tree->n_op==STRASG*/tree->n_type==STRUCT) {
1273 /* size = tree->fa_mask;
1274 tree = tree->tn_tr1;*/
1275 size = tree->n_strp->S.ssize;
1276 tree = strfunc(tree);
1277 if (size <= sizeof(_INT)) {
1281 if (size <= sizeof(_LONG)) {
1285 if (tree->n_op!=NAME && tree->n_op!=STAR) {
1286 error1("Unimplemented structure assignment");
1289 tree = (struct node *)tnode(AMPER, STRUCT+PTR, tree, (struct node *)NULL);
1290 tree = (struct node *)tnode(PLUS, STRUCT+PTR, tree, (struct node *)tconst(size, INT));
1292 retval = rcexpr1(tree, regtab, 0);
1295 for (i=0; i<size; i++)
1296 fprintf(temp_fp[temp_fi], "mov -(r%d),-(sp)\n", retval);
1299 fprintf(temp_fp[temp_fi], "mov r%d,r0\n", retval);
1300 fprintf(temp_fp[temp_fi], "mov $%o,r1\n", UNS(size));
1301 fprintf(temp_fp[temp_fi], "L%d:mov -(r0),-(sp)\ndec\tr1\njne\tL%d\n", isn1, isn1);
1308 if (nstack || isfloat(tree) || tree->n_type==LONG || tree->n_type==UNLONG) {
1309 rcexpr1(tree, sptab, 0);
1310 retval = arlength(tree->n_type);
1313 rcexpr1(tree, lsptab, 0);
1319 struct node *strfunc(tp) register struct node *tp; {
1320 if (tp->n_op != CALL)
1322 paint(tp, STRUCT+PTR);
1323 return((struct node *)tnode(STAR, STRUCT, tp, (struct node *)NULL));
1327 * Compile an initializing expression
1329 void doinit(type, tree) register int type; register struct node *tree; {
1334 if (type==CHAR || type==UNCHAR) {
1335 fprintf(temp_fp[temp_fi], ".byte ");
1336 if (tree->n_type&XTYPE)
1345 if (tree->n_op==FTOI) {
1346 if (((struct tnode *)tree)->tn_tr1->n_op!=FCON && ((struct tnode *)tree)->tn_tr1->n_op!=SFCON)
1348 tree = ((struct tnode *)tree)->tn_tr1;
1349 fval = ((struct fnode *)tree)->fn_fvalue;
1350 ((struct cnode *)tree)->cn_op = CON;
1352 ((struct cnode *)tree)->cn_value = fval;
1354 ((struct cnode *)tree)->cn_value = fp_double_to_int(fval);
1356 } else if (tree->n_op==LTOI) {
1357 if (((struct tnode *)tree)->tn_tr1->n_op!=LCON)
1359 tree = ((struct tnode *)tree)->tn_tr1;
1360 lval = ((struct lnode *)tree)->ln_lvalue;
1361 ((struct cnode *)tree)->cn_op = CON;
1362 ((struct cnode *)tree)->cn_value = lval;
1364 if (tree->n_op == CON)
1365 fprintf(temp_fp[temp_fi], "%o\n", UNS(((struct cnode *)tree)->cn_value));
1366 else if (tree->n_op==AMPER) {
1367 pname(((struct tnode *)tree)->tn_tr1, 0);
1368 fputc('\n', temp_fp[temp_fi]) /*putchar('\n')*/;
1375 if (tree->n_op==ITOF) {
1376 #define ttree ((struct tnode *)tree)
1377 if (ttree->tn_tr1->n_op==CON) {
1378 /* note: this should be changed to respect the signedness of the int */
1380 fval = ((struct cnode *)ttree->tn_tr1)->cn_value;
1382 fval = fp_int_to_double(((struct cnode *)ttree->tn_tr1)->cn_value);
1387 } else if (tree->n_op==FCON || tree->n_op==SFCON) {
1388 fval = ((struct fnode *)tree)->fn_fvalue;
1389 } else if (tree->n_op==LTOF) {
1390 #define ttree ((struct tnode *)tree)
1391 if (ttree->tn_tr1->n_op!=LCON)
1393 /* note: this should be changed to respect the signedness of the long */
1395 fval = ((struct lnode *)ttree->tn_tr1)->ln_lvalue;
1397 fval = fp_long_to_double(((struct lnode *)ttree->tn_tr1)->ln_lvalue);
1406 fprintf(temp_fp[temp_fi], "%o; %o\n",
1407 ((_UNSIGNED_INT *)&sfval)[0],
1408 ((_UNSIGNED_INT *)&sfval)[1]);
1410 sfval = fp_double_to_float(fval);
1411 fprintf(temp_fp[temp_fi], "%o; %o\n",
1412 (int)(sfval.h >> 16) & 0xffff,
1413 (int)sfval.h & 0xffff);
1418 fprintf(temp_fp[temp_fi], "%o; %o; %o; %o\n",
1419 ((_UNSIGNED_INT *)&fval)[0],
1420 ((_UNSIGNED_INT *)&fval)[1],
1421 ((_UNSIGNED_INT *)&fval)[2],
1422 ((_UNSIGNED_INT *)&fval)[3]);
1424 fprintf(temp_fp[temp_fi], "%o; %o; %o; %o\n",
1425 (int)(fval.h >> 16) & 0xffff,
1426 (int)fval.h & 0xffff,
1427 (int)(fval.l >> 16) & 0xffff,
1428 (int)fval.l & 0xffff);
1435 if (tree->n_op==FTOL) {
1436 tree = ((struct tnode *)tree)->tn_tr1;
1437 if (tree->n_op==SFCON)
1439 if (tree->n_op!= FCON)
1442 lval = ((struct fnode *)tree)->fn_fvalue;
1444 lval = fp_double_to_long(((struct fnode *)tree)->fn_fvalue);
1446 } else if (tree->n_op==ITOL) {
1447 #define ttree ((struct tnode *)tree)
1448 if (ttree->tn_tr1->n_op != CON)
1450 if (uns(ttree->tn_tr1))
1451 lval = (_UNSIGNED_INT)((struct cnode *)ttree->tn_tr1)->cn_value;
1453 lval = ((struct cnode *)ttree->tn_tr1)->cn_value;
1455 } else if (tree->n_op==LCON) {
1456 lval = ((struct lnode *)tree)->ln_lvalue;
1460 fprintf(temp_fp[temp_fi], "%o; %o\n", UNS((lval>>16)), UNS(lval));
1464 error1("Illegal initialization");
1467 void movreg(r0, r1, tree) int r0; int r1; struct node *tree; {
1473 if (tree->n_type==LONG || tree->n_type == UNLONG) {
1474 if (r0>=nreg || r1>=nreg) {
1475 error1("register overflow: compiler error");
1477 s = "mov r%d,r%d\nmov r%d,r%d\n";
1479 fprintf(temp_fp[temp_fi], s, r0+1,r1+1,r0,r1);
1481 fprintf(temp_fp[temp_fi], s, r0,r1,r0+1,r1+1);
1485 fprintf(temp_fp[temp_fi], "mov%.1s r%d,r%d\n", &c, r0, r1);