Annotation of researchv10no/cmd/gre/regress.d/t6.i, revision 1.1

1.1     ! root        1: #include "alloc.h"
        !             2: #include <libc.h>
        !             3: 
        !             4: char *
        !             5: emalloc(unsigned long n)
        !             6: {
        !             7:        char *p;
        !             8:        p=malloc((unsigned)n);
        !             9:        if(p==0){
        !            10:                warn("out of memory; exiting");
        !            11:                exits("out of memory");
        !            12:        }
        !            13:        return p;
        !            14: }
        !            15: char *
        !            16: erealloc(char *p, unsigned long n)
        !            17: {
        !            18:        p=realloc(p, (unsigned)n);
        !            19:        if(p==0){
        !            20:                warn("out of memory; exiting");
        !            21:                exits("out of memory");
        !            22:        }
        !            23:        return p;
        !            24: }
        !            25: #include "alloc.h"
        !            26: #include "word.h"
        !            27: #include "store.h"
        !            28: #include "comm.h"
        !            29: #include <libc.h>
        !            30: 
        !            31: /*
        !            32:  * Push constants
        !            33:  */
        !            34: 
        !            35: ipushconst(Proc *proc)
        !            36: {
        !            37:        *proc->sp++=(SWord)*++proc->pc;
        !            38:        return 1;
        !            39: }
        !            40: 
        !            41: ipush_2(Proc *proc)
        !            42: {
        !            43:        *proc->sp++=-2;
        !            44:        return 1;
        !            45: }
        !            46: 
        !            47: ipush_1(Proc *proc)
        !            48: {
        !            49:        *proc->sp++=-1;
        !            50:        return 1;
        !            51: }
        !            52: 
        !            53: ipush0(Proc *proc)
        !            54: {
        !            55:        *proc->sp++=0;
        !            56:        return 1;
        !            57: }
        !            58: 
        !            59: ipush1(Proc *proc)
        !            60: {
        !            61:        *proc->sp++=1;
        !            62:        return 1;
        !            63: }
        !            64: 
        !            65: ipush2(Proc *proc)
        !            66: {
        !            67:        *proc->sp++=2;
        !            68:        return 1;
        !            69: }
        !            70: 
        !            71: ipush3(Proc *proc)
        !            72: {
        !            73:        *proc->sp++=3;
        !            74:        return 1;
        !            75: }
        !            76: 
        !            77: ipush4(Proc *proc)
        !            78: {
        !            79:        *proc->sp++=4;
        !            80:        return 1;
        !            81: }
        !            82: 
        !            83: ipush5(Proc *proc)
        !            84: {
        !            85:        *proc->sp++=5;
        !            86:        return 1;
        !            87: }
        !            88: 
        !            89: ipush6(Proc *proc)
        !            90: {
        !            91:        *proc->sp++=6;
        !            92:        return 1;
        !            93: }
        !            94: 
        !            95: ipush7(Proc *proc)
        !            96: {
        !            97:        *proc->sp++=7;
        !            98:        return 1;
        !            99: }
        !           100: 
        !           101: ipush8(Proc *proc)
        !           102: {
        !           103:        *proc->sp++=8;
        !           104:        return 1;
        !           105: }
        !           106: 
        !           107: ipush9(Proc *proc)
        !           108: {
        !           109:        *proc->sp++=9;
        !           110:        return 1;
        !           111: }
        !           112: 
        !           113: ipush10(Proc *proc)
        !           114: {
        !           115:        *proc->sp++=10;
        !           116:        return 1;
        !           117: }
        !           118: 
        !           119: /*
        !           120:  * Binary operators
        !           121:  */
        !           122: ige(Proc *proc)
        !           123: {
        !           124:        --proc->sp;
        !           125:        proc->sp[-1]=proc->sp[-1]>=proc->sp[0];
        !           126:        return 1;
        !           127: }
        !           128: 
        !           129: ile(Proc *proc)
        !           130: {
        !           131:        --proc->sp;
        !           132:        proc->sp[-1]=proc->sp[-1]<=proc->sp[0];
        !           133:        return 1;
        !           134: }
        !           135: 
        !           136: ine(Proc *proc)
        !           137: {
        !           138:        --proc->sp;
        !           139:        proc->sp[-1]=proc->sp[-1]!=proc->sp[0];
        !           140:        return 1;
        !           141: }
        !           142: 
        !           143: ieq(Proc *proc)
        !           144: {
        !           145:        --proc->sp;
        !           146:        proc->sp[-1]=proc->sp[-1]==proc->sp[0];
        !           147:        return 1;
        !           148: }
        !           149: 
        !           150: igt(Proc *proc)
        !           151: {
        !           152:        --proc->sp;
        !           153:        proc->sp[-1]=proc->sp[-1]>proc->sp[0];
        !           154:        return 1;
        !           155: }
        !           156: 
        !           157: ilt(Proc *proc)
        !           158: {
        !           159:        --proc->sp;
        !           160:        proc->sp[-1]=proc->sp[-1]<proc->sp[0];
        !           161:        return 1;
        !           162: }
        !           163: 
        !           164: iadd(Proc *proc)
        !           165: {
        !           166:        --proc->sp;
        !           167:        proc->sp[-1]+=proc->sp[0];
        !           168:        return 1;
        !           169: }
        !           170: 
        !           171: isub(Proc *proc)
        !           172: {
        !           173:        --proc->sp;
        !           174:        proc->sp[-1]-=proc->sp[0];
        !           175:        return 1;
        !           176: }
        !           177: 
        !           178: imul(Proc *proc)
        !           179: {
        !           180:        long l0, l1, l;
        !           181:        --proc->sp;
        !           182:        l0=proc->sp[-1];
        !           183:        l1=proc->sp[0];
        !           184:        l=l0*l1;
        !           185:        if(l1 && l/l1 != l0)
        !           186:                rerror("product overflow");
        !           187:        proc->sp[-1]=l;
        !           188:        return 1;
        !           189: }
        !           190: 
        !           191: idiv(Proc *proc)
        !           192: {
        !           193:        --proc->sp;
        !           194:        if(proc->sp[0]==0)
        !           195:                rerror("zero divide");
        !           196:        proc->sp[-1]/=proc->sp[0];
        !           197:        return 1;
        !           198: }
        !           199: 
        !           200: imod(Proc *proc)
        !           201: {
        !           202:        --proc->sp;
        !           203:        if(proc->sp[0]==0)
        !           204:                rerror("zero modulo");
        !           205:        proc->sp[-1]%=proc->sp[0];
        !           206:        return 1;
        !           207: }
        !           208: 
        !           209: iand(Proc *proc)
        !           210: {
        !           211:        --proc->sp;
        !           212:        proc->sp[-1]&=proc->sp[0];
        !           213:        return 1;
        !           214: }
        !           215: 
        !           216: ior(Proc *proc)
        !           217: {
        !           218:        --proc->sp;
        !           219:        proc->sp[-1]|=proc->sp[0];
        !           220:        return 1;
        !           221: }
        !           222: 
        !           223: ixor(Proc *proc)
        !           224: {
        !           225:        --proc->sp;
        !           226:        proc->sp[-1]^=proc->sp[0];
        !           227:        return 1;
        !           228: }
        !           229: 
        !           230: ilsh(Proc *proc)
        !           231: {
        !           232:        --proc->sp;
        !           233:        proc->sp[-1]<<=proc->sp[0];
        !           234:        return 1;
        !           235: }
        !           236: 
        !           237: irsh(Proc *proc)
        !           238: {
        !           239:        --proc->sp;
        !           240:        proc->sp[-1]>>=proc->sp[0];
        !           241:        return 1;
        !           242: }
        !           243: 
        !           244: imax(Proc *proc)
        !           245: {
        !           246:        SWord l;
        !           247:        l=*--proc->sp;
        !           248:        if(l>proc->sp[-1])
        !           249:                proc->sp[-1]=l;
        !           250:        return 1;
        !           251: }
        !           252: 
        !           253: /*
        !           254:  * Unary operators
        !           255:  */
        !           256: 
        !           257: ineg(Proc *proc)
        !           258: {
        !           259:        proc->sp[-1]=-proc->sp[-1];
        !           260:        return 1;
        !           261: }
        !           262: 
        !           263: inot(Proc *proc)
        !           264: {
        !           265:        proc->sp[-1]=~proc->sp[-1];
        !           266:        return 1;
        !           267: }
        !           268: 
        !           269: ilnot(Proc *proc)
        !           270: {
        !           271:        proc->sp[-1]=!proc->sp[-1];
        !           272:        return 1;
        !           273: }
        !           274: 
        !           275: iref(Proc *proc)
        !           276: {
        !           277:        Store *s=(Store *)*--proc->sp;
        !           278:        *proc->sp++=s->ref-1;
        !           279:        decref(&s);
        !           280:        return 1;
        !           281: }
        !           282: 
        !           283: ilen(Proc *proc)
        !           284: {
        !           285:        Store *s=(Store *)*--proc->sp;
        !           286:        *proc->sp++=s->len;
        !           287:        decref(&s);
        !           288:        return 1;
        !           289: }
        !           290: 
        !           291: /*
        !           292:  * String comparison: put value of strcmp() on stack
        !           293:  */
        !           294: 
        !           295: istrcmp(Proc *proc)
        !           296: {
        !           297:        int cmp;
        !           298:        Store *s1, *s2;
        !           299:        s1=(Store *)proc->sp[-2];
        !           300:        s2=(Store *)proc->sp[-1];
        !           301:        cmp=strcmp((char *)s1->data, (char *)s2->data);
        !           302:        decref(&s1);
        !           303:        decref(&s2);
        !           304:        proc->sp--;
        !           305:        proc->sp[-1]=cmp;
        !           306:        return 1;
        !           307: }
        !           308: 
        !           309: /*
        !           310:  * Print
        !           311:  */
        !           312: 
        !           313: iprintint(Proc *proc)
        !           314: {
        !           315:        pprint(proc, "%ld", *--proc->sp);
        !           316:        return 1;
        !           317: }
        !           318: 
        !           319: iprintnewline(Proc *proc)
        !           320: {
        !           321:        pprint(proc, "\n");
        !           322:        return 1;
        !           323: }
        !           324: 
        !           325: iprintblank(Proc *proc)
        !           326: {
        !           327:        pprint(proc, " ");
        !           328:        return 1;
        !           329: }
        !           330: 
        !           331: iprintunit(Proc *proc)
        !           332: {
        !           333:        pprint(proc, "(unit)");
        !           334:        return 1;
        !           335: }
        !           336: 
        !           337: iprintchar(Proc *proc)
        !           338: {
        !           339:        pprint(proc, "%c", *--proc->sp);
        !           340:        return 1;
        !           341: }
        !           342: 
        !           343: pprint(proc, fmt, a, b, c, d, e)
        !           344:        Proc *proc;
        !           345:        char *fmt;
        !           346: {
        !           347:        char buf[1024];
        !           348:        long n;
        !           349:        n=sprint(buf, fmt, a, b, c, d, e);
        !           350:        if(proc->prbuf==0){
        !           351:                proc->prbuf=emalloc(64+n);
        !           352:                proc->maxprbuf=64+n;
        !           353:                proc->nprbuf=0;
        !           354:        }
        !           355:        if(n+proc->nprbuf+1>proc->maxprbuf){
        !           356:                proc->prbuf=erealloc(proc->prbuf, proc->maxprbuf+64+n);
        !           357:                proc->maxprbuf+=64+n;
        !           358:        }
        !           359:        strcpy(proc->prbuf+proc->nprbuf, buf);
        !           360:        proc->nprbuf+=n;
        !           361: }
        !           362: /*
        !           363:  * Stack management
        !           364:  */
        !           365: 
        !           366: ipop(Proc *proc)
        !           367: {
        !           368:        --proc->sp;
        !           369:        return 1;
        !           370: }
        !           371: 
        !           372: ipopptr(Proc *proc)
        !           373: {
        !           374:        decref((Store **)(proc->sp-1));
        !           375:        --proc->sp;
        !           376:        return 1;
        !           377: }
        !           378: 
        !           379: idup(Proc *proc)
        !           380: {
        !           381:        proc->sp++;
        !           382:        proc->sp[-1]=proc->sp[-2];
        !           383:        return 1;
        !           384: }
        !           385: 
        !           386: idupptr(Proc *proc)
        !           387: {
        !           388:        proc->sp++;
        !           389:        proc->sp[-1]=proc->sp[-2];
        !           390:        ((Store *)(proc->sp[-1]))->ref++;
        !           391:        return 1;
        !           392: }
        !           393: #include "node.h"
        !           394: #include "symbol.h"
        !           395: #include "alloc.h"
        !           396: #include "word.h"
        !           397: #include "store.h"
        !           398: #include "comm.h"
        !           399: #include "inst.h"
        !           400: #include <libc.h>
        !           401: 
        !           402: #define        FNS
        !           403: #include "lib.h"
        !           404: #undef FNS
        !           405: 
        !           406: #define        C       0x40000000
        !           407: #define        I       0x20000000
        !           408: #define        F       0x10000000
        !           409: #define        M(x)    ((x)&~(C|I|F))
        !           410: 
        !           411: long call0[]={ /* plain function, 0 arguments */
        !           412:        I+Ipushfp,      C+0,    F,      I+Iret, C+0*WS, I+Idone,        0
        !           413: };
        !           414: long call1[]={ /* plain function, 1 argument */
        !           415:        I+Ipushfp,      C+0,    F,      I+Iret, C+1*WS, I+Idone,        0
        !           416: };
        !           417: long call2[]={ /* plain function, 2 arguments */
        !           418:        I+Ipushfp,      C+0,    F,      I+Iret, C+2*WS, I+Idone,        0
        !           419: };
        !           420: long call3[]={ /* plain function, 3 arguments */
        !           421:        I+Ipushfp,      C+0,    F,      I+Iret, C+3*WS, I+Idone,        0
        !           422: };
        !           423: long call4[]={ /* plain function, 4 arguments */
        !           424:        I+Ipushfp,      C+0,    F,      I+Iret, C+4*WS, I+Idone,        0
        !           425: };
        !           426: long call5[]={ /* plain function, 5 arguments */
        !           427:        I+Ipushfp,      C+0,    F,      I+Iret, C+5*WS, I+Idone,        0
        !           428: };
        !           429: long call2_0[]={/* two-step function, 0 arguments */
        !           430:        I+Ipushfp,      C+0,    F+0,    F+1,    I+Iret, C+0*WS, I+Idone,        0
        !           431: };
        !           432: 
        !           433: struct{
        !           434:        char    *name;
        !           435:        int     (*fn[3])();
        !           436:        int     nargs;
        !           437:        long    *template;
        !           438: }bltin[]={
        !           439: #include "lib.h"
        !           440:        0,      {0,     0,      0},     0,      0,
        !           441: };
        !           442: 
        !           443: bltinlookup(char *s)
        !           444: {
        !           445:        int i;
        !           446:        for(i=0; bltin[i].name; i++)
        !           447:                if(strcmp(s, bltin[i].name)==0)
        !           448:                        return i;
        !           449:        error("%s not a builtin", s);
        !           450:        return -1;
        !           451: }
        !           452: 
        !           453: long
        !           454: bltinval(char *name, Node *t)
        !           455: {
        !           456:        int i, nargs, len;
        !           457:        long *template, *p;
        !           458:        Store *s;
        !           459:        SWord *d;
        !           460:        if(t->o.t!=TProg)
        !           461:                error("builtin %s not a function", name);
        !           462:        i=bltinlookup(name);
        !           463:        nargs=bltin[i].nargs;
        !           464:        if(nargs!=length(t->l)) /* necessary but not sufficient */
        !           465:                error("wrong #args to builtin %s: %d (should be %d)", name, length(t->l), nargs);
        !           466:        template=bltin[i].template;
        !           467:        p=template;
        !           468:        for(len=0; *p; p++)
        !           469:                len++;
        !           470:        s=(Store *)emalloc(SHSZ+len*LWS);
        !           471:        s->ref=1;
        !           472:        s->type=Sprog;
        !           473:        s->sbits=0;
        !           474:        s->len=len;
        !           475:        d=s->data;
        !           476:        for(p=template; *p; p++)
        !           477:                if(*p&C)
        !           478:                        *d++=(SWord)M(*p);
        !           479:                else if(*p&I)
        !           480:                        *d++=(SWord)insttab[M(*p)].fp;
        !           481:                else if(*p&F)
        !           482:                        *d++=(SWord)bltin[i].fn[M(*p)];
        !           483:        return (long)s;
        !           484: }
        !           485: 
        !           486: Store *
        !           487: mk(type, len)
        !           488: {
        !           489:        Store *s;
        !           490:        if(type==Sstruct)
        !           491:                len++;
        !           492:        s=(Store *)emalloc(SHSZ+len*LWS);
        !           493:        s->ref=1;
        !           494:        s->type=type;
        !           495:        if(type==Sstruct){
        !           496:                s->sbits=1;
        !           497:                s->data[0]=0;
        !           498:        }else
        !           499:                s->sbits=0;
        !           500:        s->len=len;
        !           501:        return s;
        !           502: }
        !           503: #include "node.h"
        !           504: #include "symbol.h"
        !           505: #include "alloc.h"
        !           506: #include "ydefs.h"
        !           507: #include "word.h"
        !           508: #include "store.h"
        !           509: #include "comm.h"
        !           510: #include "inst.h"
        !           511: #include "errjmp.h"
        !           512: #include <libc.h>
        !           513: 
        !           514: long           resultloc;
        !           515: long           returnloc;
        !           516: Node           *formals;
        !           517: long           autooffset;
        !           518: extern int     bflag;
        !           519: extern int     cflag;
        !           520: extern int     nscope;
        !           521: extern Node    arychartype;
        !           522: 
        !           523: compile(n)     /* called from parser only */
        !           524:        Node *n;
        !           525: {
        !           526:        extern long autooffset;
        !           527:        Errjmp x;
        !           528:        n=constants(n);
        !           529:        if(cflag){
        !           530:                fileline();
        !           531:                fprint(2, "constants:\n");
        !           532:                dump(n, 0);
        !           533:        }
        !           534:        errsave(x);
        !           535:        if(errmark()){
        !           536:                autooffset=0;
        !           537:                freenode(n);
        !           538:                errrest(x);
        !           539:                errjmp();
        !           540:        }
        !           541:        istart();
        !           542:        gen(n, 0);
        !           543:        freenode(n);
        !           544:        errrest(x);
        !           545: }
        !           546: 
        !           547: gen(Node *n, int retain)
        !           548: {
        !           549:        int i;
        !           550:        if(n==0)
        !           551:                return;
        !           552:        switch(n->t){
        !           553:        case NArrayref:
        !           554:                arygen(n->l, n->r, 0, 0L);
        !           555:                if(!retain)
        !           556:                        popgen(n->l->o.s->val->type->r);
        !           557:                return;
        !           558:        case NBecome:
        !           559:                if(n->l->t==NCall && !bflag){
        !           560:                        callgen(n->l, Ibecome);
        !           561:                        return;
        !           562:                }
        !           563:                gen(n->l, 1);
        !           564:                n=n->r;
        !           565:                if(n->o.t==TID)
        !           566:                        n=typeoftid(n);
        !           567:                switch(n->o.t){
        !           568:                case TInt:
        !           569:                case TChar:
        !           570:                        emit(Istoreauto);
        !           571:                        emitconst(-LWS*(3+length(formals)));
        !           572:                        break;
        !           573:                case TArray:
        !           574:                case TChan:
        !           575:                case TProg:
        !           576:                case TStruct:
        !           577:                        emit(Istoreptrauto);
        !           578:                        emitconst(-LWS*(3+length(formals)));
        !           579:                        break;
        !           580:                case TUnit:
        !           581:                        break;
        !           582:                default:
        !           583:                        panic("can't compile %t become", n->o.t);
        !           584:                }
        !           585:                scopedecrefgen();
        !           586:                trlrgen();
        !           587:                return;
        !           588:        case NBegin:
        !           589:                callgen(n->l, Ibegin);
        !           590:                return;
        !           591:        case NCall:
        !           592:                callgen(n, Icall);
        !           593:                if(!retain)
        !           594:                        popgen(etypeoft(n->l)->r);
        !           595:                return;
        !           596:        case NDecl:
        !           597:        case NDeclsc:
        !           598:                declare(n, 0, 0, 1);
        !           599:                return;
        !           600:        case NExpr:
        !           601:                switch(n->o.i){
        !           602:                case GE:
        !           603:                        i=Ige;
        !           604:                Binop:
        !           605:                        gen(n->l, 1);
        !           606:                        gen(n->r, 1);
        !           607:                        if(eqtype(etypeof(n->l), &arychartype)){
        !           608:                                emit(Istrcmp);
        !           609:                                constgen(0L);
        !           610:                        }
        !           611:                        emit(i);
        !           612:                Popit:
        !           613:                        if(!retain)
        !           614:                                emit(Ipop);
        !           615:                        return;
        !           616:                case LE:
        !           617:                        i=Ile;
        !           618:                        goto Binop;
        !           619:                case NE:
        !           620:                        i=Ine;
        !           621:                        goto Binop;
        !           622:                case EQ:
        !           623:                        i=Ieq;
        !           624:                        goto Binop;
        !           625:                case '>':
        !           626:                        i=Igt;
        !           627:                        goto Binop;
        !           628:                case '<':
        !           629:                        i=Ilt;
        !           630:                        goto Binop;
        !           631:                case '+':
        !           632:                        i=Iadd;
        !           633:                        goto Binop;
        !           634:                case '-':
        !           635:                        i=Isub;
        !           636:                        goto Binop;
        !           637:                case '*':
        !           638:                        i=Imul;
        !           639:                        goto Binop;
        !           640:                case '/':
        !           641:                        i=Idiv;
        !           642:                        goto Binop;
        !           643:                case '%':
        !           644:                        i=Imod;
        !           645:                        goto Binop;
        !           646:                case '&':
        !           647:                        i=Iand;
        !           648:                        goto Binop;
        !           649:                case '|':
        !           650:                        i=Ior;
        !           651:                        goto Binop;
        !           652:                case '^':
        !           653:                        i=Ixor;
        !           654:                        goto Binop;
        !           655:                case LSH:
        !           656:                        i=Ilsh;
        !           657:                        goto Binop;
        !           658:                case RSH:
        !           659:                        i=Irsh;
        !           660:                        goto Binop;
        !           661:                case ANDAND:
        !           662:                        condgen(n->l, n->r, Ijmptrue, Ijmpfalse, 0L, 1L, retain);
        !           663:                        return;
        !           664:                case OROR:
        !           665:                        condgen(n->l, n->r, Ijmpfalse, Ijmptrue, 1L, 0L, retain);
        !           666:                        return;
        !           667:                case PRINT:
        !           668:                        gen(n->l, 1);
        !           669:                        printgen(n->l);
        !           670:                        emit(Isprint);
        !           671:                        if(!retain)
        !           672:                                emit(Iprint);
        !           673:                        return;
        !           674:                case SND:
        !           675:                        gen(n->l, 1);
        !           676:                        constgen((long)Cissnd);
        !           677:                        emit(Icommset1);
        !           678:                        emit(Icommcln1);
        !           679:                        gen(n->r, 1);
        !           680:                        if(isptrtype(etypeoft(n->l)->r))
        !           681:                                emit(Isndptr);
        !           682:                        else
        !           683:                                emit(Isnd);
        !           684:                        if(!retain)
        !           685:                                popgen(etypeof(n));
        !           686:                        return;
        !           687:                case RCV:
        !           688:                        gen(n->l, 1);
        !           689:                        constgen(0L);   /* not Cissnd */
        !           690:                        emit(Icommset1);
        !           691:                        emit(Icommcln1);
        !           692:                        return;
        !           693:                case '=':
        !           694:                        gen(n->r, 1);
        !           695:                        if(retain)
        !           696:                                dupgen(etypeof(n->r), 1);
        !           697:                        lgen(n->l);
        !           698:                        return;
        !           699:                case LEN:
        !           700:                        gen(n->l, 1);
        !           701:                        emit(Ilen);
        !           702:                        goto Popit;
        !           703:                case REF:
        !           704:                        if(isptrtype(etypeof(n->l))){
        !           705:                                gen(n->l, 1);
        !           706:                                emit(Iref);
        !           707:                        }else
        !           708:                                constgen(1L);
        !           709:                        goto Popit;
        !           710:                case DEF:
        !           711:                        if(retain && n->l->t==NID && isinttype(etypeof(n->l))){
        !           712:                                constgen(1L);
        !           713:                                return;
        !           714:                        }
        !           715:                        /*
        !           716:                         * don't really need to call lgen1, which will uniquify our
        !           717:                         * array for us, but it does no harm, and it's easy.
        !           718:                         */
        !           719:                        lgen1(n->l, Idefauto, Idef, Idefary);
        !           720:                        goto Popit;
        !           721:                case UMINUS:
        !           722:                        gen(n->l, 1);
        !           723:                        emit(Ineg);
        !           724:                        goto Popit;
        !           725:                case '~':
        !           726:                        gen(n->l, 1);
        !           727:                        emit(Inot);
        !           728:                        goto Popit;
        !           729:                case '!':
        !           730:                        gen(n->l, 1);
        !           731:                        emit(Ilnot);
        !           732:                        goto Popit;
        !           733:                case INC:
        !           734:                        lgen1(n->l, Iincauto, Iinc, Iincary);
        !           735:                        goto Popit;
        !           736:                case DEC:
        !           737:                        lgen1(n->l, Idecauto, Idec, Idecary);
        !           738:                        goto Popit;
        !           739:                default:
        !           740:                        panic("can't compile %e expression", n->o.i);
        !           741:                }
        !           742: 
        !           743:        case NExprlist:
        !           744:                /*
        !           745:                 * This is an arg or element list; first is pushed last
        !           746:                 */
        !           747:                gen(n->r, 1);
        !           748:                gen(n->l, 1);
        !           749:                return;
        !           750:        case NID:
        !           751:                if(!retain)
        !           752:                        return;
        !           753:                switch(typeof(n)->o.t){
        !           754:                case TInt:
        !           755:                case TChar:
        !           756:                        if(n->o.s->val->isauto){
        !           757:                                emit(Ipushauto);
        !           758:                                emitconst(n->o.s->val->store.off);
        !           759:                        }else{
        !           760:                                emit(Ipush);
        !           761:                                emitconst((long)&n->o.s->val->store.l);
        !           762:                        }
        !           763:                        return;
        !           764:                case TProg:
        !           765:                case TArray:
        !           766:                case TChan:
        !           767:                case TStruct:
        !           768:                        if(n->o.s->val->isauto){
        !           769:                                emit(Ipushptrauto);
        !           770:                                emitconst(n->o.s->val->store.off);
        !           771:                        }else{
        !           772:                                emit(Ipushptr);
        !           773:                                emitconst((long)&n->o.s->val->store.l);
        !           774:                        }
        !           775:                        return;
        !           776:                case TUnit:
        !           777:                        if(retain)
        !           778:                                constgen(0L);
        !           779:                        return;
        !           780:                case TType:
        !           781:                        lerror(n, "attempt to evaluate type variable %m", n);
        !           782:                default:
        !           783:                        panic("can't compile type %t", n->o.s->val->type->o.t);
        !           784:                }
        !           785:        case NIf:
        !           786:                ifgen(n);
        !           787:                return;
        !           788:        case NList:
        !           789:                gen(n->l, 0);
        !           790:                gen(n->r, 0);
        !           791:                return;
        !           792:        case NLoop:
        !           793:                loopgen(n);
        !           794:                return;
        !           795:        case NMk:
        !           796:                mkgen(n->l, n->r);
        !           797:                return;
        !           798:        case NNum:
        !           799:                if(retain)
        !           800:                        constgen(n->o.l);
        !           801:                return;
        !           802:        case NProg:
        !           803:                if(retain)
        !           804:                        proggen(n->l, n->r);
        !           805:                return;
        !           806:        case NResult:
        !           807:                gen(n->l, 1);
        !           808:                emit(Ijmp);
        !           809:                emitconst((long)(resultloc-here()-1)*WS);
        !           810:                return;
        !           811:        case NScope:
        !           812:                pushscope();
        !           813:                if(nscope==1){
        !           814:                        int nauto;
        !           815:                        autooffset=0;
        !           816:                        emit(Ipushfp);
        !           817:                        nauto=here();
        !           818:                        emitconst(0L);
        !           819:                        gen(n->l, 0);
        !           820:                        patch((int)nauto, autooffset);
        !           821:                }else
        !           822:                        gen(n->l, 0);
        !           823:                scopedecrefgen();
        !           824:                popscope();
        !           825:                return;
        !           826:        case NSelect:
        !           827:                selgen(n->l);
        !           828:                return;
        !           829:        case NSmash:{
        !           830:                Value *vl, *vr;
        !           831:                vl=n->l->o.s->val;
        !           832:                vr=n->r->o.s->val;
        !           833:                if(vr->type->o.t==TType){
        !           834:                        freenode(vl->type);
        !           835:                        vl->type=dupnode(vr->type);
        !           836:                        return;
        !           837:                }
        !           838:                gen(n->r, 1);
        !           839:                /*
        !           840:                 * Free old values; tricky: push as int, pop as ptr
        !           841:                 */
        !           842:                if(isptrtype(vl->type)){
        !           843:                        if(vl->isauto){
        !           844:                                emit(Ipushauto);
        !           845:                                emitconst(vl->store.off);
        !           846:                        }else{
        !           847:                                emit(Ipush);
        !           848:                                emitconst((long)&vl->store.l);
        !           849:                        }
        !           850:                        emit(Ipopptr);
        !           851:                }
        !           852:                if(vl->isauto){
        !           853:                        emit(Istoreauto);
        !           854:                        emitconst(vl->store.l);
        !           855:                        return;
        !           856:                }
        !           857:                emit(Istore);
        !           858:                emitconst((long)&vl->store.l);
        !           859:                return;
        !           860:        }
        !           861:        case NString:
        !           862:                if(retain){
        !           863:                        Store *s;
        !           864:                        s=(Store *)emalloc(SHSZ+strlen(n->o.c)+1);
        !           865:                        strcpy((char *)(s->data), n->o.c);
        !           866:                        s->ref=1;
        !           867:                        s->len=strlen(n->o.c);
        !           868:                        s->type=Sarychar;
        !           869:                        emit(Ipushdata);
        !           870:                        emitconst((long)s);
        !           871:                }
        !           872:                return;
        !           873:        case NStructref:
        !           874:                arygen(n->l, n->r, 1, n->o.l);
        !           875:                return;
        !           876:        case NSwitch:
        !           877:                switchgen(n->l, n->r);
        !           878:                return;
        !           879:        case NUnit:
        !           880:                if(retain)
        !           881:                        constgen(0L);
        !           882:                return;
        !           883:        case NVal:
        !           884:                valgen(n->l);
        !           885:                if(!retain)
        !           886:                        popgen(n->o.n);
        !           887:                return;
        !           888:        }
        !           889:        panic("can't compile node %n", n->t);
        !           890:        return;
        !           891: }
        !           892: 
        !           893: arygen(Node *a, Node *i, int isstr, long off)
        !           894: {
        !           895:        int ptr, ischar;
        !           896:        if(isstr){
        !           897:                ptr=isptrtype(i);
        !           898:                constgen(off);
        !           899:                ischar=0;
        !           900:        }else{
        !           901:                Node *t=etypeoft(a)->r;
        !           902:                ptr=isptrtype(t);
        !           903:                gen(i, 1);
        !           904:                ischar=t->o.t==TChar;
        !           905:        }
        !           906:        if(a->t!=NID){
        !           907:                gen(a, 1);
        !           908:                emit(ptr? Ipusharyptrexpr :
        !           909:                        (ischar? Ipusharycharexpr :Ipusharyexpr));
        !           910:        }else if(a->o.s->val->isauto){
        !           911:                emit(ptr? Ipusharyptrauto :
        !           912:                        (ischar? Ipusharycharauto :Ipusharyauto));
        !           913:                emitconst(a->o.s->val->store.off);
        !           914:        }else{
        !           915:                emit(ptr? Ipusharyptr :
        !           916:                        (ischar? Ipusharychar :Ipushary));
        !           917:                emitconst((long)&a->o.s->val->store.l);
        !           918:        }
        !           919: }
        !           920: 
        !           921: lgen(Node *n)
        !           922: {
        !           923:        switch(n->t){
        !           924:        case NID:
        !           925:                switch(typeof(n)->o.t){
        !           926:                case TChar:
        !           927:                        if(n->o.s->val->isauto){
        !           928:                                emit(Istorecharauto);
        !           929:                                emitconst(n->o.s->val->store.off);
        !           930:                                return;
        !           931:                        }
        !           932:                        emit(Istorechar);
        !           933:                        emitconst((long)&n->o.s->val->store.l);
        !           934:                        return;
        !           935:                case TInt:
        !           936:                case TUnit:
        !           937:                        if(n->o.s->val->isauto){
        !           938:                                emit(Istoreauto);
        !           939:                                emitconst(n->o.s->val->store.off);
        !           940:                                return;
        !           941:                        }
        !           942:                        emit(Istore);
        !           943:                        emitconst((long)&n->o.s->val->store.l);
        !           944:                        return;
        !           945:                case TArray:
        !           946:                case TChan:
        !           947:                case TProg:
        !           948:                case TStruct:
        !           949:                        if(n->o.s->val->isauto){
        !           950:                                emit(Istoreptrauto);
        !           951:                                emitconst(n->o.s->val->store.off);
        !           952:                                return;
        !           953:                        }
        !           954:                        emit(Istoreptr);
        !           955:                        emitconst((long)&n->o.s->val->store.l);
        !           956:                        return;
        !           957: 
        !           958:                default:
        !           959:                        panic("lgen: ID type %t", n->o.s->val->type->o.t);
        !           960:                        return;
        !           961:                }
        !           962:        case NArrayref:
        !           963:                gen(n->r, 1);
        !           964:                goto Genref;
        !           965:        case NStructref:
        !           966:                constgen(n->o.l);
        !           967:        Genref:
        !           968:                lgen1(n->l, Ipushuniqauto, Ipushuniq, Ipushuniqary);
        !           969:                emit(Istoreary);
        !           970:                return;
        !           971:        default:
        !           972:                panic("lgen: lvalue node %n", n->t);
        !           973:        }
        !           974: }
        !           975: 
        !           976: /*
        !           977:  * n is a compound object about to be assigned into
        !           978:  */
        !           979: lgen1(Node *n, int Iauto, int Ivar, int Iary)
        !           980: {
        !           981:        switch(n->t){
        !           982:        case NID:
        !           983:                if(n->o.s->val->isauto){
        !           984:                        emit(Iauto);
        !           985:                        emitconst(n->o.s->val->store.off);
        !           986:                        return;
        !           987:                }
        !           988:                emit(Ivar);
        !           989:                emitconst((long)&n->o.s->val->store.l);
        !           990:                return;
        !           991:        case NArrayref:
        !           992:                gen(n->r, 1);
        !           993:                goto Genref;
        !           994:        case NStructref:
        !           995:                constgen(n->o.l);
        !           996:        Genref:
        !           997:                lgen1(n->l, Ipushuniqauto, Ipushuniq, Ipushuniqary);
        !           998:                emit(Iary);
        !           999:                return;
        !          1000:        default:
        !          1001:                panic("lgen1: lvalue node %n", n->t);
        !          1002:        }
        !          1003: }
        !          1004: 
        !          1005: ifgen(Node *n)
        !          1006: {
        !          1007:        int loc1, loc2;
        !          1008:        gen(n->o.n, 1);
        !          1009:        emit(Ijmpfalse);
        !          1010:        loc1=here();
        !          1011:        emit(0);
        !          1012:        gen(n->l, 0);
        !          1013:        if(n->r==0){
        !          1014:                patch(loc1, (long)(here()-loc1-1)*WS);
        !          1015:                return;
        !          1016:        }
        !          1017:        emit(Ijmp);
        !          1018:        loc2=here();
        !          1019:        emit(0);
        !          1020:        patch(loc1, (long)(here()-loc1-1)*WS);
        !          1021:        gen(n->r, 0);
        !          1022:        patch(loc2, (long)(here()-loc2-1)*WS);
        !          1023:        return;
        !          1024: }
        !          1025: 
        !          1026: valgen(Node *n)
        !          1027: {
        !          1028:        int loc1, loc2;
        !          1029:        int orl;
        !          1030:        emit(Ijmp);
        !          1031:        loc1=here();
        !          1032:        emitconst(0L);
        !          1033:        orl=resultloc;
        !          1034:        resultloc=here();
        !          1035:        emit(Ijmp);
        !          1036:        loc2=here();
        !          1037:        emitconst(0L);
        !          1038:        patch(loc1, (long)(here()-loc1-1)*WS);
        !          1039:        gen(n, 1);
        !          1040:        emit(Ivalnoresult);
        !          1041:        patch(loc2, (long)(here()-loc2-1)*WS);
        !          1042:        resultloc=orl;
        !          1043: }
        !          1044: 
        !          1045: loopgen(Node *n)
        !          1046: {
        !          1047:        int loc0, loc1, loc2;
        !          1048:        if(n->o.i){     /* enter loop at top, so jump to body */
        !          1049:                emit(Ijmp);
        !          1050:                loc0=here();
        !          1051:                emit(0);
        !          1052:        }
        !          1053:        gen(n->r->l, 0);        /* left expr */
        !          1054:        if(n->r->r){            /* jump to condition */
        !          1055:                emit(Ijmp);
        !          1056:                loc1=here();
        !          1057:                emit(0);
        !          1058:        }
        !          1059:        if(n->o.i)
        !          1060:                patch(loc0, (here()-loc0-1)*LWS);
        !          1061:        loc2=here();
        !          1062:        gen(n->l, 0);           /* body */
        !          1063:        gen(n->r->o.n, 0);      /* right expr */
        !          1064:        if(n->r->r){
        !          1065:                patch(loc1, (here()-loc1-1)*LWS);
        !          1066:                gen(n->r->r, 1);
        !          1067:                emit(Ijmptrue);
        !          1068:        }else
        !          1069:                emit(Ijmp);
        !          1070:        emitconst((loc2-here()-1)*LWS);
        !          1071: }
        !          1072: 
        !          1073: condgen(Node *l, Node *r, Inst i1, Inst i2, long t1, long t2, int retain)
        !          1074: {
        !          1075:        int loc1, loc2, loc3;
        !          1076:        gen(l, 1);
        !          1077:        emit(i1);
        !          1078:        loc1=here();
        !          1079:        emit(0);
        !          1080:        loc2=here();
        !          1081:        if(retain)
        !          1082:                constgen(t1);
        !          1083:        emit(Ijmp);
        !          1084:        loc3=here();
        !          1085:        emit(0);
        !          1086:        patch(loc1, (long)(here()-loc1-1)*WS);
        !          1087:        gen(r, 1);
        !          1088:        emit(i2);
        !          1089:        emitconst((long)(loc2-here()-1)*WS);
        !          1090:        if(retain)
        !          1091:                constgen(t2);
        !          1092:        patch(loc3, (long)(here()-loc3-1)*WS);
        !          1093: }
        !          1094: 
        !          1095: callgen(Node *n, int callinst)
        !          1096: {
        !          1097:        Node *pt;
        !          1098:        pt=etypeof(n->l);
        !          1099:        /*
        !          1100:         * Space for result
        !          1101:         */
        !          1102:        constgen(0L);
        !          1103:        /*
        !          1104:         * Args
        !          1105:         */
        !          1106:        gen(n->r, 1);
        !          1107:        /*
        !          1108:         * Call
        !          1109:         */
        !          1110:        emit(Ipushconst);
        !          1111:        if(n->l->t==NID)
        !          1112:                emitconst((long)n->l->o.s->name);
        !          1113:        else{
        !          1114:                char buf[128];
        !          1115:                char *p;
        !          1116:                sprint(buf, "prog(){call on line %d}", n->line);
        !          1117:                p=emalloc((unsigned long)strlen(buf)+1);
        !          1118:                strcpy(p, buf);
        !          1119:                emitconst((long)p);
        !          1120:        }
        !          1121:        gen(n->l, 1);
        !          1122:        switch(callinst){
        !          1123:        case Icall:
        !          1124:                emit(Icall);
        !          1125:                return;
        !          1126:        case Ibegin:
        !          1127:                constgen(LWS*(1+1+length(pt->l)));      /* result+procname+args */
        !          1128:                emit(Ibegin);
        !          1129:                return;
        !          1130:        case Ibecome:
        !          1131:                constgen(LWS*(1+1+length(pt->l)));      /* result+procname+args */
        !          1132:                scopedecrefgen();
        !          1133:                fdecrefgen(formals, -3L*WS);
        !          1134:                emit(Ibecome);
        !          1135:                if(formals)
        !          1136:                        emitconst(length(formals)*LWS);
        !          1137:                else
        !          1138:                        emitconst(0L);
        !          1139:                return;
        !          1140:        }
        !          1141:        panic("callgen");
        !          1142: }
        !          1143: 
        !          1144: selgen(Node *n)
        !          1145: {
        !          1146:        int tbl, i;
        !          1147:        long l;
        !          1148:        int ends[200];
        !          1149:        selchangen(n);
        !          1150:        l=length(n);
        !          1151:        constgen(l);
        !          1152:        emit(Icommset);
        !          1153:        emit(Icommcln);
        !          1154:        if(l>(sizeof ends/sizeof ends[0]))
        !          1155:                panic("selgen table too small");
        !          1156:        tbl=here();
        !          1157:        emitspace(l);
        !          1158:        i=0;
        !          1159:        seltblgen(n, tbl, ends, &i);
        !          1160:        for(i=0; i<l; i++)
        !          1161:                patch(ends[i], (long)(here()-ends[i]-1)*WS);
        !          1162: }
        !          1163: 
        !          1164: selchangen(Node *n)
        !          1165: {
        !          1166:        long flags;
        !          1167:        if(n->t==NList){
        !          1168:                selchangen(n->l);
        !          1169:                selchangen(n->r);
        !          1170:                return;
        !          1171:        }
        !          1172:        if(n->t!=NCase)
        !          1173:                panic("selchangen");
        !          1174:        n=n->l->l;
        !          1175:        if(n->o.t=='=')
        !          1176:                n=n->r;         /* n is now RCV or SND */
        !          1177:        flags=0;
        !          1178:        if(n->o.t==SND)
        !          1179:                flags|=Cissnd;
        !          1180:        n=n->l;                 /* n is now channel */
        !          1181:        if(n->t==NArraycom){
        !          1182:                flags|=Cisary;
        !          1183:                n=n->l;
        !          1184:        }else if(etypeoft(n)->o.t==TArray)
        !          1185:                flags|=Cisary;
        !          1186:        gen(n, 1);
        !          1187:        constgen(flags);
        !          1188: }
        !          1189: 
        !          1190: seltblgen(Node *n, int tbl, int *ends, int *ip)
        !          1191: {
        !          1192:        Node *c, *s, *l, *t;
        !          1193:        if(n->t==NList){
        !          1194:                /* chans are eval'ed from the top, so table is backwards */
        !          1195:                seltblgen(n->r, tbl, ends, ip);
        !          1196:                seltblgen(n->l, tbl, ends, ip);
        !          1197:                return;
        !          1198:        }
        !          1199:        if(n->t!=NCase)
        !          1200:                panic("seltblgen");
        !          1201:        if(n->l->t==NList)
        !          1202:                error("sorry, empty cases not implemented");
        !          1203:        patch(tbl+*ip, (long)(here()-tbl)*WS);
        !          1204:        c=n->l->l;      /* communication */
        !          1205:        s=n->r;         /* statement */
        !          1206:        l=0;
        !          1207:        if(c->o.t=='='){
        !          1208:                l=c->l; /* lvalue */
        !          1209:                c=c->r;
        !          1210:        }
        !          1211:        if(c->o.t==SND){
        !          1212:                gen(c->r, 1);
        !          1213:                if(isptrtype(etypeoft(c->l)->r))
        !          1214:                        emit(Isndptr);
        !          1215:                else
        !          1216:                        emit(Isnd);
        !          1217:        }
        !          1218:        c=c->l; /* channel expression */
        !          1219:        /*
        !          1220:         * The value is still on the stack; save it or toss it
        !          1221:         */
        !          1222:        if(l)
        !          1223:                lgen(l);
        !          1224:        else if(c->t==NArraycom){
        !          1225:                t=etypeoft(c->l)->r;
        !          1226:                if(t->o.t==TID)
        !          1227:                        t=typeoftid(t);
        !          1228:                popgen(t->r);
        !          1229:        }else
        !          1230:                popgen(etypeoft(c)->r);
        !          1231:        if(c->t==NArraycom){    /* save array index */
        !          1232:                if(c->r)
        !          1233:                        lgen(c->r);
        !          1234:                else
        !          1235:                        emit(Ipop);
        !          1236:        }
        !          1237:        gen(s, 0);
        !          1238:        emit(Ijmp);
        !          1239:        ends[*ip]=here();
        !          1240:        (*ip)++;
        !          1241:        emitconst(0L);
        !          1242: }
        !          1243: 
        !          1244: switchgen(Node *s, Node *e)
        !          1245: {
        !          1246:        int isptr, out;
        !          1247:        isptr=isptrtype(etypeof(e));
        !          1248:        gen(e, 1);
        !          1249:        emit(Ijmp);
        !          1250:        emitconst(2*LWS);
        !          1251:        emit(Ijmp);     /* each case jumps to here to get out */
        !          1252:        out=here();
        !          1253:        emitconst(0L);
        !          1254:        switchgen1(s, isptr, out-1);
        !          1255:        /* pop leftover value if no case matched */
        !          1256:        if(isptr)
        !          1257:                emit(Ipopptr);
        !          1258:        else
        !          1259:                emit(Ipop);
        !          1260:        patch(out, (here()-out-1)*LWS);
        !          1261: }
        !          1262: 
        !          1263: switchgen1(Node *s, int isptr, int out)
        !          1264: {
        !          1265:        Node *e;
        !          1266:        int loc;
        !          1267:        if(s->t==NList){
        !          1268:                switchgen1(s->l, isptr, out);
        !          1269:                switchgen1(s->r, isptr, out);
        !          1270:                return;
        !          1271:        }
        !          1272:        if(s->t!=NCase)
        !          1273:                panic("switchgen1");
        !          1274:        if(s->r==0)
        !          1275:                error("sorry; can't fold cases together yet");
        !          1276:        if(s->l->t==NDefault)
        !          1277:                loc=-1;
        !          1278:        else{
        !          1279:                e=s->l->l;
        !          1280:                if(isptr){      /* string */
        !          1281:                        emit(Idupptr);
        !          1282:                        gen(e, 1);
        !          1283:                        emit(Istrcmp);
        !          1284:                        constgen(0L);
        !          1285:                }else{
        !          1286:                        emit(Idup);
        !          1287:                        gen(e, 1);
        !          1288:                }
        !          1289:                emit(Ieq);
        !          1290:                emit(Ijmpfalse);
        !          1291:                loc=here();
        !          1292:                emitconst(0L);
        !          1293:        }
        !          1294:        if(isptr)
        !          1295:                emit(Ipopptr);
        !          1296:        else
        !          1297:                emit(Ipop);
        !          1298:        gen(s->r, 0);
        !          1299:        emit(Ijmp);
        !          1300:        emitconst((out-here()-1)*LWS);
        !          1301:        if(loc!=-1)
        !          1302:                patch(loc, (here()-loc-1)*LWS);
        !          1303: }
        !          1304: 
        !          1305: popgen(Node *t)
        !          1306: {
        !          1307:        if(isptrtype(t))
        !          1308:                emit(Ipopptr);
        !          1309:        else if(isinttype(t) || t->o.t==TUnit)
        !          1310:                emit(Ipop);
        !          1311:        else
        !          1312:                panic("popgen %t\n", t->o.t);
        !          1313: }
        !          1314: 
        !          1315: genfreeauto(Symbol *s)
        !          1316: {
        !          1317:        if(!s->val->isauto)
        !          1318:                panic("genfreeauto");
        !          1319:        if(isptrtype(s->val->type)){
        !          1320:                emit(Idecrefauto);
        !          1321:                emitconst(s->val->store.off);
        !          1322:        }
        !          1323: }
        !          1324: 
        !          1325: printgen(Node *n)
        !          1326: {
        !          1327:        Node *t;
        !          1328:        if(n==0)
        !          1329:                return;
        !          1330:        if(n->t==NExprlist){
        !          1331:                printgen(n->l);
        !          1332:                printgen(n->r);
        !          1333:                return;
        !          1334:        }
        !          1335:        t=etypeoft(n);
        !          1336:        switch(t->o.t){
        !          1337:        case TArray:
        !          1338:        case TChan:
        !          1339:        case TProg:
        !          1340:        case TStruct:
        !          1341:                emit(Iprintary);
        !          1342:                break;
        !          1343:        case TChar:
        !          1344:                emit(Iprintchar);
        !          1345:                break;
        !          1346:        case TInt:
        !          1347:                emit(Iprintint);
        !          1348:                break;
        !          1349:        case TUnit:
        !          1350:                emit(Iprintunit);
        !          1351:                break;
        !          1352:        default:
        !          1353:                panic("printgen: bad type %t", t->o.t);
        !          1354:        }
        !          1355: }
        !          1356: 
        !          1357: proggen(Node *t, Node *n)
        !          1358: {
        !          1359:        int or;
        !          1360:        Node *of;
        !          1361:        Errjmp s;
        !          1362:        Store *p;
        !          1363:        long len, loc;
        !          1364:        long nauto, oao;
        !          1365:        extern int (*prog[])();
        !          1366:        oao=autooffset;
        !          1367:        or=returnloc;
        !          1368:        of=formals;
        !          1369:        autooffset=0;
        !          1370:        returnloc=0;
        !          1371:        formals=t->l;
        !          1372:        errsave(s);
        !          1373:        if(errmark()){
        !          1374:                returnloc=or;
        !          1375:                formals=of;
        !          1376:                autooffset=oao;
        !          1377:                errrest(s);
        !          1378:                errjmp();
        !          1379:        }
        !          1380:        loc=here();
        !          1381:        pushscope();
        !          1382:        dclformals(t->l);
        !          1383:        autooffset=0;
        !          1384:        emit(Ipushfp);
        !          1385:        nauto=here();
        !          1386:        emitconst(0L);
        !          1387:        gen(n, 0);
        !          1388:        trlrgen();
        !          1389:        patch((int)nauto, autooffset);
        !          1390:        popscope();
        !          1391:        errrest(s);
        !          1392:        autooffset=oao;
        !          1393:        returnloc=or;
        !          1394:        formals=of;
        !          1395:        len=here()-loc+1;
        !          1396:        p=(Store *)emalloc(SHSZ+len*LWS);
        !          1397:        memcpy((char *)(p->data), (char *)(prog+loc), len*LWS);
        !          1398:        p->ref=1;
        !          1399:        p->len=len;
        !          1400:        p->type=Sprog;
        !          1401:        setprog(loc);
        !          1402:        emit(Ipushdata);
        !          1403:        emitconst((long)p);
        !          1404: }
        !          1405: 
        !          1406: trlrgen()
        !          1407: {
        !          1408:        if(returnloc){
        !          1409:                emit(Ijmp);
        !          1410:                emitconst((long)(returnloc-here()-1)*WS);
        !          1411:                return;
        !          1412:        }
        !          1413:        returnloc=here();
        !          1414:        fdecrefgen(formals, -3L*WS);
        !          1415:        emit(Iret);
        !          1416:        if(formals)
        !          1417:                emitconst(length(formals)*LWS);
        !          1418:        else
        !          1419:                emitconst(0L);
        !          1420: }
        !          1421: 
        !          1422: fdecrefgen(Node *types, long offset)
        !          1423: {
        !          1424:        if(types==0)
        !          1425:                return 0;
        !          1426:        if(types->t==NList){
        !          1427:                offset=fdecrefgen(types->l, offset);
        !          1428:                return fdecrefgen(types->r, offset);
        !          1429:        }
        !          1430:        if(types->t!=NFormal)
        !          1431:                panic("fdecrefgen");
        !          1432:        types=types->r;
        !          1433:        if(isptrtype(types)){
        !          1434:                emit(Idecrefauto);
        !          1435:                emitconst(offset);
        !          1436:        }
        !          1437:        return offset-WS;
        !          1438: }
        !          1439: 
        !          1440: dupgen(Node *t, int n)
        !          1441: {
        !          1442:        while(n--)
        !          1443:                emit(isptrtype(t)? Idupptr : Idup);
        !          1444: }
        !          1445: 
        !          1446: mkgen(Node *t, Node *v)
        !          1447: {
        !          1448:        switch(t->o.t){
        !          1449:        case TChar:
        !          1450:        case TInt:
        !          1451:        case TUnit:
        !          1452:                if(v)
        !          1453:                        gen(v, 1);
        !          1454:                else
        !          1455:                        constgen(0L);
        !          1456:                return;
        !          1457:        case TID:
        !          1458:                mkgen(typeoftid(t), v);
        !          1459:                return;
        !          1460:        case TChan:
        !          1461:                if(v)
        !          1462:                        gen(v, 1);
        !          1463:                else{
        !          1464:                        constgen((long)(sizeof(Chan)-sizeof(Store)));
        !          1465:                        mallocgen(t);
        !          1466:                }
        !          1467:                return;
        !          1468:        case TArray:
        !          1469:                if(v==0){
        !          1470:                        gen(t->l, 1);
        !          1471:                        mallocgen(t);
        !          1472:                        return;
        !          1473:                }
        !          1474:                gen(v, 1);
        !          1475:                if(v->t!=NExprlist && eqtype(t, etypeof(v)))
        !          1476:                        return;
        !          1477:                if(v->t==NString)
        !          1478:                        constgen((long)strlen(v->o.c));
        !          1479:                else
        !          1480:                        constgen((long)length(v));
        !          1481:                emit(Idup);
        !          1482:                if(t->l)
        !          1483:                        gen(t->l, 1);
        !          1484:                else
        !          1485:                        constgen(0L);
        !          1486:                emit(Imax);
        !          1487:                mallocgen(t);
        !          1488:                if(t->r->o.t==TChar){
        !          1489:                        if(v->t==NString)
        !          1490:                                emit(Imemcpychar);
        !          1491:                        else
        !          1492:                                emit(Imemcpycharint);
        !          1493:                }else
        !          1494:                        emit(Imemcpy);
        !          1495:                return;
        !          1496:        case TProg:
        !          1497:                if(v==0){
        !          1498:                        v=new(NProg, dupnode(t), (Node *)0, (Node *)0);
        !          1499:                        gen(v, 1);
        !          1500:                        freenode(v);
        !          1501:                        return;
        !          1502:                }
        !          1503:                gen(v, 1);
        !          1504:                return;
        !          1505:        case TStruct:
        !          1506:                if(v==0){
        !          1507:                        mallocgen(t);
        !          1508:                        return;
        !          1509:                }
        !          1510:                gen(v, 1);
        !          1511:                if(v->t!=NExprlist && eqtype(t, etypeof(v)))
        !          1512:                        return;
        !          1513:                constgen((long)length(v));
        !          1514:                mallocgen(t);
        !          1515:                emit(Imemcpystruct);
        !          1516:                return;         
        !          1517:        default:
        !          1518:                panic("mkgen: bad type %t", t->o.t);
        !          1519:        }
        !          1520: }
        !          1521: 
        !          1522: mallocgen(Node *t)
        !          1523: {
        !          1524:        switch(t->o.t){
        !          1525:        case TArray:
        !          1526:                t=t->r;
        !          1527:                if(t->o.t==TID)
        !          1528:                        t=typeoftid(t);
        !          1529:                if(isptrtype(t)){
        !          1530:                        constgen((long)Saryptr);
        !          1531:                        emit(Imalloc);
        !          1532:                }else if(t->o.t==TInt || t->o.t==TUnit){
        !          1533:                        constgen((long)Saryint);
        !          1534:                        emit(Imalloc);
        !          1535:                }else if(t->o.t==TChar)
        !          1536:                        emit(Imallocarychar);
        !          1537:                else
        !          1538:                        panic("mallocgen array of %t", t->o.t);
        !          1539:                return;
        !          1540:        case TStruct:{
        !          1541:                int pos=0;
        !          1542:                long bits=0;
        !          1543:                t=t->l;
        !          1544:                elembitsgen(t, &pos, &bits);
        !          1545:                if(pos)
        !          1546:                        constgen(bits);
        !          1547:                constgen((long)length(t));
        !          1548:                emit(Imallocstruct);
        !          1549:                return;
        !          1550:        }
        !          1551:        case TChan:
        !          1552:                constgen((long)Schan);
        !          1553:                emit(Imalloc);
        !          1554:                return;
        !          1555:        }
        !          1556:        panic("mallocgen of %t", t->o.t);
        !          1557: }
        !          1558: 
        !          1559: elembitsgen(Node *t, int *pos, long *bits)
        !          1560: {
        !          1561:        int i;
        !          1562:        if(t->t==NList){
        !          1563:                elembitsgen(t->l, pos, bits);
        !          1564:                elembitsgen(t->r, pos, bits);
        !          1565:                return;
        !          1566:        }
        !          1567:        if(t->t!=NElem)
        !          1568:                panic("elembitsgen %n", t->t);
        !          1569:        for(i=length(t); --i>=0; ){
        !          1570:                if(*pos==BPW){
        !          1571:                        constgen(*bits);
        !          1572:                        *pos=0;
        !          1573:                        *bits=0;
        !          1574:                }
        !          1575:                if(isptrtype(t->r))
        !          1576:                        *bits|=1L<<*pos;
        !          1577:                (*pos)++;
        !          1578:        }
        !          1579: }
        !          1580: 
        !          1581: constgen(long l)
        !          1582: {
        !          1583:        if(l<-2 || l>10){
        !          1584:                emit(Ipushconst);
        !          1585:                emitconst(l);
        !          1586:                return;
        !          1587:        };
        !          1588:        switch((int)l){
        !          1589:        case -2:
        !          1590:                emit(Ipush_2);
        !          1591:                break;
        !          1592:        case -1:
        !          1593:                emit(Ipush_1);
        !          1594:                break;
        !          1595:        case 0:
        !          1596:                emit(Ipush0);
        !          1597:                break;
        !          1598:        case 1:
        !          1599:                emit(Ipush1);
        !          1600:                break;
        !          1601:        case 2:
        !          1602:                emit(Ipush2);
        !          1603:                break;
        !          1604:        case 3:
        !          1605:                emit(Ipush3);
        !          1606:                break;
        !          1607:        case 4:
        !          1608:                emit(Ipush4);
        !          1609:                break;
        !          1610:        case 5:
        !          1611:                emit(Ipush5);
        !          1612:                break;
        !          1613:        case 6:
        !          1614:                emit(Ipush6);
        !          1615:                break;
        !          1616:        case 7:
        !          1617:                emit(Ipush7);
        !          1618:                break;
        !          1619:        case 8:
        !          1620:                emit(Ipush8);
        !          1621:                break;
        !          1622:        case 9:
        !          1623:                emit(Ipush9);
        !          1624:                break;
        !          1625:        case 10:
        !          1626:                emit(Ipush10);
        !          1627:                break;
        !          1628:        default:
        !          1629:                panic("constgen");
        !          1630:        }
        !          1631: }
        !          1632: 
        !          1633: printable(Node *n)
        !          1634: {
        !          1635:        if(n==0)
        !          1636:                return 0;
        !          1637:        switch(n->t){
        !          1638:        case NExpr:
        !          1639:                return n->o.t!='=';
        !          1640:        case NArrayref:
        !          1641:        case NCall:
        !          1642:        case NID:
        !          1643:        case NMk:
        !          1644:        case NNum:
        !          1645:        case NProg:
        !          1646:        case NString:
        !          1647:        case NStructref:
        !          1648:        case NUnit:
        !          1649:        case NVal:
        !          1650:                return 1;
        !          1651:        }
        !          1652:        return 0;
        !          1653: }
        !          1654: #include "alloc.h"
        !          1655: #include "node.h"
        !          1656: #include "symbol.h"
        !          1657: #include "ydefs.h"
        !          1658: #include "word.h"
        !          1659: #include "store.h"
        !          1660: #include <libc.h>
        !          1661: 
        !          1662: Node           *doconst();
        !          1663: extern int     Cflag;
        !          1664: 
        !          1665: Node *
        !          1666: constants(Node *n)
        !          1667: {
        !          1668:        if(n==0)
        !          1669:                return 0;
        !          1670:        if(Cflag)
        !          1671:                return n;
        !          1672:        switch(n->t){
        !          1673:        case NArrayref:
        !          1674:                if(isconst(n))
        !          1675:                        return doconst(n);
        !          1676:                break;
        !          1677:        case NArraycom:
        !          1678:                break;
        !          1679:        case NBecome:
        !          1680:                break;
        !          1681:        case NBegin:
        !          1682:                break;
        !          1683:        case NCall:
        !          1684:                break;
        !          1685:        case NCase:
        !          1686:                break;
        !          1687:        case NDecl:
        !          1688:                n->r=constants(n->r);
        !          1689:                n->o.n=constants(n->o.n);
        !          1690:                declare(n, 0, 0, 0);
        !          1691:                return n;
        !          1692:        case NDeclsc:
        !          1693:                break;
        !          1694:        case NDefault:
        !          1695:                return n;
        !          1696:        case NElem:
        !          1697:                n->r=constants(n->r);
        !          1698:                return n;
        !          1699:        case NExpr:
        !          1700:                switch(n->o.i){
        !          1701:                case GE:
        !          1702:                case LE:
        !          1703:                case NE:
        !          1704:                case EQ:
        !          1705:                case '>':
        !          1706:                case '<':
        !          1707:                case '+':
        !          1708:                case '-':
        !          1709:                case '*':
        !          1710:                case '/':
        !          1711:                case '%':
        !          1712:                case '&':
        !          1713:                case '|':
        !          1714:                case '^':
        !          1715:                case ANDAND:
        !          1716:                case OROR:
        !          1717:                case LSH:
        !          1718:                case RSH:
        !          1719:                        if(isconst(n->l) && isconst(n->r))
        !          1720:                                return doconst(n);
        !          1721:                        break;
        !          1722:                case DEF:
        !          1723:                case REF:
        !          1724:                case LEN:
        !          1725:                case UMINUS:
        !          1726:                case '~':
        !          1727:                case '!':
        !          1728:                        if(isconst(n->l))
        !          1729:                                return doconst(n);
        !          1730:                        break;
        !          1731:                case PRINT:
        !          1732:                case RCV:
        !          1733:                case SND:
        !          1734:                case INC:
        !          1735:                case DEC:
        !          1736:                        break;
        !          1737:                case '=':
        !          1738:                        break;
        !          1739:                default:
        !          1740:                        fprint(2, "can't const expression %e\n", n->o.i);
        !          1741:                        return n;
        !          1742:                }
        !          1743:                break;
        !          1744:        case NExprlist:
        !          1745:                break;
        !          1746:        case NFormal:
        !          1747:                n->r=constants(n->r);
        !          1748:                return n;
        !          1749:        case NLabel:
        !          1750:                break;
        !          1751:        case NID:
        !          1752:                if(isconst(n))
        !          1753:                        return doconst(n);
        !          1754:                break;
        !          1755:        case NIf:
        !          1756:                n->l=constants(n->l);
        !          1757:                n->r=constants(n->r);
        !          1758:                n->o.n=constants(n->o.n);
        !          1759:                if(isconst(n->o.n)){
        !          1760:                        Node *m;
        !          1761:                        gen(n->o.n, 1);
        !          1762:                        execute();
        !          1763:                        if(topofstack()){
        !          1764:                                m=n->l;
        !          1765:                                n->l=0;
        !          1766:                        }else{
        !          1767:                                m=n->r;
        !          1768:                                n->r=0;
        !          1769:                        }
        !          1770:                        freenode(n);
        !          1771:                        return m;
        !          1772:                }
        !          1773:                return n;
        !          1774:        case NList:
        !          1775:                break;
        !          1776:        case NLoop:
        !          1777:                break;
        !          1778:        case NLoopexpr:
        !          1779:                n->o.n=constants(n->o.n);
        !          1780:                break;
        !          1781:        case NMk:
        !          1782:                break;
        !          1783:        case NNum:
        !          1784:                return n;
        !          1785:        case NProg:
        !          1786:                pushscope();
        !          1787:                dclformals(n->l->l);
        !          1788:                n->r=constants(n->r);
        !          1789:                popscope();
        !          1790:                return n;
        !          1791:        case NResult:
        !          1792:                break;
        !          1793:        case NScope:
        !          1794:                pushscope();
        !          1795:                n->l=constants(n->l);
        !          1796:                popscope();
        !          1797:                return n;
        !          1798:        case NSelect:
        !          1799:                break;
        !          1800:        case NSmash:
        !          1801:                return n;
        !          1802:        case NString:
        !          1803:                return n;
        !          1804:        case NSwitch:
        !          1805:                break;
        !          1806:        case NStructref:
        !          1807:                if(isconst(n))
        !          1808:                        return (n);
        !          1809:                break;
        !          1810:        case NType:
        !          1811:                break;
        !          1812:        case NUnit:
        !          1813:                break;
        !          1814:        case NVal:
        !          1815:                if(isconst(n->l))
        !          1816:                        return doconst(n);
        !          1817:                break;
        !          1818:        default:
        !          1819:                fprint(2, "can't const node %n\n", n->t);
        !          1820:                return n;
        !          1821:        }
        !          1822:        n->l=constants(n->l);
        !          1823:        n->r=constants(n->r);
        !          1824:        return n;
        !          1825: }
        !          1826: 
        !          1827: isconst(Node *n)
        !          1828: {
        !          1829:        if(n==0)
        !          1830:                return 1;
        !          1831:        switch(n->t){
        !          1832:        case NArrayref:
        !          1833:                return isconst(n->l) && isconst(n->r);
        !          1834:        case NCall:
        !          1835:                return 0;
        !          1836:        case NExpr:
        !          1837:                switch(n->o.i){
        !          1838:                case GE:
        !          1839:                case LE:
        !          1840:                case NE:
        !          1841:                case EQ:
        !          1842:                case '>':
        !          1843:                case '<':
        !          1844:                case '+':
        !          1845:                case '-':
        !          1846:                case '*':
        !          1847:                case '/':
        !          1848:                case '%':
        !          1849:                case '&':
        !          1850:                case '|':
        !          1851:                case '^':
        !          1852:                case ANDAND:
        !          1853:                case OROR:
        !          1854:                case LSH:
        !          1855:                case RSH:
        !          1856:                        return isconst(n->l) && isconst(n->r);
        !          1857:                case DEF:
        !          1858:                case LEN:
        !          1859:                case UMINUS:
        !          1860:                case '~':
        !          1861:                case '!':
        !          1862:                        return isconst(n->l);
        !          1863:                case REF:
        !          1864:                case '=':
        !          1865:                case RCV:
        !          1866:                case SND:
        !          1867:                case INC:
        !          1868:                case DEC:
        !          1869:                        return 0;
        !          1870:                }
        !          1871:                fprint(2, "can't isconst expression %e", n->o.i);
        !          1872:                return 0;
        !          1873:        case NID:
        !          1874:                return n->o.s->val->scope==0 && (n->o.s->val->stclass&SCconst);
        !          1875:        case NIf:
        !          1876:                return isconst(n->o.n) && isconst(n->l) && isconst(n->r);
        !          1877:        case NList:
        !          1878:                return 0;
        !          1879:        case NLoop:
        !          1880:                return 0;
        !          1881:        case NNum:
        !          1882:                return 1;
        !          1883:        case NResult:
        !          1884:                return isconst(n->l);
        !          1885:        case NScope:
        !          1886:                return isconst(n->l);
        !          1887:        case NString:
        !          1888:                return 1;
        !          1889:        case NStructref:
        !          1890:                return isconst(n->l);
        !          1891:        case NVal:
        !          1892:                return isconst(n->l);
        !          1893:        case NUnit:
        !          1894:                return 1;
        !          1895:        }
        !          1896:        fprint(2, "can't isconst node %n\n", n->t);
        !          1897:        return 0;
        !          1898: }
        !          1899: 
        !          1900: Node *
        !          1901: doconst(Node *n)
        !          1902: {
        !          1903:        Node *t;
        !          1904:        if(n->t==NNum || n->t==NString || n->t==NUnit)
        !          1905:                return n;       /* already const */
        !          1906:        t=etypeoft(n);
        !          1907:        switch(t->o.t){
        !          1908:        case TChar:
        !          1909:        case TInt:
        !          1910:                gen(n, 1);
        !          1911:                freenode(n);
        !          1912:                execute();
        !          1913:                return new(NNum, (Node *)0, (Node *)0, (Node *)topofstack());
        !          1914:        case TUnit:
        !          1915:                return new(NUnit, (Node *)0, (Node *)0, (Node *)0);
        !          1916:        case TArray:
        !          1917:                if(t->r->o.t==TChar){
        !          1918:                        Store *s;
        !          1919:                        char *c;
        !          1920:                        gen(n, 1);
        !          1921:                        freenode(n);
        !          1922:                        execute();
        !          1923:                        s=(Store *)topofstack();
        !          1924:                        c=emalloc(s->len+1);
        !          1925:                        strncpy(c, (char *)s->data, (int)s->len);
        !          1926:                        return newc(NString, (Node *)0, (Node *)0, c);
        !          1927:                }
        !          1928:                return n;
        !          1929:        }
        !          1930:        return n;
        !          1931: }
        !          1932: #include "alloc.h"
        !          1933: #include "word.h"
        !          1934: #include "store.h"
        !          1935: #include "comm.h"
        !          1936: #include <libc.h>
        !          1937: 
        !          1938: extern int     pflag;
        !          1939: 
        !          1940: /*
        !          1941:  * Jumps
        !          1942:  */
        !          1943: 
        !          1944: ijmp(Proc *proc)
        !          1945: {
        !          1946:        SWord l;
        !          1947:        l=(SWord)*++proc->pc;
        !          1948:        proc->pc+=l/WS;
        !          1949:        return 1;
        !          1950: }
        !          1951: 
        !          1952: ijmpfalse(Proc *proc)
        !          1953: {
        !          1954:        SWord l;
        !          1955:        l=(SWord)*++proc->pc;
        !          1956:        if(*--proc->sp==0)
        !          1957:                proc->pc+=l/WS;
        !          1958:        return 1;
        !          1959: }
        !          1960: 
        !          1961: ijmptrue(Proc *proc)
        !          1962: {
        !          1963:        SWord l;
        !          1964:        l=(SWord)*++proc->pc;
        !          1965:        if(*--proc->sp!=0)
        !          1966:                proc->pc+=l/WS;
        !          1967:        return 1;
        !          1968: }
        !          1969: 
        !          1970: ivalnoresult(Proc *proc)
        !          1971: {
        !          1972:        rerror("val produces no result");
        !          1973:        return 0;
        !          1974: }
        !          1975: 
        !          1976: /*
        !          1977:  * Progs
        !          1978:  *
        !          1979:  *   Layout of a stack frame
        !          1980:  *
        !          1981:  *     sp:
        !          1982:  *             automatics
        !          1983:  *     fp:     old fp
        !          1984:  *             old pc
        !          1985:  *             symbol
        !          1986:  *             arg1
        !          1987:  *             arg2
        !          1988:  *             ...
        !          1989:  *             result
        !          1990:  */
        !          1991: 
        !          1992: iret(Proc *proc)
        !          1993: {
        !          1994:        SWord nargs;
        !          1995:        nargs=(SWord)(proc->pc[1]);
        !          1996:        proc->sp=(SWord *)proc->fp+1;
        !          1997:        proc->fp=(SWord *)*--proc->sp;
        !          1998:        proc->pc=(int (**)())*--proc->sp;
        !          1999:        proc->sp-=(sizeof(char *)+nargs)/WS;
        !          2000:        if(proc->pc==0){
        !          2001:                if(pflag)
        !          2002:                        fprint(2, "%d halts\n", proc->procnum);
        !          2003:                halt(proc);
        !          2004:                return 0;
        !          2005:        }
        !          2006:        return 1;
        !          2007: }
        !          2008: 
        !          2009: ibecome(Proc *proc)
        !          2010: {
        !          2011:        int nargs;
        !          2012:        int (**newpc)();
        !          2013:        SWord oldfp, oldpc, *oldresultaddr, *newresultaddr;
        !          2014:        Store *s;
        !          2015:        nargs=*--proc->sp/LWS;
        !          2016:        nargs+=2;       /* includes result and sym; add pc, fp */
        !          2017:        s=(Store *)*--proc->sp;
        !          2018:        if(--(s->ref)==0)
        !          2019:                rpanic("ibecome ref==0");
        !          2020:        newpc=((int (**)())s->data);
        !          2021:        oldfp=proc->fp[0];
        !          2022:        oldpc=proc->fp[-1];
        !          2023:        *proc->sp++=oldpc;
        !          2024:        *proc->sp++=oldfp;
        !          2025:        oldresultaddr=proc->fp-3-(long)(*++proc->pc)/LWS;
        !          2026:        newresultaddr=proc->sp-nargs;
        !          2027:        memcpy((char *)oldresultaddr, (char *)newresultaddr, LWS*nargs);
        !          2028:        /* args in place.  do the call by hand, jmp to pushfp */
        !          2029:        proc->sp=oldresultaddr+(nargs-2);
        !          2030:        *proc->sp++=oldpc;
        !          2031:        proc->fp=(SWord *)oldfp;
        !          2032:        proc->pc=newpc-1;
        !          2033:        return 1;
        !          2034: }
        !          2035: 
        !          2036: ipushfp(Proc *proc)
        !          2037: {
        !          2038:        int nauto;
        !          2039:        *proc->sp=(SWord)proc->fp;
        !          2040:        proc->fp=proc->sp++;
        !          2041:        nauto=((SWord)*++proc->pc)/WS;
        !          2042:        while(nauto--)
        !          2043:                *proc->sp++=0;
        !          2044:        if(proc->sp>=&proc->stack[NSTACK])
        !          2045:                rerror("stack overflow");
        !          2046:        return 1;
        !          2047: }
        !          2048: 
        !          2049: icall(Proc *proc)
        !          2050: {
        !          2051:        int (**newpc)();
        !          2052:        Store *s;
        !          2053:        s=(Store *)*--proc->sp;
        !          2054:        if(--(s->ref)==0)
        !          2055:                rpanic("icall ref==0");
        !          2056:        newpc=((int (**)())s->data);
        !          2057:        *proc->sp++=(SWord)proc->pc;
        !          2058:        proc->pc=newpc-1;
        !          2059:        return 1;
        !          2060: }
        !          2061: #include "node.h"
        !          2062: #include "symbol.h"
        !          2063: #include "alloc.h"
        !          2064: #include "ydefs.h"
        !          2065: #include "word.h"
        !          2066: #include "store.h"
        !          2067: #include <libc.h>
        !          2068: 
        !          2069: extern int     nscope;
        !          2070: 
        !          2071: declare(Node *n, int stclass, int dotypchk, int docomp)
        !          2072: {
        !          2073:        extern int iflag;
        !          2074:        if(n==0)
        !          2075:                return;
        !          2076:        if(n->t==NList){
        !          2077:                declare(n->l, stclass, dotypchk, docomp);
        !          2078:                declare(n->r, stclass, dotypchk, docomp);
        !          2079:                return;
        !          2080:        }
        !          2081:        if(n->t==NDeclsc){
        !          2082:                declare(n->l, n->o.i, dotypchk, docomp);
        !          2083:                return;
        !          2084:        }
        !          2085:        if(dotypchk)
        !          2086:                type(n->o.n, 0);
        !          2087:        if(n->r==0){
        !          2088:                if(n->o.n==0)
        !          2089:                        panic("declare: no type");
        !          2090:                if(n->o.n->t==NMk && n->o.n->l==0)
        !          2091:                        lerror(n, "can't derive type in declaration");
        !          2092:                n->r=dupnode(etypeof(n->o.n));
        !          2093:        }
        !          2094:        if(dotypchk){
        !          2095:                type(n->r, 0);
        !          2096:                if(n->o.n){
        !          2097:                        /*
        !          2098:                         * Make it a mk
        !          2099:                         */
        !          2100:                        if(n->o.n->t!=NMk)
        !          2101:                                n->o.n=new(NMk, (Node *)0, n->o.n, (Node *)0);
        !          2102:                        /*
        !          2103:                         * Default type for mk
        !          2104:                         */
        !          2105:                        if(n->o.n->l==0)
        !          2106:                                n->o.n->l=dupnode(n->r);
        !          2107:                        else if(!compattype(n->r, n->o.n->l))
        !          2108:                                lerror(n, "type clash in declaration (%t %t)\n",
        !          2109:                                        n->r->o.t, etypeof(n->o.n)->o.t);
        !          2110:                        mkcheck(n->o.n->l, n->o.n->r);
        !          2111:                }
        !          2112:        }
        !          2113:        if(docomp && n->o.n){
        !          2114:                if(dotypchk)    /* top level declaration */
        !          2115:                        n->o.n=constants(n->o.n);
        !          2116:                gen(n->o.n, 1);
        !          2117:                dupgen(n->r, length(n->l)-1);
        !          2118:        }else
        !          2119:                docomp=0;
        !          2120:        dcl(n->l, n->r, stclass, n->o.n, docomp);
        !          2121:        if(n->o.n && docomp && nscope==0){
        !          2122:                if(iflag)
        !          2123:                        idump();
        !          2124:                execute();
        !          2125:        }
        !          2126: }
        !          2127: 
        !          2128: dcl(id, typ, stclass, val, docomp)
        !          2129:        Node *id, *typ, *val;
        !          2130: {
        !          2131:        if(id->t==NList){
        !          2132:                dcl(id->l, typ, stclass, val, docomp);
        !          2133:                dcl(id->r, typ, stclass, val, docomp);
        !          2134:                return;
        !          2135:        }
        !          2136:        if(typ->o.t==TID && typ->l->o.s->val->type->o.t!=TType)
        !          2137:                error("%m not a type", typ->l);
        !          2138:        if(id->t!=NID)
        !          2139:                panic("dcl not ID");
        !          2140:        pushval(id->o.s, dupnode(typ));
        !          2141:        if(stclass&SCbltin)
        !          2142:                id->o.s->val->store.l=bltinval(id->o.s->name, typ);
        !          2143:        if(docomp)
        !          2144:                lgen(id);
        !          2145:        id->o.s->val->stclass=stclass;
        !          2146: }
        !          2147: 
        !          2148: /*
        !          2149:  * To compile this
        !          2150:  *     rec {
        !          2151:  *             x : chan of T = f(x,y);
        !          2152:  *             y : chan of T = g(x,y);
        !          2153:  *     };
        !          2154:  * convert it to this
        !          2155:  *     x : chan of T = mk();
        !          2156:  *     y : chan of T = mk();
        !          2157:  *     x1 : chan of T = f(x,y);
        !          2158:  *     y1 : chan of T = g(x,y);
        !          2159:  *     x <- x1;
        !          2160:  *     y <- y1;
        !          2161:  *     toss x1, y1;
        !          2162:  * where the operator x <- x1 means copy the representation of x1 into x.
        !          2163:  *
        !          2164:  *     rec type T: struct of { t:T; };
        !          2165:  *
        !          2166:  * is handled similarly.
        !          2167:  */
        !          2168: 
        !          2169: Node *
        !          2170: op1(Node *n)
        !          2171: {
        !          2172:        Node *m;
        !          2173:        if(n->t==NDeclsc){
        !          2174:                m=op1(n->l);
        !          2175:                return newi(NDeclsc, m, (Node *)0, n->o.i);
        !          2176:        }
        !          2177:        if(n->r==0){
        !          2178:                if(n->o.n && (n->o.n->t==NProg || (n->o.n->t==NMk && n->o.n->l)))
        !          2179:                        n->r=dupnode(n->o.n->l);
        !          2180:                else                    
        !          2181:                        lerror(n, "can't deduce type for rec decl");
        !          2182:        }else if(n->r->o.t==TType){
        !          2183:                m=newi(NType, (Node *)0, (Node *)0, n->r->l->o.t);
        !          2184:                m=new(NDecl, dupnode(n->l), m, (Node *)0);
        !          2185:                return m;
        !          2186:        }
        !          2187:        m=new(NMk, dupnode(n->r), (Node *)0, (Node *)0);
        !          2188:        m=new(NDecl, dupnode(n->l), dupnode(n->r), m);
        !          2189:        return m;
        !          2190: }
        !          2191: 
        !          2192: Node *
        !          2193: op2(Node *n)
        !          2194: {
        !          2195:        Node *m;
        !          2196:        char s[Namesize+2];
        !          2197:        if(n->t==NDeclsc){
        !          2198:                m=op2(n->l);
        !          2199:                return newi(NDeclsc, m, (Node *)0, n->o.i);
        !          2200:        }
        !          2201:        if(n->l->t==NList)
        !          2202:                error("no identifier lists in rec's, please");
        !          2203:        strcpy(s+1, n->l->o.s->name);
        !          2204:        s[0]='*';
        !          2205:        m=new(NDecl, idnode(lookup(s, ID)), dupnode(n->r), dupnode(n->o.n));
        !          2206:        return m;
        !          2207: }
        !          2208: 
        !          2209: Node *
        !          2210: op3(Node *n)
        !          2211: {
        !          2212:        Node *m;
        !          2213:        char s[Namesize+2];
        !          2214:        if(n->t==NDeclsc)
        !          2215:                return op3(n->l);
        !          2216:        if(n->l->t==NList)
        !          2217:                error("no lists in rec's, please");
        !          2218:        strcpy(s+1, n->l->o.s->name);
        !          2219:        s[0]='*';
        !          2220:        m=new(NSmash, idnode(lookup(s+1, ID)), idnode(lookup(s, ID)), (Node *)0);
        !          2221:        return m;
        !          2222: }
        !          2223: 
        !          2224: Node *
        !          2225: rewr(Node *n, Node *(*f)())
        !          2226: {
        !          2227:        if(n->t==NList)
        !          2228:                return new(NList, rewr(n->l, f), rewr(n->r, f), (Node *)0);
        !          2229:        return (*f)(n);
        !          2230: }
        !          2231: 
        !          2232: recrewrite(Node *n)
        !          2233: {
        !          2234:        Node *n1, *n2, *n3;
        !          2235:        n1=rewr(n->l, op1);
        !          2236:        n2=rewr(n->l, op2);
        !          2237:        n3=rewr(n->l, op3);
        !          2238:        freenode(n->l);
        !          2239:        n->t=NList;
        !          2240:        n->r=n3;
        !          2241:        n->l=new(NList, n1, n2, (Node *)0);
        !          2242:        ndump(n);
        !          2243: }
        !          2244: 
        !          2245: /*
        !          2246:  *
        !          2247:  * To compile this
        !          2248:  *
        !          2249:  *     prog(a:int){
        !          2250:  *             begin prog(b:int){ f(a, b); }(b);
        !          2251:  *     }
        !          2252:  *
        !          2253:  * convert it to this
        !          2254:  *
        !          2255:  *     prog(a:int){
        !          2256:  *             begin prog(b:int, a:int){ f(a, b); }(b, a);
        !          2257:  *     }
        !          2258:  *
        !          2259:  */
        !          2260: 
        !          2261: Node   *begf;
        !          2262: Node   *bega;
        !          2263: int    fscope;
        !          2264: int    progerr;
        !          2265: 
        !          2266: proglocals(Node *n)
        !          2267: {
        !          2268:        progerr=1;
        !          2269:        pushscope();
        !          2270:        fscope=nscope;
        !          2271:        begf=n->l->l;
        !          2272:        bega=0;
        !          2273:        dclformals(begf);
        !          2274:        progid(n->r);
        !          2275:        popscope();
        !          2276: }
        !          2277: 
        !          2278: begrewrite(Node *n)
        !          2279: {
        !          2280:        progerr=0;
        !          2281:        pushscope();
        !          2282:        fscope=nscope;
        !          2283:        begf=n->l->l->l;
        !          2284:        bega=n->r;
        !          2285:        dclformals(begf);
        !          2286:        progid(n->l->r);
        !          2287:        popscope();
        !          2288:        n->l->l->l=begf;
        !          2289:        n->r=bega;
        !          2290: }
        !          2291: 
        !          2292: addformal(Node *n)
        !          2293: {
        !          2294:        Node *nf;
        !          2295:        if(!alreadyformal(n, begf)){
        !          2296:                nf=new(NFormal, dupnode(n), dupnode(n->o.s->val->type), (Node *)0);
        !          2297:                if(begf)
        !          2298:                        begf=new(NList, begf, nf, (Node *)0);
        !          2299:                else
        !          2300:                        begf=nf;
        !          2301:                nf=dupnode(n);
        !          2302:                if(bega)
        !          2303:                        bega=new(NExprlist, bega, nf, (Node *)0);
        !          2304:                else
        !          2305:                        bega=nf;
        !          2306:        }               
        !          2307: }
        !          2308: 
        !          2309: alreadyformal(Node *n, Node *f)
        !          2310: {
        !          2311:        if(f==0)
        !          2312:                return 0;
        !          2313:        if(f->t==NList)
        !          2314:                return alreadyformal(n, f->l) || alreadyformal(n, f->r);
        !          2315:        return strcmp(n->o.s->name, f->l->o.s->name)==0;
        !          2316: }
        !          2317: 
        !          2318: progid(Node *n)
        !          2319: {
        !          2320:        if(n==0)
        !          2321:                return;
        !          2322:        switch(n->t){
        !          2323:        case NArrayref:
        !          2324:        case NArraycom:
        !          2325:        case NBecome:
        !          2326:        case NBegin:
        !          2327:        case NCall:
        !          2328:        case NCase:
        !          2329:                break;
        !          2330:        case NDecl:
        !          2331:                progid(n->r);
        !          2332:                progid(n->o.n);
        !          2333:                declare(n, 0, 0, 0);
        !          2334:                return;
        !          2335:        case NDeclsc:
        !          2336:        case NDefault:
        !          2337:                break;
        !          2338:        case NElem:
        !          2339:                return;
        !          2340:        case NExpr:
        !          2341:        case NExprlist:
        !          2342:        case NFormal:
        !          2343:                break;
        !          2344:        case NID:
        !          2345:                if(n->o.s->val)
        !          2346:                if(0<n->o.s->val->scope && n->o.s->val->scope<fscope){
        !          2347:                        if(progerr)
        !          2348:                                lerror(n, "%m not in an accessible scope", n);
        !          2349:                        addformal(n);
        !          2350:                }
        !          2351:                return;
        !          2352:        case NLabel:
        !          2353:        case NList:
        !          2354:        case NLoop:
        !          2355:                break;
        !          2356:        case NLoopexpr:
        !          2357:                progid(n->o.n);
        !          2358:                break;
        !          2359:        case NIf:
        !          2360:                progid(n->o.n);
        !          2361:                break;
        !          2362:        case NMk:
        !          2363:                break;
        !          2364:        case NNum:
        !          2365:                return;
        !          2366:        case NProg:
        !          2367:                pushscope();
        !          2368:                dclformals(n->l->l);
        !          2369:                progid(n->r);
        !          2370:                popscope();
        !          2371:                return;
        !          2372:        case NResult:
        !          2373:                break;
        !          2374:        case NScope:
        !          2375:                pushscope();
        !          2376:                progid(n->l);
        !          2377:                popscope();
        !          2378:                return;
        !          2379:        case NSelect:
        !          2380:                break;
        !          2381:        case NSmash:
        !          2382:                return; /* ?? */
        !          2383:        case NString:
        !          2384:                return;
        !          2385:        case NSwitch:
        !          2386:        case NStructref:
        !          2387:                break;
        !          2388:        case NType:
        !          2389:                break;
        !          2390:        case NUnit:
        !          2391:                return;
        !          2392:        case NVal:
        !          2393:                break;
        !          2394:        default:
        !          2395:                fprint(2, "can't progid node %n\n", n->t);
        !          2396:                return;
        !          2397:        }
        !          2398:        progid(n->l);
        !          2399:        progid(n->r);
        !          2400: }
        !          2401: 
        !          2402: #include "nodenames.h"
        !          2403: #include "typenames.h"
        !          2404: #include "errjmp.h"
        !          2405: #include "node.h"
        !          2406: #include "symbol.h"
        !          2407: #include "ydefs.h"
        !          2408: #include <libc.h>
        !          2409: 
        !          2410: lerror(Node *n, char *s, a, b, c, d, e, f)
        !          2411: {
        !          2412:        lfileline(n->line);
        !          2413:        fprint(2, s, a, b, c, d, e, f);
        !          2414:        if(s[strlen(s)-1]!='\n')
        !          2415:                fprint(2, "\n");
        !          2416:        errflush();
        !          2417:        errjmp();
        !          2418: }
        !          2419: 
        !          2420: error(char *s, a, b, c, d, e, f)
        !          2421: {
        !          2422:        fileline();
        !          2423:        fprint(2, s, a, b, c, d, e, f);
        !          2424:        if(s[strlen(s)-1]!='\n')
        !          2425:                fprint(2, "\n");
        !          2426:        errflush();
        !          2427:        errjmp();
        !          2428: }
        !          2429: 
        !          2430: rerror(char *s, a, b, c, d, e, f)
        !          2431: {
        !          2432:        fileline();
        !          2433:        fprint(2, s, a, b, c, d, e, f);
        !          2434:        fprint(2, "\n");
        !          2435:        processes(0);
        !          2436:        errflush();
        !          2437:        errjmp();
        !          2438: }
        !          2439: 
        !          2440: warn(char *s, a, b, c, d, e, f)
        !          2441: {
        !          2442:        fileline();
        !          2443:        fprint(2, "warning: ");
        !          2444:        fprint(2, s, a, b, c, d, e, f);
        !          2445:        fprint(2, "\n");
        !          2446: }
        !          2447: 
        !          2448: panic(char *s, a, b, c, d, e, f)
        !          2449: {
        !          2450:        fileline();
        !          2451:        fprint(2, "internal error: ");
        !          2452:        fprint(2, s, a, b, c, d, e, f);
        !          2453:        fprint(2, "\n");
        !          2454:        abort();
        !          2455: }
        !          2456: 
        !          2457: rpanic(char *s, a, b, c, d, e, f)
        !          2458: {
        !          2459:        fileline();
        !          2460:        processes(0);
        !          2461:        fprint(2, "internal error: ");
        !          2462:        fprint(2, s, a, b, c, d, e, f);
        !          2463:        fprint(2, "\n");
        !          2464:        abort();
        !          2465: }
        !          2466: 
        !          2467: bconv(int *o, int f1, int f2)
        !          2468: {
        !          2469:        extern int printcol;
        !          2470:        while(printcol<*o-8)
        !          2471:                strconv("\t", f1, f2);
        !          2472:        strconv("        "+(8-(*o-printcol)), f1, f2);
        !          2473:        return sizeof(int);
        !          2474: }
        !          2475: 
        !          2476: nconv(int *o, int f1, int f2)
        !          2477: {
        !          2478:        if(*o<0 || sizeof(Ntypename)/sizeof(Ntypename[0])<=*o)
        !          2479:                strconv("mystery node", f1, f2);
        !          2480:        else
        !          2481:                strconv(Ntypename[*o], f1, f2);
        !          2482:        return sizeof(int);
        !          2483: }
        !          2484: 
        !          2485: tconv(int *o, int f1, int f2)
        !          2486: {
        !          2487:        if(*o<0 || sizeof(Ttypename)/sizeof(Ttypename[0])<=*o)
        !          2488:                strconv("mystery type", f1, f2);
        !          2489:        else
        !          2490:                strconv(Ttypename[*o], f1, f2);
        !          2491:        return sizeof(int);
        !          2492: }
        !          2493: 
        !          2494: char   bufx[128][10];
        !          2495: int    bufno=9;
        !          2496: 
        !          2497: char *
        !          2498: prbuf(){
        !          2499:        if(++bufno==10)
        !          2500:                bufno=0;
        !          2501:        return bufx[bufno];
        !          2502: }
        !          2503: 
        !          2504: econv(int *o, int f1, int f2)
        !          2505: {
        !          2506:        char *buf=prbuf();
        !          2507:        char *x;
        !          2508:        int t=*o;
        !          2509:        if(t<128 && strchr("+-*/%|&^~?!><=", t))
        !          2510:                sprint(buf, "%c", t);
        !          2511:        else{
        !          2512:                switch(t){
        !          2513:                case GE:
        !          2514:                        x=">=";
        !          2515:                        break;
        !          2516:                case LE:
        !          2517:                        x="<=";
        !          2518:                        break;
        !          2519:                case NE:
        !          2520:                        x="!=";
        !          2521:                        break;
        !          2522:                case EQ:
        !          2523:                        x="==";
        !          2524:                        break;
        !          2525:                case ANDAND:
        !          2526:                        x="&&";
        !          2527:                        break;
        !          2528:                case OROR:
        !          2529:                        x="||";
        !          2530:                        break;
        !          2531:                case REF:
        !          2532:                        x="ref";
        !          2533:                        break;
        !          2534:                case LEN:
        !          2535:                        x="len";
        !          2536:                        break;
        !          2537:                case UMINUS:
        !          2538:                        x="unary -";
        !          2539:                        break;
        !          2540:                case RCV:
        !          2541:                        x="rcv";
        !          2542:                        break;
        !          2543:                case SND:
        !          2544:                        x="send";
        !          2545:                        break;
        !          2546:                case LSH:
        !          2547:                        x="<<";
        !          2548:                        break;
        !          2549:                case RSH:
        !          2550:                        x=">>";
        !          2551:                        break;
        !          2552:                case DEC:
        !          2553:                        x="--";
        !          2554:                        break;
        !          2555:                case INC:
        !          2556:                        x="++";
        !          2557:                        break;
        !          2558:                default:
        !          2559:                        x="mystery expression";
        !          2560:                        break;
        !          2561:                }
        !          2562:                strcpy(buf, x);
        !          2563:        }
        !          2564:        strconv(buf, f1, f2);
        !          2565:        return sizeof(int);
        !          2566: }
        !          2567: 
        !          2568: mconv(int *o, int f1, int f2)
        !          2569: {
        !          2570:        char *buf=prbuf();
        !          2571:        Node *n=(Node *)*o;
        !          2572:        switch(n->t){

unix.superglobalmegacorp.com

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