Annotation of lucent/sys/src/alef/k/sugen.c, revision 1.1.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.