Add original unix v6
This commit is contained in:
+709
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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; };
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user