Annotation of 3BSD/cmd/mip/reader.c, revision 1.1.1.1

1.1       root        1: # include "mfile2"
                      2: 
                      3: /*     some storage declarations */
                      4: 
                      5: # ifndef ONEPASS
                      6: NODE node[TREESZ];
                      7: char filename[100] = "";  /* the name of the file */
                      8: int ftnno;  /* number of current function */
                      9: int lineno;
                     10: # else
                     11: # define NOMAIN
                     12: #endif
                     13: 
                     14: int nrecur;
                     15: int lflag;
                     16: extern int Wflag;
                     17: int edebug = 0;
                     18: int xdebug = 0;
                     19: int udebug = 0;
                     20: 
                     21: OFFSZ tmpoff;  /* offset for first temporary, in bits for current block */
                     22: OFFSZ maxoff;  /* maximum temporary offset over all blocks in current ftn, in bits */
                     23: int maxtreg;
                     24: 
                     25: NODE *stotree;
                     26: int stocook;
                     27: 
                     28: OFFSZ baseoff = 0;
                     29: OFFSZ maxtemp = 0;
                     30: 
                     31: p2init( argc, argv ) char *argv[];{
                     32:        /* set the values of the pass 2 arguments */
                     33: 
                     34:        register int c;
                     35:        register char *cp;
                     36:        register files;
                     37: 
                     38:        allo0();  /* free all regs */
                     39:        files = 0;
                     40: 
                     41:        for( c=1; c<argc; ++c ){
                     42:                if( *(cp=argv[c]) == '-' ){
                     43:                        while( *++cp ){
                     44:                                switch( *cp ){
                     45: 
                     46:                                case 'X':  /* pass1 flags */
                     47:                                        while( *++cp ) { /* VOID */ }
                     48:                                        --cp;
                     49:                                        break;
                     50: 
                     51:                                case 'l':  /* linenos */
                     52:                                        ++lflag;
                     53:                                        break;
                     54: 
                     55:                                case 'W': /*Shut up warning: etc. */
                     56:                                        ++Wflag;
                     57:                                        break;
                     58: 
                     59:                                case 'e':  /* expressions */
                     60:                                        ++edebug;
                     61:                                        break;
                     62: 
                     63:                                case 'o':  /* orders */
                     64:                                        ++odebug;
                     65:                                        break;
                     66: 
                     67:                                case 'r':  /* register allocation */
                     68:                                        ++rdebug;
                     69:                                        break;
                     70: 
                     71:                                case 'a':  /* rallo */
                     72:                                        ++radebug;
                     73:                                        break;
                     74: 
                     75:                                case 't':  /* ttype calls */
                     76:                                        ++tdebug;
                     77:                                        break;
                     78: 
                     79:                                case 's':  /* shapes */
                     80:                                        ++sdebug;
                     81:                                        break;
                     82: 
                     83:                                case 'u':  /* Sethi-Ullman testing (machine dependent) */
                     84:                                        ++udebug;
                     85:                                        break;
                     86: 
                     87:                                case 'x':  /* general machine-dependent debugging flag */
                     88:                                        ++xdebug;
                     89:                                        break;
                     90: 
                     91:                                default:
                     92:                                        cerror( "bad option: %c", *cp );
                     93:                                        }
                     94:                                }
                     95:                        }
                     96:                else files = 1;  /* assumed to be a filename */
                     97:                }
                     98: 
                     99:        mkdope();
                    100:        setrew();
                    101:        return( files );
                    102: 
                    103:        }
                    104: 
                    105: # ifndef NOMAIN
                    106: 
                    107: mainp2( argc, argv ) char *argv[]; {
                    108:        register files;
                    109:        register temp;
                    110:        register c;
                    111:        register char *cp;
                    112:        register NODE *p;
                    113: 
                    114:        files = p2init( argc, argv );
                    115:        tinit();
                    116: 
                    117:        reread:
                    118: 
                    119:        if( files ){
                    120:                while( files < argc && argv[files][0] == '-' ) {
                    121:                        ++files;
                    122:                        }
                    123:                if( files > argc ) return( nerrors );
                    124:                freopen( argv[files], "r", stdin );
                    125:                }
                    126:        while( (c=getchar()) > 0 ) switch( c ){
                    127:        case ')':
                    128:                /* copy line unchanged */
                    129:                while( (c=getchar()) > 0 ){
                    130:                        PUTCHAR(c);
                    131:                        if( c == '\n' ) break;
                    132:                        }
                    133:                continue;
                    134: 
                    135:        case '[':
                    136:                /* beginning of a block */
                    137:                temp = rdin(10);  /* ftnno */
                    138:                tmpoff = baseoff = rdin(10); /* autooff for block gives max offset of autos in block */
                    139:                maxtreg = rdin(10);
                    140:                if( getchar() != '\n' ) cerror( "intermediate file format error");
                    141: 
                    142:                if( temp != ftnno ){ /* beginning of function */
                    143:                        maxoff = baseoff;
                    144:                        ftnno = temp;
                    145:                        maxtemp = 0;
                    146:                        }
                    147:                else {
                    148:                        if( baseoff > maxoff ) maxoff = baseoff;
                    149:                        /* maxoff at end of ftn is max of autos and temps
                    150:                           over all blocks in the function */
                    151:                        }
                    152:                setregs();
                    153:                continue;
                    154: 
                    155:        case ']':  /* end of block */
                    156:                SETOFF( maxoff, ALSTACK );
                    157:                eobl2();
                    158:                while( (c=getchar()) != '\n' ){
                    159:                        if( c <= 0 ) cerror( "intermediate file format eof" );
                    160:                        }
                    161:                continue;
                    162: 
                    163:        case '.':
                    164:                /* compile code for an expression */
                    165:                lineno = rdin( 10 );
                    166:                for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */
                    167:                *cp = '\0';
                    168:                if( lflag ) lineid( lineno, filename );
                    169: 
                    170:                tmpoff = baseoff;  /* expression at top level reuses temps */
                    171:                p = eread();
                    172: 
                    173:                if( edebug ) fwalk( p, eprint, 0 );
                    174: 
                    175: # ifdef MYREADER
                    176:                MYREADER(p);  /* do your own laundering of the input */
                    177: # endif
                    178: 
                    179:                nrecur = 0;
                    180:                delay( p );  /* expression statement  throws out results */
                    181:                reclaim( p, RNULL, 0 );
                    182: 
                    183:                allchk();
                    184:                tcheck();
                    185:                continue;
                    186: 
                    187:        default:
                    188:                cerror( "intermediate file format error" );
                    189: 
                    190:                }
                    191: 
                    192:        /* EOF */
                    193:        if( files ) goto reread;
                    194:        return(nerrors);
                    195: 
                    196:        }
                    197: 
                    198: # endif
                    199: 
                    200: # ifdef ONEPASS
                    201: 
                    202: p2compile( p ) NODE *p; {
                    203: 
                    204:        if( lflag ) lineid( lineno, filename );
                    205:        tmpoff = baseoff;  /* expression at top level reuses temps */
                    206:        /* generate code for the tree p */
                    207:        if( edebug ) fwalk( p, eprint, 0 );
                    208: 
                    209: # ifdef MYREADER
                    210:        MYREADER(p);  /* do your own laundering of the input */
                    211: # endif
                    212:        nrecur = 0;
                    213:        delay( p );  /* do the code generation */
                    214:        reclaim( p, RNULL, 0 );
                    215:        allchk();
                    216:        /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */
                    217:        /* first pass will do it... */
                    218:        }
                    219: 
                    220: p2bbeg( aoff, myreg ) {
                    221:        static int myftn = -1;
                    222:        tmpoff = baseoff = aoff;
                    223:        maxtreg = myreg;
                    224:        if( myftn != ftnno ){ /* beginning of function */
                    225:                maxoff = baseoff;
                    226:                myftn = ftnno;
                    227:                maxtemp = 0;
                    228:                }
                    229:        else {
                    230:                if( baseoff > maxoff ) maxoff = baseoff;
                    231:                /* maxoff at end of ftn is max of autos and temps over all blocks */
                    232:                }
                    233:        setregs();
                    234:        }
                    235: 
                    236: p2bend(){
                    237:        SETOFF( maxoff, ALSTACK );
                    238:        eobl2();
                    239:        }
                    240: 
                    241: # endif
                    242: 
                    243: NODE *deltrees[DELAYS];
                    244: int deli;
                    245: 
                    246: delay( p ) register NODE *p; {
                    247:        /* look in all legal places for COMOP's and ++ and -- ops to delay */
                    248:        /* note; don't delay ++ and -- within calls or things like
                    249:        /* getchar (in their macro forms) will start behaving strangely */
                    250:        register i;
                    251: 
                    252:        /* look for visible COMOPS, and rewrite repeatedly */
                    253: 
                    254:        while( delay1( p ) ) { /* VOID */ }
                    255: 
                    256:        /* look for visible, delayable ++ and -- */
                    257: 
                    258:        deli = 0;
                    259:        delay2( p );
                    260:        codgen( p, FOREFF );  /* do what is left */
                    261:        for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF );  /* do the rest */
                    262:        }
                    263: 
                    264: delay1( p ) register NODE *p; {  /* look for COMOPS */
                    265:        register o, ty;
                    266: 
                    267:        o = p->op;
                    268:        ty = optype( o );
                    269:        if( ty == LTYPE ) return( 0 );
                    270:        else if( ty == UTYPE ) return( delay1( p->left ) );
                    271: 
                    272:        switch( o ){
                    273: 
                    274:        case QUEST:
                    275:        case ANDAND:
                    276:        case OROR:
                    277:                /* don't look on RHS */
                    278:                return( delay1(p->left ) );
                    279: 
                    280:        case COMOP:  /* the meat of the routine */
                    281:                delay( p->left );  /* completely evaluate the LHS */
                    282:                /* rewrite the COMOP */
                    283:                { register NODE *q;
                    284:                        q = p->right;
                    285:                        ncopy( p, p->right );
                    286:                        q->op = FREE;
                    287:                        }
                    288:                return( 1 );
                    289:                }
                    290: 
                    291:        return( delay1(p->left) || delay1(p->right ) );
                    292:        }
                    293: 
                    294: delay2( p ) register NODE *p; {
                    295: 
                    296:        /* look for delayable ++ and -- operators */
                    297: 
                    298:        register o, ty;
                    299:        o = p->op;
                    300:        ty = optype( o );
                    301: 
                    302:        switch( o ){
                    303: 
                    304:        case NOT:
                    305:        case QUEST:
                    306:        case ANDAND:
                    307:        case OROR:
                    308:        case CALL:
                    309:        case UNARY CALL:
                    310:        case STCALL:
                    311:        case UNARY STCALL:
                    312:        case FORTCALL:
                    313:        case UNARY FORTCALL:
                    314:        case COMOP:
                    315:        case CBRANCH:
                    316:                /* for the moment, don7t delay past a conditional context, or
                    317:                /* inside of a call */
                    318:                return;
                    319: 
                    320:        case UNARY MUL:
                    321:                /* if *p++, do not rewrite */
                    322:                if( autoincr( p ) ) return;
                    323:                break;
                    324: 
                    325:        case INCR:
                    326:        case DECR:
                    327:                if( deltest( p ) ){
                    328:                        if( deli < DELAYS ){
                    329:                                register NODE *q;
                    330:                                deltrees[deli++] = tcopy(p);
                    331:                                q = p->left;
                    332:                                p->right->op = FREE;  /* zap constant */
                    333:                                ncopy( p, q );
                    334:                                q->op = FREE;
                    335:                                return;
                    336:                                }
                    337:                        }
                    338: 
                    339:                }
                    340: 
                    341:        if( ty == BITYPE ) delay2( p->right );
                    342:        if( ty != LTYPE ) delay2( p->left );
                    343:        }
                    344: 
                    345: codgen( p, cookie ) NODE *p; {
                    346: 
                    347:        /* generate the code for p;
                    348:           order may call codgen recursively */
                    349:        /* cookie is used to describe the context */
                    350: 
                    351:        for(;;){
                    352:                canon(p);  /* creats OREG from * if possible and does sucomp */
                    353:                stotree = NIL;
                    354:                if( edebug ){
                    355:                        printf( "store called on:\n" );
                    356:                        fwalk( p, eprint, 0 );
                    357:                        }
                    358:                store(p);
                    359:                if( stotree==NIL ) break;
                    360: 
                    361:                /* because it's minimal, can do w.o. stores */
                    362: 
                    363:                order( stotree, stocook );
                    364:                }
                    365: 
                    366:        order( p, cookie );
                    367: 
                    368:        }
                    369: 
                    370: char *cnames[] = {
                    371:        "SANY",
                    372:        "SAREG",
                    373:        "STAREG",
                    374:        "SBREG",
                    375:        "STBREG",
                    376:        "SCC",
                    377:        "SNAME",
                    378:        "SCON",
                    379:        "SFLD",
                    380:        "SOREG",
                    381:        "STARNM",
                    382:        "STARREG",
                    383:        "INTEMP",
                    384:        "FORARG",
                    385:        "SWADD",
                    386:        0,
                    387:        };
                    388: 
                    389: prcook( cookie ){
                    390: 
                    391:        /* print a nice-looking description of cookie */
                    392: 
                    393:        int i, flag;
                    394: 
                    395:        if( cookie & SPECIAL ){
                    396:                if( cookie == SZERO ) printf( "SZERO" );
                    397:                else if( cookie == SONE ) printf( "SONE" );
                    398:                else if( cookie == SMONE ) printf( "SMONE" );
                    399:                else printf( "SPECIAL+%d", cookie & ~SPECIAL );
                    400:                return;
                    401:                }
                    402: 
                    403:        flag = 0;
                    404:        for( i=0; cnames[i]; ++i ){
                    405:                if( cookie & (1<<i) ){
                    406:                        if( flag ) printf( "|" );
                    407:                        ++flag;
                    408:                        printf( cnames[i] );
                    409:                        }
                    410:                }
                    411: 
                    412:        }
                    413: 
                    414: int odebug = 0;
                    415: 
                    416: order(p,cook) NODE *p; {
                    417: 
                    418:        register o, ty, m;
                    419:        int m1;
                    420:        int cookie;
                    421:        NODE *p1, *p2;
                    422: 
                    423:        /* by this time, p should be able to be generated without stores;
                    424:           the only question is how */
                    425: 
                    426:        again:
                    427: 
                    428:        cookie = cook;
                    429:        rcount();
                    430:        canon(p);
                    431:        rallo( p, p->rall );
                    432: 
                    433:        if( odebug ){
                    434:                printf( "order( %o, ", p );
                    435:                prcook( cookie );
                    436:                printf( " )\n" );
                    437:                fwalk( p, eprint, 0 );
                    438:                }
                    439: 
                    440:        o = p->op;
                    441:        ty = optype(o);
                    442: 
                    443:        /* first of all, for most ops, see if it is in the table */
                    444: 
                    445:        /* look for ops */
                    446: 
                    447:        switch( m = p->op ){
                    448: 
                    449:        default:
                    450:                /* look for op in table */
                    451:                for(;;){
                    452:                        if( (m = match( p, cookie ) ) == MDONE ) goto cleanup;
                    453:                        else if( m == MNOPE ){
                    454:                                if( !(cookie = nextcook( p, cookie ) ) ) goto nomat;
                    455:                                continue;
                    456:                                }
                    457:                        else break;
                    458:                        }
                    459:                break;
                    460: 
                    461:        case COMOP:
                    462:        case FORCE:
                    463:        case CBRANCH:
                    464:        case QUEST:
                    465:        case ANDAND:
                    466:        case OROR:
                    467:        case NOT:
                    468:        case UNARY CALL:
                    469:        case CALL:
                    470:        case UNARY STCALL:
                    471:        case STCALL:
                    472:        case UNARY FORTCALL:
                    473:        case FORTCALL:
                    474:                /* don't even go near the table... */
                    475:                ;
                    476: 
                    477:                }
                    478:        /* get here to do rewriting if no match or
                    479:           fall through from above for hard ops */
                    480: 
                    481:        p1 = p->left;
                    482:        if( ty == BITYPE ) p2 = p->right;
                    483:        else p2 = NIL;
                    484:        
                    485:        if( odebug ){
                    486:                printf( "order( %o, ", p );
                    487:                prcook( cook );
                    488:                printf( " ), cookie " );
                    489:                prcook( cookie );
                    490:                printf( ", rewrite %s\n", opst[m] );
                    491:                }
                    492:        switch( m ){
                    493:        default:
                    494:                nomat:
                    495:                cerror( "no table entry for op %s", opst[p->op] );
                    496: 
                    497:        case COMOP:
                    498:                codgen( p1, FOREFF );
                    499:                p2->rall = p->rall;
                    500:                codgen( p2, cookie );
                    501:                ncopy( p, p2 );
                    502:                p2->op = FREE;
                    503:                goto cleanup;
                    504: 
                    505:        case FORCE:
                    506:                /* recurse, letting the work be done by rallo */
                    507:                p = p->left;
                    508:                cook = INTAREG|INTBREG;
                    509:                goto again;
                    510: 
                    511:        case CBRANCH:
                    512:                o = p2->lval;
                    513:                cbranch( p1, -1, o );
                    514:                p2->op = FREE;
                    515:                p->op = FREE;
                    516:                return;
                    517: 
                    518:        case QUEST:
                    519:                cbranch( p1, -1, m=getlab() );
                    520:                p2->left->rall = p->rall;
                    521:                codgen( p2->left, INTAREG|INTBREG );
                    522:                /* force right to compute result into same reg used by left */
                    523:                p2->right->rall = p2->left->rval|MUSTDO;
                    524:                reclaim( p2->left, RNULL, 0 );
                    525:                cbgen( 0, m1 = getlab(), 'I' );
                    526:                deflab( m );
                    527:                codgen( p2->right, INTAREG|INTBREG );
                    528:                deflab( m1 );
                    529:                p->op = REG;  /* set up node describing result */
                    530:                p->lval = 0;
                    531:                p->rval = p2->right->rval;
                    532:                p->type = p2->right->type;
                    533:                tfree( p2->right );
                    534:                p2->op = FREE;
                    535:                goto cleanup;
                    536: 
                    537:        case ANDAND:
                    538:        case OROR:
                    539:        case NOT:  /* logical operators */
                    540:                /* if here, must be a logical operator for 0-1 value */
                    541:                cbranch( p, -1, m=getlab() );
                    542:                p->op = CCODES;
                    543:                p->label = m;
                    544:                order( p, INTAREG );
                    545:                goto cleanup;
                    546: 
                    547:        case FLD:       /* fields of funny type */
                    548:                if ( p1->op == UNARY MUL ){
                    549:                        offstar( p1->left );
                    550:                        goto again;
                    551:                        }
                    552: 
                    553:        case UNARY MINUS:
                    554:                order( p1, INBREG|INAREG );
                    555:                goto again;
                    556: 
                    557:        case NAME:
                    558:                /* all leaves end up here ... */
                    559:                if( o == REG ) goto nomat;
                    560:                order( p, INTAREG|INTBREG );
                    561:                goto again;
                    562: 
                    563:        case INIT:
                    564:                uerror( "illegal initialization" );
                    565:                return;
                    566: 
                    567:        case UNARY FORTCALL:
                    568:                p->right = NIL;
                    569:        case FORTCALL:
                    570:                o = p->op = UNARY FORTCALL;
                    571:                if( genfcall( p, cookie ) ) goto nomat;
                    572:                goto cleanup;
                    573: 
                    574:        case UNARY CALL:
                    575:                p->right = NIL;
                    576:        case CALL:
                    577:                o = p->op = UNARY CALL;
                    578:                if( gencall( p, cookie ) ) goto nomat;
                    579:                goto cleanup;
                    580: 
                    581:        case UNARY STCALL:
                    582:                p->right = NIL;
                    583:        case STCALL:
                    584:                o = p->op = UNARY STCALL;
                    585:                if( genscall( p, cookie ) ) goto nomat;
                    586:                goto cleanup;
                    587: 
                    588:                /* if arguments are passed in register, care must be taken that reclaim
                    589:                /* not throw away the register which now has the result... */
                    590: 
                    591:        case UNARY MUL:
                    592:                if( cook == FOREFF ){
                    593:                        /* do nothing */
                    594:                        order( p->left, FOREFF );
                    595:                        p->op = FREE;
                    596:                        return;
                    597:                        }
                    598:                offstar( p->left );
                    599:                canon(p);
                    600:                if( canaddr(p) && cook != INTEMP ) goto cleanup;
                    601:                goto again;
                    602: 
                    603:        case INCR:  /* INCR and DECR */
                    604:                if( setincr(p) ) goto again;
                    605: 
                    606:                /* x++ becomes (x += 1) -1; */
                    607: 
                    608:                if( cook & FOREFF ){  /* result not needed so inc or dec and be done with it */
                    609:                        /* x++ => x += 1 */
                    610:                        p->op = (p->op==INCR)?ASG PLUS:ASG MINUS;
                    611:                        goto again;
                    612:                        }
                    613: 
                    614:                p1 = tcopy(p);
                    615:                reclaim( p->left, RNULL, 0 );
                    616:                p->left = p1;
                    617:                p1->op = (p->op==INCR)?ASG PLUS:ASG MINUS;
                    618:                p->op = (p->op==INCR)?MINUS:PLUS;
                    619:                goto again;
                    620: 
                    621:        case STASG:
                    622:                if( setstr( p ) ) goto again;
                    623:                goto nomat;
                    624: 
                    625:        case ASG PLUS:  /* and other assignment ops */
                    626:                if( setasop(p) ) goto again;
                    627: 
                    628:                /* there are assumed to be no side effects in LHS */
                    629: 
                    630:                p2 = tcopy(p);
                    631:                p->op = ASSIGN;
                    632:                reclaim( p->right, RNULL, 0 );
                    633:                p->right = p2;
                    634:                canon(p);
                    635:                rallo( p, p->rall );
                    636: 
                    637:                if( odebug ) fwalk( p, eprint, 0 );
                    638: 
                    639:                order( p2->left, INTBREG|INTAREG );
                    640:                order( p2, INTBREG|INTAREG );
                    641:                goto again;
                    642: 
                    643:        case ASSIGN:
                    644:                if( setasg( p ) ) goto again;
                    645:                goto nomat;
                    646: 
                    647: 
                    648:        case BITYPE:
                    649:                if( setbin( p ) ) goto again;
                    650:                /* try to replace binary ops by =ops */
                    651:                switch(o){
                    652: 
                    653:                case PLUS:
                    654:                case MINUS:
                    655:                case MUL:
                    656:                case DIV:
                    657:                case MOD:
                    658:                case AND:
                    659:                case OR:
                    660:                case ER:
                    661:                case LS:
                    662:                case RS:
                    663:                        p->op = ASG o;
                    664:                        goto again;
                    665:                        }
                    666:                goto nomat;
                    667: 
                    668:                }
                    669: 
                    670:        cleanup:
                    671: 
                    672:        /* if it is not yet in the right state, put it there */
                    673: 
                    674:        if( cook & FOREFF ){
                    675:                reclaim( p, RNULL, 0 );
                    676:                return;
                    677:                }
                    678: 
                    679:        if( p->op==FREE ) return;
                    680: 
                    681:        if( tshape( p, cook ) ) return;
                    682: 
                    683:        if( (m=match(p,cook) ) == MDONE ) return;
                    684: 
                    685:        /* we are in bad shape, try one last chance */
                    686:        if( lastchance( p, cook ) ) goto again;
                    687: 
                    688:        goto nomat;
                    689:        }
                    690: 
                    691: int callflag;
                    692: int fregs;
                    693: 
                    694: store( p ) register NODE *p; {
                    695: 
                    696:        /* find a subtree of p which should be stored */
                    697: 
                    698:        register o, ty;
                    699: 
                    700:        o = p->op;
                    701:        ty = optype(o);
                    702: 
                    703:        if( ty == LTYPE ) return;
                    704: 
                    705:        switch( o ){
                    706: 
                    707:        case UNARY CALL:
                    708:        case UNARY FORTCALL:
                    709:        case UNARY STCALL:
                    710:                ++callflag;
                    711:                break;
                    712: 
                    713:        case UNARY MUL:
                    714:                if( asgop(p->left->op) ) stoasg( p->left, UNARY MUL );
                    715:                break;
                    716: 
                    717:        case CALL:
                    718:        case FORTCALL:
                    719:        case STCALL:
                    720:                store( p->left );
                    721:                stoarg( p->right, o );
                    722:                ++callflag;
                    723:                return;
                    724: 
                    725:        case COMOP:
                    726:                markcall( p->right );
                    727:                if( p->right->su > fregs ) SETSTO( p, INTEMP );
                    728:                store( p->left );
                    729:                return;
                    730: 
                    731:        case ANDAND:
                    732:        case OROR:
                    733:        case QUEST:
                    734:                markcall( p->right );
                    735:                if( p->right->su > fregs ) SETSTO( p, INTEMP );
                    736:        case CBRANCH:   /* to prevent complicated expressions on the LHS from being stored */
                    737:        case NOT:
                    738:                constore( p->left );
                    739:                return;
                    740: 
                    741:                }
                    742: 
                    743:        if( ty == UTYPE ){
                    744:                store( p->left );
                    745:                return;
                    746:                }
                    747: 
                    748:        if( asgop( p->right->op ) ) stoasg( p->right, o );
                    749: 
                    750:        if( p->su>fregs ){ /* must store */
                    751:                mkadrs( p );  /* set up stotree and stocook to subtree
                    752:                                 that must be stored */
                    753:                }
                    754: 
                    755:        store( p->right );
                    756:        store( p->left );
                    757:        }
                    758: 
                    759: constore( p ) register NODE *p; {
                    760: 
                    761:        /* store conditional expressions */
                    762:        /* the point is, avoid storing expressions in conditional
                    763:           conditional context, since the evaluation order is predetermined */
                    764: 
                    765:        switch( p->op ) {
                    766: 
                    767:        case ANDAND:
                    768:        case OROR:
                    769:        case QUEST:
                    770:                markcall( p->right );
                    771:        case NOT:
                    772:                constore( p->left );
                    773:                return;
                    774: 
                    775:                }
                    776: 
                    777:        store( p );
                    778:        }
                    779: 
                    780: markcall( p ) register NODE *p; {  /* mark off calls below the current node */
                    781: 
                    782:        again:
                    783:        switch( p->op ){
                    784: 
                    785:        case UNARY CALL:
                    786:        case UNARY STCALL:
                    787:        case UNARY FORTCALL:
                    788:        case CALL:
                    789:        case STCALL:
                    790:        case FORTCALL:
                    791:                ++callflag;
                    792:                return;
                    793: 
                    794:                }
                    795: 
                    796:        switch( optype( p->op ) ){
                    797: 
                    798:        case BITYPE:
                    799:                markcall( p->right );
                    800:        case UTYPE:
                    801:                p = p->left;
                    802:                /* eliminate recursion (aren't I clever...) */
                    803:                goto again;
                    804:        case LTYPE:
                    805:                return;
                    806:                }
                    807: 
                    808:        }
                    809: 
                    810: stoarg( p, calltype ) register NODE *p; {
                    811:        /* arrange to store the args */
                    812: 
                    813:        if( p->op == CM ){
                    814:                stoarg( p->left, calltype );
                    815:                p = p->right ;
                    816:                }
                    817:        if( calltype == CALL ){
                    818:                STOARG(p);
                    819:                }
                    820:        else if( calltype == STCALL ){
                    821:                STOSTARG(p);
                    822:                }
                    823:        else {
                    824:                STOFARG(p);
                    825:                }
                    826:        callflag = 0;
                    827:        store(p);
                    828: # ifndef NESTCALLS
                    829:        if( callflag ){ /* prevent two calls from being active at once  */
                    830:                SETSTO(p,INTEMP);
                    831:                store(p); /* do again to preserve bottom up nature....  */
                    832:                }
                    833: #endif
                    834:        }
                    835: 
                    836: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;  /* negatives of relationals */
                    837: 
                    838: cbranch( p, true, false ) NODE *p; {
                    839:        /* evaluate p for truth value, and branch to true or false
                    840:        /* accordingly: label <0 means fall through */
                    841: 
                    842:        register o, lab, flab, tlab;
                    843: 
                    844:        lab = -1;
                    845: 
                    846:        switch( o=p->op ){
                    847: 
                    848:        case ULE:
                    849:        case ULT:
                    850:        case UGE:
                    851:        case UGT:
                    852:        case EQ:
                    853:        case NE:
                    854:        case LE:
                    855:        case LT:
                    856:        case GE:
                    857:        case GT:
                    858:                if( true < 0 ){
                    859:                        o = p->op = negrel[ o-EQ ];
                    860:                        true = false;
                    861:                        false = -1;
                    862:                        }
                    863: #ifndef NOOPT
                    864:                if( p->right->op == ICON && p->right->lval == 0 && p->right->name[0] == '\0' ){
                    865:                        switch( o ){
                    866: 
                    867:                        case UGT:
                    868:                        case ULE:
                    869:                                o = p->op = (o==UGT)?NE:EQ;
                    870:                        case EQ:
                    871:                        case NE:
                    872:                        case LE:
                    873:                        case LT:
                    874:                        case GE:
                    875:                        case GT:
                    876:                                if( logop(p->left->op) ){
                    877:                                        /* strange situation: e.g., (a!=0) == 0 */
                    878:                                        /* must prevent reference to p->left->lable, so get 0/1 */
                    879:                                        /* we could optimize, but why bother */
                    880:                                        codgen( p->left, INAREG|INBREG );
                    881:                                        }
                    882:                                codgen( p->left, FORCC );
                    883:                                cbgen( o, true, 'I' );
                    884:                                break;
                    885: 
                    886:                        case UGE:
                    887:                                cbgen( 0, true, 'I' );  /* unconditional branch */
                    888:                        case ULT:
                    889:                                ;   /* do nothing for LT */
                    890:                                }
                    891:                        }
                    892:                else
                    893: #endif
                    894:                        {
                    895:                        p->label = true;
                    896:                        codgen( p, FORCC );
                    897:                        }
                    898:                if( false>=0 ) cbgen( 0, false, 'I' );
                    899:                reclaim( p, RNULL, 0 );
                    900:                return;
                    901: 
                    902:        case ANDAND:
                    903:                lab = false<0 ? getlab() : false ;
                    904:                cbranch( p->left, -1, lab );
                    905:                cbranch( p->right, true, false );
                    906:                if( false < 0 ) deflab( lab );
                    907:                p->op = FREE;
                    908:                return;
                    909: 
                    910:        case OROR:
                    911:                lab = true<0 ? getlab() : true;
                    912:                cbranch( p->left, lab, -1 );
                    913:                cbranch( p->right, true, false );
                    914:                if( true < 0 ) deflab( lab );
                    915:                p->op = FREE;
                    916:                return;
                    917: 
                    918:        case NOT:
                    919:                cbranch( p->left, false, true );
                    920:                p->op = FREE;
                    921:                break;
                    922: 
                    923:        case COMOP:
                    924:                codgen( p->left, FOREFF );
                    925:                p->op = FREE;
                    926:                cbranch( p->right, true, false );
                    927:                return;
                    928: 
                    929:        case QUEST:
                    930:                flab = false<0 ? getlab() : false;
                    931:                tlab = true<0 ? getlab() : true;
                    932:                cbranch( p->left, -1, lab = getlab() );
                    933:                cbranch( p->right->left, tlab, flab );
                    934:                deflab( lab );
                    935:                cbranch( p->right->right, true, false );
                    936:                if( true < 0 ) deflab( tlab);
                    937:                if( false < 0 ) deflab( flab );
                    938:                p->right->op = FREE;
                    939:                p->op = FREE;
                    940:                return;
                    941: 
                    942:        case ICON:
                    943:                if( p->type != FLOAT && p->type != DOUBLE ){
                    944: 
                    945:                        if( p->lval || p->name[0] ){
                    946:                                /* addresses of C objects are never 0 */
                    947:                                if( true>=0 ) cbgen( 0, true, 'I' );
                    948:                                }
                    949:                        else if( false>=0 ) cbgen( 0, false, 'I' );
                    950:                        p->op = FREE;
                    951:                        return;
                    952:                        }
                    953:                /* fall through to default with other strange constants */
                    954: 
                    955:        default:
                    956:                /* get condition codes */
                    957:                codgen( p, FORCC );
                    958:                if( true >= 0 ) cbgen( NE, true, 'I' );
                    959:                if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' );
                    960:                reclaim( p, RNULL, 0 );
                    961:                return;
                    962: 
                    963:                }
                    964: 
                    965:        }
                    966: 
                    967: rcount(){ /* count recursions */
                    968:        if( ++nrecur > NRECUR ){
                    969:                cerror( "expression causes compiler loop: try simplifying" );
                    970:                }
                    971: 
                    972:        }
                    973: 
                    974: eprint( p, down, a, b ) NODE *p; int *a, *b; {
                    975: 
                    976:        *a = *b = down+1;
                    977:        while( down >= 2 ){
                    978:                printf( "\t" );
                    979:                down -= 2;
                    980:                }
                    981:        if( down-- ) printf( "    " );
                    982: 
                    983: 
                    984:        printf( "%o) %s", p, opst[p->op] );
                    985:        switch( p->op ) { /* special cases */
                    986: 
                    987:        case REG:
                    988:                printf( " %s", rnames[p->rval] );
                    989:                break;
                    990: 
                    991:        case ICON:
                    992:        case NAME:
                    993:        case OREG:
                    994:                printf( " " );
                    995:                adrput( p );
                    996:                break;
                    997: 
                    998:        case STCALL:
                    999:        case UNARY STCALL:
                   1000:        case STARG:
                   1001:        case STASG:
                   1002:                printf( " size=%d", p->stsize );
                   1003:                printf( " align=%d", p->stalign );
                   1004:                break;
                   1005:                }
                   1006: 
                   1007:        printf( ", " );
                   1008:        tprint( p->type );
                   1009:        printf( ", " );
                   1010:        if( p->rall == NOPREF ) printf( "NOPREF" );
                   1011:        else {
                   1012:                if( p->rall & MUSTDO ) printf( "MUSTDO " );
                   1013:                else printf( "PREF " );
                   1014:                printf( "%s", rnames[p->rall&~MUSTDO]);
                   1015:                }
                   1016:        printf( ", SU= %d\n", p->su );
                   1017: 
                   1018:        }
                   1019: 
                   1020: # ifndef NOMAIN
                   1021: NODE *
                   1022: eread(){
                   1023: 
                   1024:        /* call eread recursively to get subtrees, if any */
                   1025: 
                   1026:        register NODE *p;
                   1027:        register i, c;
                   1028:        register char *pc;
                   1029:        register j;
                   1030: 
                   1031:        i = rdin( 10 );
                   1032: 
                   1033:        p = talloc();
                   1034: 
                   1035:        p->op = i;
                   1036: 
                   1037:        i = optype(i);
                   1038: 
                   1039:        if( i == LTYPE ) p->lval = rdin( 10 );
                   1040:        if( i != BITYPE ) p->rval = rdin( 10 );
                   1041: 
                   1042:        p->type = rdin(8 );
                   1043:        p->rall = NOPREF;  /* register allocation information */
                   1044: 
                   1045:        if( p->op == STASG || p->op == STARG || p->op == STCALL || p->op == UNARY STCALL ){
                   1046:                p->stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR;
                   1047:                p->stalign = rdin(10) / SZCHAR;
                   1048:                if( getchar() != '\n' ) cerror( "illegal \n" );
                   1049:                }
                   1050:        else {   /* usual case */
                   1051:                if( p->op == REG ) rbusy( p->rval, p->type );  /* non usually, but sometimes justified */
                   1052:                for( pc=p->name,j=0; ( c = getchar() ) != '\n'; ++j ){
                   1053:                        if( j < NCHNAM ) *pc++ = c;
                   1054:                        }
                   1055:                if( j < NCHNAM ) *pc = '\0';
                   1056:                }
                   1057: 
                   1058:        /* now, recursively read descendents, if any */
                   1059: 
                   1060:        if( i != LTYPE ) p->left = eread();
                   1061:        if( i == BITYPE ) p->right = eread();
                   1062: 
                   1063:        return( p );
                   1064: 
                   1065:        }
                   1066: 
                   1067: CONSZ
                   1068: rdin( base ){
                   1069:        register sign, c;
                   1070:        CONSZ val;
                   1071: 
                   1072:        sign = 1;
                   1073:        val = 0;
                   1074: 
                   1075:        while( (c=getchar()) > 0 ) {
                   1076:                if( c == '-' ){
                   1077:                        if( val != 0 ) cerror( "illegal -");
                   1078:                        sign = -sign;
                   1079:                        continue;
                   1080:                        }
                   1081:                if( c == '\t' ) break;
                   1082:                if( c>='0' && c<='9' ) {
                   1083:                        val *= base;
                   1084:                        if( sign > 0 )
                   1085:                                val += c-'0';
                   1086:                        else
                   1087:                                val -= c-'0';
                   1088:                        continue;
                   1089:                        }
                   1090:                cerror( "illegal character `%c' on intermediate file", c );
                   1091:                break;
                   1092:                }
                   1093: 
                   1094:        if( c <= 0 ) {
                   1095:                cerror( "unexpected EOF");
                   1096:                }
                   1097:        return( val );
                   1098:        }
                   1099: # endif
                   1100: 
                   1101: #ifndef FIELDOPS
                   1102:        /* do this if there is no special hardware support for fields */
                   1103: 
                   1104: ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; {
                   1105:         /* look for fields that are not in an lvalue context, and rewrite them... */
                   1106:        register NODE *shp;
                   1107:        register s, o, v, ty;
                   1108: 
                   1109:        *down1 =  asgop( p->op );
                   1110:        *down2 = 0;
                   1111: 
                   1112:        if( !down && p->op == FLD ){ /* rewrite the node */
                   1113: 
                   1114:                if( !rewfld(p) ) return;
                   1115: 
                   1116:                ty = (szty(p->type) == 2)? LONG: INT;
                   1117:                v = p->rval;
                   1118:                s = UPKFSZ(v);
                   1119: # ifdef RTOLBYTES
                   1120:                o = UPKFOFF(v);  /* amount to shift */
                   1121: # else
                   1122:                o = szty(p->type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
                   1123: #endif
                   1124: 
                   1125:                /* make & mask part */
                   1126: 
                   1127:                p->left->type = ty;
                   1128: 
                   1129:                p->op = AND;
                   1130:                p->right = talloc();
                   1131:                p->right->op = ICON;
                   1132:                p->right->rall = NOPREF;
                   1133:                p->right->type = ty;
                   1134:                p->right->lval = 1;
                   1135:                p->right->rval = 0;
                   1136:                p->right->name[0] = '\0';
                   1137:                p->right->lval <<= s;
                   1138:                p->right->lval--;
                   1139: 
                   1140:                /* now, if a shift is needed, do it */
                   1141: 
                   1142:                if( o != 0 ){
                   1143:                        shp = talloc();
                   1144:                        shp->op = RS;
                   1145:                        shp->rall = NOPREF;
                   1146:                        shp->type = ty;
                   1147:                        shp->left = p->left;
                   1148:                        shp->right = talloc();
                   1149:                        shp->right->op = ICON;
                   1150:                        shp->right->rall = NOPREF;
                   1151:                        shp->right->type = ty;
                   1152:                        shp->right->rval = 0;
                   1153:                        shp->right->lval = o;  /* amount to shift */
                   1154:                        shp->right->name[0] = '\0';
                   1155:                        p->left = shp;
                   1156:                        /* whew! */
                   1157:                        }
                   1158:                }
                   1159:        }
                   1160: #endif
                   1161: 
                   1162: oreg2( p ) register NODE *p; {
                   1163: 
                   1164:        /* look for situations where we can turn * into OREG */
                   1165: 
                   1166:        NODE *q;
                   1167:        register i;
                   1168:        register r;
                   1169:        register char *cp;
                   1170:        register NODE *ql, *qr;
                   1171:        CONSZ temp;
                   1172: 
                   1173:        if( p->op == UNARY MUL ){
                   1174:                q = p->left;
                   1175:                if( q->op == REG ){
                   1176:                        temp = q->lval;
                   1177:                        r = q->rval;
                   1178:                        cp = q->name;
                   1179:                        goto ormake;
                   1180:                        }
                   1181: 
                   1182:                if( q->op != PLUS && q->op != MINUS ) return;
                   1183:                ql = q->left;
                   1184:                qr = q->right;
                   1185: 
                   1186: #ifdef R2REGS
                   1187: 
                   1188:                /* look for doubly indexed expressions */
                   1189: 
                   1190:                if( q->op == PLUS) {
                   1191:                        if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
                   1192:                                makeor2(p, ql, r, i);
                   1193:                                return;
                   1194:                        } else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
                   1195:                                makeor2(p, qr, r, i);
                   1196:                                return;
                   1197:                                }
                   1198:                        }
                   1199: 
                   1200: 
                   1201: #endif
                   1202: 
                   1203:                if( (q->op==PLUS || q->op==MINUS) && qr->op == ICON &&
                   1204:                                ql->op==REG && szty(qr->type)==1) {
                   1205:                        temp = qr->lval;
                   1206:                        if( q->op == MINUS ) temp = -temp;
                   1207:                        r = ql->rval;
                   1208:                        temp += ql->lval;
                   1209:                        cp = qr->name;
                   1210:                        if( *cp && ( q->op == MINUS || *ql->name ) ) return;
                   1211:                        if( !*cp ) cp = ql->name;
                   1212: 
                   1213:                        ormake:
                   1214:                        if( notoff( p->type, r, temp, cp ) ) return;
                   1215:                        p->op = OREG;
                   1216:                        p->rval = r;
                   1217:                        p->lval = temp;
                   1218:                        for( i=0; i<NCHNAM; ++i )
                   1219:                                p->name[i] = *cp++;
                   1220:                        tfree(q);
                   1221:                        return;
                   1222:                        }
                   1223:                }
                   1224: 
                   1225:        }
                   1226: 
                   1227: canon(p) NODE *p; {
                   1228:        /* put p in canonical form */
                   1229:        int oreg2(), sucomp();
                   1230: 
                   1231: #ifndef FIELDOPS
                   1232:        int ffld();
                   1233:        fwalk( p, ffld, 0 ); /* look for field operators */
                   1234: # endif
                   1235:        walkf( p, oreg2 );  /* look for and create OREG nodes */
                   1236: #ifdef MYCANON
                   1237:        MYCANON(p);  /* your own canonicalization routine(s) */
                   1238: #endif
                   1239:        walkf( p, sucomp );  /* do the Sethi-Ullman computation */
                   1240: 
                   1241:        }
                   1242: 

unix.superglobalmegacorp.com

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