Annotation of researchv10no/cmd/lcc/c/stmt.c, revision 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.