Annotation of researchv10no/cmd/lcc/c/stmt.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.