|
|
1.1 ! root 1: /* C compiler: statement parsing */ ! 2: ! 3: #include "c.h" ! 4: ! 5: #define SWITCHSIZE 512 /* initial size of switch arrays */ ! 6: ! 7: float density = 0.5; /* minimum switch density */ ! 8: float refinc = 1.0; /* amount by which ref field is incremented */ ! 9: ! 10: static struct equate { /* deferred equates: */ ! 11: Symbol new; /* new label, i.e., label being defined */ ! 12: Symbol old; /* old label */ ! 13: struct equate *oldlink; /* pointer to equate structure for old=x */ ! 14: struct equate *link; /* next equate on list */ ! 15: } *equlist; /* list of deferred equates */ ! 16: struct swtch { /* switch statement data: */ ! 17: Symbol sym; /* local holding the switch value */ ! 18: int lab; /* label of selection code */ ! 19: Symbol deflab; /* default label */ ! 20: int ncases; /* number of cases */ ! 21: int size; /* size of value & label arrays */ ! 22: int *values; /* value, label pairs */ ! 23: Symbol *labels; ! 24: }; ! 25: ! 26: dclproto(static void branch,(int)); ! 27: dclproto(static void caselabel,(struct swtch *, int, int)); ! 28: dclproto(static void cmp,(int, Symbol, int, int)); ! 29: dclproto(static void dostmt,(int, struct swtch *, int)); ! 30: dclproto(static int foldcond,(Tree, Tree)); ! 31: dclproto(static void forstmt,(int, struct swtch *, int)); ! 32: dclproto(static void ifstmt,(int, int, struct swtch *, int)); ! 33: dclproto(static Symbol localaddr,(Tree)); ! 34: dclproto(static void stmtlabel,(char *)); ! 35: dclproto(static int swcode,(struct swtch *, int *, int, int, int)); ! 36: dclproto(static void swgen,(struct swtch *)); ! 37: dclproto(static void swstmt,(int, int, int)); ! 38: dclproto(static void visit,(struct equate *)); ! 39: dclproto(static void whilestmt,(int, struct swtch *, int)); ! 40: ! 41: /* branch - jump to lab */ ! 42: static void branch(lab) { ! 43: Code cp; ! 44: ! 45: walk(0, 0, 0); ! 46: for (cp = codelist; cp->kind < Label; ) ! 47: cp = cp->prev; ! 48: if (lab) ! 49: while (cp->kind == Label && islabel(cp->u.node) ! 50: && cp->u.node->syms[0]->u.l.label != lab) { ! 51: Symbol old = findlabel(lab); ! 52: equatelab(cp->u.node->syms[0], old); ! 53: old->ref++; ! 54: if (cp->prev->next = cp->next) ! 55: cp->next->prev = cp->prev; ! 56: else ! 57: codelist = cp->prev; ! 58: do ! 59: cp = cp->prev; ! 60: while (cp->kind < Label); ! 61: } ! 62: if (cp->kind != Jump) { ! 63: code(Jump); ! 64: codelist->u.node = lab ? jump(lab) : (Node)0; ! 65: } ! 66: /* else do nothing and thus delete dead branch */ ! 67: } ! 68: ! 69: /* caselabel - add a label to the current switch list */ ! 70: static void caselabel(swp, val, lab) struct swtch *swp; { ! 71: int k; ! 72: ! 73: if (swp->ncases >= swp->size) { ! 74: int *vals = swp->values; ! 75: Symbol *labs = swp->labels; ! 76: swp->size *= 2; ! 77: swp->values = (int *) talloc(swp->size*sizeof (int)); ! 78: swp->labels = (Symbol *) talloc(swp->size*sizeof (Symbol)); ! 79: for (k = 0; k < swp->ncases; k++) { ! 80: swp->values[k] = vals[k]; ! 81: swp->labels[k] = labs[k]; ! 82: } ! 83: } ! 84: for (k = swp->ncases; k > 0 && swp->values[k-1] >= val; k--) { ! 85: swp->values[k] = swp->values[k-1]; ! 86: swp->labels[k] = swp->labels[k-1]; ! 87: } ! 88: if (k < swp->ncases && swp->values[k] == val) ! 89: error("duplicate case label `%d'\n", val); ! 90: swp->values[k] = val; ! 91: swp->labels[k] = findlabel(lab); ! 92: ++swp->ncases; ! 93: if (Aflag >= 2 && swp->ncases == 258) ! 94: warning("more than 257 cases in a switch statement\n"); ! 95: } ! 96: ! 97: /* cmp - generate code for `if (p op n) goto lab' for integer n */ ! 98: static void cmp(op, p, n, lab) Symbol p; { ! 99: listnodes(eqnode(op, cast(idnode(p), inttype), constnode(n, inttype)), lab, 0); ! 100: } ! 101: ! 102: /* definelab - define a label */ ! 103: void definelab(lab) { ! 104: Code cp; ! 105: ! 106: walk(0, 0, 0); ! 107: code(Label); ! 108: codelist->u.node = newnode(LABEL+V, 0, 0, findlabel(lab)); ! 109: for (cp = codelist; cp->kind <= Label; ) ! 110: cp = cp->prev; ! 111: while (cp->kind == Jump && cp->u.node && cp->u.node->kids[0] ! 112: && cp->u.node->kids[0]->op == ADDRG+P ! 113: && cp->u.node->kids[0]->syms[0]->u.l.label == lab) { ! 114: cp->u.node->kids[0]->syms[0]->ref--; ! 115: assert(cp->next); ! 116: cp->prev->next = cp->next; ! 117: cp->next->prev = cp->prev; ! 118: cp = cp->prev; ! 119: } ! 120: } ! 121: ! 122: /* definept - define an execution point n: current token at current pc */ ! 123: Code definept(p) Coordinate *p; { ! 124: int n; ! 125: Code cp = code(Defpoint); ! 126: ! 127: cp->u.point.src = p ? *p : src; ! 128: cp->u.point.point = npoints; ! 129: if (ncalled > 0 && (n = findcount(src.file, src.x, src.y)) >= 0) ! 130: refinc = n/ncalled + 1; ! 131: if (glevel > 2) ! 132: locus(identifiers, &cp->u.point.src); ! 133: if (events.points) { ! 134: Tree e = 0; ! 135: apply(events.points, (Generic)&cp->u.point.src, (Generic)&e); ! 136: if (e) ! 137: listnodes(e, 0, 0); ! 138: } ! 139: return cp; ! 140: } ! 141: ! 142: /* dostmt - do statement while ( expression ) */ ! 143: static void dostmt(lab, swp, lev) struct swtch *swp; { ! 144: refinc *= 10; ! 145: t = gettok(); ! 146: definelab(lab); ! 147: statement(lab, swp, lev); ! 148: definelab(lab + 1); ! 149: expect(WHILE); ! 150: expect('('); ! 151: definept(0); ! 152: walk(conditional(')'), lab, 0); ! 153: if (findlabel(lab + 2)->ref) ! 154: definelab(lab + 2); ! 155: } ! 156: ! 157: /* equatelab - add new=old to list of deferred equates */ ! 158: void equatelab(new, old) Symbol new, old; { ! 159: struct equate *e = (struct equate *) talloc(sizeof *e); ! 160: ! 161: e->new = new; ! 162: e->old = old; ! 163: e->oldlink = 0; ! 164: e->link = equlist; ! 165: equlist = e; ! 166: for (e = e->link; e; e = e->link) ! 167: if (e->old == new) ! 168: e->oldlink = equlist; ! 169: else if (e->new == old) ! 170: equlist->oldlink = e; ! 171: } ! 172: ! 173: /* flushequ - flush deferred equates */ ! 174: void flushequ() { ! 175: for ( ; equlist; equlist = equlist->link) ! 176: visit(equlist); ! 177: } ! 178: ! 179: /* foldcond - check if initial test in for(e1;e2;e3) S is necessary */ ! 180: static int foldcond(e1, e2) Tree e1, e2; { ! 181: Opcode op = generic(e2->op); ! 182: Symbol v; ! 183: ! 184: if (e1 == 0 || e2 == 0) ! 185: return 0; ! 186: if (generic(e1->op) == ASGN && isaddrop(e1->kids[0]->op) ! 187: && generic(e1->kids[1]->op) == CNST) { ! 188: v = e1->kids[0]->u.sym; ! 189: e1 = e1->kids[1]; ! 190: } else ! 191: return 0; ! 192: if ((op==LE || op==LT || op==EQ || op==NE || op==GT || op==GE) ! 193: && generic(e2->kids[0]->op) == INDIR ! 194: && e2->kids[0]->kids[0]->u.sym == v ! 195: && e2->kids[1]->op == e1->op) { ! 196: e1 = simplify(op, e2->type, e1, e2->kids[1]); ! 197: if (e1->op == CNST+I) ! 198: return e1->u.v.i; ! 199: } ! 200: return 0; ! 201: } ! 202: ! 203: /* forstmt - for ( [expr1] ; [expr2] ; [expr3] ) statement */ ! 204: static void forstmt(lab, swp, lev) struct swtch *swp; { ! 205: Tree e1, e2, e3; ! 206: Coordinate pt2, pt3; ! 207: static char follow[] = { IF, ID, '}', 0 }; ! 208: ! 209: e1 = e2 = e3 = 0; ! 210: t = gettok(); ! 211: expect('('); ! 212: definept(0); ! 213: if (kind[t] == ID) ! 214: e1 = expr0(';'); ! 215: else ! 216: expect(';'); ! 217: walk(e1, 0, 0); ! 218: pt2 = src; ! 219: refinc *= 10; ! 220: if (kind[t] == ID) ! 221: e2 = texpr(conditional, ';'); ! 222: else ! 223: expect(';'); ! 224: pt3 = src; ! 225: if (kind[t] == ID) ! 226: e3 = texpr(expr0, ')'); ! 227: else ! 228: test(')', follow); ! 229: if (glevel == 2) { /* e1; L: if (!e2) goto L+2; S; L+1: e3; goto L; L+2: */ ! 230: definelab(lab); ! 231: definept(&pt2); ! 232: if (e2) ! 233: walk(e2, 0, lab + 2); ! 234: statement(lab, swp, lev); ! 235: definelab(lab + 1); ! 236: definept(&pt3); ! 237: if (e3) ! 238: walk(e3, 0, 0); ! 239: branch(lab); ! 240: } else { /* e1; goto L+3; L: S; L+1: e3; L+3: if (e2) goto L; L+2: */ ! 241: int once = 0; ! 242: if (e2) { ! 243: once = foldcond(e1, e2); ! 244: if (!once) ! 245: branch(lab + 3); ! 246: } ! 247: definelab(lab); ! 248: statement(lab, swp, lev); ! 249: definelab(lab + 1); ! 250: definept(&pt3); ! 251: if (e3) ! 252: walk(e3, 0, 0); ! 253: if (e2) { ! 254: if (!once) ! 255: definelab(lab + 3); ! 256: definept(&pt2); ! 257: walk(e2, lab, 0); ! 258: } else { ! 259: definept(&pt2); ! 260: branch(lab); ! 261: } ! 262: } ! 263: if (findlabel(lab + 2)->ref) ! 264: definelab(lab + 2); ! 265: } ! 266: ! 267: /* ifstmt - if ( expression ) statement [ else statement ] */ ! 268: static void ifstmt(lab, loop, swp, lev) struct swtch *swp; { ! 269: t = gettok(); ! 270: expect('('); ! 271: definept(0); ! 272: walk(conditional(')'), 0, lab); ! 273: refinc /= 2; ! 274: statement(loop, swp, lev); ! 275: if (t == ELSE) { ! 276: branch(lab + 1); ! 277: t = gettok(); ! 278: definelab(lab); ! 279: statement(loop, swp, lev); ! 280: if (findlabel(lab + 1)->ref) ! 281: definelab(lab + 1); ! 282: } else ! 283: definelab(lab); ! 284: } ! 285: ! 286: /* localaddr - returns q if p yields the address of local/parameter q; otherwise returns 0 */ ! 287: static Symbol localaddr(p) Tree p; { ! 288: if (p == 0) ! 289: return 0; ! 290: switch (generic(p->op)) { ! 291: case INDIR: case CALL: case ARG: ! 292: return 0; ! 293: case ADDRL: case ADDRF: ! 294: return p->u.sym; ! 295: case RIGHT: case ASGN: ! 296: if (p->kids[1]) ! 297: return localaddr(p->kids[1]); ! 298: return localaddr(p->kids[0]); ! 299: case COND: { ! 300: Symbol q; ! 301: if (p->kids[1] && (q = localaddr(p->kids[1]))) ! 302: return q; ! 303: return localaddr(p->kids[2]); ! 304: } ! 305: default: { ! 306: Symbol q; ! 307: if (p->kids[0] && (q = localaddr(p->kids[0]))) ! 308: return q; ! 309: return localaddr(p->kids[1]); ! 310: } ! 311: } ! 312: } ! 313: ! 314: /* retcode - return p from the current function */ ! 315: void retcode(p, lab) Tree p; { ! 316: if (p == 0) { ! 317: if (events.returns) ! 318: apply(events.returns, (Generic)cfunc, (Generic)0); ! 319: p = tree(RET+V, voidtype, 0, 0); ! 320: } else { ! 321: Type ty; ! 322: p = pointer(p); ! 323: if (ty = assign(freturn(cfunc->type), p)) ! 324: p = cast(p, ty); ! 325: else ! 326: error("illegal return type; found `%t' expected `%t'\n", ! 327: p->type, freturn(cfunc->type)); ! 328: if (retv) { ! 329: if (p->op == RIGHT && p->kids[0]->op == CALL+B ! 330: && p->kids[1]->op == INDIR+B) { ! 331: p = p->kids[0]; ! 332: p->kids[1] = idnode(retv); ! 333: } else ! 334: p = asgnnode(ASGN, rvalue(idnode(retv)), p); ! 335: walk(p, 0, 0); ! 336: if (events.returns) ! 337: apply(events.returns, (Generic)cfunc, (Generic)rvalue(idnode(retv))); ! 338: p = tree(RET+V, voidtype, 0, 0); ! 339: } else { ! 340: if (events.returns) { ! 341: Symbol t1 = genident(AUTO, p->type, level); ! 342: addlocal(t1); ! 343: walk(asgn(t1, p), 0, 0); ! 344: apply(events.returns, (Generic)cfunc, (Generic)idnode(t1)); ! 345: p = idnode(t1); ! 346: } ! 347: p = cast(p, promote(p->type)); ! 348: if (isptr(p->type)) { ! 349: Symbol q = localaddr(p); ! 350: if (q && (q->computed || q->generated)) ! 351: warning("pointer to a %s is an illegal return value\n", ! 352: q->scope == PARAM ? "parameter" : "local"); ! 353: else if (q) ! 354: warning("pointer to %s `%s' is an illegal return value\n", ! 355: q->scope == PARAM ? "parameter" : "local", q->name); ! 356: p = cast(p, unsignedtype); ! 357: } ! 358: p = tree(RET + widen(p->type), p->type, p, 0); ! 359: } ! 360: } ! 361: walk(p, 0, 0); ! 362: branch(lab); ! 363: } ! 364: ! 365: /* statement - parse statements */ ! 366: void statement(loop, swp, lev) struct swtch *swp; { ! 367: int lab; ! 368: float ref = refinc; ! 369: ! 370: if (Aflag >= 2 && lev == 15) ! 371: warning("more than 15 levels of nested statements\n"); ! 372: switch (t) { ! 373: case IF: ! 374: ifstmt(genlabel(2), loop, swp, lev + 1); ! 375: break; ! 376: case WHILE: ! 377: whilestmt(genlabel(3), swp, lev + 1); ! 378: break; ! 379: case DO: ! 380: dostmt(genlabel(3), swp, lev + 1); ! 381: expect(';'); ! 382: break; ! 383: case FOR: ! 384: forstmt(genlabel(4), swp, lev + 1); ! 385: break; ! 386: case SWITCH: ! 387: swstmt(loop, genlabel(2), lev + 1); ! 388: break; ! 389: case CASE: ! 390: if (swp == 0) ! 391: error("illegal case label\n"); ! 392: definelab(lab = genlabel(1)); ! 393: while (t == CASE) { ! 394: static char follow[] = { IF, ID, 0 }; ! 395: Tree p; ! 396: t = gettok(); ! 397: p = constexpr(0); ! 398: if (generic(p->op) == CNST && isint(p->type)) { ! 399: if (swp) { ! 400: needconst++; ! 401: p = cast(p, swp->sym->type); ! 402: needconst--; ! 403: caselabel(swp, p->u.v.i, lab); ! 404: } ! 405: } else ! 406: error("case label must be a constant integer expression\n"); ! 407: test(':', follow); ! 408: ntree = 0; ! 409: } ! 410: statement(loop, swp, lev); ! 411: break; ! 412: case DEFAULT: ! 413: if (swp) ! 414: if (swp->deflab) ! 415: error("extra default label\n"); ! 416: else { ! 417: swp->deflab = findlabel(swp->lab); ! 418: definelab(swp->deflab->u.l.label); ! 419: } ! 420: else ! 421: error("illegal default label\n"); ! 422: t = gettok(); ! 423: expect(':'); ! 424: statement(loop, swp, lev); ! 425: break; ! 426: case RETURN: ! 427: t = gettok(); ! 428: definept(0); ! 429: if (t != ';') ! 430: if (freturn(cfunc->type) == voidtype) { ! 431: error("extraneous return value\n"); ! 432: expr(0); ! 433: retcode(0, cfunc->u.f.label); ! 434: } else ! 435: retcode(expr(0), cfunc->u.f.label); ! 436: else { ! 437: if (freturn(cfunc->type) != voidtype ! 438: && (freturn(cfunc->type) != inttype || Aflag >= 1)) ! 439: warning("missing return value\n"); ! 440: retcode(0, cfunc->u.f.label); ! 441: } ! 442: expect(';'); ! 443: break; ! 444: case BREAK: ! 445: walk(0, 0, 0); ! 446: if (swp && swp->lab > loop) { ! 447: definept(0); ! 448: branch(swp->lab + 1); ! 449: t = gettok(); ! 450: expect(';'); ! 451: break; ! 452: } ! 453: case CONTINUE: ! 454: walk(0, 0, 0); ! 455: definept(0); ! 456: if (loop) ! 457: branch(loop + (t == BREAK ? 2 : 1)); ! 458: else ! 459: error("illegal %k statement\n", t); ! 460: t = gettok(); ! 461: expect(';'); ! 462: break; ! 463: case '{': ! 464: compound(loop, swp, lev + 1); ! 465: break; ! 466: case ';': ! 467: definept(0); ! 468: t = gettok(); ! 469: break; ! 470: case GOTO: ! 471: walk(0, 0, 0); ! 472: definept(0); ! 473: t = gettok(); ! 474: if (t == ID) { ! 475: Symbol p = lookup(token, labels[0]); ! 476: if (p == 0) { ! 477: p = install(token, &labels[0], 0); ! 478: p->u.l.label = genlabel(1); ! 479: p->u.l.equatedto = p; ! 480: p->src = src; ! 481: } ! 482: p->ref++; ! 483: use(p, src); ! 484: branch(p->u.l.label); ! 485: t = gettok(); ! 486: } else ! 487: error("missing label in goto\n"); ! 488: expect(';'); ! 489: break; ! 490: case ID: ! 491: if (getchr() == ':') { ! 492: stmtlabel(token); ! 493: statement(loop, swp, lev); ! 494: break; ! 495: } ! 496: default: ! 497: definept(0); ! 498: if (kind[t] != ID) { ! 499: error("unrecognized statement\n"); ! 500: t = gettok(); ! 501: } else { ! 502: Tree e = expr0(0); ! 503: listnodes(e, 0, 0); ! 504: if (glevel > 1 || nodecount == 0 || nodecount > 200) ! 505: walk(0, 0, 0); ! 506: ntree = 0; ! 507: } ! 508: expect(';'); ! 509: } ! 510: if (kind[t] != IF && kind[t] != ID && t != '}' && t != EOI) { ! 511: static char follow[] = { IF, ID, '}', 0 }; ! 512: error("illegal statement termination\n"); ! 513: skipto(0, follow); ! 514: } ! 515: refinc = ref; ! 516: } ! 517: ! 518: /* stmtlabel - label : */ ! 519: static void stmtlabel(label) char *label; { ! 520: Symbol p; ! 521: ! 522: if ((p = lookup(label, labels[0])) == 0) { ! 523: p = install(label, &labels[0], 0); ! 524: p->u.l.label = genlabel(1); ! 525: p->u.l.equatedto = p; ! 526: } ! 527: if (p->defined) ! 528: error("redefinition of label `%s' previously defined at %w\n", ! 529: label, &p->src); ! 530: p->defined = 1; ! 531: p->src = src; ! 532: definelab(p->u.l.label); ! 533: t = gettok(); ! 534: expect(':'); ! 535: } ! 536: ! 537: /* swcode - generate switch decision code for buckets b[lb..ub] */ ! 538: static int swcode(swp, b, lb, ub, n) struct swtch *swp; int b[]; { ! 539: int hilab, k, l, lolab, median, u, *v; ! 540: ! 541: v = swp->values; ! 542: median = ((float)v[b[lb]] + (float)v[b[ub+1]-1] + 1)/2; ! 543: for (l = lb, u = ub; l <= u; ) { ! 544: k = (l + u)/2; ! 545: if (v[b[k]] > median) ! 546: u = k - 1; ! 547: else if (v[b[k+1]-1] < median) ! 548: l = k + 1; ! 549: else ! 550: break; ! 551: } ! 552: if (l > u) { /* which of two buckets is closest to the median? */ ! 553: l = b[k]; ! 554: u = b[k+1] - 1; ! 555: if (median < v[l] && k > lb && v[l] - median > median - v[l-1]) ! 556: k--; ! 557: else if (median > v[u] && k < ub && median - v[u] > v[u+1] - median) ! 558: k++; ! 559: } ! 560: l = b[k]; ! 561: u = b[k+1] - 1; ! 562: lolab = hilab = swp->deflab->u.l.label; ! 563: if (k > lb) { ! 564: lolab = 0; ! 565: if (k < ub) ! 566: hilab = genlabel(1); ! 567: } else if (k < ub) ! 568: hilab = 0; ! 569: if (n == 0) ! 570: lolab = hilab = 0; ! 571: if (u - l + 1 <= 3) { ! 572: int i; ! 573: for (i = l; i <= u; i++) ! 574: cmp(EQ, swp->sym, swp->values[i], swp->labels[i]->u.l.label); ! 575: if (lolab && lolab == hilab) ! 576: branch(lolab); ! 577: else { ! 578: if (lolab) ! 579: cmp(LT, swp->sym, swp->values[l], lolab); ! 580: if (hilab) ! 581: cmp(GT, swp->sym, swp->values[u], hilab); ! 582: walk(0, 0, 0); ! 583: } ! 584: } else { ! 585: int lab = genlabel(2); ! 586: Tree e; ! 587: cmp(LT, swp->sym, swp->values[l], lolab ? lolab : lab); ! 588: cmp(GT, swp->sym, swp->values[u], hilab ? hilab : lab); ! 589: e = tree(ADDRG+P, ptr(voidptype), 0, 0); ! 590: e->u.sym = findlabel(lab + 1); ! 591: e->u.sym->sclass = STATIC; ! 592: e->u.sym->type = e->type; ! 593: walk(tree(JUMP, voidtype, rvalue((*opnode['+'])(ADD, e, ! 594: (*opnode['-'])(SUB, cast(idnode(swp->sym), inttype), ! 595: constnode(swp->values[l], inttype)))), 0), 0, 0); ! 596: definelab(lab + 1); ! 597: code(Switch); ! 598: codelist->u.swtch.sym = swp->sym; ! 599: codelist->u.swtch.deflab = swp->deflab; ! 600: codelist->u.swtch.size = u - l + 1; ! 601: codelist->u.swtch.values = &swp->values[l]; ! 602: codelist->u.swtch.labels = &swp->labels[l]; ! 603: branch(0); ! 604: definelab(lab); ! 605: if (swp->values[u] - swp->values[l] + 1 >= 10000) ! 606: warning("switch generates a huge table\n"); ! 607: } ! 608: if (k > lb) ! 609: n = swcode(swp, b, lb, k - 1, n - 1); ! 610: if (k < ub) { ! 611: if (hilab) ! 612: definelab(hilab); ! 613: n = swcode(swp, b, k + 1, ub, n - 1); ! 614: } ! 615: return n; ! 616: } ! 617: ! 618: /* swgen - partition case labels into buckets, initiate code generation */ ! 619: #define den(k,n) ((float)(k-buckets[n]+1)/(float)(v[k]-v[buckets[n]]+1)) ! 620: static void swgen(swp) struct swtch *swp; { ! 621: int *buckets, k, n, *v; ! 622: ! 623: if (swp->ncases == 0) ! 624: return; ! 625: buckets = (int *) talloc((swp->ncases + 1)*sizeof *buckets); ! 626: v = swp->values; ! 627: n = 0; ! 628: for (k = 0; k < swp->ncases; k++, n++) { ! 629: buckets[n] = k; ! 630: while (n > 0) { ! 631: float d = den(k, n-1); ! 632: if (d < density || k < swp->ncases - 1 && d < den(k+1, n)) ! 633: break; ! 634: n--; ! 635: } ! 636: } ! 637: buckets[n--] = swp->ncases; ! 638: swcode(swp, buckets, 0, n, n); ! 639: } ! 640: ! 641: /* swstmt - switch ( expression ) statement */ ! 642: static void swstmt(loop, lab, lev) { ! 643: Tree e; ! 644: struct swtch sw; ! 645: Code head, tail; ! 646: ! 647: t = gettok(); ! 648: expect('('); ! 649: definept(0); ! 650: e = expr(')'); ! 651: if (!isint(e->type)) { ! 652: error("illegal type `%t' in switch expression\n", e->type); ! 653: e = retype(e, inttype); ! 654: } ! 655: e = cast(e, promote(e->type)); ! 656: if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op) ! 657: && e->kids[0]->u.sym->type == e->type && !isvolatile(e->kids[0]->u.sym->type)) { ! 658: sw.sym = e->kids[0]->u.sym; ! 659: walk(0, 0, 0); ! 660: } else { ! 661: sw.sym = genident(REGISTER, e->type, level); ! 662: addlocal(sw.sym); ! 663: walk(asgn(sw.sym, e), 0, 0); ! 664: } ! 665: code(Switch); ! 666: head = codelist; ! 667: sw.lab = lab; ! 668: sw.deflab = 0; ! 669: sw.ncases = 0; ! 670: sw.size = SWITCHSIZE; ! 671: sw.values = (int *) talloc(SWITCHSIZE*sizeof (int)); ! 672: sw.labels = (Symbol *) talloc(SWITCHSIZE*sizeof (Symbol)); ! 673: refinc /= 10; ! 674: statement(loop, &sw, lev); ! 675: if (sw.deflab == 0) { ! 676: sw.deflab = findlabel(lab); ! 677: definelab(lab); ! 678: if (sw.ncases == 0) ! 679: warning("switch statement with no cases\n"); ! 680: } ! 681: if (findlabel(lab + 1)->ref) ! 682: definelab(lab + 1); ! 683: tail = codelist; ! 684: codelist = head->prev; ! 685: swgen(&sw); ! 686: branch(lab); ! 687: head->next->prev = codelist; ! 688: codelist->next = head->next; ! 689: codelist = tail; ! 690: } ! 691: ! 692: /* visit - equate p->new=p->old, equating predecessor first */ ! 693: static void visit(p) struct equate *p; { ! 694: if (p && p->old) { ! 695: visit(p->oldlink); ! 696: p->new->u.l.equatedto = p->old->u.l.equatedto; ! 697: p->old = 0; ! 698: } ! 699: } ! 700: ! 701: /* whilestmt - while ( expression ) statement */ ! 702: static void whilestmt(lab, swp, lev) struct swtch *swp; { ! 703: Coordinate pt; ! 704: Tree e; ! 705: ! 706: refinc *= 10; ! 707: t = gettok(); ! 708: expect('('); ! 709: walk(0, 0, 0); ! 710: pt = src; ! 711: e = texpr(conditional, ')'); ! 712: if (generic(e->op) == CNST || glevel == 2) { ! 713: /* L, L+1: if (!e) goto L+2; S; goto L; L+2: */ ! 714: definelab(lab); ! 715: definelab(lab + 1); ! 716: definept(&pt); ! 717: walk(e, 0, lab + 2); ! 718: statement(lab, swp, lev); ! 719: branch(lab); ! 720: } else { /* goto L+1; L: S; L+1: if (E) goto L; L+2: */ ! 721: branch(lab + 1); ! 722: definelab(lab); ! 723: statement(lab, swp, lev); ! 724: definelab(lab + 1); ! 725: definept(&pt); ! 726: walk(e, lab, 0); ! 727: } ! 728: if (findlabel(lab + 2)->ref) ! 729: definelab(lab + 2); ! 730: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.