📄 ccgen1.c
字号:
break;
case Q_CONTINUE:
false = looplabel;
nelse = NULL;
break;
case Q_BREAK:
false = brklabel;
nelse = NULL;
break;
default:
false = newlabel();
}
switch(nthen->Nop) { /* we could invert the boolean here, */
case Q_GOTO: /* but instead we merely set label */
case N_LABEL: /* at the end of the condition. */
case Q_CASE: /* fixes gotos in both clauses. */
l->Nendlab = nthen->Nxfsym;
break;
case Q_CONTINUE:
l->Nendlab = looplabel;
break;
case Q_BREAK:
l->Nendlab = brklabel;
default:
; /* do nothing */
}
gboolean(l, false, 0);
nthen->Nendlab = true;
genstmt(nthen);
if (nelse) {
code6(P_JRST, NULL, true);
codlabel(false);
nelse->Nendlab = true;
genstmt(nelse);
}
} else if (nelse) {
gboolean(l, true, 1);
nelse->Nendlab = true;
genstmt(nelse);
}
/* then emit exit label */
if (!n->Nendlab) codlabel(true); /* emit exit label */
}
/* LABCHK - returns true if parse tree contains any labels.
*/
static int
labchk(n)
NODE *n;
{
if (n == NULL) return 0;
switch (n->Nop) {
case Q_CASE: /* These three are all labels */
case N_LABEL:
case Q_DEFAULT:
return 1;
case N_STATEMENT: /* Compound statement, scan it. */
if (n->Nleft && n->Nleft->Nop == N_DATA) /* Skip auto inits */
n = n->Nright; /* move on to real statements */
for(; n != NULL; n = n->Nright) {
if(n->Nop != N_STATEMENT)
int_error("labchk: bad stmt %N", n);
if(n->Nleft && labchk(n->Nleft))
return 1;
}
return 0;
case Q_IF: /* Has two substatements */
return labchk(n->Nright->Nleft) || labchk(n->Nright->Nright);
case Q_DO: /* Standard substatements */
case Q_FOR:
case Q_SWITCH:
case Q_WHILE:
return labchk(n->Nright);
case Q_BREAK: /* Not labels and no substatements */
case Q_GOTO:
case Q_CONTINUE:
case Q_RETURN:
case N_EXPRLIST: /* Same as expression stmt */
default: /* None of above, assume expression stmt */
return 0;
}
}
/* ------------------------- */
/* while statement */
/* ------------------------- */
static void
gwhile(n)
NODE *n;
{
SYMBOL *saveb, *savel;
/* ok, we do, so we need to make a label for the top */
savel = looplabel;
looplabel = gtoplab(); /* Get new label and emit */
/* now, see if there is a body or just the test */
if (n->Nright == NULL) {
n->Nleft->Nendlab = n->Nendlab; /* propagate exit point */
gboolean(n->Nleft, looplabel, 1); /* no body, just test */
} else {
saveb = brklabel; /* full body, need another label */
brklabel = (n->Nendlab != NULL)? n->Nendlab : newlabel();
n->Nright->Nendlab = looplabel; /* exit from body is to loop top */
gboolean(n->Nleft, brklabel, 0); /* first the test, if any */
genstmt(n->Nright); /* then the actual body */
code6(P_JRST, NULL, looplabel); /* body jumps back to test */
if (n->Nendlab == NULL) codlabel(brklabel); /* emit end label */
brklabel = saveb; /* restore label for outer loop */
}
/* in either case we need to restore the outer loop top label */
freelabel (looplabel);
looplabel = savel; /* fix the label */
}
/* GTOPLAB - auxiliary for loops which need to generate a label at top.
*/
static SYMBOL *
gtoplab()
{
SYMBOL *lab;
flushcode(); /* Ensure all previous code forced out */
lab = newlabel(); /* Get new label */
outlab(lab); /* and emit it directly */
return lab;
}
/* ---------------------- */
/* do statement */
/* ---------------------- */
static void
gdo(n)
NODE *n;
{
SYMBOL *saveb, *savel, *toplabel;
toplabel = gtoplab(); /* Get new label and emit */
saveb = brklabel;
brklabel = (n->Nendlab != NULL) ? n->Nendlab : newlabel();
if (n->Nright) {
savel = looplabel;
n->Nright->Nendlab = looplabel = newlabel();
genstmt(n->Nright);
codlabel(looplabel);
looplabel = savel; /* restore outer loop label */
}
if ((n->Nleft->Nop) != N_ICONST) {
n->Nleft->Nendlab = brklabel;
gboolean(n->Nleft, toplabel, 1);
} else if (n->Nleft->Niconst) code6(P_JRST, NULL, toplabel);
if (n->Nendlab == NULL) codlabel(brklabel);
brklabel = saveb; /* restore for outer breaks */
freelabel (toplabel); /* no more use for this one */
}
/* ----------------------- */
/* for statement */
/* ----------------------- */
static void
gfor(n)
NODE *n;
{
NODE *cond, *body, *incr, *init;
SYMBOL *saveb, *savel, *toplabel;
int endtest; /* safe to move test to end of loop */
cond = n->Nleft;
body = n->Nright;
incr = cond->Nright->Nleft;
cond = cond->Nleft;
init = cond->Nleft;
cond = cond->Nright;
/* See if conditional test can be put at the end of the loop, which is
** usually more efficient. endtest is true if so. Note that it
** will not be true if no test exists.
*/
endtest = optgen && /* Never, if not optimizing. */
cond && /* And only if have a condition. */
((body == NULL && incr == NULL) /* OK if no body or increment */
|| istrue(cond, init)); /* or if test exists & is TRUE */
if (init) genxrelease(init);
toplabel = gtoplab(); /* Generate top-of-loop label and emit */
saveb = brklabel;
brklabel = (n->Nendlab != NULL) ? n->Nendlab : newlabel();
savel = looplabel; /* remember prev outer label */
looplabel = (body == NULL || (incr == NULL && !endtest)) ?
toplabel : newlabel();
/* Normally generate test at start of loop */
if (cond && !endtest) /* If have condition, and at beg, */
gboolean(cond, brklabel, 0); /* generate test at start of loop */
/* Now generate body */
if (body != NULL) { /* If we have one, of course */
body->Nendlab = looplabel;
genstmt(body);
if (looplabel != toplabel) codlabel(looplabel);
}
/* Now generate increment */
if (incr != NULL) {
if (!endtest) incr->Nendlab = toplabel;
genxrelease(incr);
}
/* Finally generate loop back to condition test at top, unless actually
** doing the test here.
*/
if (endtest) { /* If test comes at end of loop */
cond->Nendlab = brklabel; /* set end label for it */
gboolean(cond,toplabel,1); /* and gen the conditional jump */
}
else code6(P_JRST, NULL, toplabel); /* Otherwise just loop */
if (n->Nendlab == NULL)
codlabel(brklabel);
brklabel = saveb; /* restore old break label */
looplabel = savel; /* restore outer loop continuation */
freelabel(toplabel); /* don't need top label any more */
}
/*
* greturn ()
*/
static
void
greturn (NODE *n)
{
INT siz;
VREG* r;
VREG* r2;
int i = n->Nreg;
if (optobj && deadjump ()) /* If in dead code, do nothing */
return;
if ((n = n->Nright) != NULL)
{ /* If returning a value, set it */
if (n->Ntype->Tspec == TS_ARRAY)
{ /* Just in case */
int_error("greturn: returning array");
return;
}
siz = sizetype(n->Ntype); /* Remember size */
n->Nflag |= NF_RETEXPR; /* Tell genexpr this is return value */
if ((r = genexpr(n)) == NULL)
{ /* Make return expression */
if (!deadjump()) /* If no expr, must be in dead code */
int_error("greturn: null vreg");
return; /* Assume tail-recursed, so win! */
}
if (siz == 1) /* Return 1-word value */
code0 (P_MOVE, VR_RETVAL, r);
else if (siz == 2) /* Return 2-word value */
code0 (P_DMOVE, VR_RETVAL, r);
else
{ /* Return N-word value */
r2 = vrget();
code13(P_MOVE, r2, -1 - stackoffset); /* Get addr of arg 0 */
code4(P_MOVE, r2, r2); /* Get ptr to place to return block */
code4s(P_SMOVE, r2, r, 0, siz); /* Copy the block */
vrfree(r2);
}
}
if (optobj)
killstack (); /* Flush spurious MOVEMs */
#if 0 /* qq Reg linkage */
if (!fn_main && R_PRESERVE_COUNT >= i && i > 0) /* Reg linkage */
stackoffset -= i;
printf ("stackoffset=%d i=%d\n", stackoffset, i);
#endif
code8 (P_ADJSP, VR_SP, -stackoffset); /* flush local vars from stk */
if (profbliss)
{ /* for BLISS profiler */
flushcode ();
outepilog (curfn); /* added 09/15/89 by MVS */
}
/*
* Restore any preserved registers that were used for
* register variables.
*/
if (!fn_main && R_PRESERVE_COUNT >= i) /* Reg linkage */
{
while (i-- > 0)
{
code00 (P_POP, R_SP, i + r_maxnopreserve + 1); /* FW 2A(52) */
oline++;
}
}
if (isr) /* FW 2A(52) */
{
flushcode ();
outiepilog ();
}
else
code5 (P_POPJ, VR_SP); /* emit the return */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -