📄 gen.c
字号:
oldbp = bp;
isinstruction = IR->x._isinstruction[rulenum];
genericOp = generic(p->op);
if (p->x.intrinsic) {
if (p->x.emitted) {
outs(p->syms[RX]->x.name);
return 0;
}
p->x.emitted = 1;
Intrinsic(p);
return 0;
}
if (isinstruction && p->x.emitted) {
/* When an instruction has already been emitted, only the name of the
register where the instruction left its result will be output
*/
outs(p->syms[RX]->x.name);
}
else if (*fmt == '#')
/* This is an escape hatch to generate machine specific code like
structure arguments
*/
(*IR->x.emit2)(p);
else {
if (*fmt == '?') {
/* Omit redundant expressions */
fmt++;
/*assert(p->x.kids[0]);*/
/* This was updated after my complaints about redundant expressions */
if (p->x.kids[0] && p->syms[RX] == p->x.kids[0]->syms[RX])
while (*fmt++ != '\n')
;
else if (p->x.kids[1] && p->syms[RX] == p->x.kids[1]->syms[RX]) {
/*
This happens mainly in the case of a return instruction, where
the return expression assigns eax to one of its members,
specifically to p->x.kids[1]. This is a bug in the register
allocator that doesn't take into account the registers assigned
with rtarget. This correction works, well I hope.
*/
int i;
fmt = strchr(fmt,'\n');
assert(fmt);
fmt++;
if (*fmt == '\t')
fmt++;
i = 1;
newfmt[0] = '\t';
if (generic(p->op) == SUB || generic(p->op) == BXORU) {
strcpy(newfmt,"\txchgl\t%0,%c\n\t");
i = strlen(newfmt);
}
while (*fmt && *fmt != '\t') {
newfmt[i++] = *fmt++;
}
newfmt[i++] = '\t';
newfmt[i] = 0;
strcat(newfmt,"%0,%c\n");
fmt = newfmt;
// printf("%s: (%d)\n",cfunc->name,src.y);
// dumptree(p,0);
// printf("\n");
}
}
if (p->x.Flags && (p->op == LTI || p->op == GTI)) {
while (*fmt++ != '\n')
;
}
booleanAsgn = p->x.booleanAsgn;
if (glevel > 2 && genericOp == CALL) {
if (glevel == 3) {
if (FunctionInfo.FnNrOfLines < 256)
print("\tmovb\t$%d,-8(%%ebp)\n",src.y - cfunc->src.y);
else
print("\tmovw\t$%d,-8(%%ebp)\n",src.y - cfunc->src.y);
}
NeedsCallReset=1;
}
for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++) {
if (*fmt != '%')
*bp++ = *fmt;
else {
++fmt;
if (*fmt >= '0' && *fmt <= '9') {
int n = *fmt - '0';
/* Emit recursively the subtree corresponding to the 'digit'-th
nonterminal for the pattern, counting from zero, left to
right.
*/
emitasm(kids[n], nts[n]);
if (genericOp == CALL) { /* call instruction */
if (kids[n]->syms && kids[n]->syms[0] &&
kids[n]->syms[0]->Flags) {
*bp++ = '\n';
goto exitEmit;
}
else if (oldbp[7] == 'a' && !strncmp(oldbp+6,"_alloca",7)) {
int c = oldbp[13];
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'z') ||
(c >= '0' && c <= '9'))) {
hasAllocA = 1;
*bp++ = '\n';
goto exitEmit;
}
}
}
}
else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms)) {
/* This evaluates to a register name */
if (FunctionInfo.noFrame) {
if (*fmt == 'a' && !strcmp(fmt+1,"(%%ebp)")) {
char tmpbuf[20];
int offset = atoi(p->syms[0]->x.name);
offset -= 4;
offset += FunctionInfo.pushedRegs;
assert(offset > 0);
sprintf(tmpbuf,"%d(%%esp)",offset);
outs(tmpbuf);
goto exitEmit;
}
}
outs(p->syms[*fmt - 'a']->x.name);
}
else
*bp++ = *fmt;
}
if (booleanAsgn && *fmt == '\n')
break;
}
}
if (OptimizeFlag && hasExceptions == 0 && genericOp == LABEL) {
SendToOptimizer();
}
exitEmit:
if (glevel > 2) {
if (NeedsCallReset)
RestoreGlevelStack();
if (glevel > 3 && genericOp == LABEL)
NeedsLineReset = 1;
}
return 0;
}
void emit(Node p)
{
if (IntermediateLanguageFile)
fprintf(ilFile,"\n; Tree\n");
for (; p; p = p->x.next) {
assert(p->x.registered);
if (p->x.equatable && requate(p) || moveself(p)) {
;
}
else {
char *oldbp = bp;
(*emitter)(p, p->x.inst);
if (IntermediateLanguageFile) {
int rulenum;
ildumptree(p,0);
fprintf(ilFile,"\n");
rulenum = getrule(p, p->x.inst);
ildumprule(rulenum);
fprintf(ilFile,"%s",oldbp);
}
oldbp = bp;
}
p->x.emitted = 1;
}
}
int moveself(Node p)
{
if (p->x.kids[0] == NULL) return 0;
return p->x.copy
&& p->syms[RX]->x.name == p->x.kids[0]->syms[RX]->x.name;
}
int move(Node p)
{
p->x.copy = 1;
return 1;
}
int requate(Node q)
{
Symbol src = q->x.kids[0]->syms[RX];
Symbol tmp = q->syms[RX];
Node p;
int n = 0;
#ifdef DODEBUG
fprint(2, "(requate(%x): tmp=%s src=%s)\n", q, tmp->x.name, src->x.name);
#endif
for (p = q->x.next; p; p = p->x.next)
if (p->x.copy && p->syms[RX] == src
&& p->x.kids[0]->syms[RX] == tmp)
#ifdef DODEBUG
fprint(2, "(requate arm 0 at %x)\n", p),
#endif
p->syms[RX] = tmp;
else if (setsrc(p->syms[RX]) && !moveself(p) && !readsreg(p))
return 0;
#if OLD
else if (generic(p->op) == ASGN && p->kids[0]->op == ADDRLP
&& p->kids[0]->syms[0]->temporary
&& p->kids[1]->syms[RX]->x.name == tmp->x.name)
return 0;
#else
else if (p->x.spills)
return 0;
#endif
else if (generic(p->op) == CALL && p->x.next)
return 0;
else if (p->op == LABEL+V && p->x.next)
return 0;
else if (p->syms[RX] == tmp && readsreg(p))
#ifdef DODEBUG
fprint(2, "(requate arm 5 at %x)\n", p),
#endif
n++;
else if (p->syms[RX] == tmp)
break;
#ifdef DODEBUG
fprint(2, "(requate arm 7 at %x)\n", p);
#endif
assert(n > 0);
for (p = q->x.next; p; p = p->x.next)
if (p->syms[RX] == tmp && readsreg(p)) {
p->syms[RX] = src;
if (--n <= 0)
break;
}
return 1;
}
extern int clobbersWhich(Node);
static int DoesNotUse(Node tree,Symbol r)
{
int clobberedMask;
if (tree == NULL) return 1;
clobberedMask = clobbersWhich(tree);
if (r->x.regnode && (clobberedMask & r->x.regnode->mask))
return 0;
if (tree->syms[RX]->x.name == r->x.name) return 0;
if (tree->syms[0] && tree->syms[0]->x.name == r->x.name) return 0;
if (!DoesNotUse(tree->kids[0],r)) return 0;
if (!DoesNotUse(tree->kids[1],r)) return 0;
if (tree->syms[0] == NULL) return 1;
return 1;
}
static int IsSafeOp(Node q)
{
if (q == NULL) return 0;
return (
q->op == ADDI || q->op == SUBI || q->op == BANDU || q->op == BORU
|| q->op == CVSI || q->op == CVSU || q->op == NEGI) ? 1 : 0;
}
static void prelabel(Node p)
{
if (p == NULL)
return;
prelabel(p->kids[0]);
prelabel(p->kids[1]);
if (NeedsReg[opindex(p->op)] || p->op == JUMPI)
setreg(p, rmap[optype(p->op)]);
switch (generic(p->op)) {
case ADDRF: case ADDRL:
if (p->syms[0]->sclass == REGISTER)
p->op = VREG+P;
return;
case INDIR:
if (p->kids[0]->op == VREG+P)
setreg(p, p->kids[0]->syms[0]);
return;
case ASGN:
if (p->kids[0]->op == VREG+P) {
Node q = p->kids[1];
Symbol r = p->kids[0]->syms[0];
#ifdef DODEBUG
fprint(2, "(cse=%x)\n", p->kids[0]->syms[0]->u.t.cse);
#endif
rtarget(p, 1, r);
(IR->x.target)(p);
if (OptimizeFlag && r->x.wildcard == NULL && IsSafeOp(q)) {
if (q->kids[0]->syms[RX]->x.wildcard && IsSafeOp(q->kids[0])) {
if (DoesNotUse(q->kids[0],r) &&
DoesNotUse(q->kids[1],r)) {
setreg(q->kids[0],r);
#if 0
printf("%s: setting operation %d to %s. Line %d\n",
src.file,q->kids[0]->op,r->x.name,src.y);
#endif
}
}
}
return;
}
break;
}
(IR->x.target)(p);
}
void setreg(Node p,Symbol r)
{
p->syms[RX] = r;
}
void rtarget(Node p,int n,Symbol r)
{
Node q = p->kids[n];
assert(q);
assert(r->sclass == REGISTER || !r->x.wildcard);
assert(q->syms[RX]);
if (r != q->syms[RX] && !q->syms[RX]->x.wildcard) {
lab1:
q = newnode(LOAD + optype(q->op),
q, NULL, q->syms[0]);
if (r->u.t.cse == p->kids[n])
r->u.t.cse = q;
p->kids[n] = p->x.kids[n] = q;
q->x.kids[0] = q->kids[0];
setreg(q,r);
}
else if (q->kids[1] == NULL ||
p->kids[0]->syms[0] == NULL ||
p->kids[0]->syms[0]->u.t.cse ||
!(/*q->kids[0]->syms[RX]->x.name[0] == '?' &&*/
p->kids[0]->syms[0] == q->kids[1]->syms[RX]))
setreg(q, r);
else {
// printf("not taken line %d\n",src.y);
goto lab1;
}
// q->x.unsafe = 1;
#ifdef DODEBUG
fprint(2, "(targeting %x->x.kids[%d]=%x to %s)\n", p, n, p->kids[n], r->x.name);
#endif
}
static void rewrite(Node p)
{
assert(p->x.inst == 0);
prelabel(p);
#ifdef DODEBUG
dumptree(p,0);
fprint(2, "\n");
#endif
(*IR->x._label)(p);
#ifdef DODEBUG
dumpcover(p, 1, 0);
#endif
reduce(p, 1);
}
static void SetClobberedRegs(Node p,int clobbered)
{
if (p == NULL) return;
p->x.clobbersWhich = clobbered;
SetClobberedRegs(p->kids[0],clobbered);
SetClobberedRegs(p->kids[1],clobbered);
}
/*
The interface function gen receives a forest from the front end and makes
several passes over the trees.
*/
Node gen(Node forest)
{
int i;
struct node sentinel;
Node dummy, p;
head = forest;
if (OptimizeFlag)
unsafe = head->x.unsafe;
else
unsafe = 1;
/*
The first pass calls rewrite to select instructions, and the second
prunes the subinstructions out of the tree.
*/
for (p = forest; p; p = p->link) {
assert(p->count == 0);
if (generic(p->op) == CALL)
docall(p);
else /* If the call returns no value, or if the returned
value is ignored, then the call itself appears in the forst.
This statement recognizes this pattern */
if (generic(p->op) == ASGN
&& generic(p->kids[1]->op) == CALL)
docall(p->kids[1]);
else if (generic(p->op) == ARG)
(*IR->x.doarg)(p);
rewrite(p);
p->x.listed = 1;
}
for (p = forest; p; p = p->link)
prune(p, &dummy);
relink(&sentinel, &sentinel);
for (p = forest; p; p = p->link)
linearize(p, &sentinel);
forest = sentinel.x.next;
assert(forest);
sentinel.x.next->x.prev = NULL;
sentinel.x.prev->x.next = NULL;
for (p = forest; p; p = p->x.next)
for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
assert(p->x.kids[i]->syms[RX]);
if (p->x.kids[i]->syms[RX]->temporary) {
p->x.kids[i]->x.prevuse =
p->x.kids[i]->syms[RX]->x.lastuse;
p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
}
}
#if 0 // This is the patch proposed by Chris Fraser end of April 97.
for (p = forest; p; p = p->x.next)
if (p->x.copy && p->x.kids[0] && p->x.kids[0]->syms[RX]->u.t.cse) {
Symbol dst = p->syms[RX];
Symbol temp = p->x.kids[0]->syms[RX];
Node q;
assert(temp->x.lastuse);
for (q = temp->u.t.cse; q; q = q->x.next)
if (p != q && dst == q->syms[RX]
|| (q->op == LABELV || q->op == JUMPV || generic(q->op)==RET ||
generic(q->op)==EQ || generic(q->op)==NE ||
generic(q->op)==LE || generic(q->op)==LT ||
generic(q->op)==GE || generic(q->op)==GT ||
q->op == ASGNB || /* This costed me a week */
(generic(q->op) == CALL && dst->sclass != REGISTER)))
break;
if (!q)
for (q = temp->x.lastuse; q; q = q->x.prevuse)
q->syms[RX] = dst;
}
#endif
if (OptimizeFlag) {
int clobberswhich = 0;
for (p = forest; p ; p = p->x.next) {
if (p->op != JUMPI)
clobberswhich = clobbersWhich(p);
else
clobberswhich = (1 << 6)|(1<< 7);
if (clobberswhich) {
SetClobberedRegs(p,clobberswhich);
}
if (p->op == DIVI && p != forest && p->x.prev)
p->x.prev->x.clobbersWhich |= (1 << 2)|1;
}
}
for (p = forest; p; p = p->x.next) {
if (p->x.unsafe || (p->x.next && p->x.next->x.unsafe))
unsafe = 1;
ralloc(p);
if (p->x.listed && (NeedsReg[opindex(p->op)] || p->op == JUMPI)
&& rmap[optype(p->op)]) {
assert(generic(p->op) == CALL || p->op == JUMPI ||
generic(p->op) == LOAD);
putreg(p->syms[RX]);
}
}
unsafe = 1;
return forest;
}
int notarget(Node p)
{
return p->syms[RX]->x.wildcard ? 0 : LBURG_MAX;
}
static void putreg(Symbol r)
{
assert(r && r->x.regnode);
freemask[r->x.regnode->set] |= r->x.regnode->mask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -