Annotation of lucent/sys/src/alef/k/sugen.c, revision 1.1

1.1     ! root        1: #include <u.h>
        !             2: #include <libc.h>
        !             3: #include <bio.h>
        !             4: #include <ctype.h>
        !             5: #define Extern extern
        !             6: #include "parl.h"
        !             7: #include "globl.h"
        !             8: 
        !             9: static Glab *gotos;
        !            10: static Glab *labels;
        !            11: static Jmps *contstack;
        !            12: static Jmps *brkstack;
        !            13: static Jmps *retstack;
        !            14: static Jmps *rescues;
        !            15: static Node *lstmnt;
        !            16: 
        !            17: /* Compile a function */
        !            18: void
        !            19: fungen(Node *code, Node *args)
        !            20: {
        !            21:        int l;
        !            22:        Type *t;
        !            23:        Node n1;
        !            24:        ulong rpc;
        !            25:        Inst *fcode;
        !            26: 
        !            27:        l = line;
        !            28:        fcode = ipc;
        !            29: 
        !            30:        iter(code, 1);
        !            31:        typechk(code, 0);
        !            32:        rewrite(code);
        !            33: 
        !            34:        args->left->right = code;
        !            35: 
        !            36:        if(code)
        !            37:                sucalc(code);
        !            38: 
        !            39:        if(opt('t')) {
        !            40:                print("\nTree:\n");
        !            41:                ptree(code, 0);
        !            42:        }
        !            43: 
        !            44:        /* Clear the label stack */
        !            45:        labels = 0;
        !            46:        gotos = 0;
        !            47:        rescues = 0;
        !            48: 
        !            49:        if(opt('q') == 0 && nerr == 0) {
        !            50:                t = curfunc->t->next;
        !            51:                switch(t->type) {
        !            52:                case TPOLY:
        !            53:                        curfunc = dupn(curfunc);
        !            54:                        curfunc->t = at(TFUNC, polyshape);
        !            55:                        /* No Break */
        !            56:                case TADT:
        !            57:                case TUNION:
        !            58:                case TAGGREGATE:
        !            59:                        t = at(TIND, t);
        !            60:                        regret(&n1, t);
        !            61:                        rnode = stknode(n1.t);
        !            62:                        assign(&n1, rnode);
        !            63:                        regfree(&n1);
        !            64:                        becomentry = ipc;
        !            65:                }
        !            66: 
        !            67:                lstmnt = nil;
        !            68:                if(code)
        !            69:                        stmnt(code);
        !            70: 
        !            71:                if(t->type != TVOID)
        !            72:                if(lstmnt == 0 ||
        !            73:                  (lstmnt->type != ORET && lstmnt->type != OBECOME))
        !            74:                        diag(lstmnt, "typed function has no return");
        !            75: 
        !            76:                rpc = ipc->pc+1;
        !            77:                /* Improve optimiser by using non return register */
        !            78:                switch(t->type) {
        !            79:                case TVOID:
        !            80:                        instruction(ANOP, ZeroN, ZeroN, regn(Freg));
        !            81:                        instruction(ANOP, ZeroN, ZeroN, regn(Retireg));
        !            82:                        break;
        !            83:                case TFLOAT:
        !            84:                        instruction(ANOP, ZeroN, ZeroN, regn(Retireg));
        !            85:                        break;
        !            86:                default:
        !            87:                        instruction(ANOP, ZeroN, ZeroN, regn(Freg));
        !            88:                        break;
        !            89:                }
        !            90: 
        !            91:                instruction(ARETURN, ZeroN, ZeroN, ZeroN);
        !            92: 
        !            93:                /* Patch in all the returns */
        !            94:                while(retstack) {
        !            95:                        label(retstack->i, rpc);
        !            96:                        popjmp(&retstack);
        !            97:                }
        !            98: 
        !            99:                /* Back patch the entry */
        !           100:                resolvegoto();
        !           101: 
        !           102:                /* Patch in the frame size */
        !           103:                funentry->dst.ival = maxframe + frame;
        !           104:        }
        !           105: 
        !           106:        leaveblock();
        !           107: 
        !           108:        regcheck();
        !           109: 
        !           110:        if(opt('N') || opt('R') || opt('P'))
        !           111:                regopt(fcode);
        !           112: 
        !           113:        line = l;
        !           114: }
        !           115: 
        !           116: void
        !           117: bstmnt(Node *n)
        !           118: {
        !           119:        Node *tmp;
        !           120: 
        !           121:        tmp = lstmnt;
        !           122:        stmnt(n);
        !           123:        lstmnt = tmp;
        !           124: }
        !           125: 
        !           126: /* Compile code for a statement */
        !           127: void
        !           128: stmnt(Node *n)
        !           129: {
        !           130:        Jmps *p;
        !           131:        Node *l, *r, n1, com;
        !           132:        Inst *false, *truedone, *loop, *enter;
        !           133: 
        !           134:        if(n == ZeroN)
        !           135:                return;
        !           136: 
        !           137:        l = n->left;
        !           138:        r = n->right;
        !           139:        iline = n->srcline;
        !           140:        lstmnt = n;
        !           141: 
        !           142:        switch(n->type) {
        !           143:        default:
        !           144:                genexp(n, ZeroN);
        !           145:                break;
        !           146: 
        !           147:        case OLIST:
        !           148:                stmnt(l);
        !           149:                stmnt(r);
        !           150:                break;
        !           151: 
        !           152:        case OBLOCK:
        !           153:                stmnt(l);
        !           154:                break;
        !           155: 
        !           156:        case OLBLOCK:
        !           157:                if(l == ZeroN) {
        !           158:                        warn(n, "empty guarded block");
        !           159:                        break;
        !           160:                }
        !           161:                lblock(l);
        !           162:                break;
        !           163: 
        !           164:        case OPAR:
        !           165:                parcode(l->left);
        !           166:                break;
        !           167: 
        !           168:        case OSWITCH:
        !           169:                switchcode(n);
        !           170:                break;
        !           171: 
        !           172:        case OSELECT:
        !           173:                selcode(n);
        !           174:                break;
        !           175: 
        !           176:        case OGOTO:
        !           177:                instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           178:                setgoto(n, ipc);
        !           179:                break;
        !           180: 
        !           181:        case OLABEL:
        !           182:                setlabel(n, ipc->pc+1);
        !           183:                break;
        !           184: 
        !           185:        case OCASE:
        !           186:        case ODEFAULT:
        !           187:                n->pc = ipc->pc+1;
        !           188: 
        !           189:                if(l && l->type != OCONST)
        !           190:                        stmnt(l);
        !           191: 
        !           192:                if(r)
        !           193:                        stmnt(r);
        !           194:                break;
        !           195: 
        !           196:        case OIF:
        !           197:                gencond(l, ZeroN, True);
        !           198:                false = ipc;
        !           199:                if(r && r->type == OELSE) {
        !           200:                        stmnt(r->left);
        !           201:                        truedone = instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           202:                        label(false, ipc->pc+1);
        !           203:                        stmnt(r->right);
        !           204:                        label(truedone, ipc->pc+1);
        !           205:                        break;
        !           206:                }
        !           207: 
        !           208:                if(r)
        !           209:                        stmnt(r);
        !           210: 
        !           211:                label(false, ipc->pc+1);
        !           212:                break;
        !           213: 
        !           214:        case ORET:
        !           215:                if(l) {
        !           216:                        switch(l->t->type) {
        !           217:                        default:
        !           218:                                regret(&n1, l->t);
        !           219:                                genexp(l, &n1);
        !           220:                                regfree(&n1);
        !           221:                                break;
        !           222: 
        !           223:                        case TADT:
        !           224:                        case TUNION:
        !           225:                        case TAGGREGATE:
        !           226:                                com.type = OASGN;
        !           227:                                com.t = l->t;
        !           228:                                com.left = an(OIND, rnode, ZeroN);
        !           229:                                com.left->t = rnode->t->next;
        !           230:                                com.right = l;
        !           231:                                sucalc(&com);
        !           232:                                genexp(&com, ZeroN);
        !           233:                                break;
        !           234:                        }
        !           235:                }
        !           236: 
        !           237:                instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           238:                pushjmp(&retstack);
        !           239:                break;
        !           240: 
        !           241:        case ODWHILE:
        !           242:                instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           243:                enter = ipc;
        !           244:                instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */
        !           245:                pushjmp(&contstack);
        !           246:                instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */
        !           247:                pushjmp(&brkstack);
        !           248: 
        !           249:                label(enter, ipc->pc+1);
        !           250:                loop = ipc;
        !           251:                if(r)
        !           252:                        stmnt(r);
        !           253: 
        !           254:                label(contstack->i, ipc->pc+1);
        !           255:                if(l) {
        !           256:                        gencond(l, ZeroN, True);
        !           257:                        label(ipc, brkstack->i->pc);
        !           258:                }
        !           259:                instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Loop */
        !           260:                label(ipc, loop->pc+1);
        !           261: 
        !           262:                label(brkstack->i, ipc->pc+1);
        !           263:                popjmp(&contstack);
        !           264:                popjmp(&brkstack);
        !           265:                break;
        !           266: 
        !           267:        case OWHILE:
        !           268:                instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */
        !           269:                pushjmp(&contstack);
        !           270:                instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */
        !           271:                pushjmp(&brkstack);
        !           272: 
        !           273:                label(contstack->i, ipc->pc+1);
        !           274:                loop = ipc;
        !           275:                if(l) {                                 /* Cond */
        !           276:                        gencond(l, ZeroN, True);
        !           277:                        label(ipc, brkstack->i->pc);
        !           278:                }
        !           279:                
        !           280:                if(r)
        !           281:                        stmnt(r);
        !           282: 
        !           283:                instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Loop */
        !           284:                label(ipc, loop->pc+1);
        !           285: 
        !           286:                label(brkstack->i, ipc->pc+1);
        !           287:                popjmp(&contstack);
        !           288:                popjmp(&brkstack);
        !           289:                break;
        !           290: 
        !           291:        case OFOR:
        !           292:                if(l->left)                             /* Assign */
        !           293:                        genexp(l->left, ZeroN);
        !           294: 
        !           295:                l = l->right;
        !           296: 
        !           297:                instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           298:                enter = ipc;
        !           299:                instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */
        !           300:                pushjmp(&contstack);
        !           301:                instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */
        !           302:                pushjmp(&brkstack);
        !           303:                label(enter, ipc->pc+1);
        !           304: 
        !           305:                if(l->left) {                           /* Cond */
        !           306:                        gencond(l->left, ZeroN, True);
        !           307:                        label(ipc, brkstack->i->pc);
        !           308:                }
        !           309:                if(r)
        !           310:                        stmnt(r);
        !           311:                label(contstack->i, ipc->pc+1);
        !           312:                if(l->right)                            /* Action */
        !           313:                        genexp(l->right, ZeroN);
        !           314: 
        !           315:                instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           316:                label(ipc, enter->pc);
        !           317: 
        !           318:                label(brkstack->i, ipc->pc+1);
        !           319:                popjmp(&contstack);
        !           320:                popjmp(&brkstack);
        !           321:                break;
        !           322: 
        !           323:        case ORAISE:
        !           324:                if(l) {
        !           325:                        instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           326:                        setgoto(l, ipc);
        !           327:                        break;
        !           328:                }
        !           329:                if(rescues == 0) {
        !           330:                        diag(n, "raise without rescue");
        !           331:                        break;
        !           332:                }
        !           333:                instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           334:                label(ipc, rescues->i->pc+1);
        !           335:                if(rescues->par != inpar)
        !           336:                        diag(n, "raise breaks join in par");
        !           337:                if(rescues->crit != incrit)
        !           338:                        diag(n, "raise breaks critical section");
        !           339:                break;
        !           340: 
        !           341:        case ORESCUE:
        !           342:                instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           343:                enter = ipc;
        !           344:                if(l->type == OLABEL) {
        !           345:                        setlabel(l, ipc->pc+1);
        !           346:                        l = l->left;
        !           347:                }
        !           348:                stmnt(l);
        !           349:                label(enter, ipc->pc+1);
        !           350:                pushlab(&rescues, enter);
        !           351:                break;
        !           352: 
        !           353:        case OBREAK:
        !           354:                p = brkstack;
        !           355:                while(p) {
        !           356:                        n->ival--;
        !           357:                        if(n->ival == 0)
        !           358:                                break;
        !           359:                        p = p->next;
        !           360:                }
        !           361:                if(p) {
        !           362:                        if(p->par != inpar)
        !           363:                                diag(n, "break breaks join in par");
        !           364:                        if(p->crit != incrit)
        !           365:                                diag(n, "break breaks critical section");
        !           366:                        instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           367:                        label(ipc, p->i->pc);
        !           368:                        break;
        !           369:                }
        !           370:                diag(n, "break not in loop/switch/select");
        !           371:                break;
        !           372: 
        !           373:        case OCONT:
        !           374:                p = contstack;
        !           375:                while(p) {
        !           376:                        n->ival--;
        !           377:                        if(n->ival == 0)
        !           378:                                break;
        !           379:                        p = p->next;
        !           380:                }
        !           381:                if(p) {
        !           382:                        if(p->par != inpar)
        !           383:                                diag(n, "continue breaks join in par");
        !           384:                        if(p->crit != incrit)
        !           385:                                diag(n, "continue breaks critical section");
        !           386:                        instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           387:                        label(ipc, p->i->pc);
        !           388:                        break;
        !           389:                }
        !           390:                diag(n, "continue not in loop");
        !           391:                break;
        !           392:        }
        !           393: }
        !           394: 
        !           395: int
        !           396: cascmp(Node **a, Node **b)
        !           397: {
        !           398:        int av, bv;
        !           399: 
        !           400:        av = (*a)->left->ival;
        !           401:        bv = (*b)->left->ival;
        !           402:        if(av < bv)
        !           403:                return -1;
        !           404:        return  av > bv;
        !           405: }
        !           406: 
        !           407: void
        !           408: casecount(Node *n, Node **vec)
        !           409: {
        !           410:        if(n == ZeroN)
        !           411:                return;
        !           412: 
        !           413:        switch(n->type) {
        !           414:        case ODEFAULT:
        !           415:        case OCASE:
        !           416:                if(vec)
        !           417:                        vec[veccnt] = n;
        !           418:                veccnt++;       
        !           419:                break;
        !           420: 
        !           421:        default:
        !           422:                casecount(n->left, vec);
        !           423:                casecount(n->right, vec);
        !           424:                break;
        !           425:        }
        !           426: }
        !           427: 
        !           428: void
        !           429: switchcode(Node *n)
        !           430: {
        !           431:        Node val;
        !           432:        long defpc;
        !           433:        Inst *enter;
        !           434:        int i, r, safe;
        !           435:        Node **cases, *defl, *c, *il, com;
        !           436: 
        !           437:        c = n->right;
        !           438:        if(c == ZeroN) {
        !           439:                warn(n, "empty switch statement");
        !           440:                return;
        !           441:        }
        !           442: 
        !           443:        instruction(AJMP, ZeroN, ZeroN, ZeroN);         /* Entry */
        !           444:        enter = ipc;
        !           445:        instruction(AJMP, ZeroN, ZeroN, ZeroN);         /* Break */
        !           446:        pushjmp(&brkstack);
        !           447: 
        !           448:        safe = 0;
        !           449:        if(c->type == OLBLOCK) {
        !           450:                incrit++;
        !           451:                safe = 1;
        !           452:                c = c->left;
        !           453:        }
        !           454:        /* Generate the code */
        !           455:        stmnt(c);
        !           456: 
        !           457:        instruction(AJMP, ZeroN, ZeroN, ZeroN);         /* Done break */
        !           458:        label(ipc, brkstack->i->pc);
        !           459: 
        !           460:        /* Count */
        !           461:        veccnt = 0;
        !           462:        casecount(c, 0);
        !           463: 
        !           464:        /* Save */
        !           465:        cases = malloc(sizeof(Node*)*veccnt);
        !           466:        veccnt = 0;
        !           467:        casecount(c, cases);
        !           468: 
        !           469:        defl = 0;
        !           470:        for(i = 0; i < veccnt; i++) {
        !           471:                c = cases[i];
        !           472:                switch(c->type) {
        !           473:                case OCASE:
        !           474:                        if(c->left->type != OCONST) {
        !           475:                                diag(c, "case must be constant");
        !           476:                                cases[i] = ZeroN;
        !           477:                        }
        !           478:                        break;
        !           479: 
        !           480:                case ODEFAULT:
        !           481:                        if(defl)
        !           482:                                diag(c, "switch already has default");
        !           483:                        defl = c;
        !           484:                        cases[i] = ZeroN;
        !           485:                        break;
        !           486:                }
        !           487:        }
        !           488: 
        !           489:        /* Close up the table */
        !           490:        for(i = 0; i < veccnt; i++) {
        !           491:                if(cases[i] == ZeroN) {
        !           492:                        veccnt--;
        !           493:                        memmove(cases+i, cases+i+1,  (veccnt-i)*sizeof(Node*));
        !           494:                }
        !           495:        }
        !           496: 
        !           497:        qsort(cases, veccnt, sizeof(Node*), cascmp);
        !           498: 
        !           499:        for(i = 0; i < veccnt-1; i++) {
        !           500:                r = cases[i]->left->ival;
        !           501:                if(r == cases[i+1]->left->ival)
        !           502:                        diag(cases[i+1], "duplicate case %d in switch", r);
        !           503:        }
        !           504: 
        !           505:        label(enter, ipc->pc+1);
        !           506:        SET(il);
        !           507:        if(safe) {
        !           508:                il = internnode(builtype[TIND]);
        !           509:                il = an(OADDR, il, ZeroN);
        !           510:                il->t = builtype[TIND];
        !           511: 
        !           512:                com.type = OCALL;
        !           513:                com.t = builtype[TVOID];
        !           514:                com.left = ginode;
        !           515:                com.right = il;
        !           516: 
        !           517:                sucalc(&com);
        !           518:                stmnt(&com);
        !           519:        }
        !           520: 
        !           521:        reg(&val, builtype[TINT], ZeroN);
        !           522:        genexp(n->left, &val);
        !           523: 
        !           524:        defpc = brkstack->i->pc;
        !           525:        if(defl)
        !           526:                defpc = defl->pc;
        !           527:  
        !           528:        gencmps(cases, veccnt, defpc, &val);
        !           529: 
        !           530:        regfree(&val);
        !           531:        label(brkstack->i, ipc->pc+1);
        !           532: 
        !           533:        if(safe) {
        !           534:                com.type = OCALL;
        !           535:                com.t = builtype[TVOID];
        !           536:                com.left = gonode;
        !           537:                com.right = il;
        !           538: 
        !           539:                sucalc(&com);
        !           540:                stmnt(&com);
        !           541:                incrit--;
        !           542:        }
        !           543:        popjmp(&brkstack);
        !           544: }
        !           545: 
        !           546: Node*
        !           547: gcom(Node *n)
        !           548: {
        !           549:        Node *l;
        !           550: 
        !           551:        if(n == 0)
        !           552:                return ZeroN;
        !           553: 
        !           554:        switch(n->type) {
        !           555:        case ORECV:
        !           556:                return n;
        !           557:        case OCALL:
        !           558:                if(issend(n->left))
        !           559:                        return n;
        !           560:                /* Fall through */
        !           561:        default:
        !           562:                l = gcom(n->left);
        !           563:                if(l == 0)
        !           564:                        l = gcom(n->right);
        !           565:                return l;
        !           566:        }
        !           567: }
        !           568: 
        !           569: int
        !           570: regcode(Node **cases, int cnt)
        !           571: {
        !           572:        int i, var;
        !           573:        Node *l, *c;
        !           574: 
        !           575:        var = 0;
        !           576:        for(i = 0; i < cnt; i++) {
        !           577:                c = cases[i];
        !           578:                switch(c->type) {
        !           579:                case OCASE:
        !           580:                        l = gcom(c->left);
        !           581:                        if(l == 0) {
        !           582:                                diag(c, "case expr needs send/receive");
        !           583:                                cases[i] = ZeroN;
        !           584:                                break;
        !           585:                        }
        !           586:                        if(l->t->variant)
        !           587:                                var++;
        !           588:                        switch(l->type) {
        !           589:                        default:                /* Catch the send rewrites */
        !           590:                                l->left = selsend;
        !           591:                                c->t = l->t;
        !           592:                                l->t = builtype[TVOID];
        !           593:                                break;
        !           594:                        case ORECV:
        !           595:                        case OCRCV:
        !           596:                                c->left = l;
        !           597:                                l->type = OCALL;
        !           598:                                c->t = l->t;
        !           599:                                l->t = builtype[TVOID];
        !           600:                                l->left = selrecv;
        !           601:                                break;
        !           602:                        }
        !           603:                        /* Only the channel argument */
        !           604:                        while(l->right->type == OLIST)
        !           605:                                l->right = l->right->left;
        !           606:                        break;
        !           607:                case ODEFAULT:
        !           608:                        diag(c, "alt already has default");
        !           609:                        cases[i] = ZeroN;
        !           610:                        break;
        !           611:                }
        !           612:        }
        !           613:        return var;
        !           614: }
        !           615: 
        !           616: void
        !           617: selcode(Node *n)
        !           618: {
        !           619:        Inst *enter;
        !           620:        Node val, com;
        !           621:        int i, x, safe, var;
        !           622:        Node **cases, *c, *il;
        !           623: 
        !           624:        safe = 0;
        !           625: 
        !           626:        val.srcline = n->srcline;
        !           627:        com.srcline = n->srcline;
        !           628: 
        !           629:        instruction(AJMP, ZeroN, ZeroN, ZeroN);         /* Entry */
        !           630:        enter = ipc;
        !           631:        instruction(AJMP, ZeroN, ZeroN, ZeroN);         /* Break */
        !           632:        pushjmp(&brkstack);
        !           633: 
        !           634:        c = n->left;
        !           635:        if(c == nil)
        !           636:                return;
        !           637:        if(c->type == OLBLOCK) {
        !           638:                incrit++;
        !           639:                safe = 1;
        !           640:                c = c->left;
        !           641:        }
        !           642:        stmnt(c);
        !           643: 
        !           644:        instruction(AJMP, ZeroN, ZeroN, ZeroN);         /* Done break */
        !           645:        label(ipc, brkstack->i->pc);
        !           646: 
        !           647:        veccnt = 0;
        !           648:        casecount(n->left, 0);
        !           649:        cases = malloc(sizeof(Node*)*veccnt);
        !           650:        veccnt = 0;
        !           651:        casecount(n->left, cases);
        !           652: 
        !           653:        /* Convert expression to register channels for select */
        !           654:        var = regcode(cases, veccnt);
        !           655: 
        !           656:        for(i = 0; i < veccnt; i++) {
        !           657:                if(cases[i] == ZeroN) {
        !           658:                        veccnt--;
        !           659:                        memmove(cases+i, cases+i+1,  (veccnt-i)*sizeof(Node*));
        !           660:                }
        !           661:        }
        !           662:        if(veccnt == 0)
        !           663:                return;
        !           664: 
        !           665:        label(enter, ipc->pc+1);
        !           666:        SET(il);
        !           667:        if(safe) {
        !           668:                il = internnode(builtype[TIND]);
        !           669:                il = an(OADDR, il, ZeroN);
        !           670:                il->t = builtype[TIND];
        !           671: 
        !           672:                com.type = OCALL;
        !           673:                com.t = builtype[TVOID];
        !           674:                com.left = ginode;
        !           675:                com.right = il;
        !           676: 
        !           677:                sucalc(&com);
        !           678:                stmnt(&com);
        !           679:        }
        !           680: 
        !           681:        /* Assign values */
        !           682:        for(i = 0; i < veccnt; i++) {
        !           683:                c = cases[i];
        !           684:                x = i;
        !           685:                if(var)
        !           686:                        x = typesig(c->t);
        !           687:                c->left->ival = x;
        !           688:        }
        !           689: 
        !           690:        /* Sort if type match */
        !           691:        if(var)
        !           692:                qsort(cases, veccnt, sizeof(Node*), cascmp);
        !           693: 
        !           694:        /* Detect type clashes */
        !           695:        for(i = 0; i < veccnt-1; i++) {
        !           696:                c = cases[i];
        !           697:                if(c->left->ival == cases[i+1]->left->ival)
        !           698:                        diag(c, "duplicate variant type %V", c->t);
        !           699:        }
        !           700: 
        !           701:        /* Code the selsend/selrecv expressions */
        !           702:        for(i = 0; i < veccnt; i++)
        !           703:                genexp(cases[i]->left, ZeroN);
        !           704: 
        !           705:        com.type = OCALL;
        !           706:        com.t = builtype[TVOID];
        !           707:        com.left = doselect;
        !           708:        if(var)
        !           709:                com.left = varselect;
        !           710:        com.right = ZeroN;
        !           711:        sucalc(&com);
        !           712:        stmnt(&com);
        !           713: 
        !           714:        regret(&val, builtype[TINT]);
        !           715:        gencmps(cases, veccnt, -1, &val);
        !           716:        regfree(&val);
        !           717: 
        !           718:        label(brkstack->i, ipc->pc+1);
        !           719:        if(safe) {
        !           720:                com.type = OCALL;
        !           721:                com.t = builtype[TVOID];
        !           722:                com.left = gonode;
        !           723:                com.right = il;
        !           724:                sucalc(&com);
        !           725:                stmnt(&com);
        !           726:                incrit--;
        !           727:        }
        !           728:        popjmp(&brkstack);
        !           729: }
        !           730: 
        !           731: void
        !           732: gencmps(Node **c, int cnt, long defpc, Node *val)
        !           733: {
        !           734:        Node n, con, **r;
        !           735:        int i;
        !           736:        Inst *patch;
        !           737: 
        !           738:        con.type = OCONST;
        !           739:        con.t = builtype[TINT];
        !           740: 
        !           741:        if(cnt < 4) {
        !           742:                for(i = 0; i < cnt; i++) {
        !           743:                        con.ival = (*c)->left->ival;
        !           744:                        reg(&n, builtype[TINT], ZeroN);
        !           745:                        assign(&con, &n);
        !           746:                        codcond(OEQ, &n, val);
        !           747:                        label(ipc, (*c)->pc);
        !           748:                        regfree(&n);
        !           749:                        c++;
        !           750:                }
        !           751:                if(defpc != -1) {
        !           752:                        instruction(AJMP, ZeroN, ZeroN, ZeroN);
        !           753:                        label(ipc, defpc);
        !           754:                }
        !           755:                return;
        !           756:        }
        !           757:        i = cnt/2;
        !           758:        r = c+i;
        !           759: 
        !           760:        con.ival = (*r)->left->ival;
        !           761:        reg(&n, builtype[TINT], ZeroN);
        !           762:        assign(&con, &n);
        !           763:        codcond(OLT, &n, val);
        !           764:        patch = ipc;
        !           765:        codcond(OEQ, &n, val);
        !           766:        label(ipc, (*r)->pc);
        !           767:        regfree(&n);
        !           768:        gencmps(c, i, defpc, val);
        !           769: 
        !           770:        label(patch, ipc->pc+1);
        !           771:        gencmps(r+1, cnt-i-1, defpc, val);
        !           772: }
        !           773: 
        !           774: ulong
        !           775: framefind(Node *n)
        !           776: {
        !           777:        ulong l, r;
        !           778: 
        !           779:        if(n == ZeroN)
        !           780:                return 0;
        !           781: 
        !           782:        switch(n->type) {
        !           783:        default:
        !           784:                l = framefind(n->left);
        !           785:                r = framefind(n->right);
        !           786:                if(r > l)
        !           787:                        l = r;
        !           788:                break;
        !           789:        case OCALL:
        !           790:                frsize = 0;
        !           791:                framesize(n->right);
        !           792:                l = frsize;
        !           793:        }
        !           794:        return l;
        !           795: }
        !           796: 
        !           797: void
        !           798: parcode(Node *n)
        !           799: {
        !           800:        Type *t;
        !           801:        ulong frs;
        !           802:        int i, cnt;
        !           803:        Inst *loop;
        !           804:        Node *barrier, **slist, com, retr;
        !           805:        Node *stv, *stvp, *oatv, *p;
        !           806: 
        !           807:        veccnt = 0;
        !           808:        listcount(n, 0);
        !           809:        slist = malloc(sizeof(Node*)*veccnt);
        !           810:        veccnt = 0;
        !           811:        listcount(n, slist);
        !           812: 
        !           813:        if(opt('O')) {
        !           814:                for(i = 0; i < veccnt; i++) {
        !           815:                        ptree(slist[i], 0);
        !           816:                        print("*\n");
        !           817:                }
        !           818:        }
        !           819: 
        !           820:        if(veccnt < 2) {
        !           821:                warn(n, "only one statement in par");
        !           822:                stmnt(slist[0]);
        !           823:                return;
        !           824:        }
        !           825: 
        !           826:        inpar++;
        !           827:        oatv = atv;
        !           828:        cnt = veccnt;
        !           829: 
        !           830:        /*
        !           831:         * This slime is Parrend in the runtime
        !           832:         */
        !           833:        t = at(TAGGREGATE, 0);
        !           834:        t->size = SZPAREND*builtype[TINT]->size;
        !           835:        barrier = an(OADDR, stknode(t), ZeroN);
        !           836:        barrier->t = at(TIND, t);
        !           837: 
        !           838:        /*
        !           839:         * Build activation vector
        !           840:         */
        !           841:        t = at(TIND, builtype[TIND]);
        !           842:        t->size = t->next->size * cnt;  
        !           843:        stv = stknode(t);
        !           844:        stv->ti->t = at(TARRAY, 0);
        !           845: 
        !           846:        /*
        !           847:         * craft: pid = pfork(cnt, stv)
        !           848:         */
        !           849:        com.type = OCALL;
        !           850:        com.t = builtype[TINT];
        !           851:        com.left = pforknode;
        !           852:        stvp = an(OADDR, stv, ZeroN);
        !           853:        stvp->t = builtype[TIND];
        !           854:        com.right = an(OLIST, con(veccnt-1), an(OLIST, stvp, barrier));
        !           855: 
        !           856:        sucalc(&com);
        !           857:        genexp(&com, ZeroN);
        !           858: 
        !           859:        for(i = 0; i < cnt-1; i++) {
        !           860:                regret(&retr, builtype[TINT]);
        !           861:                instruction(ACMP, con(i), ZeroN, &retr);
        !           862:                instruction(ABNE, ZeroN, ZeroN, ZeroN);
        !           863:                loop = ipc;
        !           864:                regfree(&retr);
        !           865: 
        !           866:                /*
        !           867:                 * find the largest frame in this activation
        !           868:                 */
        !           869:                frs = framefind(slist[i]);
        !           870:                /* ensure enough space for ALEF_pexit args */
        !           871:                if(frs < 2*builtype[TIND]->size) {
        !           872:                        frs = 2*builtype[TIND]->size;
        !           873:                        frs = align(frs, builtype[TIND]);
        !           874:                }
        !           875:                if(opt('O'))
        !           876:                        print("%d: frame %d\n", i, frs);
        !           877: 
        !           878:                /*
        !           879:                 * Compute my activation from stack vector: atv = stv[pid]
        !           880:                 */
        !           881:                t = builtype[TIND];
        !           882:                atv = stknode(t);
        !           883:                p = an(OADD, stvp, con(i*builtype[TIND]->size));
        !           884:                p->t = t;
        !           885:                p = an(OIND, p, ZeroN);
        !           886:                p->t = t;
        !           887:                /*
        !           888:                 * 2*sizeof(*) is enough for save SP at activation top plus hole
        !           889:                 * for the saved activation pc
        !           890:                 */
        !           891:                p = an(OSUB, p, con(frs+2*builtype[TIND]->size));
        !           892:                p->t = t;
        !           893:                /*
        !           894:                 * word used for activation link
        !           895:                 */
        !           896:                atv->atvsafe = frs+builtype[TIND]->size;
        !           897:                p = an(OASGN, atv, p);
        !           898:                p->t = t;
        !           899: 
        !           900:                sucalc(p);
        !           901:                genexp(p, ZeroN);
        !           902: 
        !           903:                stmnt(slist[i]);
        !           904: 
        !           905:                com.type = OCALL;
        !           906:                com.t = builtype[TVOID];
        !           907:                com.left = pexitnode;
        !           908:                com.right = barrier;
        !           909: 
        !           910:                sucalc(&com);
        !           911:                stmnt(&com);
        !           912: 
        !           913:                label(loop, ipc->pc+1);
        !           914:        }
        !           915:        atv = oatv;
        !           916: 
        !           917:        stmnt(slist[i]);
        !           918: 
        !           919:        /*
        !           920:         * craft terminator: ALEF_pdone(&barrier, stv);
        !           921:         */
        !           922:        com.type = OCALL;
        !           923:        com.t = builtype[TINT];
        !           924:        com.left = pdonenode;
        !           925:        stvp = an(OADDR, stv, ZeroN);
        !           926:        stvp->t = builtype[TIND];
        !           927:        com.right = an(OLIST, barrier, stvp);
        !           928: 
        !           929:        sucalc(&com);
        !           930:        stmnt(&com);
        !           931: 
        !           932:        inpar--;
        !           933: }
        !           934: 
        !           935: void
        !           936: lblock(Node *n)
        !           937: {
        !           938:        Node com, *i;
        !           939: 
        !           940:        i = internnode(builtype[TIND]);
        !           941:        i = an(OADDR, i, ZeroN);
        !           942:        i->t = builtype[TIND];
        !           943: 
        !           944:        com.type = OCALL;
        !           945:        com.t = builtype[TVOID];
        !           946:        com.left = ginode;
        !           947:        com.right = i;
        !           948:        sucalc(&com);
        !           949:        stmnt(&com);
        !           950: 
        !           951:        incrit++;
        !           952:        stmnt(n);
        !           953:        incrit--;
        !           954: 
        !           955:        com.type = OCALL;
        !           956:        com.t = builtype[TVOID];
        !           957:        com.left = gonode;
        !           958:        com.right = i;
        !           959:        sucalc(&com);
        !           960:        stmnt(&com);
        !           961: }
        !           962: 
        !           963: /* determine addressablility and number of registers */
        !           964: void
        !           965: sucalc(Node *n)
        !           966: {
        !           967:        Node *l, *r;
        !           968: 
        !           969:        if(n == 0)
        !           970:                return;
        !           971: 
        !           972:        l = n->left;
        !           973:        r = n->right;
        !           974:        n->sun = 0;
        !           975:        n->islval = 0;
        !           976: 
        !           977:        /* Addressability */
        !           978:        switch(n->type) {
        !           979:        case OBECOME:
        !           980:                sucalc(l);
        !           981:                if(l->type == OCALL)
        !           982:                        n->right = paramdep(l->right);
        !           983:                return;
        !           984: 
        !           985:        case OCONST:
        !           986:                n->islval = 20;
        !           987:                return;
        !           988: 
        !           989:        case OREGISTER:
        !           990:                n->islval = 11;
        !           991:                return;
        !           992: 
        !           993:        case OINDREG:
        !           994:                n->islval = 12;
        !           995:                return;
        !           996: 
        !           997:        case ONAME:
        !           998:                n->islval = 10;
        !           999:                return;
        !          1000: 
        !          1001:        case OADDR:
        !          1002:                sucalc(l);
        !          1003:                if(l->islval == 10)
        !          1004:                        n->islval = 2;
        !          1005:                if(l->islval == 12)
        !          1006:                        n->islval = 3;
        !          1007:                break;
        !          1008: 
        !          1009:        case OIND:
        !          1010:                sucalc(l);
        !          1011:                if(l->islval == 11)
        !          1012:                        n->islval = 12;
        !          1013:                if(l->islval == 3)
        !          1014:                        n->islval = 12;
        !          1015:                if(l->islval == 2)
        !          1016:                        n->islval = 10;
        !          1017:                break;
        !          1018: 
        !          1019:        case OADD:
        !          1020:                sucalc(l);
        !          1021:                sucalc(r);
        !          1022:                if(l->islval == 20) {
        !          1023:                        if(r->islval == 2)
        !          1024:                                n->islval = 2;
        !          1025:                        if(r->islval == 3)
        !          1026:                                n->islval = 3;
        !          1027:                }
        !          1028:                if(r->islval == 20) {
        !          1029:                        if(l->islval == 2)
        !          1030:                                n->islval = 2;
        !          1031:                        if(l->islval == 3)
        !          1032:                                n->islval = 3;
        !          1033:                }
        !          1034:                break;
        !          1035: 
        !          1036:        default:
        !          1037:                sucalc(l);
        !          1038:                sucalc(r);
        !          1039:                break;
        !          1040:        }
        !          1041: 
        !          1042:        /* Number of registers */
        !          1043:        switch(n->type) {
        !          1044:        default:
        !          1045:                if(l != ZeroN)
        !          1046:                        n->sun = l->sun;
        !          1047:                if(r != ZeroN) {
        !          1048:                        if(n->sun == r->sun)
        !          1049:                                n->sun = n->sun + 1;
        !          1050:                        else if(r->sun > n->sun)
        !          1051:                                n->sun = r->sun;
        !          1052:                }
        !          1053:                if(n->sun == 0)
        !          1054:                        n->sun = 1;
        !          1055:                break;
        !          1056: 
        !          1057:        case OCALL:
        !          1058:        case OSEND:
        !          1059:        case ORECV:
        !          1060:                n->sun = Sucall;
        !          1061:                break;
        !          1062:        }
        !          1063: }
        !          1064: 
        !          1065: void
        !          1066: setlabel(Node *n, ulong pc)
        !          1067: {
        !          1068:        Glab *i;
        !          1069: 
        !          1070:        for(i = labels; i; i = i->next) {
        !          1071:                if(i->n->sym == n->sym) {
        !          1072:                        diag(n, "label %s used twice", n->sym->name);
        !          1073:                        return;
        !          1074:                }
        !          1075:        }
        !          1076:        i = malloc(sizeof(Glab));
        !          1077:        i->n = n;
        !          1078:        i->par = inpar;
        !          1079:        i->crit = incrit;
        !          1080:        i->pc = pc;
        !          1081:        i->next = labels;
        !          1082:        labels = i;     
        !          1083: }
        !          1084: 
        !          1085: void
        !          1086: setgoto(Node *n, Inst *i)
        !          1087: {
        !          1088:        Glab *g;
        !          1089: 
        !          1090:        g = malloc(sizeof(Glab));
        !          1091:        g->n = n;
        !          1092:        g->i = i;
        !          1093:        g->par = inpar;
        !          1094:        g->crit = incrit;
        !          1095:        g->next = gotos;
        !          1096:        gotos = g;
        !          1097: }
        !          1098: 
        !          1099: Glab*
        !          1100: findlab(Node *n)
        !          1101: {
        !          1102:        Glab *i;
        !          1103: 
        !          1104:        for(i = labels; i; i = i->next)
        !          1105:                if(i->n->sym == n->sym)
        !          1106:                        return i;
        !          1107: 
        !          1108:        return 0;
        !          1109: }
        !          1110: 
        !          1111: void
        !          1112: resolvegoto(void)
        !          1113: {
        !          1114:        Glab *g, *l;
        !          1115: 
        !          1116:        for(g = gotos; g; g = g->next) {
        !          1117:                l = findlab(g->n);
        !          1118:                if(l == 0) {
        !          1119:                        diag(g->n, "no label called %s", g->n->sym->name);
        !          1120:                        continue;
        !          1121:                }
        !          1122: 
        !          1123:                if(g->par != l->par)
        !          1124:                        diag(g->n, "raise/goto breaks join from par");
        !          1125:                if(g->crit != l->crit)
        !          1126:                        diag(g->n, "raise/goto breaks critical section");
        !          1127: 
        !          1128:                label(g->i, l->pc);
        !          1129:        }
        !          1130: }

unix.superglobalmegacorp.com

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