📄 c10.c
字号:
#/* C compiler, part 2*/#include "c1h.c"char maprel[] { EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ, LESS, GREATQP, GREATP, LESSEQP, LESSP};char notrel[] { NEQUAL, EQUAL, GREAT, GREATEQ, LESS, LESSEQ, GREATP, GREATQP, LESSP, LESSEQP};struct tconst czero { CON, INT, 0, 0};struct tconst cone { CON, INT, 0, 1};struct tconst fczero { SFCON, DOUBLE, 0, 0 };struct table *cregtab;int nreg 3;int isn 10000;int namsiz 8;main(argc, argv)char *argv[];{ extern fout; if (argc<4) { error("Arg count"); exit(1); } if(fopen(argv[1], ascbuf)<0) { error("Missing temp file"); exit(1); } if ((fout = creat(argv[3], 0666)) < 0) { error("Can't create %s", argv[3]); exit(1); } spacep = treespace; getree(); /* * If any floating-point instructions * were used, generate a reference which * pulls in the floating-point part of printf. */ if (nfloat) printf(".globl fltused\n"); /* * tack on the string file. */ close(ascbuf[0]); if (fopen(argv[2], ascbuf)<0) { error("Missing temp file"); exit(1); } printf(".globl\n.data\n"); getree(); flush(); exit(nerror!=0);}/* * Given a tree, a code table, and a * count of available registers, find the code table * for the appropriate operator such that the operands * are of the right type and the number of registers * required is not too large. * Return a ptr to the table entry or 0 if none found. */char *match(atree, table, nrleft)struct tnode *atree;struct table *table;{ int op, d1, d2, t1, t2, dope; struct tnode *p2; register struct tnode *p1, *tree; register struct optab *opt; if ((tree=atree)==0) return(0); if (table==lsptab) table = sptab; if ((op = tree->op)==0) return(0); dope = opdope[op]; if ((dope&LEAF) == 0) p1 = tree->tr1; else p1 = tree; t1 = p1->type; d1 = dcalc(p1, nrleft); if ((dope&BINARY)!=0) { p2 = tree->tr2; /* * If a subtree starts off with a conversion operator, * try for a match with the conversion eliminated. * E.g. int = double can be done without generating * the converted int in a register by * movf double,fr0; movfi fr0,int . */ if(opdope[p1->op]&CNVRT && (opdope[p2->op]&CNVRT)==0) { tree->tr1 = p1->tr1; if (opt = match(tree, table, nrleft)) return(opt); tree->tr1 = p1; } else if (opdope[p2->op]&CNVRT && (opdope[p1->op]&CNVRT)==0) { tree->tr2 = p2->tr1; if (opt = match(tree, table, nrleft)) return(opt); tree->tr2 = p2; } t2 = p2->type; d2 = dcalc(p2, nrleft); } for (; table->op!=op; table++) if (table->op==0) return(0); for (opt = table->tabp; opt->tabdeg1!=0; opt++) { if (d1 > (opt->tabdeg1&077) || (opt->tabdeg1 >= 0100 && (p1->op != STAR))) continue; if (notcompat(p1, opt->tabtyp1, op)) { continue; } if ((opdope[op]&BINARY)!=0 && p2!=0) { if (d2 > (opt->tabdeg2&077) || (opt->tabdeg2 >= 0100) && (p2->op != STAR) ) continue; if (notcompat(p2,opt->tabtyp2, 0)) continue; } return(opt); } return(0);}/* * Given a tree, a code table, and a register, * produce code to evaluate the tree with the appropriate table. * Registers reg and upcan be used. * If there is a value, it is desired that it appear in reg. * The routine returns the register in which the value actually appears. * This routine must work or there is an error. * If the table called for is cctab, sptab, or efftab, * and tree can't be done using the called-for table, * another try is made. * If the tree can't be compiled using cctab, regtab is * used and a "tst" instruction is produced. * If the tree can't be compiled using sptab, * regtab is used and the register is pushed on the stack. * If the tree can't be compiled using efftab, * just use regtab. * Regtab must succeed or an "op not found" error results. * * A number of special cases are recognized, and * there is an interaction with the optimizer routines. */rcexpr(atree, atable, reg)struct tnode *atree;struct table *atable;{ register r; int modf, nargs, recurf; register struct tnode *tree; register struct table *table; table = atable; recurf = 0; if (reg<0) { recurf++; reg = ~reg; if (reg>=020) { reg =- 020; recurf++; } } if((tree=atree)==0) return(0); switch (tree->op) { /* * A conditional branch */ case CBRANCH: cbranch(optim(tree->btree), tree->lbl, tree->cond, 0); return(0); /* * An initializing expression */ case INIT: if (tree->tr1->op == AMPER) tree->tr1 = tree->tr1->tr1; if (tree->tr1->op==NAME) pname(tree->tr1); else if (tree->tr1==CON) psoct(tree->tr1->value); else error("Illegal initialization"); putchar('\n'); return(0); /* * Put the value of an expression in r0, * for a switch or a return */ case RFORCE: if((r=rcexpr(tree->tr1, regtab, reg)) != 0) printf("mov%c r%d,r0\n", isfloat(tree->tr1), r); return(0); /* * sequential execution */ case COMMA: rcexpr(tree->tr1, efftab, reg); atree = tree = tree->tr2; break; /* * In the generated &~ operator, * fiddle things so a PDP-11 "bit" * instruction will be produced when cctab is used. */ case NAND: if (table==cctab) { tree->op = TAND; tree->tr2 = optim(block(1, COMPL, INT, 0, tree->tr2)); } break; /* * Handle a subroutine call. It has to be done * here because if cexpr got called twice, the * arguments might be compiled twice. * There is also some fiddling so the * first argument, in favorable circumstances, * goes to (sp) instead of -(sp), reducing * the amount of stack-popping. */ case CALL: r = 0; nargs = 0; modf = 0; if (tree->tr1->op!=NAME) { /* get nargs right */ nargs++; nstack++; } tree = tree->tr2; if(tree->op) { while (tree->op==COMMA) { r =+ comarg(tree->tr2, &modf); tree = tree->tr1; nargs++; } r =+ comarg(tree, &modf); nargs++; } tree = atree; tree->op = CALL2; if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN) tree->op = CALL1; cexpr(tree, regtab, reg); popstk(r); nstack =- nargs; if (table==efftab || table==regtab) return(0); r = 0; goto fixup; /* * Longs need special treatment. */ case ASLSH: case LSHIFT: if (tree->type==LONG) { if (tree->tr2->op==ITOL) tree->tr2 = tree->tr2->tr1; if (tree->op==ASLSH) tree->op = ASLSHL; else tree->op = LLSHIFT; } break; /* * Try to change * and / to shifts. */ case TIMES: case DIVIDE: case ASTIMES: case ASDIV: tree = pow2(tree); } /* * Try to find postfix ++ and -- operators that can be * pulled out and done after the rest of the expression */ if (table!=cctab && table!=cregtab && recurf<2 && (opdope[tree->op]&LEAF)==0) { if (r=delay(&atree, table, reg)) { tree = atree; table = efftab; reg = r-1; } } /* * Basically, try to reorder the computation * so reg = x+y is done as reg = x; reg =+ y */ if (recurf==0 && reorder(&atree, table, reg)) { if (table==cctab && atree->op==NAME) return(reg); } tree = atree; if (table==efftab && tree->op==NAME) return(reg); if ((r=cexpr(tree, table, reg))>=0) return(r); if (table!=regtab) { if((r=cexpr(tree, regtab, reg))>=0) { fixup: modf = isfloat(tree); if (table==sptab || table==lsptab) { if (tree->type==LONG) { printf("mov\tr%d,-(sp)\n",r+1); nstack++; } printf("mov%c r%d,%c(sp)\n", modf, r, table==sptab? '-':0); nstack++; } if (table==cctab) printf("tst%c r%d\n", modf, r); return(r); } } if (tree->op>0 && tree->op<RFORCE && opntab[tree->op]) error("No code table for op: %s", opntab[tree->op]); else error("No code table for op %d", tree->op); return(reg);}/* * Try to compile the tree with the code table using * registers areg and up. If successful, * return the register where the value actually ended up. * If unsuccessful, return -1. * * Most of the work is the macro-expansion of the * code table. */cexpr(atree, table, areg)struct tnode *atree;struct table *table;{ int c, r; register struct tnode *p, *p1, *tree; struct table *ctable; struct tnode *p2; char *string; int reg, reg1, rreg, flag, opd; char *opt; tree = atree; reg = areg; p1 = tree->tr2; c = tree->op; opd = opdope[c]; /* * When the value of a relational or a logical expression is * desired, more work must be done. */ if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) { cbranch(tree, c=isn++, 1, reg); rcexpr(&czero, table, reg); branch(isn, 0); label(c); rcexpr(&cone, table, reg); label(isn++); return(reg); } if(c==QUEST) { if (table==cctab) return(-1); cbranch(tree->tr1, c=isn++, 0, reg); flag = nstack; rreg = rcexpr(p1->tr1, table, reg); nstack = flag; branch(r=isn++, 0); label(c); reg = rcexpr(p1->tr2, table, rreg); if (rreg!=reg) printf("mov%c r%d,r%d\n", isfloat(tree),reg,rreg); label(r); return(rreg); } reg = oddreg(tree, reg); reg1 = reg+1; /* * long values take 2 registers. */ if (tree->type==LONG && tree->op!=ITOL) reg1++; /* * Leaves of the expression tree */ if ((r = chkleaf(tree, table, reg)) >= 0) return(r); /* * x + (-1) is better done as x-1. */ if ((tree->op==PLUS||tree->op==ASPLUS) && (p1=tree->tr2)->op == CON && p1->value == -1) { p1->value = 1; tree->op =+ (MINUS-PLUS); } if (table==cregtab) table = regtab; /* * The following peculiar code depends on the fact that * if you just want the codition codes set, efftab * will generate the right code unless the operator is * postfix ++ or --. Unravelled, if the table is * cctab and the operator is not special, try first * for efftab; if the table isn't, if the operator is, * or the first match fails, try to match * with the table actually asked for. */ if (table!=cctab || c==INCAFT || c==DECAFT || (opt = match(tree, efftab, nreg-reg)) == 0) if ((opt=match(tree, table, nreg-reg))==0) return(-1); string = opt->tabstring; p1 = tree->tr1; p2 = 0; if (opdope[tree->op]&BINARY) p2 = tree->tr2;loop: /* * The 0200 bit asks for a tab. */ if ((c = *string++) & 0200) { c =& 0177; putchar('\t'); } switch (c) { case '\0': if (!isfloat(tree)) if (tree->op==DIVIDE || tree->op==ASDIV)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -