📄 stmt.c
字号:
}
if (findlabel(lab + 1)->ref)
definelab(lab + 1);
tail = codelist;
codelist = head->prev;
codelist->next = head->prev = NULL;
if (sw.ncases > 0)
swgen(&sw);
branch(lab);
head->next->prev = codelist;
codelist->next = head->next;
codelist = tail;
definept(NULL,POINT_ENDSWITCH);
}
static void caselabel(Swtch swp,int val,int lab)
{
int k;
if (swp->ncases >= swp->size)
{
int *vals = swp->values;
Symbol *labs = swp->labels;
swp->size *= 2;
swp->values = newarray(swp->size, sizeof *swp->values, FUNC);
swp->labels = newarray(swp->size, sizeof *swp->labels, FUNC);
for (k = 0; k < swp->ncases; k++) {
swp->values[k] = vals[k];
swp->labels[k] = labs[k];
}
}
k = swp->ncases;
for ( ; k > 0 && swp->values[k-1] >= val; k--) {
swp->values[k] = swp->values[k-1];
swp->labels[k] = swp->labels[k-1];
}
if (k < swp->ncases && swp->values[k] == val)
error(StrTab[74], val);// <duplicate case label `%d'\n>
swp->values[k] = val;
swp->labels[k] = findlabel(lab);
++swp->ncases;
if (Aflag >= 2 && swp->ncases == 258)
warning(StrTab[75]);// <more than 257 cases in a switch\n>
}
static void swgen(Swtch swp)
{
int *buckets, k, n, *v = swp->values;
buckets = newarray(swp->ncases + 1,
sizeof *buckets, FUNC);
for (n = k = 0; k < swp->ncases; k++, n++) {
buckets[n] = k;
while (n > 0 && den(n-1, k) >= density)
n--;
}
buckets[n] = swp->ncases;
swcode(swp, buckets, 0, n - 1);
}
static void swcode(Swtch swp,int b[],int lb,int ub)
{
int hilab, lolab, l, u, k = (lb + ub)/2;
int *v = swp->values;
if (k > lb && k < ub) {
lolab = genlabel(1);
hilab = genlabel(1);
} else if (k > lb) {
lolab = genlabel(1);
hilab = swp->deflab->u.l.label;
} else if (k < ub) {
lolab = swp->deflab->u.l.label;
hilab = genlabel(1);
} else
lolab = hilab = swp->deflab->u.l.label;
l = b[k];
u = b[k+1] - 1;
if (u - l + 1 <= 3)
{
int i,lastvalue;
Tree ResultTree;
for (i = l; i <= u; i++) {
ResultTree = cmp(EQ, swp->sym, v[i], swp->labels[i]->u.l.label);
lastvalue = v[i];
}
if (k > lb && k < ub) {
ResultTree = cmp(GT, swp->sym, v[u], hilab);
if (lastvalue == v[u])
SetForestFlags(1);
}
else if (k > lb) {
ResultTree = cmp(GT, swp->sym, v[u], hilab);
if (lastvalue == v[u])
SetForestFlags(1);
}
else if (k < ub) {
ResultTree = cmp(LT, swp->sym, v[l], lolab);
if (lastvalue == v[l])
SetForestFlags(1);
}
else
#ifndef NDEBUG
assert(lolab == hilab),
#endif
branch(lolab);
walk(NULL, 0, 0);
}
else {
Symbol table = genident(STATIC,
array(voidptype, u - l + 1, 0), LABELS);
(*IR->defsymbol)(table);
cmp(LT, swp->sym, v[l], lolab);
cmp(GT, swp->sym, v[u], hilab);
walk(tree(JUMP, voidtype,
rvalue((*optree['+'])(ADD, pointer(idtree(table)),
(*optree['-'])(SUB,
cast(idtree(swp->sym), inttype),
consttree(v[l], inttype)))), NULL), 0, 0);
code(Switch);
codelist->u.swtch.table = table;
codelist->u.swtch.sym = swp->sym;
codelist->u.swtch.deflab = swp->deflab;
codelist->u.swtch.size = u - l + 1;
codelist->u.swtch.values = &v[l];
codelist->u.swtch.labels = &swp->labels[l];
if (v[u] - v[l] + 1 >= 10000)
warning(StrTab[76]);// <switch generates a huge table\n>
}
if (k > lb) {
assert(lolab != swp->deflab->u.l.label);
definelab(lolab);
swcode(swp, b, lb, k - 1);
}
if (k < ub) {
assert(hilab != swp->deflab->u.l.label);
definelab(hilab);
swcode(swp, b, k + 1, ub);
}
}
static Tree cmp(int op,Symbol p,int n,int lab)
{
Tree Result;
Result = eqtree(op,cast(idtree(p), inttype),
consttree(n, inttype));
listnodes(Result,lab, 0);
return Result;
}
void retcode(Tree p)
{
Type ty;
if (p == NULL) {
if (events.returns)
apply(events.returns, cfunc, NULL);
return;
}
/*
There is no need to do anything if the called function returns
an integer and the function return type is integer
*/
if ( (p->op == CALLI && isint(cfunc->type)) ||
(p->op == CALLL && cfunc->type == longlongtype) ||
(p->op == CALLD && cfunc->type == doubletype)){
walk(tree(RET + widen(p->type), p->type, p, NULL), 0, 0);
return;
}
p = pointer(p);
ty = assign(freturn(cfunc->type), p);
if (ty == NULL) {
error(StrTab[77],// <illegal return type; found `%t' expected `%t'\n>
p->type, freturn(cfunc->type));
return;
}
p = cast(p, ty);
if (retv)
{
if (iscallb(p))
p = tree(RIGHT, p->type,
tree(CALL+B, p->type,
p->kids[0]->kids[0], idtree(retv)),
rvalue(idtree(retv)));
else
p = asgntree(ASGN, rvalue(idtree(retv)), p);
walk(p, 0, 0);
if (events.returns)
apply(events.returns, cfunc, rvalue(idtree(retv)));
return;
}
if (events.returns)
{
Symbol t1 = genident(AUTO, p->type, level);
addlocal(t1);
walk(asgn(t1, p), 0, 0);
apply(events.returns, cfunc, idtree(t1));
p = idtree(t1);
}
p = cast(p, promote(p->type));
if (isptr(p->type)) {
Symbol q = localaddr(p);
if (q && (q->computed || q->generated))
warning(StrTab[78],// <pointer to a %s is an illegal return value\n>
q->scope == PARAM ? StrTab[79] : "local");// <parameter>
else if (q)
warning(StrTab[81],// <pointer to %s `%s' is an illegal return value\n>
q->scope == PARAM ? StrTab[82] : "local", q->name);// <parameter>
p = cast(p, unsignedtype);
}
walk(tree(RET + widen(p->type), p->type, p, NULL), 0, 0);
}
void definelab(int lab)
{
Code cp;
Symbol p = findlabel(lab);
assert(lab);
walk(NULL, 0, 0);
code(Label)->u.forest = newnode(LABELV, NULL, NULL, p);
for (cp = codelist->prev; cp->kind <= Label; )
cp = cp->prev;
while ( cp->kind == Jump
&& cp->u.forest->kids[0]
&& cp->u.forest->kids[0]->op == ADDRGP
&& cp->u.forest->kids[0]->syms[0] == p) {
assert(cp->u.forest->kids[0]->syms[0]->u.l.label == lab);
p->ref--;
assert(cp->next);
assert(cp->prev);
cp->prev->next = cp->next;
cp->next->prev = cp->prev;
cp = cp->prev;
while (cp->kind <= Label)
cp = cp->prev;
}
}
Node jump(int lab)
{
Symbol p = findlabel(lab);
p->ref++;
return newnode(JUMPV, newnode(ADDRGP, NULL, NULL, p),
NULL, NULL);
}
static void branch(int lab)
{
Code cp;
Symbol p = findlabel(lab);
assert(lab);
walk(NULL, 0, 0);
code(Label)->u.forest = jump(lab);
for (cp = codelist->prev; cp->kind < Label; )
cp = cp->prev;
while ( cp->kind == Label
&& cp->u.forest->op == LABELV
&& !equal(cp->u.forest->syms[0], p)) {
equatelab(cp->u.forest->syms[0], p);
assert(cp->next);
assert(cp->prev);
cp->prev->next = cp->next;
cp->next->prev = cp->prev;
cp = cp->prev;
while (cp->kind < Label)
cp = cp->prev;
}
if (cp->kind == Jump || cp->kind == Switch) {
p->ref--;
codelist->prev->next = NULL;
codelist = codelist->prev;
} else {
codelist->kind = Jump;
if (cp->kind == Label
&& cp->u.forest->op == LABELV
&& equal(cp->u.forest->syms[0], p))
warning(StrTab[84]);// <source code specifies an infinite loop>
}
}
void equatelab(Symbol old,Symbol new)
{
assert(old->u.l.equatedto == NULL);
old->u.l.equatedto = new;
new->ref++;
}
static int equal(Symbol lprime,Symbol dst)
{
assert(dst && lprime);
for ( ; dst; dst = dst->u.l.equatedto)
if (lprime == dst)
return 1;
return 0;
}
/* dostmt - do statement while ( expression ) */
static void dostmt(int lab,Swtch swp,int lev)
{
int start = StatementCount;
refinc *= (float)10.0;
t = gettok();
definelab(lab);
statement(lab, swp, lev);
definelab(lab + 1);
expect(WHILE);
expect('(');
definept(NULL,POINT_STARTDO);
walk(conditional(')'), lab, 0);
if (findlabel(lab + 2)->ref)
definelab(lab + 2);
if (OptimizeFlag) {
ExtendDomain(level,start);
}
definept(NULL,POINT_ENDDO);
}
/* foldcond - check if initial test in for(e1;e2;e3) S is necessary */
static int foldcond(Tree e1,Tree e2,Symbol *pIndex)
{
int op = generic(e2->op);
Symbol v;
*pIndex = 0;
if (e1 == 0 || e2 == 0)
return 0;
if (generic(e1->op) == ASGN && isaddrop(e1->kids[0]->op)
&& generic(e1->kids[1]->op) == CNST) {
v = e1->kids[0]->u.sym;
e1 = e1->kids[1];
} else
return 0;
if ((op==LE || op==LT || op==EQ || op==NE || op==GT || op==GE)
&& generic(e2->kids[0]->op) == INDIR
&& e2->kids[0]->kids[0]->u.sym == v
&& e2->kids[1]->op == e1->op) {
e1 = simplify(op, e2->type, e1, e2->kids[1]);
if (e1->op == CNST+I) {
*pIndex = v;
return e1->u.v.i;
}
}
return 0;
}
/* localaddr - returns q if p yields the address of local/parameter q; otherwise returns 0 */
static Symbol localaddr(Tree p)
{
if (p == NULL)
return NULL;
switch (generic(p->op)) {
case INDIR: case CALL: case ARG:
return NULL;
case ADDRL: case ADDRF:
return p->u.sym;
case RIGHT: case ASGN:
if (p->kids[1])
return localaddr(p->kids[1]);
return localaddr(p->kids[0]);
case COND: {
Symbol q;
assert(p->kids[1] && p->kids[1]->op == RIGHT);
if ((q = localaddr(p->kids[1]->kids[0])) != NULL)
return q;
return localaddr(p->kids[1]->kids[1]);
}
default: {
Symbol q;
if (p->kids[0] && (q = localaddr(p->kids[0])) != NULL)
return q;
return localaddr(p->kids[1]);
}
}
}
/* whilestmt - while ( expression ) statement */
static void whilestmt(int lab,Swtch swp,int lev)
{
Coordinate pt;
Tree e;
int start = StatementCount;
refinc *= (float)10.0;
t = gettok();
expect('(');
walk(NULL, 0, 0);
pt = src;
e = texpr(conditional, ')', FUNC);
branch(lab + 1);
definelab(lab);
statement(lab, swp, lev);
definelab(lab + 1);
definept(&pt,POINT_STARTWHILE);
walk(e, lab, 0);
if (findlabel(lab + 2)->ref)
definelab(lab + 2);
if (OptimizeFlag) {
ExtendDomain(level,start);
}
definept(NULL,POINT_ENDWHILE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -