📄 stmt.c
字号:
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;}static void caselabel(Swtch swp, long val, int lab) { int k; if (swp->ncases >= swp->size) { long *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("duplicate case label `%d'\n", val); swp->values[k] = val; swp->labels[k] = findlabel(lab); ++swp->ncases; if (Aflag >= 2 && swp->ncases == 258) warning("more than 257 cases in a switch\n");}void swgen(Swtch swp) { int *buckets, k, n; long *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);}void swcode(Swtch swp, int b[], int lb, int ub) { int hilab, lolab, l, u, k = (lb + ub)/2; long *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; for (i = l; i <= u; i++) cmp(EQ, swp->sym, v[i], swp->labels[i]->u.l.label); if (k > lb && k < ub) cmp(GT, swp->sym, v[u], hilab); else if (k > lb) cmp(GT, swp->sym, v[u], hilab); else if (k < ub) cmp(LT, swp->sym, v[l], lolab); else assert(lolab == hilab), branch(lolab); walk(NULL, 0, 0); } else { Tree e; Type ty = signedint(swp->sym->type); Symbol table = genident(STATIC, array(voidptype, u - l + 1, 0), GLOBAL); (*IR->defsymbol)(table); if (!isunsigned(swp->sym->type) || v[l] != 0) cmp(LT, swp->sym, v[l], lolab); cmp(GT, swp->sym, v[u], hilab); e = (*optree['-'])(SUB, cast(idtree(swp->sym), ty), cnsttree(ty, v[l])); if (e->type->size < unsignedptr->size) e = cast(e, unsignedlong); walk(tree(JUMP, voidtype, rvalue((*optree['+'])(ADD, pointer(idtree(table)), e)), 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("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 void cmp(int op, Symbol p, long n, int lab) { Type ty = signedint(p->type); listnodes(eqtree(op, cast(idtree(p), ty), cnsttree(ty, n)), lab, 0);}void retcode(Tree p) { Type ty; if (p == NULL) { if (events.returns) apply(events.returns, cfunc, NULL); return; } p = pointer(p); ty = assign(freturn(cfunc->type), p); if (ty == NULL) { error("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 { Type ty = retv->type->type; assert(isstruct(ty)); if (ty->u.sym->u.s.cfields) { ty->u.sym->u.s.cfields = 0; p = asgntree(ASGN, rvalue(idtree(retv)), p); ty->u.sym->u.s.cfields = 1; } 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); } if (!isfloat(p->type)) p = cast(p, promote(p->type)); if (isptr(p->type)) { Symbol q = localaddr(p); if (q && (q->computed || q->generated)) warning("pointer to a %s is an illegal return value\n", q->scope == PARAM ? "parameter" : "local"); else if (q) warning("pointer to %s `%s' is an illegal return value\n", q->scope == PARAM ? "parameter" : "local", q->name); } walk(tree(mkop(RET,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(LABEL+V, NULL, NULL, p); for (cp = codelist->prev; cp->kind <= Label; ) cp = cp->prev; while ( cp->kind == Jump && cp->u.forest->kids[0] && specific(cp->u.forest->kids[0]->op) == ADDRG+P && 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(JUMP+V, newnode(ADDRG+ttob(voidptype), NULL, NULL, p), NULL, NULL);}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 == LABEL+V && !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 == LABEL+V && equal(cp->u.forest->syms[0], p)) warning("source code specifies an infinite loop\n"); }}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) { refinc *= 10.0; t = gettok(); definelab(lab); statement(lab, swp, lev); definelab(lab + 1); expect(WHILE); expect('('); definept(NULL); walk(conditional(')'), lab, 0); if (findlabel(lab + 2)->ref) definelab(lab + 2);}/* foldcond - check if initial test in for(e1;e2;e3) S is necessary */static int foldcond(Tree e1, Tree e2) { int op = generic(e2->op); Symbol v; 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) 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; refinc *= 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); walk(e, lab, 0); if (findlabel(lab + 2)->ref) definelab(lab + 2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -