diff options
Diffstat (limited to 'lcc/src/stmt.c')
-rw-r--r-- | lcc/src/stmt.c | 696 |
1 files changed, 0 insertions, 696 deletions
diff --git a/lcc/src/stmt.c b/lcc/src/stmt.c deleted file mode 100644 index 9c3bdbe..0000000 --- a/lcc/src/stmt.c +++ /dev/null @@ -1,696 +0,0 @@ -#include "c.h" - - -#define SWSIZE 512 - -#define den(i,j) ((j-buckets[i]+1.0)/(v[j]-v[buckets[i]]+1)) - -struct code codehead = { Start }; -Code codelist = &codehead; -float density = 0.5; -Table stmtlabs; - -static int foldcond(Tree e1, Tree e2); -static void caselabel(Swtch, long, int); -static void cmp(int, Symbol, long, int); -static Tree conditional(int); -static void dostmt(int, Swtch, int); -static int equal(Symbol, Symbol); -static void forstmt(int, Swtch, int); -static void ifstmt(int, int, Swtch, int); -static Symbol localaddr(Tree); -static void stmtlabel(void); -static void swstmt(int, int, int); -static void whilestmt(int, Swtch, int); -Code code(int kind) { - Code cp; - - if (!reachable(kind)) - warning("unreachable code\n"); - - NEW(cp, FUNC); - cp->kind = kind; - cp->prev = codelist; - cp->next = NULL; - codelist->next = cp; - codelist = cp; - return cp; -} -int reachable(int kind) { - - if (kind > Start) { - Code cp; - for (cp = codelist; cp->kind < Label; ) - cp = cp->prev; - if (cp->kind == Jump || cp->kind == Switch) - return 0; - } - return 1; -} -void addlocal(Symbol p) { - if (!p->defined) { - code(Local)->u.var = p; - p->defined = 1; - p->scope = level; - } -} -void definept(Coordinate *p) { - Code cp = code(Defpoint); - - cp->u.point.src = p ? *p : src; - cp->u.point.point = npoints; - if (ncalled > 0) { - int n = findcount(cp->u.point.src.file, - cp->u.point.src.x, cp->u.point.src.y); - if (n > 0) - refinc = (float)n/ncalled; - } - if (glevel > 2) locus(identifiers, &cp->u.point.src); - if (events.points && reachable(Gen)) - { - Tree e = NULL; - apply(events.points, &cp->u.point.src, &e); - if (e) - listnodes(e, 0, 0); - } -} -void statement(int loop, Swtch swp, int lev) { - float ref = refinc; - - if (Aflag >= 2 && lev == 15) - warning("more than 15 levels of nested statements\n"); - switch (t) { - case IF: ifstmt(genlabel(2), loop, swp, lev + 1); - break; - case WHILE: whilestmt(genlabel(3), swp, lev + 1); break; - case DO: dostmt(genlabel(3), swp, lev + 1); expect(';'); - break; - - case FOR: forstmt(genlabel(4), swp, lev + 1); - break; - case BREAK: walk(NULL, 0, 0); - definept(NULL); - if (swp && swp->lab > loop) - branch(swp->lab + 1); - else if (loop) - branch(loop + 2); - else - error("illegal break statement\n"); - t = gettok(); expect(';'); - break; - - case CONTINUE: walk(NULL, 0, 0); - definept(NULL); - if (loop) - branch(loop + 1); - else - error("illegal continue statement\n"); - t = gettok(); expect(';'); - break; - - case SWITCH: swstmt(loop, genlabel(2), lev + 1); - break; - case CASE: { - int lab = genlabel(1); - if (swp == NULL) - error("illegal case label\n"); - definelab(lab); - while (t == CASE) { - static char stop[] = { IF, ID, 0 }; - Tree p; - t = gettok(); - p = constexpr(0); - if (generic(p->op) == CNST && isint(p->type)) { - if (swp) { - needconst++; - p = cast(p, swp->sym->type); - if (p->type->op == UNSIGNED) - p->u.v.i = extend(p->u.v.u, p->type); - needconst--; - caselabel(swp, p->u.v.i, lab); - } - } else - error("case label must be a constant integer expression\n"); - - test(':', stop); - } - statement(loop, swp, lev); - } break; - case DEFAULT: if (swp == NULL) - error("illegal default label\n"); - else if (swp->deflab) - error("extra default label\n"); - else { - swp->deflab = findlabel(swp->lab); - definelab(swp->deflab->u.l.label); - } - t = gettok(); - expect(':'); - statement(loop, swp, lev); break; - case RETURN: { - Type rty = freturn(cfunc->type); - t = gettok(); - definept(NULL); - if (t != ';') - if (rty == voidtype) { - error("extraneous return value\n"); - expr(0); - retcode(NULL); - } else - retcode(expr(0)); - else { - if (rty != voidtype) - warning("missing return value\n"); - retcode(NULL); - } - branch(cfunc->u.f.label); - } expect(';'); - break; - - case '{': compound(loop, swp, lev + 1); break; - case ';': definept(NULL); t = gettok(); break; - case GOTO: walk(NULL, 0, 0); - definept(NULL); - t = gettok(); - if (t == ID) { - Symbol p = lookup(token, stmtlabs); - if (p == NULL) { - p = install(token, &stmtlabs, 0, FUNC); - p->scope = LABELS; - p->u.l.label = genlabel(1); - p->src = src; - } - use(p, src); - branch(p->u.l.label); - t = gettok(); - } else - error("missing label in goto\n"); expect(';'); - break; - - case ID: if (getchr() == ':') { - stmtlabel(); - statement(loop, swp, lev); - break; - } - default: definept(NULL); - if (kind[t] != ID) { - error("unrecognized statement\n"); - t = gettok(); - } else { - Tree e = expr0(0); - listnodes(e, 0, 0); - if (nodecount == 0 || nodecount > 200) - walk(NULL, 0, 0); - else if (glevel) walk(NULL, 0, 0); - deallocate(STMT); - } expect(';'); - break; - - } - if (kind[t] != IF && kind[t] != ID - && t != '}' && t != EOI) { - static char stop[] = { IF, ID, '}', 0 }; - error("illegal statement termination\n"); - skipto(0, stop); - } - refinc = ref; -} - -static void ifstmt(int lab, int loop, Swtch swp, int lev) { - t = gettok(); - expect('('); - definept(NULL); - walk(conditional(')'), 0, lab); - refinc /= 2.0; - statement(loop, swp, lev); - if (t == ELSE) { - branch(lab + 1); - t = gettok(); - definelab(lab); - statement(loop, swp, lev); - if (findlabel(lab + 1)->ref) - definelab(lab + 1); - } else - definelab(lab); -} -static Tree conditional(int tok) { - Tree p = expr(tok); - - if (Aflag > 1 && isfunc(p->type)) - warning("%s used in a conditional expression\n", - funcname(p)); - return cond(p); -} -static void stmtlabel(void) { - Symbol p = lookup(token, stmtlabs); - - if (p == NULL) { - p = install(token, &stmtlabs, 0, FUNC); - p->scope = LABELS; - p->u.l.label = genlabel(1); - p->src = src; - } - if (p->defined) - error("redefinition of label `%s' previously defined at %w\n", p->name, &p->src); - - p->defined = 1; - definelab(p->u.l.label); - t = gettok(); - expect(':'); -} -static void forstmt(int lab, Swtch swp, int lev) { - int once = 0; - Tree e1 = NULL, e2 = NULL, e3 = NULL; - Coordinate pt2, pt3; - - t = gettok(); - expect('('); - definept(NULL); - if (kind[t] == ID) - e1 = texpr(expr0, ';', FUNC); - else - expect(';'); - walk(e1, 0, 0); - pt2 = src; - refinc *= 10.0; - if (kind[t] == ID) - e2 = texpr(conditional, ';', FUNC); - else - expect(';'); - pt3 = src; - if (kind[t] == ID) - e3 = texpr(expr0, ')', FUNC); - else { - static char stop[] = { IF, ID, '}', 0 }; - test(')', stop); - } - if (e2) { - once = foldcond(e1, e2); - if (!once) - branch(lab + 3); - } - definelab(lab); - statement(lab, swp, lev); - definelab(lab + 1); - definept(&pt3); - if (e3) - walk(e3, 0, 0); - if (e2) { - if (!once) - definelab(lab + 3); - definept(&pt2); - walk(e2, lab, 0); - } else { - definept(&pt2); - branch(lab); - } - if (findlabel(lab + 2)->ref) - definelab(lab + 2); -} -static void swstmt(int loop, int lab, int lev) { - Tree e; - struct swtch sw; - Code head, tail; - - t = gettok(); - expect('('); - definept(NULL); - e = expr(')'); - if (!isint(e->type)) { - error("illegal type `%t' in switch expression\n", - e->type); - e = retype(e, inttype); - } - e = cast(e, promote(e->type)); - if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op) - && e->kids[0]->u.sym->type == e->type - && !isvolatile(e->kids[0]->u.sym->type)) { - sw.sym = e->kids[0]->u.sym; - walk(NULL, 0, 0); - } else { - sw.sym = genident(REGISTER, e->type, level); - addlocal(sw.sym); - walk(asgn(sw.sym, e), 0, 0); - } - head = code(Switch); - sw.lab = lab; - sw.deflab = NULL; - sw.ncases = 0; - sw.size = SWSIZE; - sw.values = newarray(SWSIZE, sizeof *sw.values, FUNC); - sw.labels = newarray(SWSIZE, sizeof *sw.labels, FUNC); - refinc /= 10.0; - statement(loop, &sw, lev); - if (sw.deflab == NULL) { - sw.deflab = findlabel(lab); - definelab(lab); - if (sw.ncases == 0) - warning("switch statement with no cases\n"); - } - 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; -} -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 - 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"); - } -} -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); -} |