00001 #include "c.h"
00002
00003
00004 #define SWSIZE 512
00005
00006 #define den(i,j) ((j-buckets[i]+1.0)/(v[j]-v[buckets[i]]+1))
00007
00008 struct code codehead = { Start };
00009 Code codelist = &codehead;
00010 float density = 0.5;
00011 Table stmtlabs;
00012
00013 static int foldcond(Tree e1, Tree e2);
00014 static void caselabel(Swtch, long, int);
00015 static void cmp(int, Symbol, long, int);
00016 static Tree conditional(int);
00017 static void dostmt(int, Swtch, int);
00018 static int equal(Symbol, Symbol);
00019 static void forstmt(int, Swtch, int);
00020 static void ifstmt(int, int, Swtch, int);
00021 static Symbol localaddr(Tree);
00022 static void stmtlabel(void);
00023 static void swstmt(int, int, int);
00024 static void whilestmt(int, Swtch, int);
00025 Code code(int kind) {
00026 Code cp;
00027
00028 if (!reachable(kind))
00029 warning("unreachable code\n");
00030
00031 NEW(cp, FUNC);
00032 cp->kind = kind;
00033 cp->prev = codelist;
00034 cp->next = NULL;
00035 codelist->next = cp;
00036 codelist = cp;
00037 return cp;
00038 }
00039 int reachable(int kind) {
00040 Code cp;
00041
00042 if (kind > Start) {
00043 Code cp;
00044 for (cp = codelist; cp->kind < Label; )
00045 cp = cp->prev;
00046 if (cp->kind == Jump || cp->kind == Switch)
00047 return 0;
00048 }
00049 return 1;
00050 }
00051 void addlocal(Symbol p) {
00052 if (!p->defined) {
00053 code(Local)->u.var = p;
00054 p->defined = 1;
00055 p->scope = level;
00056 }
00057 }
00058 void definept(Coordinate *p) {
00059 Code cp = code(Defpoint);
00060
00061 cp->u.point.src = p ? *p : src;
00062 cp->u.point.point = npoints;
00063 if (ncalled > 0) {
00064 int n = findcount(cp->u.point.src.file,
00065 cp->u.point.src.x, cp->u.point.src.y);
00066 if (n > 0)
00067 refinc = (float)n/ncalled;
00068 }
00069 if (glevel > 2) locus(identifiers, &cp->u.point.src);
00070 if (events.points && reachable(Gen))
00071 {
00072 Tree e = NULL;
00073 apply(events.points, &cp->u.point.src, &e);
00074 if (e)
00075 listnodes(e, 0, 0);
00076 }
00077 }
00078 void statement(int loop, Swtch swp, int lev) {
00079 float ref = refinc;
00080
00081 if (Aflag >= 2 && lev == 15)
00082 warning("more than 15 levels of nested statements\n");
00083 switch (t) {
00084 case IF: ifstmt(genlabel(2), loop, swp, lev + 1);
00085 break;
00086 case WHILE: whilestmt(genlabel(3), swp, lev + 1); break;
00087 case DO: dostmt(genlabel(3), swp, lev + 1); expect(';');
00088 break;
00089
00090 case FOR: forstmt(genlabel(4), swp, lev + 1);
00091 break;
00092 case BREAK: walk(NULL, 0, 0);
00093 definept(NULL);
00094 if (swp && swp->lab > loop)
00095 branch(swp->lab + 1);
00096 else if (loop)
00097 branch(loop + 2);
00098 else
00099 error("illegal break statement\n");
00100 t = gettok(); expect(';');
00101 break;
00102
00103 case CONTINUE: walk(NULL, 0, 0);
00104 definept(NULL);
00105 if (loop)
00106 branch(loop + 1);
00107 else
00108 error("illegal continue statement\n");
00109 t = gettok(); expect(';');
00110 break;
00111
00112 case SWITCH: swstmt(loop, genlabel(2), lev + 1);
00113 break;
00114 case CASE: {
00115 int lab = genlabel(1);
00116 if (swp == NULL)
00117 error("illegal case label\n");
00118 definelab(lab);
00119 while (t == CASE) {
00120 static char stop[] = { IF, ID, 0 };
00121 Tree p;
00122 t = gettok();
00123 p = constexpr(0);
00124 if (generic(p->op) == CNST && isint(p->type)) {
00125 if (swp) {
00126 needconst++;
00127 p = cast(p, swp->sym->type);
00128 if (p->type->op == UNSIGNED)
00129 p->u.v.i = extend(p->u.v.u, p->type);
00130 needconst--;
00131 caselabel(swp, p->u.v.i, lab);
00132 }
00133 } else
00134 error("case label must be a constant integer expression\n");
00135
00136 test(':', stop);
00137 }
00138 statement(loop, swp, lev);
00139 } break;
00140 case DEFAULT: if (swp == NULL)
00141 error("illegal default label\n");
00142 else if (swp->deflab)
00143 error("extra default label\n");
00144 else {
00145 swp->deflab = findlabel(swp->lab);
00146 definelab(swp->deflab->u.l.label);
00147 }
00148 t = gettok();
00149 expect(':');
00150 statement(loop, swp, lev); break;
00151 case RETURN: {
00152 Type rty = freturn(cfunc->type);
00153 t = gettok();
00154 definept(NULL);
00155 if (t != ';')
00156 if (rty == voidtype) {
00157 error("extraneous return value\n");
00158 expr(0);
00159 retcode(NULL);
00160 } else
00161 retcode(expr(0));
00162 else {
00163 if (rty != voidtype)
00164 warning("missing return value\n");
00165 retcode(NULL);
00166 }
00167 branch(cfunc->u.f.label);
00168 } expect(';');
00169 break;
00170
00171 case '{': compound(loop, swp, lev + 1); break;
00172 case ';': definept(NULL); t = gettok(); break;
00173 case GOTO: walk(NULL, 0, 0);
00174 definept(NULL);
00175 t = gettok();
00176 if (t == ID) {
00177 Symbol p = lookup(token, stmtlabs);
00178 if (p == NULL) {
00179 p = install(token, &stmtlabs, 0, FUNC);
00180 p->scope = LABELS;
00181 p->u.l.label = genlabel(1);
00182 p->src = src;
00183 }
00184 use(p, src);
00185 branch(p->u.l.label);
00186 t = gettok();
00187 } else
00188 error("missing label in goto\n"); expect(';');
00189 break;
00190
00191 case ID: if (getchr() == ':') {
00192 stmtlabel();
00193 statement(loop, swp, lev);
00194 break;
00195 }
00196 default: definept(NULL);
00197 if (kind[t] != ID) {
00198 error("unrecognized statement\n");
00199 t = gettok();
00200 } else {
00201 Tree e = expr0(0);
00202 listnodes(e, 0, 0);
00203 if (nodecount == 0 || nodecount > 200)
00204 walk(NULL, 0, 0);
00205 else if (glevel) walk(NULL, 0, 0);
00206 deallocate(STMT);
00207 } expect(';');
00208 break;
00209
00210 }
00211 if (kind[t] != IF && kind[t] != ID
00212 && t != '}' && t != EOI) {
00213 static char stop[] = { IF, ID, '}', 0 };
00214 error("illegal statement termination\n");
00215 skipto(0, stop);
00216 }
00217 refinc = ref;
00218 }
00219
00220 static void ifstmt(int lab, int loop, Swtch swp, int lev) {
00221 t = gettok();
00222 expect('(');
00223 definept(NULL);
00224 walk(conditional(')'), 0, lab);
00225 refinc /= 2.0;
00226 statement(loop, swp, lev);
00227 if (t == ELSE) {
00228 branch(lab + 1);
00229 t = gettok();
00230 definelab(lab);
00231 statement(loop, swp, lev);
00232 if (findlabel(lab + 1)->ref)
00233 definelab(lab + 1);
00234 } else
00235 definelab(lab);
00236 }
00237 static Tree conditional(int tok) {
00238 Tree p = expr(tok);
00239
00240 if (Aflag > 1 && isfunc(p->type))
00241 warning("%s used in a conditional expression\n",
00242 funcname(p));
00243 return cond(p);
00244 }
00245 static void stmtlabel(void) {
00246 Symbol p = lookup(token, stmtlabs);
00247
00248 if (p == NULL) {
00249 p = install(token, &stmtlabs, 0, FUNC);
00250 p->scope = LABELS;
00251 p->u.l.label = genlabel(1);
00252 p->src = src;
00253 }
00254 if (p->defined)
00255 error("redefinition of label `%s' previously defined at %w\n", p->name, &p->src);
00256
00257 p->defined = 1;
00258 definelab(p->u.l.label);
00259 t = gettok();
00260 expect(':');
00261 }
00262 static void forstmt(int lab, Swtch swp, int lev) {
00263 int once = 0;
00264 Tree e1 = NULL, e2 = NULL, e3 = NULL;
00265 Coordinate pt2, pt3;
00266
00267 t = gettok();
00268 expect('(');
00269 definept(NULL);
00270 if (kind[t] == ID)
00271 e1 = texpr(expr0, ';', FUNC);
00272 else
00273 expect(';');
00274 walk(e1, 0, 0);
00275 pt2 = src;
00276 refinc *= 10.0;
00277 if (kind[t] == ID)
00278 e2 = texpr(conditional, ';', FUNC);
00279 else
00280 expect(';');
00281 pt3 = src;
00282 if (kind[t] == ID)
00283 e3 = texpr(expr0, ')', FUNC);
00284 else {
00285 static char stop[] = { IF, ID, '}', 0 };
00286 test(')', stop);
00287 }
00288 if (e2) {
00289 once = foldcond(e1, e2);
00290 if (!once)
00291 branch(lab + 3);
00292 }
00293 definelab(lab);
00294 statement(lab, swp, lev);
00295 definelab(lab + 1);
00296 definept(&pt3);
00297 if (e3)
00298 walk(e3, 0, 0);
00299 if (e2) {
00300 if (!once)
00301 definelab(lab + 3);
00302 definept(&pt2);
00303 walk(e2, lab, 0);
00304 } else {
00305 definept(&pt2);
00306 branch(lab);
00307 }
00308 if (findlabel(lab + 2)->ref)
00309 definelab(lab + 2);
00310 }
00311 static void swstmt(int loop, int lab, int lev) {
00312 Tree e;
00313 struct swtch sw;
00314 Code head, tail;
00315
00316 t = gettok();
00317 expect('(');
00318 definept(NULL);
00319 e = expr(')');
00320 if (!isint(e->type)) {
00321 error("illegal type `%t' in switch expression\n",
00322 e->type);
00323 e = retype(e, inttype);
00324 }
00325 e = cast(e, promote(e->type));
00326 if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op)
00327 && e->kids[0]->u.sym->type == e->type
00328 && !isvolatile(e->kids[0]->u.sym->type)) {
00329 sw.sym = e->kids[0]->u.sym;
00330 walk(NULL, 0, 0);
00331 } else {
00332 sw.sym = genident(REGISTER, e->type, level);
00333 addlocal(sw.sym);
00334 walk(asgn(sw.sym, e), 0, 0);
00335 }
00336 head = code(Switch);
00337 sw.lab = lab;
00338 sw.deflab = NULL;
00339 sw.ncases = 0;
00340 sw.size = SWSIZE;
00341 sw.values = newarray(SWSIZE, sizeof *sw.values, FUNC);
00342 sw.labels = newarray(SWSIZE, sizeof *sw.labels, FUNC);
00343 refinc /= 10.0;
00344 statement(loop, &sw, lev);
00345 if (sw.deflab == NULL) {
00346 sw.deflab = findlabel(lab);
00347 definelab(lab);
00348 if (sw.ncases == 0)
00349 warning("switch statement with no cases\n");
00350 }
00351 if (findlabel(lab + 1)->ref)
00352 definelab(lab + 1);
00353 tail = codelist;
00354 codelist = head->prev;
00355 codelist->next = head->prev = NULL;
00356 if (sw.ncases > 0)
00357 swgen(&sw);
00358 branch(lab);
00359 head->next->prev = codelist;
00360 codelist->next = head->next;
00361 codelist = tail;
00362 }
00363 static void caselabel(Swtch swp, long val, int lab) {
00364 int k;
00365
00366 if (swp->ncases >= swp->size)
00367 {
00368 long *vals = swp->values;
00369 Symbol *labs = swp->labels;
00370 swp->size *= 2;
00371 swp->values = newarray(swp->size, sizeof *swp->values, FUNC);
00372 swp->labels = newarray(swp->size, sizeof *swp->labels, FUNC);
00373 for (k = 0; k < swp->ncases; k++) {
00374 swp->values[k] = vals[k];
00375 swp->labels[k] = labs[k];
00376 }
00377 }
00378 k = swp->ncases;
00379 for ( ; k > 0 && swp->values[k-1] >= val; k--) {
00380 swp->values[k] = swp->values[k-1];
00381 swp->labels[k] = swp->labels[k-1];
00382 }
00383 if (k < swp->ncases && swp->values[k] == val)
00384 error("duplicate case label `%d'\n", val);
00385 swp->values[k] = val;
00386 swp->labels[k] = findlabel(lab);
00387 ++swp->ncases;
00388 if (Aflag >= 2 && swp->ncases == 258)
00389 warning("more than 257 cases in a switch\n");
00390 }
00391 void swgen(Swtch swp) {
00392 int *buckets, k, n;
00393 long *v = swp->values;
00394
00395 buckets = newarray(swp->ncases + 1,
00396 sizeof *buckets, FUNC);
00397 for (n = k = 0; k < swp->ncases; k++, n++) {
00398 buckets[n] = k;
00399 while (n > 0 && den(n-1, k) >= density)
00400 n--;
00401 }
00402 buckets[n] = swp->ncases;
00403 swcode(swp, buckets, 0, n - 1);
00404 }
00405 void swcode(Swtch swp, int b[], int lb, int ub) {
00406 int hilab, lolab, l, u, k = (lb + ub)/2;
00407 long *v = swp->values;
00408
00409 if (k > lb && k < ub) {
00410 lolab = genlabel(1);
00411 hilab = genlabel(1);
00412 } else if (k > lb) {
00413 lolab = genlabel(1);
00414 hilab = swp->deflab->u.l.label;
00415 } else if (k < ub) {
00416 lolab = swp->deflab->u.l.label;
00417 hilab = genlabel(1);
00418 } else
00419 lolab = hilab = swp->deflab->u.l.label;
00420 l = b[k];
00421 u = b[k+1] - 1;
00422 if (u - l + 1 <= 3)
00423 {
00424 int i;
00425 for (i = l; i <= u; i++)
00426 cmp(EQ, swp->sym, v[i], swp->labels[i]->u.l.label);
00427 if (k > lb && k < ub)
00428 cmp(GT, swp->sym, v[u], hilab);
00429 else if (k > lb)
00430 cmp(GT, swp->sym, v[u], hilab);
00431 else if (k < ub)
00432 cmp(LT, swp->sym, v[l], lolab);
00433 else
00434 assert(lolab == hilab),
00435 branch(lolab);
00436 walk(NULL, 0, 0);
00437 }
00438 else {
00439 Tree e;
00440 Type ty = signedint(swp->sym->type);
00441 Symbol table = genident(STATIC,
00442 array(voidptype, u - l + 1, 0), GLOBAL);
00443 (*IR->defsymbol)(table);
00444 if (!isunsigned(swp->sym->type) || v[l] != 0)
00445 cmp(LT, swp->sym, v[l], lolab);
00446 cmp(GT, swp->sym, v[u], hilab);
00447 e = (*optree['-'])(SUB, cast(idtree(swp->sym), ty), cnsttree(ty, v[l]));
00448 if (e->type->size < unsignedptr->size)
00449 e = cast(e, unsignedlong);
00450 walk(tree(JUMP, voidtype,
00451 rvalue((*optree['+'])(ADD, pointer(idtree(table)), e)), NULL),
00452 0, 0);
00453 code(Switch);
00454 codelist->u.swtch.table = table;
00455 codelist->u.swtch.sym = swp->sym;
00456 codelist->u.swtch.deflab = swp->deflab;
00457 codelist->u.swtch.size = u - l + 1;
00458 codelist->u.swtch.values = &v[l];
00459 codelist->u.swtch.labels = &swp->labels[l];
00460 if (v[u] - v[l] + 1 >= 10000)
00461 warning("switch generates a huge table\n");
00462 }
00463 if (k > lb) {
00464 assert(lolab != swp->deflab->u.l.label);
00465 definelab(lolab);
00466 swcode(swp, b, lb, k - 1);
00467 }
00468 if (k < ub) {
00469 assert(hilab != swp->deflab->u.l.label);
00470 definelab(hilab);
00471 swcode(swp, b, k + 1, ub);
00472 }
00473 }
00474 static void cmp(int op, Symbol p, long n, int lab) {
00475 Type ty = signedint(p->type);
00476
00477 listnodes(eqtree(op,
00478 cast(idtree(p), ty),
00479 cnsttree(ty, n)),
00480 lab, 0);
00481 }
00482 void retcode(Tree p) {
00483 Type ty;
00484
00485 if (p == NULL) {
00486 if (events.returns)
00487 apply(events.returns, cfunc, NULL);
00488 return;
00489 }
00490 p = pointer(p);
00491 ty = assign(freturn(cfunc->type), p);
00492 if (ty == NULL) {
00493 error("illegal return type; found `%t' expected `%t'\n",
00494 p->type, freturn(cfunc->type));
00495 return;
00496 }
00497 p = cast(p, ty);
00498 if (retv)
00499 {
00500 if (iscallb(p))
00501 p = tree(RIGHT, p->type,
00502 tree(CALL+B, p->type,
00503 p->kids[0]->kids[0], idtree(retv)),
00504 rvalue(idtree(retv)));
00505 else
00506 p = asgntree(ASGN, rvalue(idtree(retv)), p);
00507 walk(p, 0, 0);
00508 if (events.returns)
00509 apply(events.returns, cfunc, rvalue(idtree(retv)));
00510 return;
00511 }
00512 if (events.returns)
00513 {
00514 Symbol t1 = genident(AUTO, p->type, level);
00515 addlocal(t1);
00516 walk(asgn(t1, p), 0, 0);
00517 apply(events.returns, cfunc, idtree(t1));
00518 p = idtree(t1);
00519 }
00520 if (!isfloat(p->type))
00521 p = cast(p, promote(p->type));
00522 if (isptr(p->type))
00523 {
00524 Symbol q = localaddr(p);
00525 if (q && (q->computed || q->generated))
00526 warning("pointer to a %s is an illegal return value\n",
00527 q->scope == PARAM ? "parameter" : "local");
00528 else if (q)
00529 warning("pointer to %s `%s' is an illegal return value\n",
00530 q->scope == PARAM ? "parameter" : "local", q->name);
00531 }
00532 walk(tree(mkop(RET,p->type), p->type, p, NULL), 0, 0);
00533 }
00534 void definelab(int lab) {
00535 Code cp;
00536 Symbol p = findlabel(lab);
00537
00538 assert(lab);
00539 walk(NULL, 0, 0);
00540 code(Label)->u.forest = newnode(LABEL+V, NULL, NULL, p);
00541 for (cp = codelist->prev; cp->kind <= Label; )
00542 cp = cp->prev;
00543 while ( cp->kind == Jump
00544 && cp->u.forest->kids[0]
00545 && specific(cp->u.forest->kids[0]->op) == ADDRG+P
00546 && cp->u.forest->kids[0]->syms[0] == p) {
00547 assert(cp->u.forest->kids[0]->syms[0]->u.l.label == lab);
00548 p->ref--;
00549 assert(cp->next);
00550 assert(cp->prev);
00551 cp->prev->next = cp->next;
00552 cp->next->prev = cp->prev;
00553 cp = cp->prev;
00554 while (cp->kind <= Label)
00555 cp = cp->prev;
00556 }
00557 }
00558 Node jump(int lab) {
00559 Symbol p = findlabel(lab);
00560
00561 p->ref++;
00562 return newnode(JUMP+V, newnode(ADDRG+ttob(voidptype), NULL, NULL, p),
00563 NULL, NULL);
00564 }
00565 void branch(int lab) {
00566 Code cp;
00567 Symbol p = findlabel(lab);
00568
00569 assert(lab);
00570 walk(NULL, 0, 0);
00571 code(Label)->u.forest = jump(lab);
00572 for (cp = codelist->prev; cp->kind < Label; )
00573 cp = cp->prev;
00574 while ( cp->kind == Label
00575 && cp->u.forest->op == LABEL+V
00576 && !equal(cp->u.forest->syms[0], p)) {
00577 equatelab(cp->u.forest->syms[0], p);
00578 assert(cp->next);
00579 assert(cp->prev);
00580 cp->prev->next = cp->next;
00581 cp->next->prev = cp->prev;
00582 cp = cp->prev;
00583 while (cp->kind < Label)
00584 cp = cp->prev;
00585 }
00586 if (cp->kind == Jump || cp->kind == Switch) {
00587 p->ref--;
00588 codelist->prev->next = NULL;
00589 codelist = codelist->prev;
00590 } else {
00591 codelist->kind = Jump;
00592 if (cp->kind == Label
00593 && cp->u.forest->op == LABEL+V
00594 && equal(cp->u.forest->syms[0], p))
00595 warning("source code specifies an infinite loop");
00596 }
00597 }
00598 void equatelab(Symbol old, Symbol new) {
00599 assert(old->u.l.equatedto == NULL);
00600 old->u.l.equatedto = new;
00601 new->ref++;
00602 }
00603 static int equal(Symbol lprime, Symbol dst) {
00604 assert(dst && lprime);
00605 for ( ; dst; dst = dst->u.l.equatedto)
00606 if (lprime == dst)
00607 return 1;
00608 return 0;
00609 }
00610
00611 static void dostmt(int lab, Swtch swp, int lev) {
00612 refinc *= 10.0;
00613 t = gettok();
00614 definelab(lab);
00615 statement(lab, swp, lev);
00616 definelab(lab + 1);
00617 expect(WHILE);
00618 expect('(');
00619 definept(NULL);
00620 walk(conditional(')'), lab, 0);
00621 if (findlabel(lab + 2)->ref)
00622 definelab(lab + 2);
00623 }
00624
00625
00626 static int foldcond(Tree e1, Tree e2) {
00627 int op = generic(e2->op);
00628 Symbol v;
00629
00630 if (e1 == 0 || e2 == 0)
00631 return 0;
00632 if (generic(e1->op) == ASGN && isaddrop(e1->kids[0]->op)
00633 && generic(e1->kids[1]->op) == CNST) {
00634 v = e1->kids[0]->u.sym;
00635 e1 = e1->kids[1];
00636 } else
00637 return 0;
00638 if ((op==LE || op==LT || op==EQ || op==NE || op==GT || op==GE)
00639 && generic(e2->kids[0]->op) == INDIR
00640 && e2->kids[0]->kids[0]->u.sym == v
00641 && e2->kids[1]->op == e1->op) {
00642 e1 = simplify(op, e2->type, e1, e2->kids[1]);
00643 if (e1->op == CNST+I)
00644 return e1->u.v.i;
00645 }
00646 return 0;
00647 }
00648
00649
00650 static Symbol localaddr(Tree p) {
00651 if (p == NULL)
00652 return NULL;
00653 switch (generic(p->op)) {
00654 case INDIR: case CALL: case ARG:
00655 return NULL;
00656 case ADDRL: case ADDRF:
00657 return p->u.sym;
00658 case RIGHT: case ASGN:
00659 if (p->kids[1])
00660 return localaddr(p->kids[1]);
00661 return localaddr(p->kids[0]);
00662 case COND: {
00663 Symbol q;
00664 assert(p->kids[1] && p->kids[1]->op == RIGHT);
00665 if ((q = localaddr(p->kids[1]->kids[0])) != NULL)
00666 return q;
00667 return localaddr(p->kids[1]->kids[1]);
00668 }
00669 default: {
00670 Symbol q;
00671 if (p->kids[0] && (q = localaddr(p->kids[0])) != NULL)
00672 return q;
00673 return localaddr(p->kids[1]);
00674 }
00675 }
00676 }
00677
00678
00679 static void whilestmt(int lab, Swtch swp, int lev) {
00680 Coordinate pt;
00681 Tree e;
00682
00683 refinc *= 10.0;
00684 t = gettok();
00685 expect('(');
00686 walk(NULL, 0, 0);
00687 pt = src;
00688 e = texpr(conditional, ')', FUNC);
00689 branch(lab + 1);
00690 definelab(lab);
00691 statement(lab, swp, lev);
00692 definelab(lab + 1);
00693 definept(&pt);
00694 walk(e, lab, 0);
00695 if (findlabel(lab + 2)->ref)
00696 definelab(lab + 2);
00697 }