Add original unix v6

This commit is contained in:
memnoth
2018-01-27 22:35:41 +09:00
commit 2c7099ee50
664 changed files with 106254 additions and 0 deletions
+709
View File
@@ -0,0 +1,709 @@
#
/* C compiler
*
*
*
* Called from cc:
* c0 source temp1 temp2 [ profileflag ]
* temp1 contains some ascii text and the binary expression
* trees. Each tree is introduced by the # character.
* Strings are put on temp2, which cc tacks onto
* temp1 for assembly.
*/
#include "c0h.c"
int isn 1;
int stflg 1;
int peeksym -1;
int line 1;
int debug 0;
int dimp 0;
struct tname funcblk { NAME, 0, 0, REG, 0, 0 };
int *treespace { osspace };
struct kwtab {
char *kwname;
int kwval;
} kwtab[]
{
"int", INT,
"char", CHAR,
"float", FLOAT,
"double", DOUBLE,
"struct", STRUCT,
"long", LONG,
"auto", AUTO,
"extern", EXTERN,
"static", STATIC,
"register", REG,
"goto", GOTO,
"return", RETURN,
"if", IF,
"while", WHILE,
"else", ELSE,
"switch", SWITCH,
"case", CASE,
"break", BREAK,
"continue", CONTIN,
"do", DO,
"default", DEFAULT,
"for", FOR,
"sizeof", SIZEOF,
0, 0,
};
main(argc, argv)
char *argv[];
{
extern fin;
register char *sp;
register i;
register struct kwtab *ip;
if(argc<3) {
error("Arg count");
exit(1);
}
if((fin=open(argv[1],0))<0) {
error("Can't find %s", argv[1]);
exit(1);
}
if (fcreat(argv[2], obuf)<0 || fcreat(argv[3], sbuf)<0) {
error("Can't create temp");
exit(1);
}
if (argc>4)
proflg++;
/*
* The hash table locations of the keywords
* are marked; if an identifier hashes to one of
* these locations, it is looked up in in the keyword
* table first.
*/
for (ip=kwtab; (sp = ip->kwname); ip++) {
i = 0;
while (*sp)
i =+ *sp++;
hshtab[i%hshsiz].hflag = FKEYW;
}
while(!eof) {
extdef();
blkend();
}
outcode("B", EOF);
strflg++;
outcode("B", EOF);
fflush(obuf);
fflush(sbuf);
exit(nerror!=0);
}
/*
* Look up the identifier in symbuf in the symbol table.
* If it hashes to the same spot as a keyword, try the keyword table
* first. An initial "." is ignored in the hash.
* Return is a ptr to the symbol table entry.
*/
lookup()
{
int ihash;
register struct hshtab *rp;
register char *sp, *np;
ihash = 0;
sp = symbuf;
if (*sp=='.')
sp++;
while (sp<symbuf+ncps)
ihash =+ *sp++;
rp = &hshtab[ihash%hshsiz];
if (rp->hflag&FKEYW)
if (findkw())
return(KEYW);
while (*(np = rp->name)) {
for (sp=symbuf; sp<symbuf+ncps;)
if (*np++ != *sp++)
goto no;
csym = rp;
return(NAME);
no:
if (++rp >= &hshtab[hshsiz])
rp = hshtab;
}
if(++hshused >= hshsiz) {
error("Symbol table overflow");
exit(1);
}
rp->hclass = 0;
rp->htype = 0;
rp->hoffset = 0;
rp->dimp = 0;
rp->hflag =| xdflg;
sp = symbuf;
for (np=rp->name; sp<symbuf+ncps;)
*np++ = *sp++;
csym = rp;
return(NAME);
}
/*
* Search the keyword table.
* Ignore initial "." to avoid member-of-structure
* problems.
*/
findkw()
{
register struct kwtab *kp;
register char *p1, *p2;
char *wp;
wp = symbuf;
if (*wp=='.')
wp++;
for (kp=kwtab; (p2 = kp->kwname); kp++) {
p1 = wp;
while (*p1 == *p2++)
if (*p1++ == '\0') {
cval = kp->kwval;
return(1);
}
}
return(0);
}
/*
* Return the next symbol from the input.
* peeksym is a pushed-back symbol, peekc is a pushed-back
* character (after peeksym).
* mosflg means that the next symbol, if an identifier,
* is a member of structure or a structure tag, and it
* gets a "." prepended to it to distinguish
* it from other identifiers.
*/
symbol() {
register c;
register char *sp;
if (peeksym>=0) {
c = peeksym;
peeksym = -1;
if (c==NAME)
mosflg = 0;
return(c);
}
if (peekc) {
c = peekc;
peekc = 0;
} else
if (eof)
return(EOF);
else
c = getchar();
loop:
switch(ctab[c]) {
case INSERT: /* ignore newlines */
inhdr = 1;
c = getchar();
goto loop;
case NEWLN:
if (!inhdr)
line++;
inhdr = 0;
case SPACE:
c = getchar();
goto loop;
case EOF:
eof++;
return(0);
case PLUS:
return(subseq(c,PLUS,INCBEF));
case MINUS:
return(subseq(c,subseq('>',MINUS,ARROW),DECBEF));
case ASSIGN:
if (subseq(' ',0,1)) return(ASSIGN);
c = symbol();
if (c>=PLUS && c<=EXOR) {
if (spnextchar() != ' '
&& (c==MINUS || c==AND || c==TIMES)) {
error("Warning: assignment operator assumed");
nerror--;
}
return(c+ASPLUS-PLUS);
}
if (c==ASSIGN)
return(EQUAL);
peeksym = c;
return(ASSIGN);
case LESS:
if (subseq(c,0,1)) return(LSHIFT);
return(subseq('=',LESS,LESSEQ));
case GREAT:
if (subseq(c,0,1)) return(RSHIFT);
return(subseq('=',GREAT,GREATEQ));
case EXCLA:
return(subseq('=',EXCLA,NEQUAL));
case DIVIDE:
if (subseq('*',1,0))
return(DIVIDE);
while ((c = spnextchar()) != EOF) {
peekc = 0;
if (c=='*') {
if (spnextchar() == '/') {
peekc = 0;
c = getchar();
goto loop;
}
}
}
eof++;
error("Nonterminated comment");
return(0);
case PERIOD:
case DIGIT:
peekc = c;
if ((c=getnum(c=='0'?8:10)) == FCON)
cval = isn++;
return(c);
case DQUOTE:
return(getstr());
case SQUOTE:
return(getcc());
case LETTER:
sp = symbuf;
if (mosflg) {
*sp++ = '.';
mosflg = 0;
}
while(ctab[c]==LETTER || ctab[c]==DIGIT) {
if (sp<symbuf+ncps) *sp++ = c;
c = getchar();
}
while(sp<symbuf+ncps)
*sp++ = '\0';
peekc = c;
if ((c=lookup())==KEYW && cval==SIZEOF)
c = SIZEOF;
return(c);
case AND:
return(subseq('&', AND, LOGAND));
case OR:
return(subseq('|', OR, LOGOR));
case UNKN:
error("Unknown character");
c = getchar();
goto loop;
}
return(ctab[c]);
}
/*
* If the next input character is c, return a and advance.
* Otherwise push back the character and return a.
*/
subseq(c,a,b)
{
if (spnextchar() != c)
return(a);
peekc = 0;
return(b);
}
/*
* Read a double-quoted string, placing it on the
* string buffer.
*/
getstr()
{
register int c;
register char *sp;
nchstr = 1;
sp = savstr;
while((c=mapch('"')) >= 0) {
nchstr++;
if (sp >= &savstr[STRSIZ]) {
sp = savstr;
error("String too long");
}
*sp++ = c;
}
strptr = sp;
cval = isn++;
return(STRING);
}
/*
* Write out a string, either in-line
* or in the string temp file labelled by
* lab.
*/
putstr(lab)
{
register char *sp;
if (lab) {
strflg++;
outcode("BNB", LABEL, lab, BDATA);
} else
outcode("B", BDATA);
for (sp = savstr; sp<strptr; )
outcode("1N", *sp++ & 0377);
outcode("100");
strflg = 0;
}
/*
* read a single-quoted character constant.
* The routine is sensitive to the layout of
* characters in a word.
*/
getcc()
{
register int c, cc;
register char *ccp;
cval = 0;
ccp = &cval;
cc = 0;
while((c=mapch('\'')) >= 0)
if(cc++ < NCPW)
*ccp++ = c;
if(cc>NCPW)
error("Long character constant");
return(CON);
}
/*
* Read a character in a string or character constant,
* detecting the end of the string.
* It implements the escape sequences.
*/
mapch(ac)
{
register int a, c, n;
static mpeek;
c = ac;
if (a = mpeek)
mpeek = 0;
else
a = getchar();
loop:
if (a==c)
return(-1);
switch(a) {
case '\n':
case '\0':
error("Nonterminated string");
peekc = a;
return(-1);
case '\\':
switch (a=getchar()) {
case 't':
return('\t');
case 'n':
return('\n');
case 'b':
return('\b');
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
n = 0;
c = 0;
while (++c<=3 && '0'<=a && a<='7') {
n =<< 3;
n =+ a-'0';
a = getchar();
}
mpeek = a;
return(n);
case 'r':
return('\r');
case '\n':
if (!inhdr)
line++;
inhdr = 0;
a = getchar();
goto loop;
}
}
return(a);
}
/*
* Read an expression and return a pointer to its tree.
* It's the classical bottom-up, priority-driven scheme.
* The initflg prevents the parse from going past
* "," or ":" because those delimitesrs are special
* in initializer (and some other) expressions.
*/
tree()
{
#define SEOF 200
#define SSIZE 20
int *op, opst[SSIZE], *pp, prst[SSIZE];
register int andflg, o;
register struct hshtab *cs;
int p, ps, os;
space = treespace;
op = opst;
pp = prst;
cp = cmst;
*op = SEOF;
*pp = 06;
andflg = 0;
advanc:
switch (o=symbol()) {
case NAME:
cs = csym;
if (cs->hclass==0 && cs->htype==0)
if(nextchar()=='(') {
/* set function */
cs->hclass = EXTERN;
cs->htype = FUNC;
} else if (initflg)
cs->hclass = EXTERN;
else {
/* set label */
cs->htype = ARRAY;
if (cs->hoffset==0)
cs->hoffset = isn++;
}
*cp++ = copname(cs);
goto tand;
case FCON:
if (!initflg)
outcode("BBNB1N1N1N1N0B", DATA,LABEL,
cval, WDATA, fcval, PROG);
case CON:
case SFCON:
*cp++ = block(1,o,(o==CON?INT:DOUBLE),0,cval);
goto tand;
/* fake a static char array */
case STRING:
putstr(cval);
*cp++ = block(3, NAME, ARRAY+CHAR,0,STATIC,0,cval);
tand:
if(cp>=cmst+cmsiz) {
error("Expression overflow");
exit(1);
}
if (andflg)
goto syntax;
andflg = 1;
goto advanc;
case INCBEF:
case DECBEF:
if (andflg)
o =+ 2;
goto oponst;
case COMPL:
case EXCLA:
case SIZEOF:
if (andflg)
goto syntax;
goto oponst;
case MINUS:
if (!andflg) {
if ((peeksym=symbol())==FCON) {
fcval = - fcval;
goto advanc;
}
if (peeksym==SFCON) {
fcval = - fcval;
cval =^ 0100000;
goto advanc;
}
o = NEG;
}
andflg = 0;
goto oponst;
case AND:
case TIMES:
if (andflg)
andflg = 0; else
if(o==AND)
o = AMPER;
else
o = STAR;
goto oponst;
case LPARN:
if (andflg) {
o = symbol();
if (o==RPARN)
o = MCALL;
else {
peeksym = o;
o = CALL;
andflg = 0;
}
}
goto oponst;
case RBRACK:
case RPARN:
if (!andflg)
goto syntax;
goto oponst;
case DOT:
case ARROW:
mosflg++;
break;
}
/* binaries */
if (!andflg)
goto syntax;
andflg = 0;
oponst:
p = (opdope[o]>>9) & 077;
if ((o==COMMA || o==COLON) && initflg)
p = 05;
opon1:
ps = *pp;
if (p>ps || p==ps && (opdope[o]&RASSOC)!=0) {
switch (o) {
case INCAFT:
case DECAFT:
p = 37;
break;
case LPARN:
case LBRACK:
case CALL:
p = 04;
}
if (op >= &opst[SSIZE-1]) {
error("expression overflow");
exit(1);
}
*++op = o;
*++pp = p;
goto advanc;
}
--pp;
switch (os = *op--) {
case SEOF:
peeksym = o;
build(0); /* flush conversions */
return(*--cp);
case CALL:
if (o!=RPARN)
goto syntax;
build(os);
goto advanc;
case MCALL:
*cp++ = block(0,0,0,0); /* 0 arg call */
os = CALL;
break;
case INCBEF:
case INCAFT:
case DECBEF:
case DECAFT:
*cp++ = block(1, CON, INT, 0, 1);
break;
case LPARN:
if (o!=RPARN)
goto syntax;
goto advanc;
case LBRACK:
if (o!=RBRACK)
goto syntax;
build(LBRACK);
goto advanc;
}
build(os);
goto opon1;
syntax:
error("Expression syntax");
errflush(o);
return(0);
}
/*
* Generate a tree node for a name.
* All the relevant info from the symbol table is
* copied out, including the name if it's an external.
* This is because the symbol table is gone in the next
* pass, so a ptr isn't sufficient.
*/
copname(acs)
struct hshtab *acs;
{
register struct hshtab *cs;
register struct tname *tp;
register char *cp1;
int i;
char *cp2;
cs = acs;
tp = gblock(sizeof(*tp)/NCPW);
tp->op = NAME;
tp->type = cs->htype;
tp->dimp = cs->hdimp;
if ((tp->class = cs->hclass)==0)
tp->class = STATIC;
tp->offset = 0;
tp->nloc = cs->hoffset;
if (cs->hclass==EXTERN) {
gblock((ncps-NCPW)/NCPW);
cp1 = tp->nname;
cp2 = cs->name;
i = ncps;
do {
*cp1++ = *cp2++;
} while (--i);
}
if (cs->hflag&FFIELD)
tp->class = FMOS;
return(tp);
}
+521
View File
@@ -0,0 +1,521 @@
#
/*
* C compiler
*
*
*/
#include "c0h.c"
/*
* Called from tree, this routine takes the top 1, 2, or 3
* operands on the expression stack, makes a new node with
* the operator op, and puts it on the stack.
* Essentially all the work is in inserting
* appropriate conversions.
*/
build(op) {
register int t1;
int t2, t3, t;
struct tnode *p3, *disarray();
register struct tnode *p1, *p2;
int d, dope, leftc, cvn, pcvn;
/*
* a[i] => *(a+i)
*/
if (op==LBRACK) {
build(PLUS);
op = STAR;
}
dope = opdope[op];
if ((dope&BINARY)!=0) {
p2 = chkfun(disarray(*--cp));
t2 = p2->type;
}
p1 = *--cp;
/*
* sizeof gets turned into a number here.
* Bug: sizeof(structure-member-array) is 2 because
* the array has been turned into a ptr already.
*/
if (op==SIZEOF) {
t1 = length(p1);
p1->op = CON;
p1->type = INT;
p1->dimp = 0;
p1->value = t1;
*cp++ = p1;
return;
}
if (op!=AMPER) {
p1 = disarray(p1);
if (op!=CALL)
p1 = chkfun(p1);
}
t1 = p1->type;
pcvn = 0;
t = INT;
switch (op) {
/* end of expression */
case 0:
*cp++ = p1;
return;
/* no-conversion operators */
case QUEST:
if (p2->op!=COLON)
error("Illegal conditional");
t = t2;
case COMMA:
case LOGAND:
case LOGOR:
*cp++ = block(2, op, t, 0, p1, p2);
return;
case CALL:
if ((t1&XTYPE) != FUNC)
error("Call of non-function");
*cp++ = block(2,CALL,decref(t1),p1->dimp,p1,p2);
return;
case STAR:
if (p1->op==AMPER ) {
*cp++ = p1->tr1;
return;
}
if ((t1&XTYPE) == FUNC)
error("Illegal indirection");
*cp++ = block(1,STAR,decref(t1),p1->dimp,p1);
return;
case AMPER:
if (p1->op==STAR) {
p1->tr1->dimp = p1->dimp;
p1->tr1->type = incref(t1);
*cp++ = p1->tr1;
return;
}
if (p1->op==NAME) {
*cp++ = block(1,op,incref(t1),p1->dimp,p1);
return;
}
error("Illegal lvalue");
break;
/*
* a->b goes to (*a).b
*/
case ARROW:
*cp++ = p1;
chkw(p1, -1);
p1->type = PTR+STRUCT;
build(STAR);
p1 = *--cp;
/*
* In a.b, a fairly complicated process has to
* be used to make the left operand look
* as if it had the type of the second.
* Also, the offset in the structure has to be
* given a special type to prevent conversion.
*/
case DOT:
if (p2->op!=NAME || (p2->class!=MOS && p2->class!=FMOS))
error("Illegal structure ref");
*cp++ = p1;
t = t2;
if ((t&XTYPE) == ARRAY) {
t = decref(t);
p2->ssp++;
}
setype(p1, t, p2->dimp);
build(AMPER);
*cp++ = block(1,CON,NOTYPE,0,p2->nloc);
build(PLUS);
if ((t2&XTYPE) != ARRAY)
build(STAR);
if (p2->class == FMOS)
*cp++ = block(2, FSEL, t, 0, *--cp, p2->dimp);
return;
}
if ((dope&LVALUE)!=0)
chklval(p1);
if ((dope&LWORD)!=0)
chkw(p1, LONG);
if ((dope&RWORD)!=0)
chkw(p2, LONG);
if ((dope&BINARY)==0) {
if (op==ITOF)
t1 = DOUBLE;
else if (op==FTOI)
t1 = INT;
if (!fold(op, p1, 0))
*cp++ = block(1,op,t1,p1->dimp,p1);
return;
}
cvn = 0;
if (t1==STRUCT || t2==STRUCT) {
error("Unimplemented structure operation");
t1 = t2 = INT;
}
if (t2==NOTYPE) {
t = t1;
p2->type = INT; /* no int cv for struct */
t2 = INT;
} else
cvn = cvtab[lintyp(t1)][lintyp(t2)];
leftc = (cvn>>4)&017;
cvn =& 017;
t = leftc? t2:t1;
if (dope&ASSGOP) {
t = t1;
if (op==ASSIGN && (cvn==ITP||cvn==PTI))
cvn = leftc = 0;
if (leftc)
cvn = leftc;
leftc = 0;
} else if (op==COLON && t1>=PTR && t1==t2)
cvn = 0;
else if (dope&RELAT) {
if (op>=LESSEQ && (t1>=PTR || t2>=PTR))
op =+ LESSEQP-LESSEQ;
if (cvn==PTI)
cvn = 0;
}
if (cvn==PTI) {
cvn = 0;
if (op==MINUS) {
t = INT;
pcvn++;
} else {
if (t1!=t2 || t1!=(PTR+CHAR))
cvn = XX;
}
}
if (cvn) {
t1 = plength(p1);
t2 = plength(p2);
if (cvn==XX || (cvn==PTI&&t1!=t2))
error("Illegal conversion");
else if (leftc)
p1 = convert(p1, t, cvn, t2);
else
p2 = convert(p2, t, cvn, t1);
}
if (dope&RELAT)
t = INT;
if (fold(op, p1, p2)==0)
*cp++ = block(2,op,t,(p1->dimp==0? p2:p1)->dimp,p1,p2);
if (pcvn && t1!=(PTR+CHAR)) {
p1 = *--cp;
*cp++ = convert(p1, 0, PTI, plength(p1->tr1));
}
}
/*
* Generate the appropirate conversion operator.
* For pointer <=> integer this is a multiplication
* or division, otherwise a special operator.
*/
convert(p, t, cvn, len)
struct tnode *p;
{
register int n;
switch(cvn) {
case PTI:
case ITP:
if (len==1)
return(p);
return(block(2, (cvn==PTI?DIVIDE:TIMES), t, 0, p,
block(1, CON, 0, 0, len)));
case ITF:
n = ITOF;
break;
case FTI:
n = FTOI;
break;
case ITL:
n = ITOL;
break;
case LTI:
n = LTOI;
break;
case FTL:
n = FTOL;
break;
case LTF:
n = LTOF;
break;
}
return(block(1, n, t, 0, p));
}
/*
* Traverse an expression tree, adjust things
* so the types of things in it are consistent
* with the view that its top node has
* type at.
* Used with structure references.
*/
setype(ap, at, adimptr)
struct tnode *ap;
{
register struct tnode *p;
register t, dimptr;
p = ap;
t = at;
dimptr = adimptr;
p->type = t;
if (dimptr != -1)
p->dimp = dimptr;
switch(p->op) {
case AMPER:
setype(p->tr1, decref(t), dimptr);
return;
case STAR:
setype(p->tr1, incref(t), dimptr);
return;
case PLUS:
case MINUS:
setype(p->tr1, t, dimptr);
}
}
/*
* A mention of a function name is turned into
* a pointer to that function.
*/
chkfun(ap)
struct tnode *ap;
{
register struct tnode *p;
register int t;
p = ap;
if (((t = p->type)&XTYPE)==FUNC)
return(block(1,AMPER,incref(t),p->dimp,p));
return(p);
}
/*
* A mention of an array is turned into
* a pointer to the base of the array.
*/
struct tnode *disarray(ap)
struct tnode *ap;
{
register int t;
register struct tnode *p;
p = ap;
/* check array & not MOS */
if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->class==MOS)
return(p);
p->ssp++;
*cp++ = p;
setype(p, decref(t), -1);
build(AMPER);
return(*--cp);
}
/*
* make sure that p is a ptr to a node
* with type int or char or 'okt.'
* okt might be nonexistent or 'long'
* (e.g. for <<).
*/
chkw(p, okt)
struct tnode *p;
{
register int t;
if ((t=p->type)>CHAR && t<PTR && t!=okt)
error("Integer operand required");
return;
}
/*
*'linearize' a type for looking up in the
* conversion table
*/
lintyp(t)
{
switch(t) {
case INT:
case CHAR:
return(0);
case FLOAT:
case DOUBLE:
return(1);
case LONG:
return(2);
default:
return(3);
}
}
/*
* Report an error.
*/
error(s, p1, p2, p3, p4, p5, p6)
{
nerror++;
printf("%d: ", line);
printf(s, p1, p2, p3, p4, p5, p6);
printf("\n");
}
/*
* Generate a node in an expression tree,
* setting the operator, type, degree (unused in this pass)
* and the operands.
*/
block(an, op, t, d, p1,p2,p3)
int *p1, *p2, *p3;
{
register int *ap, *p, n;
int *oldp;
n = an+3;
p = gblock(n);
oldp = p;
ap = &op;
do {
*p++ = *ap++;
} while (--n);
return(oldp);
}
/*
* Assign an unitialized block for use in the
* expression tree.
*/
gblock(n)
{
register int *p;
p = space;
if ((space =+ n) >= &osspace[OSSIZ]) {
error("Expression overflow");
exit(1);
}
return(p);
}
/*
* Check that a tree can be used as an lvalue.
*/
chklval(ap)
struct tnode *ap;
{
register struct tnode *p;
p = ap;
if (p->op!=NAME && p->op!=STAR)
error("Lvalue required");
}
/*
* reduce some forms of `constant op constant'
* to a constant. More of this is done in the next pass
* but this is used to allow constant expressions
* to be used in switches and array bounds.
*/
fold(op, ap1, ap2)
struct tnode *ap1, *ap2;
{
register struct tnode *p1;
register int v1, v2;
p1 = ap1;
if (p1->op!=CON || (ap2!=0 && ap2->op!=CON))
return(0);
v1 = p1->value;
v2 = ap2->value;
switch (op) {
case PLUS:
v1 =+ v2;
break;
case MINUS:
v1 =- v2;
break;
case TIMES:
v1 =* v2;
break;
case DIVIDE:
v1 =/ v2;
break;
case MOD:
v1 =% v2;
break;
case AND:
v1 =& v2;
break;
case OR:
v1 =| v2;
break;
case EXOR:
v1 =^ v2;
break;
case NEG:
v1 = - v1;
break;
case COMPL:
v1 = ~ v1;
break;
case LSHIFT:
v1 =<< v2;
break;
case RSHIFT:
v1 =>> v2;
break;
default:
return(0);
}
p1->value = v1;
*cp++ = p1;
return(1);
}
/*
* Compile an expression expected to have constant value,
* for example an array bound or a case value.
*/
conexp()
{
register struct tnode *t;
initflg++;
if (t = tree())
if (t->op != CON)
error("Constant required");
initflg--;
return(t->value);
}
+673
View File
@@ -0,0 +1,673 @@
#
/* C compiler
*
*
*/
#include "c0h.c"
/*
* Process a single external definition
*/
extdef()
{
register o, elsize;
int type, sclass;
register struct hshtab *ds;
if(((o=symbol())==EOF) || o==SEMI)
return;
peeksym = o;
type = INT;
sclass = EXTERN;
xdflg = FNDEL;
if ((elsize = getkeywords(&sclass, &type)) == -1 && peeksym!=NAME)
goto syntax;
if (type==STRUCT)
blkhed();
do {
defsym = 0;
decl1(EXTERN, type, 0, elsize);
if ((ds=defsym)==0)
return;
funcsym = ds;
ds->hflag =| FNDEL;
outcode("BS", SYMDEF, ds->name);
xdflg = 0;
if ((ds->type&XTYPE)==FUNC) {
if ((peeksym=symbol())==LBRACE || peeksym==KEYW) {
funcblk.type = decref(ds->type);
cfunc(ds->name);
return;
}
} else
cinit(ds);
} while ((o=symbol())==COMMA);
if (o==SEMI)
return;
syntax:
if (o==RBRACE) {
error("Too many }'s");
peeksym = 0;
return;
}
error("External definition syntax");
errflush(o);
statement(0);
}
/*
* Process a function definition.
*/
cfunc(cs)
char *cs;
{
register savdimp;
savdimp = dimp;
outcode("BBS", PROG, RLABEL, cs);
declist(ARG);
regvar = 5;
retlab = isn++;
if ((peeksym = symbol()) != LBRACE)
error("Compound statement required");
statement(1);
outcode("BNB", LABEL, retlab, RETRN);
dimp = savdimp;
}
/*
* Process the initializers for an external definition.
*/
cinit(ds)
struct hshtab *ds;
{
register basetype, nel, ninit;
int o, width, realwidth;
nel = 1;
basetype = ds->type;
/*
* If it's an array, find the number of elements.
* "basetype" is the type of thing it's an array of.
*/
while ((basetype&XTYPE)==ARRAY) {
if ((nel = dimtab[ds->ssp&0377])==0)
nel = 1;
basetype = decref(basetype);
}
realwidth = width = length(ds) / nel;
/*
* Pretend a structure is kind of an array of integers.
* This is a kludge.
*/
if (basetype==STRUCT) {
nel =* realwidth/2;
width = 2;
}
if ((peeksym=symbol())==COMMA || peeksym==SEMI) {
outcode("BSN",CSPACE,ds->name,(nel*width+ALIGN)&~ALIGN);
return;
}
ninit = 0;
outcode("BBS", DATA, NLABEL, ds->name);
if ((o=symbol())==LBRACE) {
do
ninit = cinit1(ds, basetype, width, ninit, nel);
while ((o=symbol())==COMMA);
if (o!=RBRACE)
peeksym = o;
} else {
peeksym = o;
ninit = cinit1(ds, basetype, width, 0, nel);
}
/*
* Above we pretended that a structure was a bunch of integers.
* Readjust in accordance with reality.
* First round up partial initializations.
*/
if (basetype==STRUCT) {
if (o = 2*ninit % realwidth)
outcode("BN", SSPACE, realwidth-o);
ninit = (2*ninit+realwidth-2) / realwidth;
nel =/ realwidth/2;
}
/*
* If there are too few initializers, allocate
* more storage.
* If there are too many initializers, extend
* the declared size for benefit of "sizeof"
*/
if (ninit<nel)
outcode("BN", SSPACE, (nel-ninit)*realwidth);
else if (ninit>nel) {
if ((ds->type&XTYPE)==ARRAY)
dimtab[ds->ssp&0377] = ninit;
nel = ninit;
}
/*
* If it's not an array, only one initializer is allowed.
*/
if (ninit>1 && (ds->type&XTYPE)!=ARRAY)
error("Too many initializers");
if (((nel&width)&ALIGN))
outcode("B", EVEN);
}
/*
* Process a single expression in a sequence of initializers
* for an external. Mainly, it's for checking
* type compatibility.
*/
cinit1(ds, type, awidth, aninit, nel)
struct hshtab *ds;
{
float sf;
register struct tnode *s;
register width, ninit;
width = awidth;
ninit = aninit;
if ((peeksym=symbol())==STRING && type==CHAR) {
peeksym = -1;
if (ninit)
bxdec();
putstr(0);
if (nel>nchstr) {
strflg++;
outcode("BN", SSPACE, nel-nchstr);
strflg = 0;
nchstr = nel;
}
return(nchstr);
}
if (peeksym==RBRACE)
return(ninit);
initflg++;
s = tree();
initflg = 0;
switch(width) {
case 1:
if (s->op != CON)
goto bad;
outcode("B1N0", BDATA, s->value);
break;
case 2:
if (s->op==CON) {
outcode("B1N0", WDATA, s->value);
break;
}
if (s->op==FCON || s->op==SFCON) {
if (type==STRUCT) {
ninit =+ 3;
goto prflt;
}
goto bad;
}
rcexpr(block(1,INIT,0,0,s));
break;
case 4:
sf = fcval;
outcode("B1N1N0", WDATA, sf);
goto flt;
case 8:
prflt:
outcode("B1N1N1N1N0", WDATA, fcval);
flt:
if (s->op==FCON || s->op==SFCON)
break;
default:
bad:
bxdec();
}
return(++ninit);
}
bxdec()
{
error("Inconsistent external initialization");
}
/*
* Process one statement in a function.
*/
statement(d)
{
register o, o1, o2;
int o3, o4;
struct tnode *np;
stmt:
switch(o=symbol()) {
case EOF:
error("Unexpected EOF");
case SEMI:
return;
case LBRACE:
if (d) {
if (proflg)
outcode("BN", PROFIL, isn++);
outcode("BN", SAVE, blkhed());
}
while (!eof) {
if ((o=symbol())==RBRACE)
return;
peeksym = o;
statement(0);
}
error("Missing '}'");
return;
case KEYW:
switch(cval) {
case GOTO:
if (o1 = simplegoto())
branch(o1);
else
dogoto();
goto semi;
case RETURN:
doret();
goto semi;
case IF:
np = pexpr();
o2 = 0;
if ((o1=symbol())==KEYW) switch (cval) {
case GOTO:
if (o2=simplegoto())
goto simpif;
cbranch(np, o2=isn++, 0);
dogoto();
label(o2);
goto hardif;
case RETURN:
if (nextchar()==';') {
o2 = retlab;
goto simpif;
}
cbranch(np, o1=isn++, 0);
doret();
label(o1);
o2++;
goto hardif;
case BREAK:
o2 = brklab;
goto simpif;
case CONTIN:
o2 = contlab;
simpif:
chconbrk(o2);
cbranch(np, o2, 1);
hardif:
if ((o=symbol())!=SEMI)
goto syntax;
if ((o1=symbol())==KEYW && cval==ELSE)
goto stmt;
peeksym = o1;
return;
}
peeksym = o1;
cbranch(np, o1=isn++, 0);
statement(0);
if ((o=symbol())==KEYW && cval==ELSE) {
o2 = isn++;
branch(o2);
label(o1);
statement(0);
label(o2);
return;
}
peeksym = o;
label(o1);
return;
case WHILE:
o1 = contlab;
o2 = brklab;
label(contlab = isn++);
cbranch(pexpr(), brklab=isn++, 0);
statement(0);
branch(contlab);
label(brklab);
contlab = o1;
brklab = o2;
return;
case BREAK:
chconbrk(brklab);
branch(brklab);
goto semi;
case CONTIN:
chconbrk(contlab);
branch(contlab);
goto semi;
case DO:
o1 = contlab;
o2 = brklab;
contlab = isn++;
brklab = isn++;
label(o3 = isn++);
statement(0);
label(contlab);
contlab = o1;
if ((o=symbol())==KEYW && cval==WHILE) {
cbranch(tree(), o3, 1);
label(brklab);
brklab = o2;
goto semi;
}
goto syntax;
case CASE:
o1 = conexp();
if ((o=symbol())!=COLON)
goto syntax;
if (swp==0) {
error("Case not in switch");
goto stmt;
}
if(swp>=swtab+swsiz) {
error("Switch table overflow");
} else {
swp->swlab = isn;
(swp++)->swval = o1;
label(isn++);
}
goto stmt;
case SWITCH:
o1 = brklab;
brklab = isn++;
np = pexpr();
chkw(np, -1);
rcexpr(block(1,RFORCE,0,0,np));
pswitch();
brklab = o1;
return;
case DEFAULT:
if (swp==0)
error("Default not in switch");
if ((o=symbol())!=COLON)
goto syntax;
label(deflab = isn++);
goto stmt;
case FOR:
o1 = contlab;
o2 = brklab;
contlab = isn++;
brklab = isn++;
if (o=forstmt())
goto syntax;
label(brklab);
contlab = o1;
brklab = o2;
return;
}
error("Unknown keyword");
goto syntax;
case NAME:
if (nextchar()==':') {
peekc = 0;
o1 = csym;
if (o1->hclass>0) {
error("Redefinition");
goto stmt;
}
o1->hclass = STATIC;
o1->htype = ARRAY;
if (o1->hoffset==0)
o1->hoffset = isn++;
label(o1->hoffset);
goto stmt;
}
}
peeksym = o;
rcexpr(tree());
semi:
if ((o=symbol())==SEMI)
return;
syntax:
error("Statement syntax");
errflush(o);
}
/*
* Process a for statement.
*/
forstmt()
{
register int l, o, sline;
int sline1, *ss;
struct tnode *st;
if ((o=symbol()) != LPARN)
return(o);
if ((o=symbol()) != SEMI) { /* init part */
peeksym = o;
rcexpr(tree());
if ((o=symbol()) != SEMI)
return(o);
}
label(contlab);
if ((o=symbol()) != SEMI) { /* test part */
peeksym = o;
rcexpr(block(1,CBRANCH,tree(),brklab,0));
if ((o=symbol()) != SEMI)
return(o);
}
if ((peeksym=symbol()) == RPARN) { /* incr part */
peeksym = -1;
statement(0);
branch(contlab);
return(0);
}
l = contlab;
contlab = isn++;
st = tree();
sline = line;
if ((o=symbol()) != RPARN)
return(o);
ss = treespace;
treespace = space;
statement(0);
sline1 = line;
line = sline;
label(contlab);
rcexpr(st);
line = sline1;
treespace = ss;
branch(l);
return(0);
}
/*
* A parenthesized expression,
* as after "if".
*/
pexpr()
{
register o, t;
if ((o=symbol())!=LPARN)
goto syntax;
t = tree();
if ((o=symbol())!=RPARN)
goto syntax;
return(t);
syntax:
error("Statement syntax");
errflush(o);
return(0);
}
/*
* The switch stateent, which involves collecting the
* constants and labels for the cases.
*/
pswitch()
{
register struct swtab *cswp, *sswp;
int dl, swlab;
cswp = sswp = swp;
if (swp==0)
cswp = swp = swtab;
branch(swlab=isn++);
dl = deflab;
deflab = 0;
statement(0);
branch(brklab);
label(swlab);
if (deflab==0)
deflab = brklab;
outcode("BNN", SWIT, deflab, line);
for (; cswp < swp; cswp++)
outcode("NN", cswp->swlab, cswp->swval);
outcode("0");
label(brklab);
deflab = dl;
swp = sswp;
}
/*
* blkhed is called at the start of each function.
* It reads the declarations at the start;
* then assigns storage locations for the
* parameters (which have been linked into a list,
* in order of appearance).
* This list is necessary because in
* f(a, b) float b; int a; ...
* the names are seen before the types.
* Also, the routine adjusts structures involved
* in some kind of forward-referencing.
*/
blkhed()
{
register pl;
register struct hshtab *cs;
autolen = 6;
declist(0);
pl = 4;
while(paraml) {
parame->hoffset = 0;
cs = paraml;
paraml = paraml->hoffset;
if (cs->htype==FLOAT)
cs->htype = DOUBLE;
cs->hoffset = pl;
cs->hclass = AUTO;
if ((cs->htype&XTYPE) == ARRAY) {
cs->htype =- (ARRAY-PTR); /* set ptr */
cs->ssp++; /* pop dims */
}
pl =+ rlength(cs);
}
for (cs=hshtab; cs<hshtab+hshsiz; cs++) {
if (cs->name[0] == '\0')
continue;
/* check tagged structure */
if (cs->hclass>KEYWC && (cs->htype&TYPE)==RSTRUCT) {
cs->lenp = dimtab[cs->lenp&0377]->lenp;
cs->htype = cs->htype&~TYPE | STRUCT;
}
if (cs->hclass == STRTAG && dimtab[cs->lenp&0377]==0)
error("Undefined structure: %.8s", cs->name);
if (cs->hclass == ARG)
error("Not an argument: %.8s", cs->name);
if (stflg)
prste(cs);
}
space = treespace;
outcode("BN", SETREG, regvar);
return(autolen);
}
/*
* After a function definition, delete local
* symbols.
* Also complain about undefineds.
*/
blkend() {
register struct hshtab *cs;
for (cs=hshtab; cs<hshtab+hshsiz; cs++) {
if (cs->name[0]) {
if (cs->hclass==0 && (cs->hflag&FNUND)==0) {
error("%.8s undefined", cs->name);
cs->hflag =| FNUND;
}
if((cs->hflag&FNDEL)==0) {
cs->name[0] = '\0';
hshused--;
cs->hflag =& ~(FNUND|FFIELD);
}
}
}
}
/*
* write out special definitions of local symbols for
* benefit of the debugger. None of these are used
* by the assembler except to save them.
*/
prste(acs)
{
register struct hshtab *cs;
register nkind;
cs = acs;
switch (cs->hclass) {
case REG:
nkind = RNAME;
break;
case AUTO:
nkind = ANAME;
break;
case STATIC:
nkind = SNAME;
break;
default:
return;
}
outcode("BSN", nkind, cs->name, cs->hoffset);
}
/*
* In case of error, skip to the next
* statement delimiter.
*/
errflush(ao)
{
register o;
o = ao;
while(o>RBRACE) /* ; { } */
o = symbol();
peeksym = o;
}
+412
View File
@@ -0,0 +1,412 @@
#
/*
* C compiler, phase 1
*
*
* Handles processing of declarations,
* except for top-level processing of
* externals.
*/
#include "c0h.c"
/*
* Process a sequence of declaration statements
*/
declist(sclass)
{
register sc, elsize, offset;
int type;
offset = 0;
sc = sclass;
while ((elsize = getkeywords(&sclass, &type)) != -1) {
offset = declare(sclass, type, offset, elsize);
sclass = sc;
}
return(offset+align(INT, offset, 0));
}
/*
* Read the keywords introducing a declaration statement
*/
getkeywords(scptr, tptr)
int *scptr, *tptr;
{
register skw, tkw, longf;
int o, elsize, isadecl, ismos;
isadecl = 0;
longf = 0;
tkw = -1;
skw = *scptr;
elsize = 0;
ismos = skw==MOS;
for (;;) {
mosflg = ismos;
switch ((o=symbol())==KEYW? cval: -1) {
case AUTO:
case STATIC:
case EXTERN:
case REG:
if (skw && skw!=cval)
error("Conflict in storage class");
skw = cval;
break;
case LONG:
longf++;
break;
case STRUCT:
o = STRUCT;
elsize = strdec(&o, ismos);
cval = o;
case INT:
case CHAR:
case FLOAT:
case DOUBLE:
if (tkw>=0)
error("Type clash");
tkw = cval;
break;
default:
peeksym = o;
if (isadecl==0)
return(-1);
if (tkw<0)
tkw = INT;
if (skw==0)
skw = AUTO;
if (longf) {
if (tkw==FLOAT)
tkw = DOUBLE;
else if (tkw==INT)
tkw = LONG;
else
error("Misplaced 'long'");
}
*scptr = skw;
*tptr = tkw;
return(elsize);
}
isadecl++;
}
}
/*
* Process a structure declaration; a subroutine
* of getkeywords.
*/
strdec(tkwp, mosf)
int *tkwp;
{
register elsize, o;
register struct hshtab *ssym;
int savebits;
struct hshtab *ds;
mosflg = 1;
ssym = 0;
if ((o=symbol())==NAME) {
ssym = csym;
if (ssym->hclass==0) {
ssym->hclass = STRTAG;
ssym->lenp = dimp;
chkdim();
dimtab[dimp++] = 0;
}
if (ssym->hclass != STRTAG)
redec();
mosflg = mosf;
o = symbol();
}
mosflg = 0;
if (o != LBRACE) {
if (ssym==0) {
syntax:
decsyn(o);
return(0);
}
if (ssym->hclass!=STRTAG)
error("Bad structure name");
if ((elsize = dimtab[ssym->lenp&0377])==0) {
*tkwp = RSTRUCT;
elsize = ssym;
}
peeksym = o;
} else {
ds = defsym;
mosflg = 0;
savebits = bitoffs;
bitoffs = 0;
elsize = declist(MOS);
bitoffs = savebits;
defsym = ds;
if ((o = symbol()) != RBRACE)
goto syntax;
if (ssym) {
if (dimtab[ssym->lenp&0377])
error("%.8s redeclared", ssym->name);
dimtab[ssym->lenp&0377] = elsize;
}
}
return(elsize);
}
/*
* Check that the dimension table has not overflowed
*/
chkdim()
{
if (dimp >= dimsiz) {
error("Dimension/struct table overflow");
exit(1);
}
}
/*
* Process a comma-separated list of declarators
*/
declare(askw, tkw, offset, elsize)
{
register int o;
register int skw;
skw = askw;
do {
offset =+ decl1(skw, tkw, offset, elsize);
} while ((o=symbol()) == COMMA);
if (o==SEMI || o==RPARN && skw==ARG1)
return(offset);
decsyn(o);
}
/*
* Process a single declarator
*/
decl1(askw, tkw, offset, elsize)
{
int t1, chkoff, a;
register int type, skw;
register struct hshtab *dsym;
skw = askw;
chkoff = 0;
mosflg = skw==MOS;
if ((peeksym=symbol())==SEMI || peeksym==RPARN)
return(0);
/*
* Filler field
*/
if (peeksym==COLON && skw==MOS) {
peeksym = -1;
t1 = conexp();
elsize = align(tkw, offset, t1);
bitoffs =+ t1;
return(elsize);
}
if ((t1=getype()) < 0)
goto syntax;
type = 0;
do
type = type<<TYLEN | (t1 & XTYPE);
while (((t1=>>TYLEN) & XTYPE)!=0);
type =| tkw;
dsym = defsym;
if (!(dsym->hclass==0
|| (skw==ARG && dsym->hclass==ARG1)
|| (skw==EXTERN && dsym->hclass==EXTERN && dsym->htype==type)))
if (skw==MOS && dsym->hclass==MOS && dsym->htype==type)
chkoff = 1;
else {
redec();
goto syntax;
}
dsym->htype = type;
if (skw)
dsym->hclass = skw;
if (skw==ARG1) {
if (paraml==0)
paraml = dsym;
else
parame->hoffset = dsym;
parame = dsym;
}
if (elsize && ((type&TYPE)==RSTRUCT || (type&TYPE)==STRUCT)) {
dsym->lenp = dimp;
chkdim();
dimtab[dimp++] = elsize;
}
elsize = 0;
if (skw==MOS) {
elsize = length(dsym);
t1 = 0;
if ((peeksym = symbol())==COLON) {
elsize = 0;
peeksym = -1;
t1 = conexp();
dsym->hflag =| FFIELD;
}
a = align(type, offset, t1);
elsize =+ a;
offset =+ a;
if (t1) {
if (chkoff && (dsym->bitoffs!=bitoffs
|| dsym->flen!=t1))
redec();
dsym->bitoffs = bitoffs;
dsym->flen = t1;
bitoffs =+ t1;
}
if (chkoff && dsym->hoffset != offset)
redec();
dsym->hoffset = offset;
}
if ((dsym->htype&XTYPE)==FUNC) {
if (dsym->hclass!=EXTERN && dsym->hclass!=AUTO)
error("Bad function");
dsym->hclass = EXTERN;
}
if (dsym->hclass==AUTO) {
autolen =+ rlength(dsym);
dsym->hoffset = -autolen;
} else if (dsym->hclass==STATIC) {
dsym->hoffset = isn;
outcode("BBNBNB", BSS, LABEL, isn++,
SSPACE, rlength(dsym), PROG);
} else if (dsym->hclass==REG) {
if ((type&TYPE)>CHAR && (type&XTYPE)==0
|| (type&XTYPE)>PTR || regvar<3)
error("Bad register %o", type);
dsym->hoffset = --regvar;
}
syntax:
return(elsize);
}
/*
* Read a declarator and get the implied type
*/
getype()
{
register int o, type;
register struct hshtab *ds;
switch(o=symbol()) {
case TIMES:
return(getype()<<TYLEN | PTR);
case LPARN:
type = getype();
if ((o=symbol()) != RPARN)
goto syntax;
goto getf;
case NAME:
defsym = ds = csym;
type = 0;
ds->ssp = dimp;
getf:
switch(o=symbol()) {
case LPARN:
if (xdflg) {
xdflg = 0;
ds = defsym;
declare(ARG1, 0, 0, 0);
defsym = ds;
xdflg++;
} else
if ((o=symbol()) != RPARN)
goto syntax;
type = type<<TYLEN | FUNC;
goto getf;
case LBRACK:
chkdim();
if ((o=symbol()) != RBRACK) {
peeksym = o;
cval = conexp();
for (o=ds->ssp&0377; o<dimp; o++)
dimtab[o] =* cval;
dimtab[dimp++] = cval;
if ((o=symbol())!=RBRACK)
goto syntax;
} else
dimtab[dimp++] = 1;
type = type<<TYLEN | ARRAY;
goto getf;
}
peeksym = o;
return(type);
}
syntax:
decsyn(o);
return(-1);
}
/*
* Enforce alignment restrictions in structures,
* including bit-field considerations.
*/
align(type, offset, aflen)
{
register a, t, flen;
char *ftl;
flen = aflen;
a = offset;
t = type;
ftl = "Field too long";
if (flen==0 && bitoffs) {
a =+ (bitoffs-1) / NBPC;
bitoffs = 0;
}
while ((t&XTYPE)==ARRAY)
t = decref(t);
if (t!=CHAR) {
a = (a+ALIGN) & ~ALIGN;
if (a>offset)
bitoffs = 0;
}
if (flen) {
if (type==INT) {
if (flen > NBPW)
error(ftl);
if (flen+bitoffs > NBPW) {
bitoffs = 0;
a =+ NCPW;
}
} else if (type==CHAR) {
if (flen > NBPC)
error(ftl);
if (flen+bitoffs > NCPW) {
bitoffs = 0;
a =+ 1;
}
} else
error("Bad type for field");
}
return(a-offset);
}
/*
* Complain about syntax error in declaration
*/
decsyn(o)
{
error("Declaration syntax");
errflush(o);
}
/*
* Complain about a redeclaration
*/
redec()
{
error("%.8s redeclared", defsym->name);
}
+343
View File
@@ -0,0 +1,343 @@
#
/*
* C compiler
*
*
*/
#include "c0h.c"
/*
* Reduce the degree-of-reference by one.
* e.g. turn "ptr-to-int" into "int".
*/
decref(at)
{
register t;
t = at;
if ((t & ~TYPE) == 0) {
error("Illegal indirection");
return(t);
}
return((t>>TYLEN) & ~TYPE | t&TYPE);
}
/*
* Increase the degree of reference by
* one; e.g. turn "int" to "ptr-to-int".
*/
incref(t)
{
return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR);
}
/*
* Make a tree that causes a branch to lbl
* if the tree's value is non-zero together with the cond.
*/
cbranch(tree, lbl, cond)
struct tnode *tree;
{
rcexpr(block(1,CBRANCH,tree,lbl,cond));
}
/*
* Write out a tree.
*/
rcexpr(tree)
struct tnode *tree;
{
treeout(tree);
outcode("BN", EXPR, line);
}
treeout(atree)
struct tnode *atree;
{
register struct tnode *tree;
if ((tree = atree) == 0)
return;
switch(tree->op) {
case 0:
outcode("B", NULL);
return;
case NAME:
outcode("BNN", NAME, tree->class, tree->type);
if (tree->class==EXTERN)
outcode("S", tree->nname);
else
outcode("N", tree->nloc);
return;
case CON:
case FCON:
case SFCON:
outcode("BNN", tree->op, tree->type, tree->value);
return;
case FSEL:
treeout(tree->tr1);
outcode("BNN", tree->op, tree->type, tree->tr2);
return;
case CBRANCH:
treeout(tree->btree);
outcode("BNN", tree->op, tree->lbl, tree->cond);
return;
default:
treeout(tree->tr1);
if (opdope[tree->op]&BINARY)
treeout(tree->tr2);
outcode("BN", tree->op, tree->type);
return;
}
}
/*
* Generate a branch
*/
branch(lab) {
outcode("BN", BRANCH, lab);
}
/*
* Generate a label
*/
label(l) {
outcode("BN", LABEL, l);
}
/*
* ap is a tree node whose type
* is some kind of pointer; return the size of the object
* to which the pointer points.
*/
plength(ap)
struct tname *ap;
{
register t, l;
register struct tname *p;
p = ap;
if (p==0 || ((t=p->type)&~TYPE) == 0) /* not a reference */
return(1);
p->type = decref(t);
l = length(p);
p->type = t;
return(l);
}
/*
* return the number of bytes in the object
* whose tree node is acs.
*/
length(acs)
struct tnode *acs;
{
register t, n;
register struct tnode *cs;
cs = acs;
t = cs->type;
n = 1;
while ((t&XTYPE) == ARRAY) {
t = decref(t);
n = dimtab[cs->ssp&0377];
}
if ((t&~TYPE)==FUNC)
return(0);
if (t>=PTR)
return(2*n);
switch(t&TYPE) {
case INT:
return(2*n);
case CHAR:
return(n);
case FLOAT:
case LONG:
return(4*n);
case DOUBLE:
return(8*n);
case STRUCT:
return(n * dimtab[cs->lenp&0377]);
case RSTRUCT:
error("Bad structure");
return(0);
}
error("Compiler error (length)");
}
/*
* The number of bytes in an object, rounded up to a word.
*/
rlength(cs)
struct tnode *cs;
{
return((length(cs)+ALIGN) & ~ALIGN);
}
/*
* After an "if (...) goto", look to see if the transfer
* is to a simple label.
*/
simplegoto()
{
register struct hshtab *csp;
if ((peeksym=symbol())==NAME && nextchar()==';') {
csp = csym;
if (csp->hclass==0 && csp->htype==0) {
csp->htype = ARRAY;
if (csp->hoffset==0)
csp->hoffset = isn++;
}
if ((csp->hclass==0||csp->hclass==STATIC)
&& csp->htype==ARRAY) {
peeksym = -1;
return(csp->hoffset);
}
}
return(0);
}
/*
* Return the next non-white-space character
*/
nextchar()
{
while (spnextchar()==' ')
peekc = 0;
return(peekc);
}
/*
* Return the next character, translating all white space
* to blank and handling line-ends.
*/
spnextchar()
{
register c;
if ((c = peekc)==0)
c = getchar();
if (c=='\t')
c = ' ';
else if (c=='\n') {
c = ' ';
if (inhdr==0)
line++;
inhdr = 0;
} else if (c=='\001') { /* SOH, insert marker */
inhdr++;
c = ' ';
}
peekc = c;
return(c);
}
/*
* is a break or continue legal?
*/
chconbrk(l)
{
if (l==0)
error("Break/continue error");
}
/*
* The goto statement.
*/
dogoto()
{
register struct tnode *np;
*cp++ = tree();
build(STAR);
chkw(np = *--cp, -1);
rcexpr(block(1,JUMP,0,0,np));
}
/*
* The return statement, which has to convert
* the returned object to the function's type.
*/
doret()
{
register struct tnode *t;
if (nextchar() != ';') {
t = tree();
*cp++ = &funcblk;
*cp++ = t;
build(ASSIGN);
cp[-1] = cp[-1]->tr2;
build(RFORCE);
rcexpr(*--cp);
}
branch(retlab);
}
/*
* write out a character to the usual output
* or to the string file
*/
putchar(c)
{
write(1, &c, 1);
}
outcode(s, a)
char *s;
{
register char *sp;
register *ap, *bufp;
int n;
char *np;
bufp = obuf;
if (strflg)
bufp = sbuf;
ap = &a;
for (;;) switch(*s++) {
case 'B':
putw(*ap++ | (0376<<8), bufp);
continue;
case 'N':
putw(*ap++, bufp);
continue;
case 'S':
np = *ap++;
n = ncps;
while (n-- && *np) {
putc(*np++, bufp);
}
putc(0, bufp);
continue;
case '1':
putw(1, bufp);
continue;
case '0':
putw(0, bufp);
continue;
case '\0':
return;
}
error("Botch in outcode");
}
+176
View File
@@ -0,0 +1,176 @@
#
#include "c0h.c"
/*
* info on operators:
* 01-- is binary operator
* 02-- left (or only) operand must be lvalue
* 04-- is relational operator
* 010-- is assignment-type operator
* 020-- non-float req. on left
* 040-- non-float req. on right
* 0100-- is commutative
* 0200-- is right, not left-associative
* 0400-- is leaf of tree
* *0XX000-- XX is priority of operator
*/
int opdope[] {
000000, /* EOF */
000000, /* ; */
000000, /* { */
000000, /* } */
036000, /* [ */
002000, /* ] */
036000, /* ( */
002000, /* ) */
014201, /* : */
007001, /* , */
000000, /* field selection */
000000, /* 11 */
000000, /* 12 */
000000, /* 13 */
000000, /* 14 */
000000, /* 15 */
000000, /* 16 */
000000, /* 17 */
000000, /* 18 */
000000, /* 19 */
000400, /* name */
000400, /* short constant */
000400, /* string */
000400, /* float */
000400, /* double */
000000, /* 25 */
000000, /* 26 */
000000, /* 27 */
000000, /* 28 */
000000, /* 29 */
034203, /* ++pre */
034203, /* --pre */
034203, /* ++post */
034203, /* --post */
034220, /* !un */
034202, /* &un */
034220, /* *un */
034200, /* -un */
034220, /* ~un */
036001, /* . (structure reference) */
030101, /* + */
030001, /* - */
032101, /* * */
032001, /* / */
032001, /* % */
026061, /* >> */
026061, /* << */
020161, /* & */
017161, /* | */
017161, /* ^ */
036001, /* -> */
000000, /* int -> double */
000000, /* double -> int */
016001, /* && */
015001, /* || */
030001, /* &~ */
000000, /* 56 */
000000, /* 57 */
000000, /* 58 */
000000, /* 59 */
022005, /* == */
022005, /* != */
024005, /* <= */
024005, /* < */
024005, /* >= */
024005, /* > */
024005, /* <p */
024005, /* <=p */
024005, /* >p */
024005, /* >=p */
012213, /* =+ */
012213, /* =- */
012213, /* =* */
012213, /* =/ */
012213, /* =% */
012253, /* =>> */
012253, /* =<< */
012253, /* =& */
012253, /* =| */
012253, /* =^ */
012213, /* = */
000000, /* 81 */
000000, /* 82 */
000000, /* 83 */
000000, /* 84 */
000000, /* 85 */
000000, /* 86 */
000000, /* 87 */
000000, /* 88 */
000000, /* 89 */
014201, /* ? */
034200, /* sizeof */
000000, /* 92 */
000000, /* 93 */
000000, /* 94 */
000000, /* 95 */
000000, /* 96 */
000000, /* 97 */
000000, /* 98 */
000000, /* 99 */
036001, /* call */
036001, /* mcall */
000000, /* goto */
000000, /* jump cond */
000000, /* branch cond */
000000, /* 105 */
000000, /* 106 */
000000, /* 107 */
000000, /* 108 */
000000, /* 109 */
000000 /* force r0 */
};
/*
* conversion table:
* FTI: float (or double) to integer
* ITF: integer to float
* ITP: integer to pointer
* ITL: integer to long
* LTI: long to integer
* LTF: long to float
* FTL: float to long
* PTI: pointer to integer
* XX: usually illegal
* When FTI, LTI, FTL are added in they specify
* that it is the left operand that should be converted.
* For + this is done and the conversion is turned back into
* ITF, ITL, LTF.
* For = however the left operand can't be converted
* and the specified conversion is applied to the rhs.
*/
char cvtab[4][4] {
/* int double long ptr */
/* int */ 0, (FTI<<4)+ITF, (LTI<<4)+ITL, (ITP<<4)+ITP,
/* double */ ITF, 0, LTF, XX,
/* long */ ITL, (FTL<<4)+LTF, 0, XX,
/* ptr */ ITP, XX, XX, PTI
};
/*
* character type table
*/
char ctab[] {
EOF, INSERT, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, SPACE, NEWLN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
SPACE, EXCLA, DQUOTE, UNKN, UNKN, MOD, AND, SQUOTE,
LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, PERIOD, DIVIDE,
DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST,
UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LBRACK, UNKN, RBRACK, EXOR, LETTER,
UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, COMPL, UNKN
};
+351
View File
@@ -0,0 +1,351 @@
#
/*
C compiler-- pass 1 header
*/
/*
parameters
*/
#define ncps 8
#define hshsiz 200
#define cmsiz 40
#define swsiz 200
#define OSSIZ 500
#define dimsiz 100
#define NBPW 16
#define NBPC 8
#define NCPW 2
#define STRSIZ 256
struct tnode {
int op;
int type;
int dimp;
struct tnode *tr1, *tr2;
};
struct {
int op;
int type;
char ssp; /* subscript list */
char lenp; /* structure length */
};
struct tname {
int op;
int type;
int dimp;
int class;
int offset;
int nloc;
};
struct txname {
int op;
int type;
int dimp;
int class;
int offset;
char nname[ncps];
};
struct tconst {
int op;
int type;
int dimp;
int value;
};
struct hshtab {
char hclass;
char hflag;
int htype;
int hdimp;
int hoffset;
char name[ncps];
};
struct {
char hclass;
char hflag;
int htype;
char flen; /* Field length */
char bitoffs; /* Offset of field */
};
struct swtab {
int swlab;
int swval;
};
struct bnode {
int bop;
struct tnode *btree;
int lbl;
int cond;
};
char cvtab[4][4];
char savstr[STRSIZ];
char *strptr;
int opdope[];
char ctab[];
char symbuf[ncps+2];
int hshused;
struct hshtab hshtab[hshsiz];
int *space;
int *cp;
int cmst[cmsiz];
int isn;
struct swtab swtab[swsiz];
struct swtab *swp;
int contlab;
int brklab;
int retlab;
int deflab;
int nauto;
int autolen;
int peeksym;
int peekc;
int eof;
int line;
int osspace[OSSIZ];
int *treespace;
struct hshtab *defsym;
struct hshtab *funcsym;
int xdflg;
int proflg;
int stflg;
struct hshtab *csym;
int cval;
double fcval;
int nchstr;
int nerror;
struct hshtab *paraml;
struct hshtab *parame;
int strflg;
int mosflg;
int initflg;
int inhdr;
int dimtab[dimsiz];
char obuf[518];
char sbuf[518];
int dimp;
int regvar;
int bitoffs;
struct tname funcblk;
/*
operators
*/
#define EOF 0
#define SEMI 1
#define LBRACE 2
#define RBRACE 3
#define LBRACK 4
#define RBRACK 5
#define LPARN 6
#define RPARN 7
#define COLON 8
#define COMMA 9
#define FSEL 10
#define KEYW 19
#define NAME 20
#define CON 21
#define STRING 22
#define FCON 23
#define SFCON 24
#define SIZEOF 91
#define INCBEF 30
#define DECBEF 31
#define INCAFT 32
#define DECAFT 33
#define EXCLA 34
#define AMPER 35
#define STAR 36
#define NEG 37
#define COMPL 38
#define DOT 39
#define PLUS 40
#define MINUS 41
#define TIMES 42
#define DIVIDE 43
#define MOD 44
#define RSHIFT 45
#define LSHIFT 46
#define AND 47
#define OR 48
#define EXOR 49
#define ARROW 50
#define ITOF 51
#define FTOI 52
#define LOGAND 53
#define LOGOR 54
#define FTOL 56
#define LTOF 57
#define ITOL 58
#define LTOI 59
#define EQUAL 60
#define NEQUAL 61
#define LESSEQ 62
#define LESS 63
#define GREATEQ 64
#define GREAT 65
#define LESSEQP 66
#define LESSP 67
#define GREATQP 68
#define GREATP 69
#define ASPLUS 70
#define ASMINUS 71
#define ASTIMES 72
#define ASDIV 73
#define ASMOD 74
#define ASRSH 75
#define ASLSH 76
#define ASSAND 77
#define ASOR 78
#define ASXOR 79
#define ASSIGN 80
#define QUEST 90
#define CALL 100
#define MCALL 101
#define JUMP 102
#define CBRANCH 103
#define INIT 104
#define SETREG 105
#define RFORCE 110
#define BRANCH 111
#define LABEL 112
#define NLABEL 113
#define RLABEL 114
/*
types
*/
#define INT 0
#define CHAR 1
#define FLOAT 2
#define DOUBLE 3
#define STRUCT 4
#define RSTRUCT 5
#define LONG 6
#define NOTYPE 7 /* used internally */
#define ALIGN 01
#define TYPE 07
#define TYLEN 2
#define XTYPE (03<<3)
#define PTR 010
#define FUNC 020
#define ARRAY 030
/*
storage classes
*/
#define KEYWC 1
#define MOS 10
#define AUTO 11
#define EXTERN 12
#define STATIC 13
#define REG 14
#define STRTAG 15
#define ARG 16
#define ARG1 17
#define FMOS 18
/*
keywords
*/
#define GOTO 20
#define RETURN 21
#define IF 22
#define WHILE 23
#define ELSE 24
#define SWITCH 25
#define CASE 26
#define BREAK 27
#define CONTIN 28
#define DO 29
#define DEFAULT 30
#define FOR 31
/*
characters
*/
#define INSERT 119
#define PERIOD 120
#define SQUOTE 121
#define DQUOTE 122
#define LETTER 123
#define DIGIT 124
#define NEWLN 125
#define SPACE 126
#define UNKN 127
/*
* Special operators in intermediate code
*/
#define BDATA 200
#define WDATA 201
#define PROG 202
#define DATA 203
#define BSS 204
#define CSPACE 205
#define SSPACE 206
#define SYMDEF 207
#define SAVE 208
#define RETRN 209
#define EVEN 210
#define PROFIL 212
#define SWIT 213
#define EXPR 214
#define SNAME 215
#define RNAME 216
#define ANAME 217
#define NULL 218
/*
Flag bits
*/
#define BINARY 01
#define LVALUE 02
#define RELAT 04
#define ASSGOP 010
#define LWORD 020
#define RWORD 040
#define COMMUTE 0100
#define RASSOC 0200
#define LEAF 0400
/*
* Conversion codes
*/
#define ITF 1
#define ITL 2
#define LTF 3
#define ITP 4
#define PTI 5
#define FTI 6
#define LTI 7
#define FTL 8
#define XX 15
/*
* symbol table flags
*/
#define FNDEL 01
#define FNUND 02
#define FKEYW 04
#define FFIELD 020
+159
View File
@@ -0,0 +1,159 @@
/ assure fake printf (no floating)
.globl fltused; fltused = 0
/ convert stream to number; result is type.
/ value in cval or fcval
fpp = 1
.globl _getnum
.globl _peekc
.globl _getchar
.globl _cval
.globl _fcval
.globl _error
_getnum:
.if fpp
movif $10.,fr3
clrf fr0
.endif
clr nfract
clr totdig
clr decpt
clr _cval
mov 2(sp),base
mov r2,-(sp)
1:
jsr r5,getdig
br 2f
.if fpp
mulf fr3,fr0
movif r0,fr1
addf fr1,fr0
.endif
inc nfract
br 1b
2:
tst decpt
bne 1f
clr nfract
cmp r0,$'.
bne 1f
mov pc,decpt
br 1b
1:
tst totdig
beq 1f
cmp r0,$'e
bne 1f
clr -(sp)
clr _cval
mov pc,decpt
clr _cval
mov $10.,base
jsr pc,_getchar
cmp r0,$'+
beq 2f
cmp r0,$'-
bne 3f
inc (sp)
br 2f
3:
mov r0,_peekc
2:
jsr r5,getdig
br 2f
br 2b
2:
tst (sp)+
beq 2f
neg _cval
2:
sub _cval,nfract
1:
mov r0,_peekc
tst totdig
bne 1f
mov $39.,r0 / "." operator
9:
mov (sp)+,r2
rts pc
1:
tst decpt
bne 1f
mov $21.,r0 / fixed constant
br 9b
1:
.if fpp
movif $1,fr2
mov nfract,r2
mov r2,-(sp)
beq 2f
bgt 1f
neg r2
1:
mulf fr3,fr2
sob r2,1b
2:
tst (sp)+
ble 1f
divf fr2,fr0
br 2f
1:
mulf fr2,fr0
2:
mov $_fcval,r0
movf fr0,(r0)
tst (r0)+
tst (r0)+
bne 1f
tst (r0)+
bne 1f
tst (r0)+
bne 1f
mov $24.,r0
mov _fcval,_cval
br 9b
1:
mov $23.,r0
br 9b
.endif
.if 1-fpp
mov $fperr,-(sp)
jsr pc,_error
tst (sp)+
mov $21.,r0
br 9b
fperr: <No floating point!\0>; .even
.endif
getdig:
mov _peekc,r0
beq 1f
clr _peekc
br 2f
1:
jsr pc,_getchar
2:
sub $'0,r0
cmp r0,$9.
bhi 1f
inc totdig
mov _cval,r1
mul base,r1
add r0,r1
mov r1,_cval
tst (r5)+
rts r5
1:
add $'0,r0
rts r5
.bss
base: .=.+2
nfract: .=.+2
decpt: .=.+2
totdig: .=.+2
+922
View File
@@ -0,0 +1,922 @@
#
/*
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)
reg--;
return(reg);
/* A1 */
case 'A':
p = p1;
goto adr;
/* A2 */
case 'B':
p = p2;
goto adr;
adr:
c = 0;
if (*string=='\'') {
c = 1;
string++;
} else if (*string=='+') {
c = 2;
string++;
}
pname(p, c);
goto loop;
/* I */
case 'M':
if ((c = *string)=='\'')
string++;
else
c = 0;
prins(tree->op, c, instab);
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;
/* 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 (*string=='!') {
string++;
c =| 020; /* force right register */
}
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) {
if (c&020 && rreg!=reg1)
printf("mov%c r%d,r%d\n",
isfloat(tree),rreg,reg1);
else
reg1 = rreg;
} else if (rreg!=reg)
if ((c&020)==0 && 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 (*string=='+') {
string++;
r++;
}
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;
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;
case 'V': /* adc or sbc as required for longs */
switch(tree->op) {
case PLUS:
case ASPLUS:
case INCBEF:
case INCAFT:
printf("adc");
break;
case MINUS:
case ASMINUS:
case NEG:
case DECBEF:
case DECAFT:
printf("sbc");
break;
default:
while ((c = *string++)!='\n' && c!='\0');
break;
}
goto loop;
}
putchar(c);
goto loop;
}
/*
* This routine just calls sreorder (below)
* on the subtrees and then on the tree itself.
* It returns non-zero if anything changed.
*/
reorder(treep, table, reg)
struct tnode **treep;
struct table *table;
{
register r, r1;
register struct tnode *p;
p = *treep;
if (opdope[p->op]&LEAF)
return(0);
r1 = 0;
while(sreorder(&p->tr1, table, reg))
r1++;
if (opdope[p->op]&BINARY)
while(sreorder(&p->tr2, table, reg))
r1++;
r = 0;
while (sreorder(treep, table, reg))
r++;
*treep = optim(*treep);
return(r);
}
/*
* Basically this routine carries out two kinds of optimization.
* First, it observes that "x + (reg = y)" where actually
* the = is any assignment op is better done as "reg=y; x+reg".
* In this case rcexpr is called to do the first part and the
* tree is modified so the name of the register
* replaces the assignment.
* Moreover, expressions like "reg = x+y" are best done as
* "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!).
*/
sreorder(treep, table, reg)
struct tnode **treep;
struct table *table;
{
register struct tnode *p, *p1;
p = *treep;
if (opdope[p->op]&LEAF)
return(0);
if (p->op==PLUS)
if (reorder(&p->tr2, table, reg))
*treep = p = optim(p);
p1 = p->tr1;
if (p->op==STAR || p->op==PLUS) {
if (reorder(&p->tr1, table, reg))
*treep = p = optim(p);
p1 = p->tr1;
}
if (p1->op==NAME) switch(p->op) {
case ASLSH:
case ASRSH:
case ASSIGN:
if (p1->class != REG || isfloat(p->tr2))
return(0);
if (p->op==ASSIGN) switch (p->tr2->op) {
case TIMES:
case DIVIDE:
if (!ispow2(p->tr2))
break;
p->tr2 = pow2(p->tr2);
case PLUS:
case MINUS:
case AND:
case NAND:
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(0);
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;
*treep = p;
return(1);
}
goto OK;
case ASTIMES:
case ASDIV:
if (!ispow2(p))
return(0);
case ASPLUS:
case ASMINUS:
case ASSAND:
case ASSNAND:
case ASOR:
case ASXOR:
case DECBEF:
case INCBEF:
OK:
if (table==cctab||table==cregtab)
reg =+ 020;
rcexpr(optim(p), efftab, ~reg);
*treep = p1;
return(1);
}
return(0);
}
/*
* Delay handles postfix ++ and --
* It observes that "x + y++" is better
* treated as "x + y; y++".
* If the operator is ++ or -- itself,
* it calls rcexpr to load the operand, letting
* the calling instance of rcexpr to do the
* ++ using efftab.
* Otherwise it uses sdelay to search for inc/dec
* among the operands.
*/
delay(treep, table, reg)
struct tnode **treep;
{
register struct tnode *p, *p1;
register r;
p = *treep;
if (table!=efftab && (p->op==INCAFT||p->op==DECAFT)
&& p->tr1->op==NAME) {
return(1+rcexpr(p->tr1, table, reg));
}
p1 = 0;
if (opdope[p->op]&BINARY)
p1 = sdelay(&p->tr2);
if (p1==0)
p1 = sdelay(&p->tr1);
if (p1) {
r = rcexpr(optim(p), table, reg);
*treep = p1;
return(r+1);
}
return(0);
}
sdelay(ap)
struct tnode **ap;
{
register struct tnode *p, *p1;
p = *ap;
if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME) {
*ap = ncopy(p->tr1);
return(p);
}
if (p->op==STAR || p->op==PLUS)
if (p1=sdelay(&p->tr1))
return(p1);
if (p->op==PLUS)
return(sdelay(&p->tr2));
return(0);
}
/*
* Copy a tree node for a register variable.
* Used by sdelay because if *reg-- is turned
* into *reg; reg-- the *reg will in turn
* be changed to some offset class, accidentally
* modifying the reg--.
*/
ncopy(ap)
struct tname *ap;
{
register struct tname *p;
p = ap;
if (p->class!=REG)
return(p);
return(block(3, NAME, p->type, p->elsize, p->tr1,
p->offset, p->nloc));
}
/*
* If the tree can be immediately loaded into a register,
* produce code to do so and return success.
*/
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));
}
/*
* Compile a function argument.
* If the stack is currently empty, put it in (sp)
* rather than -(sp); this will save a pop.
* Return the number of bytes pushed,
* for future popping.
*/
comarg(atree, flagp)
int *flagp;
{
register struct tnode *tree;
register retval;
tree = atree;
if (nstack || isfloat(tree) || tree->type==LONG) {
rcexpr(tree, sptab, 0);
retval = arlength(tree->type);
} else {
(*flagp)++;
rcexpr(tree, lsptab, 0);
retval = 0;
}
return(retval);
}
+849
View File
@@ -0,0 +1,849 @@
#
/*
* C compiler
*/
#include "c1h.c"
max(a, b)
{
if (a>b)
return(a);
return(b);
}
degree(at)
struct tnode *at;
{
register struct tnode *t, *t1;
if ((t=at)==0 || t->op==0)
return(0);
if (t->op == CON)
return(-3);
if (t->op == AMPER)
return(-2);
if (t->op==ITOL && (t1 = isconstant(t)) && t1->value>= 0)
return(-2);
if ((opdope[t->op] & LEAF) != 0) {
if (t->type==CHAR || t->type==FLOAT)
return(1);
return(0);
}
return(t->degree);
}
pname(ap, flag)
struct tnode *ap;
{
register i;
register struct tnode *p;
p = ap;
loop:
switch(p->op) {
case SFCON:
case CON:
printf("$");
psoct(p->value);
return;
case FCON:
printf("L%d", p->value);
return;
case NAME:
i = p->offset;
if (flag==2)
i =+ 2;
if (i) {
psoct(i);
if (p->class!=OFFS)
putchar('+');
if (p->class==REG)
regerr();
}
switch(p->class) {
case SOFFS:
case XOFFS:
pbase(p);
case OFFS:
printf("(r%d)", p->regno);
return;
case EXTERN:
case STATIC:
pbase(p);
return;
case REG:
printf("r%d", p->nloc);
return;
}
error("Compiler error: pname");
return;
case AMPER:
putchar('$');
p = p->tr1;
if (p->op==NAME && p->class==REG)
regerr();
goto loop;
case AUTOI:
printf("(r%d)%c", p->nloc, flag==1?0:'+');
return;
case AUTOD:
printf("%c(r%d)", flag==1?0:'-', p->nloc);
return;
case STAR:
p = p->tr1;
putchar('*');
goto loop;
}
error("pname called illegally");
}
regerr()
{
error("Illegal use of register");
}
pbase(ap)
struct tnode *ap;
{
register struct tnode *p;
p = ap;
if (p->class==SOFFS || p->class==STATIC)
printf("L%d", p->nloc);
else
printf("_%.8s", &(p->nloc));
}
xdcalc(ap, nrleft)
struct tnode *ap;
{
register struct tnode *p;
register d;
p = ap;
d = dcalc(p, nrleft);
if (d<20 && p->type==CHAR) {
if (nrleft>=1)
d = 20;
else
d = 24;
}
return(d);
}
dcalc(ap, nrleft)
struct tnode *ap;
{
register struct tnode *p, *p1;
if ((p=ap)==0)
return(0);
switch (p->op) {
case NAME:
if (p->class==REG)
return(9);
case AMPER:
case FCON:
case AUTOI:
case AUTOD:
return(12);
case CON:
case SFCON:
if (p->value==0)
return(4);
if (p->value==1)
return(5);
if (p->value > 0)
return(8);
return(12);
case STAR:
p1 = p->tr1;
if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD)
if (p->type!=LONG)
return(12);
}
if (p->type==LONG)
nrleft--;
return(p->degree <= nrleft? 20: 24);
}
notcompat(ap, ast, op)
struct tnode *ap;
{
register at, st;
register struct tnode *p;
p = ap;
at = p->type;
st = ast;
if (st==0) /* word, byte */
return(at>CHAR && at<PTR);
if (st==1) /* word */
return(at>INT && at<PTR);
st =- 2;
if ((at&(~(TYPE+XTYPE))) != 0)
at = 020;
if ((at&(~TYPE)) != 0)
at = at&TYPE | 020;
if (st==FLOAT && at==DOUBLE)
at = FLOAT;
if (p->op==NAME && p->class==REG && op==ASSIGN && st==CHAR)
return(0);
return(st != at);
}
prins(op, c, itable)
struct instab *itable;
{
register struct instab *insp;
register char *ip;
for (insp=itable; insp->op != 0; insp++) {
if (insp->op == op) {
ip = c? insp->str2: insp->str1;
if (ip==0)
break;
printf("%s", ip);
return;
}
}
error("No match' for op %d", op);
}
collcon(ap)
struct tnode *ap;
{
register op;
register struct tnode *p;
p = ap;
if (p->op==STAR)
p = p->tr1;
if (p->op==PLUS) {
op = p->tr2->op;
if (op==CON || op==AMPER)
return(1);
}
return(0);
}
isfloat(at)
struct tnode *at;
{
register struct tnode *t;
t = at;
if ((opdope[t->op]&RELAT)!=0)
t = t->tr1;
if (t->type==FLOAT || t->type==DOUBLE) {
nfloat = 1;
return('f');
}
return(0);
}
oddreg(t, areg)
struct tnode *t;
{
register reg;
reg = areg;
if (!isfloat(t))
switch(t->op) {
case DIVIDE:
case MOD:
case ASDIV:
case ASMOD:
reg++;
case TIMES:
case ASTIMES:
return(reg|1);
}
return(reg);
}
arlength(t)
{
if (t>=PTR)
return(2);
switch(t) {
case INT:
case CHAR:
return(2);
case LONG:
return(4);
case FLOAT:
case DOUBLE:
return(8);
}
return(1024);
}
/*
* Strings for switch code.
*/
char dirsw[] {"\
cmp r0,$%o\n\
jhi L%d\n\
asl r0\n\
jmp *L%d(r0)\n\
.data\n\
L%d:\
" };
char simpsw[] {"\
mov $L%d,r1\n\
mov r0,L%d\n\
L%d:cmp r0,(r1)+\n\
jne L%d\n\
jmp *L%d-L%d(r1)\n\
.data\n\
L%d:\
"};
char hashsw[] {"\
mov r0,r1\n\
clr r0\n\
div $%o,r0\n\
asl r1\n\
add $L%d,r1\n\
mov r0,*(r1)+\n\
mov (r1)+,r1\n\
L%d:cmp r0,-(r1)\n\
jne L%d\n\
jmp *L%d-L%d(r1)\n\
.data\n\
L%d:\
"};
pswitch(afp, alp, deflab)
struct swtab *afp, *alp;
{
int tlab, ncase, i, j, tabs, worst, best, range;
register struct swtab *swp, *fp, *lp;
int poctab[swsiz];
fp = afp;
lp = alp;
if (fp==lp) {
printf("jbr L%d\n", deflab);
return;
}
tlab = isn++;
if (sort(fp, lp))
return;
ncase = lp-fp;
lp--;
range = lp->swval - fp->swval;
/* direct switch */
if (range>0 && range <= 3*ncase) {
if (fp->swval)
printf("sub $%o,r0\n", fp->swval);
printf(dirsw, range, deflab, isn, isn);
isn++;
for (i=fp->swval; i<=lp->swval; i++) {
if (i==fp->swval) {
printf("L%d\n", fp->swlab);
fp++;
} else
printf("L%d\n", deflab);
}
goto esw;
}
/* simple switch */
if (ncase<8) {
i = isn++;
j = isn++;
printf(simpsw, i, j, isn, isn, j, i, i);
isn++;
for (; fp<=lp; fp++)
printf("%o\n", fp->swval);
printf("L%d:..\n", j);
for (fp = afp; fp<=lp; fp++)
printf("L%d\n", fp->swlab);
printf("L%d\n", deflab);
goto esw;
}
/* hash switch */
best = 077777;
for (i=ncase/4; i<=ncase/2; i++) {
for (j=0; j<i; j++)
poctab[j] = 0;
for (swp=fp; swp<=lp; swp++)
poctab[lrem(0, swp->swval, i)]++;
worst = 0;
for (j=0; j<i; j++)
if (poctab[j]>worst)
worst = poctab[j];
if (i*worst < best) {
tabs = i;
best = i*worst;
}
}
i = isn++;
printf(hashsw, tabs, isn, i, i, isn+tabs+1, isn+1, isn);
isn++;
for (i=0; i<=tabs; i++)
printf("L%d\n", isn+i);
for (i=0; i<tabs; i++) {
printf("L%d:..\n", isn++);
for (swp=fp; swp<=lp; swp++)
if (lrem(0, swp->swval, tabs) == i)
printf("%o\n", ldiv(0, swp->swval, tabs));
}
printf("L%d:", isn++);
for (i=0; i<tabs; i++) {
printf("L%d\n", deflab);
for (swp=fp; swp<=lp; swp++)
if (lrem(0, swp->swval, tabs) == i)
printf("L%d\n", swp->swlab);
}
esw:
printf(".text\n");
}
sort(afp, alp)
struct swtab *afp, *alp;
{
register struct swtab *cp, *fp, *lp;
int intch, t;
fp = afp;
lp = alp;
while (fp < --lp) {
intch = 0;
for (cp=fp; cp<lp; cp++) {
if (cp->swval == cp[1].swval) {
error("Duplicate case (%d)", cp->swval);
return(1);
}
if (cp->swval > cp[1].swval) {
intch++;
t = cp->swval;
cp->swval = cp[1].swval;
cp[1].swval = t;
t = cp->swlab;
cp->swlab = cp[1].swlab;
cp[1].swlab = t;
}
}
if (intch==0)
break;
}
return(0);
}
ispow2(atree)
{
register int d;
register struct tnode *tree;
tree = atree;
if (!isfloat(tree) && tree->tr2->op==CON) {
d = tree->tr2->value;
if (d>1 && (d&(d-1))==0)
return(d);
}
return(0);
}
pow2(atree)
struct tnode *atree;
{
register int d, i;
register struct tnode *tree;
tree = atree;
if (d = ispow2(tree)) {
for (i=0; (d=>>1)!=0; i++);
tree->tr2->value = i;
d = tree->op;
tree->op = d==TIMES? LSHIFT:
(d==DIVIDE? RSHIFT:
(d==ASTIMES? ASLSH: ASRSH));
tree = optim(tree);
}
return(tree);
}
cbranch(atree, albl, cond, areg)
struct tnode *atree;
{
int l1, op;
register lbl, reg;
register struct tnode *tree;
lbl = albl;
reg = areg;
if ((tree=atree)==0)
return;
switch(tree->op) {
case LOGAND:
if (cond) {
cbranch(tree->tr1, l1=isn++, 0, reg);
cbranch(tree->tr2, lbl, 1, reg);
label(l1);
} else {
cbranch(tree->tr1, lbl, 0, reg);
cbranch(tree->tr2, lbl, 0, reg);
}
return;
case LOGOR:
if (cond) {
cbranch(tree->tr1, lbl, 1, reg);
cbranch(tree->tr2, lbl, 1, reg);
} else {
cbranch(tree->tr1, l1=isn++, 1, reg);
cbranch(tree->tr2, lbl, 0, reg);
label(l1);
}
return;
case EXCLA:
cbranch(tree->tr1, lbl, !cond, reg);
return;
case COMMA:
rcexpr(tree->tr1, efftab, reg);
tree = tree->tr2;
break;
}
op = tree->op;
if (tree->type==LONG || opdope[op]&RELAT&&tree->tr1->type==LONG) {
if (tree->type!=LONG) {
tree->op = MINUS;
tree->type = LONG;
tree = optim(tree);
} else
op = NEQUAL;
rcexpr(tree, regtab, 0);
printf("ashc $0,r0\n");
branch(lbl, op, !cond);
return;
}
rcexpr(tree, cctab, reg);
op = tree->op;
if ((opdope[op]&RELAT)==0)
op = NEQUAL;
else {
l1 = tree->tr2->op;
if ((l1==CON || l1==SFCON) && tree->tr2->value==0)
op =+ 200; /* special for ptr tests */
else
op = maprel[op-EQUAL];
}
if (isfloat(tree))
printf("cfcc\n");
branch(lbl, op, !cond);
}
branch(lbl, aop, c)
{
register op;
if(op=aop)
prins(op, c, branchtab);
else
printf("jbr");
printf("\tL%d\n", lbl);
}
label(l)
{
printf("L%d:", l);
}
popstk(a)
{
switch(a) {
case 0:
return;
case 2:
printf("tst (sp)+\n");
return;
case 4:
printf("cmp (sp)+,(sp)+\n");
return;
}
printf("add $%o,sp\n", a);
}
error(s, p1, p2, p3, p4, p5, p6)
{
register f;
extern fout;
nerror++;
flush();
f = fout;
fout = 1;
printf("%d: ", line);
printf(s, p1, p2, p3, p4, p5, p6);
putchar('\n');
flush();
fout = f;
}
psoct(an)
{
register int n, sign;
sign = 0;
if ((n = an) < 0) {
n = -n;
sign = '-';
}
printf("%c%o", sign, n);
}
/*
* Read in an intermediate file.
*/
getree()
{
struct tnode *expstack[20];
register struct tnode **sp;
register t, op;
static char s[9];
struct swtab *swp;
spacep = treespace;
sp = expstack;
for (;;) {
if (sp >= &expstack[20])
error("Stack botch");
op = getw(ascbuf);
if ((op&0177400) != 0177000) {
error("Intermediate file error");
exit(1);
}
switch(op =& 0377) {
case EOF:
return;
case BDATA:
printf(".byte ");
seq(',');
break;
case WDATA:
seq(';');
break;
case PROG:
printf(".text\n");
break;
case DATA:
printf(".data\n");
break;
case BSS:
printf(".bss\n");
break;
case SYMDEF:
printf(".globl _%s\n", outname(s));
break;
case RETRN:
printf("jmp cret\n");
break;
case CSPACE:
t = outname(s);
printf(".comm _%s,%o\n", t, getw(ascbuf));
break;
case SSPACE:
printf(".=.+%o\n", getw(ascbuf));
break;
case EVEN:
printf(".even\n");
break;
case SAVE:
printf("jsr r5,csv\n");
t = getw(ascbuf)-6;
if (t==2)
printf("tst -(sp)\n");
else if (t > 2)
printf("sub $%o,sp\n", t);
break;
case PROFIL:
t = getw(ascbuf);
printf("mov $L%d,r0\njsr pc,mcount\n", t);
printf(".bss\nL%d:.=.+2\n.text\n", t);
break;
case SNAME:
t = outname(s);
printf("~%s=L%d\n", t, getw(ascbuf));
break;
case ANAME:
t = outname(s);
printf("~%s=%o\n", t, getw(ascbuf));
break;
case RNAME:
t = outname(s);
printf("~%s=r%d\n", t, getw(ascbuf));
break;
case SWIT:
t = getw(ascbuf);
line = getw(ascbuf);
swp = treespace;
while (swp->swlab = getw(ascbuf)) {
swp->swval = getw(ascbuf);
swp++;
}
pswitch(treespace, swp, t);
break;
case EXPR:
line = getw(ascbuf);
if (sp != &expstack[1]) {
error("Expression input botch\n");
exit(1);
}
nstack = 0;
rcexpr(optim(*--sp), efftab, 0);
spacep = treespace;
break;
case NAME:
t = getw(ascbuf);
if (t==EXTERN) {
t = getw(ascbuf);
*sp = block(6, NAME, t, 0, EXTERN, 0, 0,0,0,0);
outname(&(*sp)->nloc);
sp++;
break;
}
*sp = block(3, NAME, 0, 0, t, 0, 0);
(*sp)->type = getw(ascbuf);
(*sp)->nloc = getw(ascbuf);
sp++;
break;
case CON:
case SFCON:
case FCON:
t = getw(ascbuf);
*sp++ = block(1, op, t, 0, getw(ascbuf));
break;
case FSEL:
t = getw(ascbuf);
sp[-1] = block(2, op, t, 0, sp[-1], getw(ascbuf));
break;
case NULL:
*sp++ = block(0, 0, 0, 0);
break;
case CBRANCH:
t = getw(ascbuf);
sp[-1] = block(1, CBRANCH, sp[-1], t, getw(ascbuf));
break;
case LABEL:
label(getw(ascbuf));
break;
case NLABEL:
printf("_%s:\n", outname(s));
break;
case RLABEL:
t = outname(s);
printf("_%s:\n~~%s:\n", t, t);
break;
case BRANCH:
branch(getw(ascbuf), 0);
break;
case SETREG:
nreg = getw(ascbuf)-1;
break;
default:
if (opdope[op]&BINARY) {
if (sp < &expstack[1]) {
error("Binary expression botch");
exit(1);
}
t = *--sp;
*sp++ = block(2, op, getw(ascbuf), 0, *--sp, t);
} else {
sp[-1] = block(1, op, getw(ascbuf), 0, sp[-1]);
}
break;
}
}
}
outname(s)
{
register char *p, c;
register n;
p = s;
n = 0;
while (c = getc(ascbuf)) {
*p++ = c;
n++;
}
while (n++ < 8)
*p++ = 0;
return(s);
}
seq(c)
{
register o;
if (getw(ascbuf) == 0)
return;
for (;;) {
printf("%o", getw(ascbuf));
if ((o = getw(ascbuf)) != 1)
break;
printf("%c", c);
}
printf("\n");
}
+621
View File
@@ -0,0 +1,621 @@
#
/*
* C compiler part 2 -- expression optimizer
*
*/
#include "c1h.c"
optim(atree)
struct tnode *atree;
{
register op, dope;
int d1, d2;
struct tnode *t;
register struct tnode *tree;
if ((tree=atree)==0)
return(0);
if ((op = tree->op)==0)
return(tree);
if (op==NAME && tree->class==AUTO) {
tree->class = OFFS;
tree->regno = 5;
tree->offset = tree->nloc;
}
dope = opdope[op];
if ((dope&LEAF) != 0)
return(tree);
if ((dope&BINARY) == 0)
return(unoptim(tree));
/* is known to be binary */
if (tree->type==CHAR)
tree->type = INT;
if ((dope&COMMUTE)!=0) {
acomm: d1 = tree->type;
tree = acommute(tree);
tree->type = d1;
/*
* PDP-11 special:
* replace a&b by a NAND ~ b.
* This will be undone when in
* truth-value context.
*/
if (tree->op!=AND)
return(tree);
tree->op = NAND;
tree->tr2 = block(1, COMPL, tree->tr2->type, 0, tree->tr2);
}
again:
tree->tr1 = optim(tree->tr1);
tree->tr2 = optim(tree->tr2);
if ((dope&RELAT) != 0) {
if ((d1=degree(tree->tr1)) < (d2=degree(tree->tr2))
|| d1==d2 && tree->tr1->op==NAME && tree->tr2->op!=NAME) {
t = tree->tr1;
tree->tr1 = tree->tr2;
tree->tr2 = t;
tree->op = maprel[op-EQUAL];
}
if (tree->tr1->type==CHAR && tree->tr2->op==CON
&& (dcalc(tree->tr1) <= 12 || tree->tr1->op==STAR)
&& tree->tr2->value <= 127 && tree->tr2->value >= 0)
tree->tr2->type = CHAR;
}
d1 = max(degree(tree->tr1), islong(tree->type));
d2 = max(degree(tree->tr2), 0);
if (tree->tr1->type==LONG && dope&RELAT)
d1 = 10;
switch (op) {
case LTIMES:
case LDIV:
case LMOD:
case LASTIMES:
case LASDIV:
case LASMOD:
tree->degree = 10;
break;
/*
* PDP-11 special:
* generate new =&~ operator out of =&
* by complementing the RHS.
*/
case ASSAND:
op = ASSNAND;
tree->op = op;
tree->tr2 = block(2, COMPL, tree->tr2->type, 0, tree->tr2);
goto again;
case NAND:
if (isconstant(tree->tr2) && tree->tr2->value==0)
return(tree->tr1);
goto def;
case CALL:
tree->degree = 10;
break;
case QUEST:
case COLON:
tree->degree = max(d1, d2);
break;
case MINUS:
if (t = isconstant(tree->tr2)) {
tree->op = PLUS;
if (t->type==DOUBLE)
/* PDP-11 FP representation */
t->value =^ 0100000;
else
t->value = -t->value;
goto acomm;
}
goto def;
case DIVIDE:
case ASDIV:
case ASTIMES:
if (tree->tr2->op==CON && tree->tr2->value==1)
return(tree->tr1);
if (ispow2(tree) == 0) {
case MOD:
case ASMOD:
d1 =+ 2;
d2 =+ 2;
}
if (tree->type==LONG)
return(hardlongs(tree));
goto constant;
case LSHIFT:
case RSHIFT:
case ASRSH:
case ASLSH:
if (tree->tr2->op==CON && tree->tr2->value==0)
return(tree->tr1);
/*
* PDP-11 special: turn right shifts into negative
* left shifts
*/
if (op==LSHIFT||op==ASLSH)
goto constant;
if (tree->tr2->op==CON && tree->tr2->value==1)
goto constant;
op =+ (LSHIFT-RSHIFT);
tree->op = op;
tree->tr2 = block(1, NEG, tree->type, 0, tree->tr2);
goto again;
constant:
if (tree->tr1->op==CON && tree->tr2->op==CON) {
const(op, &tree->tr1->value, tree->tr2->value);
return(tree->tr1);
}
def:
default:
tree->degree = d1==d2? d1+islong(tree->type): max(d1, d2);
break;
}
return(tree);
}
unoptim(atree)
struct tnode *atree;
{
register struct tnode *subtre, *tree;
register int *p;
double static fv;
struct { int integer; };
if ((tree=atree)==0)
return(0);
if (tree->op==CBRANCH) {
tree->btree = optim(tree->btree);
return(tree);
}
subtre = tree->tr1 = optim(tree->tr1);
switch (tree->op) {
case FSEL:
tree->tr1 = block(2, RSHIFT, INT, 0, subtre,
block(1, CON, INT, 0, tree->bitoffs));
tree->op = AND;
tree->type = INT;
tree->tr2 = block(1, CON, INT, 0, (1<<tree->flen)-1);
return(optim(tree));
case AMPER:
if (subtre->op==STAR)
return(subtre->tr1);
if (subtre->op==NAME && subtre->class == OFFS) {
p = block(2, PLUS, tree->type, 1, subtre, tree);
subtre->type = tree->type;
tree->op = CON;
tree->type = INT;
tree->degree = 0;
tree->value = subtre->offset;
subtre->class = REG;
subtre->nloc = subtre->regno;
subtre->offset = 0;
return(p);
}
break;
case STAR:
if (subtre->op==AMPER)
return(subtre->tr1);
if (subtre->op==NAME && subtre->class==REG) {
subtre->type = tree->type;
subtre->class = OFFS;
subtre->regno = subtre->nloc;
return(subtre);
}
p = subtre->tr1;
if ((subtre->op==INCAFT||subtre->op==DECBEF)&&tree->type!=LONG
&& p->op==NAME && p->class==REG && p->type==subtre->type) {
p->type = tree->type;
p->op = subtre->op==INCAFT? AUTOI: AUTOD;
return(p);
}
if (subtre->op==PLUS && p->op==NAME && p->class==REG) {
if (subtre->tr2->op==CON) {
p->offset =+ subtre->tr2->value;
p->class = OFFS;
p->type = tree->type;
p->regno = p->nloc;
return(p);
}
if (subtre->tr2->op==AMPER) {
subtre = subtre->tr2->tr1;
subtre->class =+ XOFFS-EXTERN;
subtre->regno = p->nloc;
subtre->type = tree->type;
return(subtre);
}
}
break;
case EXCLA:
if ((opdope[subtre->op]&RELAT)==0)
break;
tree = subtre;
tree->op = notrel[tree->op-EQUAL];
break;
case NEG:
case COMPL:
if (tree->type==CHAR)
tree->type = INT;
if (tree->op == subtre->op)
return(subtre->tr1);
if (subtre->op==ITOL) {
subtre->op = tree->op;
subtre->type = INT;
tree->op = ITOL;
}
}
if (subtre->op == CON) switch(tree->op) {
case NEG:
subtre->value = -subtre->value;
return(subtre);
case COMPL:
subtre->value = ~subtre->value;
return(subtre);
case ITOF:
fv = subtre->value;
p = &fv;
p++;
if (*p++==0 && *p++==0 && *p++==0) {
subtre->type = DOUBLE;
subtre->value = fv.integer;
subtre->op = SFCON;
return(subtre);
}
break;
}
tree->degree = max(islong(tree->type), degree(subtre));
return(tree);
}
struct acl {
int nextl;
int nextn;
struct tnode *nlist[20];
struct tnode *llist[21];
};
acommute(atree)
{
struct acl acl;
int d, i, op, flt;
register struct tnode *t1, **t2, *tree;
struct tnode *t;
acl.nextl = 0;
acl.nextn = 0;
tree = atree;
op = tree->op;
flt = isfloat(tree);
insert(op, tree, &acl);
acl.nextl--;
t2 = &acl.llist[acl.nextl];
if (!flt) {
/* put constants together */
for (i=acl.nextl;i>0&&t2[0]->op==CON&&t2[-1]->op==CON;i--) {
acl.nextl--;
t2--;
const(op, &t2[0]->value, t2[1]->value);
}
}
if (op==PLUS || op==OR) {
/* toss out "+0" */
if (acl.nextl>0 && (t1 = isconstant(*t2)) && t1->value==0) {
acl.nextl--;
t2--;
}
if (acl.nextl <= 0)
return(*t2);
/* subsume constant in "&x+c" */
if (op==PLUS && t2[0]->op==CON && t2[-1]->op==AMPER) {
t2--;
t2[0]->tr1->offset =+ t2[1]->value;
acl.nextl--;
}
} else if (op==TIMES || op==AND) {
t1 = acl.llist[acl.nextl];
if (t1->op==CON) {
if (t1->value==0)
return(t1);
if (op==TIMES && t1->value==1 && acl.nextl>0)
if (--acl.nextl <= 0)
return(acl.llist[0]);
}
}
if (op==PLUS && !flt)
distrib(&acl);
tree = *(t2 = &acl.llist[0]);
d = max(degree(tree), islong(tree->type));
if (op==TIMES && !flt)
d++;
for (i=0; i<acl.nextl; i++) {
t1 = acl.nlist[i];
t1->tr2 = t = *++t2;
t1->degree = d = d==degree(t)? d+islong(t1->type): max(d, degree(t));
t1->tr1 = tree;
tree = t1;
if (tree->type==LONG) {
if (tree->op==TIMES)
tree = hardlongs(tree);
else if (tree->op==PLUS && (t = isconstant(tree->tr1))
&& t->value < 0) {
tree->op = MINUS;
t->value = - t->value;
t = tree->tr1;
tree->tr1 = tree->tr2;
tree->tr2 = t;
}
}
}
if (tree->op==TIMES && ispow2(tree))
tree->degree = max(degree(tree->tr1), islong(tree->type));
return(tree);
}
distrib(list)
struct acl *list;
{
/*
* Find a list member of the form c1c2*x such
* that c1c2 divides no other such constant, is divided by
* at least one other (say in the form c1*y), and which has
* fewest divisors. Reduce this pair to c1*(y+c2*x)
* and iterate until no reductions occur.
*/
register struct tnode **p1, **p2;
struct tnode *t;
int ndmaj, ndmin;
struct tnode **dividend, **divisor;
struct tnode **maxnod, **mindiv;
loop:
maxnod = &list->llist[list->nextl];
ndmaj = 1000;
dividend = 0;
for (p1 = list->llist; p1 <= maxnod; p1++) {
if ((*p1)->op!=TIMES || (*p1)->tr2->op!=CON)
continue;
ndmin = 0;
for (p2 = list->llist; p2 <= maxnod; p2++) {
if (p1==p2 || (*p2)->op!=TIMES || (*p2)->tr2->op!=CON)
continue;
if ((*p1)->tr2->value == (*p2)->tr2->value) {
(*p2)->tr2 = (*p1)->tr1;
(*p2)->op = PLUS;
(*p1)->tr1 = (*p2);
*p1 = optim(*p1);
squash(p2, maxnod);
list->nextl--;
goto loop;
}
if (((*p2)->tr2->value % (*p1)->tr2->value) == 0)
goto contmaj;
if (((*p1)->tr2->value % (*p2)->tr2->value) == 0) {
ndmin++;
mindiv = p2;
}
}
if (ndmin > 0 && ndmin < ndmaj) {
ndmaj = ndmin;
dividend = p1;
divisor = mindiv;
}
contmaj:;
}
if (dividend==0)
return;
t = list->nlist[--list->nextn];
p1 = dividend;
p2 = divisor;
t->op = PLUS;
t->type = (*p1)->type;
t->tr1 = (*p1);
t->tr2 = (*p2)->tr1;
(*p1)->tr2->value =/ (*p2)->tr2->value;
(*p2)->tr1 = t;
t = optim(*p2);
if (p1 < p2) {
*p1 = t;
squash(p2, maxnod);
} else {
*p2 = t;
squash(p1, maxnod);
}
list->nextl--;
goto loop;
}
squash(p, maxp)
struct tnode **p, **maxp;
{
register struct tnode **np;
for (np = p; np < maxp; np++)
*np = *(np+1);
}
const(op, vp, av)
int *vp;
{
register int v;
v = av;
switch (op) {
case PLUS:
*vp =+ v;
return;
case TIMES:
*vp =* v;
return;
case AND:
*vp =& v;
return;
case OR:
*vp =| v;
return;
case EXOR:
*vp =^ v;
return;
case DIVIDE:
case MOD:
if (v==0)
error("Divide check");
else
if (op==DIVIDE)
*vp =/ v;
else
*vp =% v;
return;
case RSHIFT:
*vp =>> v;
return;
case LSHIFT:
*vp =<< v;
return;
case NAND:
*vp =& ~ v;
return;
}
error("C error: const");
}
insert(op, atree, alist)
struct acl *alist;
{
register d;
register struct acl *list;
register struct tnode *tree;
int d1, i;
struct tnode *t;
tree = atree;
list = alist;
if (tree->op == op) {
ins: list->nlist[list->nextn++] = tree;
insert(op, tree->tr1, list);
insert(op, tree->tr2, list);
return;
}
tree = optim(tree);
if (tree->op == op)
goto ins;
if (!isfloat(tree)) {
/* c1*(x+c2) -> c1*x+c1*c2 */
if ((tree->op==TIMES||tree->op==LSHIFT)
&& tree->tr2->op==CON && tree->tr2->value>0
&& tree->tr1->op==PLUS && tree->tr1->tr2->op==CON) {
d = tree->tr2->value;
if (tree->op==TIMES)
tree->tr2->value =* tree->tr1->tr2->value;
else
tree->tr2->value = tree->tr1->tr2->value << d;
tree->tr1->tr2->value = d;
tree->tr1->op = tree->op;
tree->op = PLUS;
if (op==PLUS)
goto ins;
}
}
d = degree(tree);
for (i=0; i<list->nextl; i++) {
if ((d1=degree(list->llist[i]))<d) {
t = list->llist[i];
list->llist[i] = tree;
tree = t;
d = d1;
}
}
list->llist[list->nextl++] = tree;
}
block(an, args)
{
register int *p;
int *oldp;
register *argp, n;
oldp = p = spacep;
n = an+3;
argp = &args;
do
*p++ = *argp++;
while (--n);
if (p >= &treespace[ossiz]) {
error("Exp. ov. pass 2");
exit(1);
}
spacep = p;
return(oldp);
}
islong(t)
{
if (t==LONG)
return(2);
return(1);
}
isconstant(at)
struct tnode *at;
{
register struct tnode *t;
t = at;
if (t->op==CON || t->op==SFCON)
return(t);
if (t->op==ITOL && t->tr1->op==CON)
return(t->tr1);
return(0);
}
hardlongs(at)
struct tnode *at;
{
register struct tnode *t;
t = at;
switch(t->op) {
case TIMES:
case DIVIDE:
case MOD:
t->op =+ LTIMES-TIMES;
break;
case ASTIMES:
case ASDIV:
case ASMOD:
t->op =+ LASTIMES-ASTIMES;
t->tr1 = block(1, AMPER, LONG+PTR, 0, t->tr1);
break;
default:
return(t);
}
return(optim(t));
}
+227
View File
@@ -0,0 +1,227 @@
int opdope[] {
000000, /* EOF */
000000, /* ; */
000000, /* { */
000000, /* } */
036000, /* [ */
002000, /* ] */
036000, /* ( */
002000, /* ) */
014201, /* : */
007001, /* , */
000000, /* field selection */
000000, /* 11 */
000000, /* 12 */
000000, /* 13 */
000000, /* 14 */
000000, /* 15 */
000000, /* 16 */
000000, /* 17 */
000000, /* 18 */
000000, /* 19 */
000400, /* name */
000400, /* short constant */
000400, /* string */
000400, /* float */
000400, /* double */
000000, /* 25 */
000000, /* 26 */
000400, /* autoi, *r++ */
000400, /* autod, *--r */
000000, /* 29 */
034203, /* ++pre */
034203, /* --pre */
034203, /* ++post */
034203, /* --post */
034220, /* !un */
034202, /* &un */
034220, /* *un */
034200, /* -un */
034220, /* ~un */
036001, /* . (structure reference) */
030101, /* + */
030001, /* - */
032101, /* * */
032001, /* / */
032001, /* % */
026061, /* >> */
026061, /* << */
020161, /* & */
016161, /* | */
016161, /* ^ */
036001, /* -> */
001000, /* int -> double */
001000, /* double -> int */
000001, /* && */
000001, /* || */
030001, /* &~ */
001000, /* double -> long */
001000, /* long -> double */
001000, /* integer -> long */
001000, /* long -> integer */
022005, /* == */
022005, /* != */
024005, /* <= */
024005, /* < */
024005, /* >= */
024005, /* > */
024005, /* <p */
024005, /* <=p */
024005, /* >p */
024005, /* >=p */
012213, /* =+ */
012213, /* =- */
012213, /* =* */
012213, /* =/ */
012213, /* =% */
012253, /* =>> */
012253, /* =<< */
012253, /* =& */
012253, /* =| */
012253, /* =^ */
012213, /* = */
030001, /* & for tests */
032101, /* * (long) */
032001, /* / (long) */
032001, /* % (long) */
012253, /* =& ~ */
012213, /* =* (long) */
012213, /* / (long) */
012213, /* % (long) */
000000, /* 89 */
014201, /* ? */
026061, /* long << */
012253, /* long =<< */
000000, /* 93 */
000000, /* 94 */
000000, /* 95 */
000000, /* 96 */
000000, /* 97 */
000000, /* 98 */
000000, /* 99 */
036001, /* call */
036000, /* mcall */
000000, /* goto */
000000, /* jump cond */
000000, /* branch cond */
000400, /* set nregs */
000000, /* 106 */
000000, /* 107 */
000000, /* 108 */
000000, /* 109 */
000000 /* force r0 */
};
char *opntab[] {
0,
0,
0,
0,
0,
0,
0,
0,
":",
",",
"field select",
0,
0,
0,
0,
0,
0,
0,
0,
0,
"name",
"short constant",
"string",
"float",
"double",
0,
0,
"*r++",
"*--r",
0,
"++pre",
"--pre",
"++post",
"--post",
"!un",
"&",
"*",
"-",
"~",
".",
"+",
"-",
"*",
"/",
"%",
">>",
"<<",
"&",
"|",
"^",
"->",
"int->double",
"double->int",
"&&",
"||",
"&~",
"double->long",
"long->double",
"integer->long",
"long->integer",
"==",
"!=",
"<=",
"<",
">=",
">",
"<p",
"<=p",
">p",
">=p",
"=+",
"=-",
"=*",
"=/",
"=%",
"=>>",
"=<<",
"=&",
"=|",
"=^",
"=",
"& for tests",
"*",
"/",
"%",
"=& ~",
"=*",
"=/",
"=%",
0,
"?",
"<<",
"=<<",
0,
0,
0,
0,
0,
"call",
"call",
"call",
0,
"goto",
"jump cond",
"branch cond",
"set nregs",
"load value",
0,
0,
0,
"force register"
};
+272
View File
@@ -0,0 +1,272 @@
/*
* C pass 2 header
*/
#define swsiz 200
#define ossiz 500
struct tnode {
int op;
int type;
int degree;
struct tnode *tr1, *tr2;
};
struct bnode {
int bop;
struct tnode *btree;
int lbl;
int cond;
};
struct tname {
int nop;
int ntype;
int elsize;
char class;
char regno;
int offset;
int nloc;
};
/*
* for field selections
*/
struct tsel {
int op;
int type;
int degree;
struct tnode *tr1;
char flen;
char bitoffs;
};
struct tconst {
int cop;
int ctype;
int cdeg;
int value;
};
struct optab {
char tabdeg1;
char tabtyp1;
char tabdeg2;
char tabtyp2;
char *tabstring;
};
struct table {
int tabop;
struct optab *tabp;
};
struct instab {
int iop;
char *str1;
char *str2;
};
struct swtab {
int swlab;
int swval;
};
char maprel[];
char notrel[];
int nreg;
int isn;
int namsiz;
int line;
char ascbuf[518];
int nerror;
struct table cctab[];
struct table efftab[];
struct table regtab[];
struct table sptab[];
struct table lsptab[];
struct instab instab[];
struct instab branchtab[];
int opdope[];
char *opntab[];
int nstack;
int nfloat;
int *spacep;
int treespace[ossiz];
int eolflg;
struct tconst czero, cone, fczero;
/*
operators
*/
#define EOF 0
#define SEMI 1
#define LBRACE 2
#define RBRACE 3
#define LBRACK 4
#define RBRACK 5
#define LPARN 6
#define RPARN 7
#define COLON 8
#define COMMA 9
#define FSEL 10
#define KEYW 19
#define NAME 20
#define CON 21
#define STRING 22
#define FCON 23
#define SFCON 24
#define AUTOI 27
#define AUTOD 28
#define INCBEF 30
#define DECBEF 31
#define INCAFT 32
#define DECAFT 33
#define EXCLA 34
#define AMPER 35
#define STAR 36
#define NEG 37
#define COMPL 38
#define DOT 39
#define PLUS 40
#define MINUS 41
#define TIMES 42
#define DIVIDE 43
#define MOD 44
#define RSHIFT 45
#define LSHIFT 46
#define AND 47
#define NAND 55
#define OR 48
#define EXOR 49
#define ARROW 50
#define ITOF 51
#define FTOI 52
#define LOGAND 53
#define LOGOR 54
#define FTOL 56
#define LTOF 57
#define ITOL 58
#define LTOI 59
#define EQUAL 60
#define NEQUAL 61
#define LESSEQ 62
#define LESS 63
#define GREATEQ 64
#define GREAT 65
#define LESSEQP 66
#define LESSP 67
#define GREATQP 68
#define GREATP 69
#define ASPLUS 70
#define ASMINUS 71
#define ASTIMES 72
#define ASDIV 73
#define ASMOD 74
#define ASRSH 75
#define ASLSH 76
#define ASSAND 77
#define ASOR 78
#define ASXOR 79
#define ASSIGN 80
#define TAND 81
#define LTIMES 82
#define LDIV 83
#define LMOD 84
#define ASSNAND 85
#define LASTIMES 86
#define LASDIV 87
#define LASMOD 88
#define QUEST 90
#define LLSHIFT 91
#define ASLSHL 92
#define CALL1 98
#define CALL2 99
#define CALL 100
#define MCALL 101
#define JUMP 102
#define CBRANCH 103
#define INIT 104
#define SETREG 105
#define LOAD 106
#define RFORCE 110
/*
* Intermediate code operators
*/
#define BRANCH 111
#define LABEL 112
#define NLABEL 113
#define RLABEL 114
#define BDATA 200
#define WDATA 201
#define PROG 202
#define DATA 203
#define BSS 204
#define CSPACE 205
#define SSPACE 206
#define SYMDEF 207
#define SAVE 208
#define RETRN 209
#define EVEN 210
#define PROFIL 212
#define SWIT 213
#define EXPR 214
#define SNAME 215
#define RNAME 216
#define ANAME 217
#define NULL 218
/*
* types
*/
#define INT 0
#define CHAR 1
#define FLOAT 2
#define DOUBLE 3
#define STRUCT 4
#define RSTRUCT 5
#define LONG 6
#define TYLEN 2
#define TYPE 07
#define XTYPE (03<<3)
#define PTR 010
#define FUNC 020
#define ARRAY 030
/*
storage classes
*/
#define KEYWC 1
#define MOS 10
#define AUTO 11
#define EXTERN 12
#define STATIC 13
#define REG 14
#define STRTAG 15
#define ARG 16
#define OFFS 20
#define XOFFS 21
#define SOFFS 22
/*
Flag bits
*/
#define BINARY 01
#define LVALUE 02
#define RELAT 04
#define ASSGOP 010
#define LWORD 020
#define RWORD 040
#define COMMUTE 0100
#define RASSOC 0200
#define LEAF 0400
#define CNVRT 01000
+85
View File
@@ -0,0 +1,85 @@
/ C operator tables
.globl fltused; fltused=.
.globl _instab
.globl _branchtab
.data
_instab:
80.; 1f; 2f; .text; 1:<mov\0>; 2:<clr\0>; .data
60.; 1f; 2f; .text; 1: <cmp\0>; 2: <tst\0>; .data
106.; 1b; 2b
61.; 1b; 2b
62.; 1b; 2b
63.; 1b; 2b
64.; 1b; 2b
65.; 1b; 2b
66.; 1b; 2b
67.; 1b; 2b
68.; 1b; 2b
69.; 1b; 2b
40.; 1f; 3f; .text; 1:<add\0>; .data
70.; 1b; 3f
41.; 2f; 4f; .text; 2:<sub\0>; .data
71.; 2b; 4f
30.; 1b; 3f; .text; 3:<inc\0>; .data
31.; 2b; 4f; .text; 4:<dec\0>; .data
32.; 1b; 3b
33.; 2b; 4b
42.; 5f; 5f; .text; 5:<mul>; .data
72.; 5b; 5b
43.; 6f; 6f; .text; 6:<div\0>; .data
73.; 6b; 6b
44.; 5b; 6b
74.; 5b; 6b
45.; 5f; 6f; .text; 6:<asr\0>; .data
75.; 5f; 6b
46.; 5f; 6f; .text; 5:<ash\0>; 6:<asl\0>; .data
76.; 5b; 6b
47.; 5f; 5f; .text; 5:<bic\0>; 6:<bic $1,\0>; .data
55.; 5b; 6b
85.; 5b; 6b
81.; 5f; 6f; .text; 5:<bit\0>; 6:<bit $1,\0>; .data
48.; 5f; 6f; .text; 5:<bis\0>; 6:<bis $1,\0>; .data
78.; 5b; 6b
49.; 5f; 5f; .text; 5:<xor\0>; .data
79.; 5b; 5b
37.; 1f; 1f; .text; 1:<neg\0>; .data
38.; 1f; 1f; .text; 1:<com\0>; .data
98.; 1f; 1f; .text; 1:<*$\0>; .data
99.; 1b+2; 1b+2
91.; 1f; 1f; .text; 1: <ashc\0>; .data
92.; 1b; 1b
82.; 1f; 1f; .text; 1:<lmul\0>; .data
83.; 1f; 1f; .text; 1:<ldiv\0>; .data
84.; 1f; 1f; .text; 1:<lrem\0>; .data
86.; 1f; 1f; .text; 1:<almul\0>; .data
87.; 1f; 1f; .text; 1:<aldiv\0>; .data
88.; 1f; 1f; .text; 1:<alrem\0>; .data
0
.data
_branchtab:
60.; 0f; 1f; .text; 0:<jeq\0>; 1:<jne\0>; .data
61.; 1b; 0b
62.; 2f; 5f; .text; 2:<jle\0>; 5:<jgt\0>; .data
63.; 3f; 4f; .text; 3:<jlt\0>; 4:<jge\0>; .data
64.; 4b; 3b
65.; 5b; 2b
66.; 6f; 9f; .text; 6:<jlos\0>; 9:<jhi\0>; .data
67.; 7f; 8f; .text; 7:<jlo\0>; 8:<jhis\0>; .data
68.; 8b; 7b
69.; 9b; 6b
260.; 0b; 1b
261.; 1b; 0b
262.; 2b; 5b
263.; 3b; 4b
264.; 4b; 3b
265.; 5b; 2b
266.; 0b; 1b
267.; 7f; 8f; .text; 7:</nop\0>; 8:<jbr\0>; .data
268.; 8b; 7b
269.; 1b; 0b
0
+673
View File
@@ -0,0 +1,673 @@
#
/*
* C object code improver
*/
#include "c2h.c"
struct optab optab[] {
"jbr", JBR,
"jeq", CBR | JEQ<<8,
"jne", CBR | JNE<<8,
"jle", CBR | JLE<<8,
"jge", CBR | JGE<<8,
"jlt", CBR | JLT<<8,
"jgt", CBR | JGT<<8,
"jlo", CBR | JLO<<8,
"jhi", CBR | JHI<<8,
"jlos", CBR | JLOS<<8,
"jhis", CBR | JHIS<<8,
"jmp", JMP,
".globl",EROU,
"mov", MOV,
"clr", CLR,
"com", COM,
"inc", INC,
"dec", DEC,
"neg", NEG,
"tst", TST,
"asr", ASR,
"asl", ASL,
"sxt", SXT,
"cmp", CMP,
"add", ADD,
"sub", SUB,
"bit", BIT,
"bic", BIC,
"bis", BIS,
"mul", MUL,
"ash", ASH,
"xor", XOR,
".text",TEXT,
".data",DATA,
".bss", BSS,
".even",EVEN,
"movf", MOVF,
"movof",MOVOF,
"movfo",MOVFO,
"addf", ADDF,
"subf", SUBF,
"divf", DIVF,
"mulf", MULF,
"clrf", CLRF,
"cmpf", CMPF,
"negf", NEGF,
"tstf", TSTF,
"cfcc", CFCC,
"sob", SOB,
"jsr", JSR,
".end", END,
0, 0};
char revbr[] { JNE, JEQ, JGT, JLT, JGE, JLE, JHIS, JLOS, JHI, JLO };
int isn 20000;
main(argc, argv)
char **argv;
{
register int niter, maxiter, isend;
extern end;
extern fin, fout;
int nflag;
if (argc>1 && argv[1][0]=='+') {
argc--;
argv++;
debug++;
}
if (argc>1 && argv[1][0]=='-') {
argc--;
argv++;
nflag++;
}
if (argc>1) {
if ((fin = open(argv[1], 0)) < 0) {
printf("C2: can't find %s\n", argv[1]);
exit(1);
}
} else
fin = dup(0);
if (argc>2) {
if ((fout = creat(argv[2], 0666)) < 0) {
fout = 1;
printf("C2: can't create %s\n", argv[2]);
exit(1);
}
} else
fout = dup(1);
lasta = firstr = lastr = sbrk(2);
maxiter = 0;
opsetup();
do {
isend = input();
movedat();
niter = 0;
do {
refcount();
do {
iterate();
clearreg();
niter++;
} while (nchange);
comjump();
rmove();
} while (nchange || jumpsw());
addsob();
output();
if (niter > maxiter)
maxiter = niter;
lasta = firstr;
} while (isend);
flush();
fout = 2;
if (nflag) {
printf("%d iterations\n", maxiter);
printf("%d jumps to jumps\n", nbrbr);
printf("%d inst. after jumps\n", iaftbr);
printf("%d jumps to .+2\n", njp1);
printf("%d redundant labels\n", nrlab);
printf("%d cross-jumps\n", nxjump);
printf("%d code motions\n", ncmot);
printf("%d branches reversed\n", nrevbr);
printf("%d redundant moves\n", redunm);
printf("%d simplified addresses\n", nsaddr);
printf("%d loops inverted\n", loopiv);
printf("%d redundant jumps\n", nredunj);
printf("%d common seqs before jmp's\n", ncomj);
printf("%d skips over jumps\n", nskip);
printf("%d sob's added\n", nsob);
printf("%d redundant tst's\n", nrtst);
printf("%d literals eliminated\n", nlit);
printf("%dK core\n", ((lastr+01777)>>10)&077);
flush();
}
exit(0);
}
input()
{
register struct node *p, *lastp;
register int op;
lastp = &first;
for (;;) {
op = getline();
switch (op.op) {
case LABEL:
p = alloc(sizeof first);
if (line[0] == 'L') {
p->combop = LABEL;
p->labno = getnum(line+1);
p->code = 0;
} else {
p->combop = DLABEL;
p->labno = 0;
p->code = copy(line);
}
break;
case JBR:
case CBR:
case JMP:
case JSW:
p = alloc(sizeof first);
p->combop = op;
if (*curlp=='L' && (p->labno = getnum(curlp+1)))
p->code = 0;
else {
p->labno = 0;
p->code = copy(curlp);
}
break;
default:
p = alloc(sizeof first);
p->combop = op;
p->labno = 0;
p->code = copy(curlp);
break;
}
p->forw = 0;
p->back = lastp;
lastp->forw = p;
lastp = p;
p->ref = 0;
if (op==EROU)
return(1);
if (op==END)
return(0);
}
}
getline()
{
register char *lp;
register c;
lp = line;
while (c = getchar()) {
if (c==':') {
*lp++ = 0;
return(LABEL);
}
if (c=='\n') {
*lp++ = 0;
return(oplook());
}
*lp++ = c;
}
*lp++ = 0;
return(END);
}
getnum(ap)
char *ap;
{
register char *p;
register n, c;
p = ap;
n = 0;
while ((c = *p++) >= '0' && c <= '9')
n = n*10 + c - '0';
if (*--p != 0)
return(0);
return(n);
}
output()
{
register struct node *t;
register struct optab *op;
register int byte;
t = &first;
while (t = t->forw) switch (t->op) {
case END:
return;
case LABEL:
printf("L%d:", t->labno);
continue;
case DLABEL:
printf("%s:", t->code);
continue;
default:
if ((byte = t->subop) == BYTE)
t->subop = 0;
for (op = optab; op->opstring!=0; op++)
if (op->opcode == t->combop) {
printf("%s", op->opstring);
if (byte==BYTE)
printf("b");
break;
}
if (t->code) {
reducelit(t);
printf("\t%s\n", t->code);
} else if (t->op==JBR || t->op==CBR)
printf("\tL%d\n", t->labno);
else
printf("\n");
continue;
case JSW:
printf("L%d\n", t->labno);
continue;
case SOB:
printf("sob %s,L%d\n", t->code, t->labno);
continue;
case 0:
if (t->code)
printf("%s", t->code);
printf("\n");
continue;
}
}
/*
* Notice addresses of the form
* $xx,xx(r)
* and replace them with (pc),xx(r)
* -- Thanx and a tip of the Hatlo hat to Bliss-11.
*/
reducelit(at)
struct node *at;
{
register char *c1, *c2;
char *c2s;
register struct node *t;
t = at;
if (*t->code != '$')
return;
c1 = t->code;
while (*c1 != ',')
if (*c1++ == '\0')
return;
c2s = c1;
c1++;
if (*c1=='*')
c1++;
c2 = t->code+1;
while (*c1++ == *c2++);
if (*--c1!='(' || *--c2!=',')
return;
t->code = copy("(pc)", c2s);
nlit++;
}
copy(ap)
char *ap;
{
register char *p, *np;
char *onp;
register n;
int na;
na = nargs();
p = ap;
n = 0;
if (*p==0)
return(0);
do
n++;
while (*p++);
if (na>1) {
p = (&ap)[1];
while (*p++)
n++;
}
onp = np = alloc(n);
p = ap;
while (*np++ = *p++);
if (na>1) {
p = (&ap)[1];
np--;
while (*np++ = *p++);
}
return(onp);
}
opsetup()
{
register struct optab *optp, **ophp;
register char *p;
for (optp = optab; p = optp->opstring; optp++) {
ophp = &ophash[(((p[0]<<3)+(p[1]<<1)+p[2])&077777) % OPHS];
while (*ophp++)
if (ophp > &ophash[OPHS])
ophp = ophash;
*--ophp = optp;
}
}
oplook()
{
register struct optab *optp;
register char *lp, *op;
static char tmpop[32];
struct optab **ophp;
op = tmpop;
for (lp = line; *lp && *lp!=' ' && *lp!='\t';)
*op++ = *lp++;
*op++ = 0;
while (*lp=='\t' || *lp==' ')
lp++;
curlp = lp;
ophp = &ophash[(((tmpop[0]<<3)+(tmpop[1]<<1)+tmpop[2])&077777) % OPHS];
while (optp = *ophp) {
op = optp->opstring;
lp = tmpop;
while (*lp == *op++)
if (*lp++ == 0)
return(optp->opcode);
if (*lp++=='b' && *lp++==0 && *--op==0)
return(optp->opcode + (BYTE<<8));
ophp++;
if (ophp >= &ophash[OPHS])
ophp = ophash;
}
if (line[0]=='L') {
lp = &line[1];
while (*lp)
if (*lp<'0' || *lp++>'9')
return(0);
curlp = line;
return(JSW);
}
curlp = line;
return(0);
}
refcount()
{
register struct node *p, *lp;
static struct node *labhash[LABHS];
register struct node **hp;
for (hp = labhash; hp < &labhash[LABHS];)
*hp++ = 0;
for (p = first.forw; p!=0; p = p->forw)
if (p->op==LABEL) {
labhash[p->labno % LABHS] = p;
p->refc = 0;
}
for (p = first.forw; p!=0; p = p->forw) {
if (p->op==JBR || p->op==CBR || p->op==JSW) {
p->ref = 0;
lp = labhash[p->labno % LABHS];
if (lp==0 || p->labno!=lp->labno)
for (lp = first.forw; lp!=0; lp = lp->forw) {
if (lp->op==LABEL && p->labno==lp->labno)
break;
}
if (lp) {
hp = nonlab(lp)->back;
if (hp!=lp) {
p->labno = hp->labno;
lp = hp;
}
p->ref = lp;
lp->refc++;
}
}
}
for (p = first.forw; p!=0; p = p->forw)
if (p->op==LABEL && p->refc==0
&& (lp = nonlab(p))->op && lp->op!=JSW)
decref(p);
}
iterate()
{
register struct node *p, *rp, *p1;
nchange = 0;
for (p = first.forw; p!=0; p = p->forw) {
if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) {
rp = nonlab(p->ref);
if (rp->op==JBR && rp->labno && p!=rp) {
nbrbr++;
p->labno = rp->labno;
decref(p->ref);
rp->ref->refc++;
p->ref = rp->ref;
nchange++;
}
}
if (p->op==CBR && (p1 = p->forw)->op==JBR) {
rp = p->ref;
do
rp = rp->back;
while (rp->op==LABEL);
if (rp==p1) {
decref(p->ref);
p->ref = p1->ref;
p->labno = p1->labno;
p1->forw->back = p;
p->forw = p1->forw;
p->subop = revbr[p->subop];
nchange++;
nskip++;
}
}
if (p->op==JBR || p->op==JMP) {
while (p->forw && p->forw->op!=LABEL
&& p->forw->op!=EROU && p->forw->op!=END) {
nchange++;
iaftbr++;
if (p->forw->ref)
decref(p->forw->ref);
p->forw = p->forw->forw;
p->forw->back = p;
}
rp = p->forw;
while (rp && rp->op==LABEL) {
if (p->ref == rp) {
p->back->forw = p->forw;
p->forw->back = p->back;
p = p->back;
decref(rp);
nchange++;
njp1++;
break;
}
rp = rp->forw;
}
xjump(p);
p = codemove(p);
}
}
}
xjump(ap)
{
register int *p1, *p2, *p3;
int nxj;
nxj = 0;
p1 = ap;
if ((p2 = p1->ref)==0)
return(0);
for (;;) {
while ((p1 = p1->back) && p1->op==LABEL);
while ((p2 = p2->back) && p2->op==LABEL);
if (!equop(p1, p2) || p1==p2)
return(nxj);
p3 = insertl(p2);
p1->combop = JBR;
p1->ref = p3;
p1->labno = p3->labno;
p1->code = 0;
nxj++;
nxjump++;
nchange++;
}
}
insertl(ap)
struct node *ap;
{
register struct node *lp, *op;
op = ap;
if (op->op == LABEL) {
op->refc++;
return(op);
}
if (op->back->op == LABEL) {
op = op->back;
op->refc++;
return(op);
}
lp = alloc(sizeof first);
lp->combop = LABEL;
lp->labno = isn++;
lp->ref = 0;
lp->code = 0;
lp->refc = 1;
lp->back = op->back;
lp->forw = op;
op->back->forw = lp;
op->back = lp;
return(lp);
}
codemove(ap)
struct node *ap;
{
register struct node *p1, *p2, *p3;
struct node *t, *tl;
int n;
p1 = ap;
if (p1->op!=JBR || (p2 = p1->ref)==0)
return(p1);
while (p2->op == LABEL)
if ((p2 = p2->back) == 0)
return(p1);
if (p2->op!=JBR && p2->op!=JMP)
goto ivloop;
p2 = p2->forw;
p3 = p1->ref;
while (p3) {
if (p3->op==JBR || p3->op==JMP) {
if (p1==p3)
return(p1);
ncmot++;
nchange++;
p1->back->forw = p2;
p1->forw->back = p3;
p2->back->forw = p3->forw;
p3->forw->back = p2->back;
p2->back = p1->back;
p3->forw = p1->forw;
decref(p1->ref);
return(p2);
} else
p3 = p3->forw;
}
return(p1);
ivloop:
if (p1->forw->op!=LABEL)
return(p1);
p3 = p2 = p2->forw;
n = 16;
do {
if ((p3 = p3->forw) == 0 || p3==p1 || --n==0)
return(p1);
} while (p3->op!=CBR || p3->labno!=p1->forw->labno);
do
if ((p1 = p1->back) == 0)
return(ap);
while (p1!=p3);
p1 = ap;
tl = insertl(p1);
p3->subop = revbr[p3->subop];
decref(p3->ref);
p2->back->forw = p1;
p3->forw->back = p1;
p1->back->forw = p2;
p1->forw->back = p3;
t = p1->back;
p1->back = p2->back;
p2->back = t;
t = p1->forw;
p1->forw = p3->forw;
p3->forw = t;
p2 = insertl(p1->forw);
p3->labno = p2->labno;
p3->ref = p2;
decref(tl);
if (tl->refc<=0)
nrlab--;
loopiv++;
nchange++;
return(p3);
}
comjump()
{
register struct node *p1, *p2, *p3;
for (p1 = first.forw; p1!=0; p1 = p1->forw)
if (p1->op==JBR && (p2 = p1->ref) && p2->refc > 1)
for (p3 = p1->forw; p3!=0; p3 = p3->forw)
if (p3->op==JBR && p3->ref == p2)
backjmp(p1, p3);
}
backjmp(ap1, ap2)
struct node *ap1, *ap2;
{
register struct node *p1, *p2, *p3;
p1 = ap1;
p2 = ap2;
for(;;) {
while ((p1 = p1->back) && p1->op==LABEL);
p2 = p2->back;
if (equop(p1, p2)) {
p3 = insertl(p1);
p2->back->forw = p2->forw;
p2->forw->back = p2->back;
p2 = p2->forw;
decref(p2->ref);
p2->labno = p3->labno;
p2->ref = p3;
nchange++;
ncomj++;
} else
return;
}
}
+659
View File
@@ -0,0 +1,659 @@
#
/*
* C object code improver-- second part
*/
#include "c2h.c"
rmove()
{
register struct node *p;
register char *cp;
register int r;
int r1, flt;
for (p=first.forw; p!=0; p = p->forw) {
if (debug) {
for (r=0; r<2*NREG; r++)
if (regs[r][0])
printf("%d: %s\n", r, regs[r]);
printf("-\n");
}
flt = 0;
switch (p->op) {
case MOVF:
case MOVFO:
case MOVOF:
flt = NREG;
case MOV:
if (p->subop==BYTE)
goto badmov;
dualop(p);
if ((r = findrand(regs[RT1], flt)) >= 0) {
if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR) {
p->forw->back = p->back;
p->back->forw = p->forw;
redunm++;
continue;
}
}
repladdr(p, 0, flt);
r = isreg(regs[RT1]);
r1 = isreg(regs[RT2]);
dest(regs[RT2], flt);
if (r >= 0)
if (r1 >= 0)
savereg(r1+flt, regs[r+flt]);
else
savereg(r+flt, regs[RT2]);
else
if (r1 >= 0)
savereg(r1+flt, regs[RT1]);
else
setcon(regs[RT1], regs[RT2]);
source(regs[RT1]);
setcc(regs[RT2]);
continue;
case ADDF:
case SUBF:
case DIVF:
case MULF:
flt = NREG;
case ADD:
case SUB:
case BIC:
case BIS:
case MUL:
case DIV:
case ASH:
badmov:
dualop(p);
repladdr(p, 0, flt);
source(regs[RT1]);
dest(regs[RT2], flt);
if (p->op==DIV && (r = isreg(regs[RT2])>=0))
regs[r+1][0] = 0;
ccloc[0] = 0;
continue;
case CLRF:
case NEGF:
flt = NREG;
case CLR:
case COM:
case INC:
case DEC:
case NEG:
case ASR:
case ASL:
case SXT:
singop(p);
dest(regs[RT1], flt);
if (p->op==CLR && flt==0)
if ((r = isreg(regs[RT1])) >= 0)
savereg(r, "$0");
else
setcon("$0", regs[RT1]);
setcc(regs[RT1]);
continue;
case TSTF:
flt = NREG;
case TST:
singop(p);
repladdr(p, 0, flt);
source(regs[RT1]);
if (equstr(regs[RT1], ccloc)) {
p->back->forw = p->forw;
p->forw->back = p->back;
p = p->back;
nrtst++;
nchange++;
}
continue;
case CMPF:
flt = NREG;
case CMP:
case BIT:
dualop(p);
source(regs[RT1]);
source(regs[RT2]);
repladdr(p, 1, flt);
ccloc[0] = 0;
continue;
case CBR:
case CFCC:
ccloc[0] = 0;
continue;
case JBR:
redunbr(p);
default:
clearreg();
}
}
}
jumpsw()
{
register struct node *p, *p1;
register t;
int nj;
t = 0;
nj = 0;
for (p=first.forw; p!=0; p = p->forw)
p->refc = ++t;
for (p=first.forw; p!=0; p = p1) {
p1 = p->forw;
if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
&& abs(p->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) {
p->subop = revbr[p->subop];
t = p1->ref;
p1->ref = p->ref;
p->ref = t;
t = p1->labno;
p1->labno = p->labno;
p->labno = t;
nrevbr++;
nj++;
}
}
return(nj);
}
addsob()
{
register struct node *p, *p1;
for (p = &first; (p1 = p->forw)!=0; p = p1) {
if (p->op==DEC && isreg(p->code)>=0
&& p1->combop==(CBR|JNE<<8)) {
if (p->refc < p1->ref->refc)
continue;
if (p->refc - p1->ref->refc > 50)
continue;
p->labno = p1->labno;
p->combop = SOB;
p1->forw->back = p;
p->forw = p1->forw;
nsob++;
}
}
}
abs(x)
{
return(x<0? -x: x);
}
equop(ap1, p2)
struct node *ap1, *p2;
{
register char *cp1, *cp2;
register struct node *p1;
p1 = ap1;
if (p1->combop != p2->combop)
return(0);
if (p1->op>0 && p1->op<MOV)
return(0);
cp1 = p1->code;
cp2 = p2->code;
if (cp1==0 && cp2==0)
return(1);
if (cp1==0 || cp2==0)
return(0);
while (*cp1 == *cp2++)
if (*cp1++ == 0)
return(1);
return(0);
}
decref(ap)
{
register struct node *p;
p = ap;
if (--p->refc <= 0) {
nrlab++;
p->back->forw = p->forw;
p->forw->back = p->back;
}
}
nonlab(ap)
struct node *ap;
{
register struct node *p;
p = ap;
while (p && p->op==LABEL)
p = p->forw;
return(p);
}
alloc(an)
{
register int n;
register char *p;
n = an;
n++;
n =& ~01;
if (lasta+n >= lastr) {
if (sbrk(2000) == -1) {
write(2, "Optimizer: out of space\n", 14);
exit(1);
}
lastr =+ 2000;
}
p = lasta;
lasta =+ n;
return(p);
}
clearreg()
{
register int i;
for (i=0; i<2*NREG; i++)
regs[i][0] = '\0';
conloc[0] = 0;
ccloc[0] = 0;
}
savereg(ai, as)
char *as;
{
register char *p, *s, *sp;
sp = p = regs[ai];
s = as;
if (source(s))
return;
while (*p++ = *s) {
if (s[0]=='(' && s[1]=='r' && s[2]<'5') {
*sp = 0;
return;
}
if (*s++ == ',')
break;
}
*--p = '\0';
}
dest(as, flt)
char *as;
{
register char *s;
register int i;
s = as;
if ((i = isreg(s)) >= 0)
regs[i+flt][0] = 0;
while ((i = findrand(s, flt)) >= 0)
regs[i][0] = 0;
while (*s) {
if ((*s=='(' && (*(s+1)!='r' || *(s+2)!='5')) || *s++=='*') {
for (i=flt; i<flt+NREG; i++) {
if (regs[i][0] != '$')
regs[i][0] = 0;
conloc[0] = 0;
}
return;
}
}
}
singop(ap)
struct node *ap;
{
register char *p1, *p2;
p1 = ap->code;
p2 = regs[RT1];
while (*p2++ = *p1++);
regs[RT2][0] = 0;
}
dualop(ap)
struct node *ap;
{
register char *p1, *p2;
register struct node *p;
p = ap;
p1 = p->code;
p2 = regs[RT1];
while (*p1 && *p1!=',')
*p2++ = *p1++;
*p2++ = 0;
p2 = regs[RT2];
*p2 = 0;
if (*p1++ !=',')
return;
while (*p2++ = *p1++);
}
findrand(as, flt)
char *as;
{
register int i;
for (i = flt; i<NREG+flt; i++) {
if (equstr(regs[i], as))
return(i);
}
return(-1);
}
isreg(as)
char *as;
{
register char *s;
s = as;
if (s[0]=='r' && s[1]>='0' && s[1]<='4' && s[2]==0)
return(s[1]-'0');
return(-1);
}
check()
{
register struct node *p, *lp;
lp = &first;
for (p=first.forw; p!=0; p = p->forw) {
if (p->back != lp)
abort();
lp = p;
}
}
source(ap)
char *ap;
{
register char *p1, *p2;
p1 = ap;
p2 = p1;
if (*p1==0)
return(0);
while (*p2++);
if (*p1=='-' && *(p1+1)=='('
|| *p1=='*' && *(p1+1)=='-' && *(p1+2)=='('
|| *(p2-2)=='+') {
while (*p1 && *p1++!='r');
if (*p1>='0' && *p1<='4')
regs[*p1 - '0'][0] = 0;
return(1);
}
return(0);
}
repladdr(p, f, flt)
struct node *p;
{
register r;
int r1;
register char *p1, *p2;
static char rt1[50], rt2[50];
if (f)
r1 = findrand(regs[RT2], flt);
else
r1 = -1;
r = findrand(regs[RT1], flt);
if (r1 >= NREG)
r1 =- NREG;
if (r >= NREG)
r =- NREG;
if (r>=0 || r1>=0) {
p2 = regs[RT1];
for (p1 = rt1; *p1++ = *p2++;);
if (regs[RT2][0]) {
p1 = rt2;
*p1++ = ',';
for (p2 = regs[RT2]; *p1++ = *p2++;);
} else
rt2[0] = 0;
if (r>=0) {
rt1[0] = 'r';
rt1[1] = r + '0';
rt1[2] = 0;
nsaddr++;
}
if (r1>=0) {
rt2[1] = 'r';
rt2[2] = r1 + '0';
rt2[3] = 0;
nsaddr++;
}
p->code = copy(rt1, rt2);
}
}
movedat()
{
register struct node *p1, *p2;
struct node *p3;
register seg;
struct node data;
struct node *datp;
if (first.forw == 0)
return;
datp = &data;
for (p1 = first.forw; p1!=0; p1 = p1->forw) {
if (p1->op == DATA) {
p2 = p1->forw;
while (p2 && p2->op!=TEXT)
p2 = p2->forw;
if (p2==0)
break;
p3 = p1->back;
p1->back->forw = p2->forw;
p2->forw->back = p3;
p2->forw = 0;
datp->forw = p1;
p1->back = datp;
p1 = p3;
datp = p2;
}
}
if (data.forw) {
datp->forw = first.forw;
first.forw->back = datp;
data.forw->back = &first;
first.forw = data.forw;
}
seg = -1;
for (p1 = first.forw; p1!=0; p1 = p1->forw) {
if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) {
if (p1->op == seg || p1->forw&&p1->forw->op==seg) {
p1->back->forw = p1->forw;
p1->forw->back = p1->back;
p1 = p1->back;
continue;
}
seg = p1->op;
}
}
}
redunbr(ap)
struct node *ap;
{
register struct node *p, *p1;
register char *ap1;
char *ap2;
if ((p1 = p->ref) == 0)
return;
p1 = nonlab(p1);
if (p1->op==TST) {
singop(p1);
savereg(RT2, "$0");
} else if (p1->op==CMP)
dualop(p1);
else
return;
if (p1->forw->op!=CBR)
return;
ap1 = findcon(RT1);
ap2 = findcon(RT2);
p1 = p1->forw;
if (compare(p1->subop, ap1, ap2)) {
nredunj++;
nchange++;
decref(p->ref);
p->ref = p1->ref;
p->labno = p1->labno;
p->ref->refc++;
}
}
findcon(i)
{
register char *p;
register r;
p = regs[i];
if (*p=='$')
return(p);
if ((r = isreg(p)) >= 0)
return(regs[r]);
if (equstr(p, conloc))
return(conval);
return(p);
}
compare(op, acp1, acp2)
char *acp1, *acp2;
{
register char *cp1, *cp2;
register n1;
int n2;
struct { int i;};
cp1 = acp1;
cp2 = acp2;
if (*cp1++ != '$' || *cp2++ != '$')
return(0);
n1 = 0;
while (*cp2 >= '0' && *cp2 <= '7') {
n1 =<< 3;
n1 =+ *cp2++ - '0';
}
n2 = n1;
n1 = 0;
while (*cp1 >= '0' && *cp1 <= '7') {
n1 =<< 3;
n1 =+ *cp1++ - '0';
}
if (*cp1=='+')
cp1++;
if (*cp2=='+')
cp2++;
do {
if (*cp1++ != *cp2)
return(0);
} while (*cp2++);
cp1 = n1;
cp2 = n2;
switch(op) {
case JEQ:
return(cp1 == cp2);
case JNE:
return(cp1 != cp2);
case JLE:
return(cp1.i <= cp2.i);
case JGE:
return(cp1.i >= cp2.i);
case JLT:
return(cp1.i < cp2.i);
case JGT:
return(cp1.i > cp2.i);
case JLO:
return(cp1 < cp2);
case JHI:
return(cp1 > cp2);
case JLOS:
return(cp1 <= cp2);
case JHIS:
return(cp1 >= cp2);
}
return(0);
}
setcon(ar1, ar2)
char *ar1, *ar2;
{
register char *cl, *cv, *p;
cl = ar2;
cv = ar1;
if (*cv != '$')
return;
if (!natural(cl))
return;
p = conloc;
while (*p++ = *cl++);
p = conval;
while (*p++ = *cv++);
}
equstr(ap1, ap2)
char *ap1, *ap2;
{
char *p1, *p2;
p1 = ap1;
p2 = ap2;
do {
if (*p1++ != *p2)
return(0);
} while (*p2++);
return(1);
}
setcc(ap)
char *ap;
{
register char *p, *p1;
p = ap;
if (!natural(p)) {
ccloc[0] = 0;
return;
}
p1 = ccloc;
while (*p1++ = *p++);
}
natural(ap)
char *ap;
{
register char *p;
p = ap;
if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(')
return(0);
while (*p++);
p--;
if (*--p == '+' || *p ==')' && *--p != '5')
return(0);
return(1);
}
+125
View File
@@ -0,0 +1,125 @@
/*
* Header for object code improver
*/
#define JBR 1
#define CBR 2
#define JMP 3
#define LABEL 4
#define DLABEL 5
#define EROU 7
#define JSW 9
#define MOV 10
#define CLR 11
#define COM 12
#define INC 13
#define DEC 14
#define NEG 15
#define TST 16
#define ASR 17
#define ASL 18
#define SXT 19
#define CMP 20
#define ADD 21
#define SUB 22
#define BIT 23
#define BIC 24
#define BIS 25
#define MUL 26
#define DIV 27
#define ASH 28
#define XOR 29
#define TEXT 30
#define DATA 31
#define BSS 32
#define EVEN 33
#define MOVF 34
#define MOVOF 35
#define MOVFO 36
#define ADDF 37
#define SUBF 38
#define DIVF 39
#define MULF 40
#define CLRF 41
#define CMPF 42
#define NEGF 43
#define TSTF 44
#define CFCC 45
#define SOB 46
#define JSR 47
#define END 48
#define JEQ 0
#define JNE 1
#define JLE 2
#define JGE 3
#define JLT 4
#define JGT 5
#define JLO 6
#define JHI 7
#define JLOS 8
#define JHIS 9
#define BYTE 100
struct node {
char op;
char subop;
struct node *forw;
struct node *back;
struct node *ref;
int labno;
char *code;
int refc;
};
struct {
int combop;
};
struct optab {
char *opstring;
int opcode;
} optab[];
char line[512];
struct node first;
char *curlp;
int nbrbr;
int nsaddr;
int redunm;
int iaftbr;
int njp1;
int nrlab;
int nxjump;
int ncmot;
int nrevbr;
int loopiv;
int nredunj;
int nskip;
int ncomj;
int nsob;
int nrtst;
int nlit;
int nchange;
int isn;
int debug;
char *lasta;
char *lastr;
char *firstr;
char revbr[];
char regs[12][20];
char conloc[20];
char conval[20];
char ccloc[20];
#define RT1 10
#define RT2 11
#define FREG 5
#define NREG 5
#define LABHS 127
#define OPHS 57
struct optab *ophash[OPHS];
struct { char lbyte; };
+370
View File
@@ -0,0 +1,370 @@
int nofloat;
int peekc;
int obuf[259];
int tabflg;
int labno 1;
main(argc, argv)
char **argv;
{
/*
A1 -> A
A2 B
A O
B1 C
B2 D
BE L
BF P
C1 E
C2 F
F G
H H
R I
R1 J
S K
I M
M N
* +1
S +2
C +4
1 +8
z -> 4
c 10
a 14
e 20
n 63
* +0100
*/
auto c,snlflg,nlflg,t,smode,m,ssmode;
extern fin;
smode = nlflg = snlflg = ssmode = 0;
if (argc>1)
if ((fin = open(argv[1], 0)) < 0) {
putchar('?\n');
return;
}
obuf[0] = 1;
if (argc>2)
if ((obuf[0] = creat(argv[2], 0666)) < 0) {
putchar('?\n');
return;
}
loop:
c = getc();
if (c!='\n' && c!='\t') nlflg = 0;
if (ssmode!=0 && c!='%') {
ssmode = 0;
printf(".data\nL%d:<", labno++);
}
switch(c) {
case '\0':
printf(".text; 0\n");
fflush(obuf);
return;
case ':':
if (!smode)
printf("=.+2; 0"); else
putchar(':');
goto loop;
case 'A':
if ((c=getc())=='1' || c=='2') {
putchar(c+'A'-'1');
goto loop;
}
putchar('O');
peekc = c;
goto loop;
case 'B':
switch (getc()) {
case '1':
putchar('C');
goto loop;
case '2':
putchar('D');
goto loop;
case 'E':
putchar('L');
goto loop;
case 'F':
putchar('P');
goto loop;
}
putchar('?');
goto loop;
case 'C':
putchar(getc()+'E'-'1');
goto loop;
case 'F':
putchar('G');
goto subtre;
case 'R':
if ((c=getc()) == '1')
putchar('J'); else {
putchar('I');
peekc = c;
}
goto loop;
case 'H':
putchar('H');
goto subtre;
case 'I':
putchar('M');
goto loop;
case 'S':
putchar('K');
subtre:
snlflg = 1;
t = 'A';
l1:
switch (c=getc()) {
case '*':
t++;
goto l1;
case 'S':
t =+ 2;
goto l1;
case 'C':
t =+ 4;
goto l1;
case '1':
t =+ 8;
goto l1;
case '2':
t =+ 16;
goto l1;
}
peekc = c;
putchar(t);
goto loop;
case '#':
if(getc()=='1')
putchar('#'); else
putchar('"');
goto loop;
case '%':
if (smode)
printf(".text;");
if (ssmode==0) {
if ((peekc=getc())=='[') {
peekc = 0;
printf(".data;");
while((c=getc())!=']')
putchar(c);
getc();
printf(";.text;");
goto loop;
}
}
loop1:
switch (c=getc()) {
case ' ':
case '\t':
goto loop1;
case 'a':
m = 16;
t = flag();
goto pf;
case ',':
putchar(';');
goto loop1;
case 'i':
m = 12;
t = flag();
goto pf;
case 'z':
m = 4;
t = flag();
goto pf;
case 'r':
m = 9;
t = flag();
goto pf;
case '1':
m = 5;
t = flag();
goto pf;
case 'c':
t = 0;
m = 8;
goto pf;
case 'e':
t = flag();
m = 20;
goto pf;
case 'n':
t = flag();
m = 63;
pf:
if ((c=getc())=='*')
m =+ 0100; else
peekc = c;
printf(".byte %o,%o", m, t);
goto loop1;
case '[':
printf("L%d=", labno++);
while ((c=getc())!=']')
putchar(c);
ssmode = 0;
smode = 0;
goto loop;
case '\n':
printf("\nL%d\n", labno);
ssmode = 1;
nlflg = 1;
smode = 1;
goto loop;
}
putchar(c);
goto loop1;
case '\t':
if (nlflg) {
nlflg = 0;
goto loop;
}
if (smode) {
tabflg++;
goto loop;
}
putchar('\t');
goto loop;
case '\n':
if (!smode) {
putchar('\n');
goto loop;
}
if (nlflg) {
nlflg = 0;
printf("\\0>\n.text\n");
smode = 0;
goto loop;
}
if (!snlflg)
printf("\\n");
snlflg = 0;
printf(">\n<");
nlflg = 1;
goto loop;
case 'X':
case 'Y':
case 'T':
snlflg++;
}
putchar(c);
goto loop;
}
getc() {
auto t, ifcnt;
ifcnt = 0;
gc:
if (peekc) {
t = peekc;
peekc = 0;
} else
t = getchar();
if (t==0)
return(0);
if (t=='{') {
ifcnt++;
t = getchar();
}
if (t=='}') {
t = getc();
if (--ifcnt==0)
if (t=='\n')
t = getc();
}
if (ifcnt && nofloat)
goto gc;
return(t);
}
flag() {
register c, f;
f = 0;
l1:
switch(c=getc()) {
case 'w':
f = 1;
goto l1;
case 'i':
f = 2;
goto l1;
case 'b':
f = 3;
goto l1;
case 'f':
f = 4;
goto l1;
case 'd':
f = 5;
goto l1;
case 's':
f = 6;
goto l1;
case 'l':
f = 8;
goto l1;
case 'p':
f =+ 16;
goto l1;
}
peekc = c;
return(f);
}
putchar(c)
{
if (tabflg) {
tabflg = 0;
printf(">;.byte %o;<", c+0200);
} else
putc(c, obuf);
}
+39
View File
@@ -0,0 +1,39 @@
cc -c -O c0[012345].c
cc -c -O c1[0123].c
as c1t.s; mv a.out c1t.o
cc cvopt.c
a.out table.s table.i
as table.i; mv a.out table.o
cc -c -O c2[01].c
ed c0t.s
g/fpp =/s/1/0/
w
q
as c0t.s; mv a.out c0t.o
cc -s -n c0?.o
cmp a.out /lib/c0
cp a.out /lib/c0
ed c0t.s
g/fpp =/s/0/1/
w
q
as c0t.s; mv a.out c0t.o
cc -f -s -n c0?.o
cmp a.out /lib/fc0
cp a.out /lib/fc0
cc -s -n c1?.o table.o
cmp a.out /lib/c1
cp a.out /lib/c1
cc -f -s -n c1?.o table.o
cmp a.out /lib/fc1
cp a.out /lib/fc1
cc -s -n c2?.o
cmp a.out /lib/c2
cp a.out /lib/c2
rm *.o table.i a.out
+1255
View File
File diff suppressed because it is too large Load Diff