V5/usr/c/c10.c
#
/*
C compiler, part 2
Copyright 1972 Bell Telephone Laboratories, Inc.
*/
#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 *tabtab[]
{
regtab,
efftab,
cctab,
sptab,
0
};
int nreg 3;
int isn 10000;
int namsiz 8;
int *treebase;
struct tnode *xdel[2];
main(argc, argv)
char *argv[];
{
int treespace[ossiz];
struct table *table;
register *sp, c, *tree;
extern fout;
if (argc<4) {
error("Arg count");
exit(1);
}
if(fopen(argv[1], ascbuf)<0 || fopen(argv[2], binbuf)<0){
error("Missing temp file");
exit(1);
}
if ((fout = creat(argv[3], 0666)) < 0) {
error("Can't create %s", argv[3]);
exit(1);
}
treebase = getw(binbuf);
if (treebase < treespace) {
error("Tree space botch");
exit(1);
}
spacemax = &treespace[ossiz];
while ((c=getc(ascbuf)) > 0) {
if(c=='#') {
sp = treebase;
c = getw(binbuf);
tree = getw(binbuf);
table = tabtab[getw(binbuf)];
line = getw(binbuf);
while(--c >= 0)
*sp++ = getw(binbuf);
if (table==0) /* is switch */
pswitch(treebase, sp, tree);
else {
spacep = sp;
tree = optim(tree);
nstack = 0;
rcexpr(tree, table, 0);
}
} else
putchar(c);
}
if (nfloat)
printf(".globl fltused\n");
flush();
exit(nerror!=0);
}
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;
op = tree->op;
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;
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);
}
rcexpr(atree, atable, reg)
struct tnode *atree;
struct table *atable;
{
register r;
int modf, nargs;
register struct tnode *tree;
register struct table *table;
table = atable;
if((tree=atree)==0)
return(0);
switch (tree->op) {
case SETREG:
nreg = tree->type-1;
return;
case CBRANCH:
cbranch(tree->btree, tree->lbl, tree->cond, 0);
return(0);
case INIT:
if (tree->tr1->op == AMPER)
tree->tr1 = tree->tr1->tr1;
if (tree->tr1->op!=NAME && tree->tr1->op!=CON)
error("Illegal initialization");
else
cexpr(tree, regtab, nreg);
return(0);
case EXCLA:
if ((opdope[tree->tr1->op] & RELAT) != 0) {
tree = tree->tr1;
tree->op = notrel[tree->op - EQUAL];
}
break;
case RFORCE:
if((r=rcexpr(tree->tr1, table, reg)) != 0)
printf("mov%c r%d,r0\n", isfloat(tree->tr1), r);
return(0);
case COMMA:
rcexpr(tree->tr1, efftab, reg);
tree = tree->tr2;
break;
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;
xdel[0] = 0;
xdel[1] = 0;
goto fixup;
case TIMES:
case DIVIDE:
case ASTIMES:
case ASDIV:
pow2(tree);
}
modf = 100;
tree = reorder(tree, reg, &modf, 0);
if (modf!=100)
tree = optim(tree);
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) {
printf("mov%c r%d,%c(sp)\n", modf, r,
table==sptab? '-':0);
nstack++;
}
atree = xdel[1];
xdel[1] = 0;
if (xdel[0]) {
tree = xdel[0];
xdel[0] = 0;
rcexpr(tree, efftab, 0);
}
if (atree)
rcexpr(atree, efftab, 0);
if (table==cctab)
printf("tst%c r%d\n", modf, r);
return(r);
}
}
error("No match for op %d", tree->op);
return(reg);
}
struct table *cregtab;
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;
struct tnode *del[2];
tree = atree;
del[0] = 0;
del[1] = 0;
reg = areg;
p1 = tree->tr2;
c = tree->op;
opd = opdope[c];
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);
reg = rreg;
label(r);
goto retrn;
}
reg = oddreg(tree, reg);
reg1 = reg+1;
if ((r = chkleaf(tree, table, reg)) >= 0)
return(r);
r = 0;
if (table==cctab || table==cregtab)
r++;
for (;;) {
flag = 0;
if ((opd & LEAF) == 0)
p1 = tree->tr1 = reorder(tree->tr1, areg, &flag,
r?0: &del[0]);
p2 = 0;
if (opd&BINARY)
p2 = tree->tr2 = reorder(tree->tr2, areg, &flag,
r?0: &del[1]);
if (flag==0)
break;
if (flag > 1 && (opd&RELAT) && p2->op==CON
&& p2->value==0 && r && opdope[p1->op]&LEAF
&& del[0]==0 && del[1]==0)
goto retrn;
tree = optim(tree);
}
if ((tree->op==PLUS||tree->op==ASPLUS) &&
p2->op == CON && p2->value == -1) {
p2->value = 1;
tree->op++; /* +, =+ to -, =- */
}
if (table==cregtab)
table = regtab;
if (table!=cctab || c==INCAFT || c==DECAFT
|| (opt = match(tree, efftab, nreg-reg)) == 0)
if ((opt=match(tree, table, nreg-reg))==0) {
xdel[0] = del[0];
xdel[1] = del[1];
return(-1);
}
string = opt->tabstring;
loop:
if ((c = *string++) & 0200) {
c =& 0177;
putchar('\t');
}
switch (c) {
case '\0':
retrn:
if (del[0])
rcexpr(del[0], efftab, 0);
if (del[1])
rcexpr(del[1], efftab, 0);
if (!isfloat(tree))
if (tree->op==DIVIDE || tree->op==ASDIV)
reg--;
return(reg);
/* A1 */
case 'A':
p = p1;
goto adr;
/* A2 */
case 'B':
p = p2;
goto adr;
/* A */
case 'O':
p = tree;
adr:
c = 0;
if (*string=='\'') {
c++;
string++;
}
pname(p, c);
goto loop;
/* I */
case 'M':
if ((c = *string)=='\'')
string++;
else
c = 0;
prins(tree->op, c);
goto loop;
/* B1 */
case 'C':
if ((opd&LEAF) != 0)
p = tree;
else
p = p1;
goto pbyte;
/* BF */
case 'P':
p = tree;
goto pb1;
/* B2 */
case 'D':
p = p2;
pbyte:
if (p->type==CHAR)
putchar('b');
pb1:
if (isfloat(p))
putchar('f');
goto loop;
/* BE */
case 'L':
if (p1->type==CHAR || p2->type==CHAR)
putchar('b');
p = tree;
goto pb1;
/* C1 */
case 'E':
p = p1->tr1;
goto const;
/* C2 */
case 'F':
p = p2->tr1;
const:
printf("%o", p);
goto loop;
/* F */
case 'G':
p = p1;
flag = 01;
goto subtre;
/* S */
case 'K':
p = p2;
flag = 02;
goto subtre;
/* H */
case 'H':
p = tree;
flag = 04;
subtre:
ctable = regtab;
c = *string++ - 'A';
if ((c&02)!=0)
ctable = sptab;
if ((c&04)!=0)
ctable = cctab;
if ((flag&01) && ctable==regtab && (c&01)==0
&& (tree->op==DIVIDE||tree->op==MOD
|| tree->op==ASDIV||tree->op==ASMOD))
ctable = cregtab;
if ((c&01)!=0) {
p = p->tr1;
if(collcon(p) && ctable!=sptab) {
if (p->op==STAR)
p = p->tr1;
p = p->tr1;
}
}
if (table==lsptab && ctable==sptab)
ctable = lsptab;
if (c&010)
r = reg1;
else
if (opdope[p->op]&LEAF || p->degree < 2)
r = reg;
else
r = areg;
rreg = rcexpr(p, ctable, r);
if (ctable!=regtab && ctable!=cregtab)
goto loop;
if (c&010)
reg1 = rreg;
else if (rreg!=reg)
if (oddreg(tree, 0)==0 && (flag&04 ||
flag&01
&& xdcalc(p2, nreg-rreg-1) <= (opt->tabdeg2&077)
|| flag&02
&& xdcalc(p1,nreg-rreg-1) <= (opt->tabdeg1&077))) {
reg = rreg;
reg1 = rreg+1;
} else
printf("mov%c\tr%d,r%d\n",
isfloat(tree), rreg, reg);
goto loop;
/* R */
case 'I':
r = reg;
if (*string=='-') {
string++;
r--;
}
goto preg;
/* R1 */
case 'J':
r = reg1;
preg:
if (r>nreg)
error("Register overflow: simplify expression");
printf("r%d", r);
goto loop;
case '-': /* check -(sp) */
if (*string=='(') {
nstack++;
if (table!=lsptab)
putchar('-');
goto loop;
}
break;
case ')': /* check (sp)+ */
putchar(')');
if (*string=='+')
nstack--;
goto loop;
/* #1 */
case '#':
p = p1->tr1;
goto nmbr;
/* #2 */
case '"':
p = p2->tr1;
nmbr:
if(collcon(p)) {
if (p->op==STAR) {
printf("*");
p = p->tr1;
}
if ((p = p->tr2)->op == CON) {
if (p->value)
psoct(p->value);
} else if (p->op==AMPER)
pname(p->tr1, 0);
}
goto loop;
/* V */
case 'V':
tree->op = maprel[tree->op - EQUAL];
goto loop;
case '^': /* for ++ --, tr2 is length */
printf("%o", tree->tr2);
goto loop;
case 'T': /* "tst R" if 1st op not in cctab */
if (dcalc(p1, 5)>12 && !match(p1, cctab, 10))
printf("tst r%d\n", reg);
goto loop;
}
putchar(c);
goto loop;
}
reorder(ap, reg, afp, delp)
struct tnode *ap;
int *afp, *delp;
{
register struct tnode *p, *p1;
register int *fp;
p = ap;
if (opdope[p->op]&LEAF)
return(p);
fp = afp;
p1 = p->tr1;
if (p->op==STAR || p->op==PLUS) {
p->tr1 = reorder(p1, reg, fp, delp);
if (p->op==PLUS)
p->tr2 = reorder(p->tr2, reg, fp, delp);
if (*fp)
*fp = 1;
return(p);
}
if (p1->op==NAME) switch(p->op) {
case ASLSH:
case ASRSH:
case ASSIGN:
if (p1->class != REG || isfloat(p->tr2))
break;
if (p->op==ASSIGN) switch (p->tr2->op) {
case TIMES:
case DIVIDE:
if (!ispow2(p->tr2))
break;
pow2(p->tr2);
case PLUS:
case MINUS:
case AND:
case OR:
case EXOR:
case LSHIFT:
case RSHIFT:
p1 = p->tr2->tr2;
if (xdcalc(p1) > 12
|| p1->op==NAME
&&(p1->nloc==p->tr1->nloc
|| p1->regno==p->tr1->nloc))
return(p);
p1 = p->tr2;
p->tr2 = p1->tr1;
if (p1->tr1->op!=NAME
|| p1->tr1->class!=REG
|| p1->tr1->nloc!=p->tr1->nloc)
rcexpr(p, efftab, reg);
p->tr2 = p1->tr2;
p->op = p1->op + ASPLUS - PLUS;
(*fp) = 2;
return(p);
}
goto OK;
case INCAFT:
case DECAFT:
if (delp && *fp < 100) {
if (p1->op==NAME && p1->class==REG)
p1 = block(3, p1->op,p1->type,p1->elsize,
p1->tr1,p1->offset,p1->nloc);
*delp = p;
*fp = 1;
return(p1);
}
break;
case ASTIMES:
case ASDIV:
if (!ispow2(p))
break;
case ASPLUS:
case ASMINUS:
case ASSAND:
case ASOR:
case ASXOR:
case DECBEF:
case INCBEF:
OK:
if (*fp >= 100)
break;
rcexpr(p, delp?efftab:cctab, reg);
(*fp) = 2;
return(p1);
}
return(p);
}
chkleaf(atree, table, reg)
struct tnode *atree;
{
struct tnode lbuf;
register struct tnode *tree;
tree = atree;
if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12)
return(-1);
lbuf.op = LOAD;
lbuf.type = tree->type;
lbuf.degree = tree->degree;
lbuf.tr1 = tree;
return(rcexpr(&lbuf, table, reg));
}
comarg(atree, flagp)
int *flagp;
{
static rathole;
register struct tnode *tree;
struct tnode *pmp;
register retval;
pmp = 0;
tree = reorder(atree, 0, &rathole, &pmp);
if (tree->type==STRUCT)
error("Illegal structure");
if (nstack || isfloat(tree)) {
rcexpr(tree, sptab, 0);
retval = arlength(tree->type);
} else {
(*flagp)++;
rcexpr(tree, lsptab, 0);
retval = 0;
}
if (pmp)
rcexpr(pmp, efftab, 0);
return(retval);
}