Annotation of researchv9/jerq/sgs/optim/func.c, revision 1.1.1.1

1.1       root        1: /* @(#) func.c: 1.4 4/28/84                            */
                      2: 
                      3: /* func.c
                      4: **
                      5: **     Function improvement routines
                      6: **
                      7: **
                      8: **     This file contains routines that require knowledge of a whole
                      9: **     function or more to perform their optimizations.
                     10: */
                     11: 
                     12: #include "optim.h"
                     13: #include "optutil.h"
                     14: #include "storclass.h"
                     15: #include <string.h>
                     16: #include "paths.h"
                     17: 
                     18: /* Macro to add new instruction:
                     19: **     opn     op code number of new instruction
                     20: **     opst    op code string of new instruction
                     21: **     opn1    operand 1 for new instruction
                     22: **     opn2    operand 2 for new instruction
                     23: */
                     24: 
                     25: #define addi(opn,opst,opn1,opn2) \
                     26:        { \
                     27:                pn = insert( pn );              /* get new node */ \
                     28:                chgop( pn, opn, opst );         /* put in opcode num, str */ \
                     29:                pn->op1 = opn1;                 /* put in operands */ \
                     30:                pn->op2 = opn2;                 \
                     31:        }
                     32: #define opm    ops[MAXOPS]
                     33: 
                     34: #ifdef IMPREGAL
                     35: /* register allocation optimization
                     36: **
                     37: ** F. B. Wolverton 6/16/83
                     38: **
                     39: ** This optimization accepts a list of autos and args from the
                     40: ** compiler and assigns them to registers if there is sufficient estimated
                     41: ** payoff.  
                     42: **
                     43: ** Scratch registers are used first, if they are available, 
                     44: ** because they are "free".  A variable can be put into a scratch register if
                     45: **     (a) the register is not used by any instruction in the procedure,
                     46: **     (b) the variable is dead, i.e., not used before being set, 
                     47: **          following any call in the procedure
                     48: ** 
                     49: ** Register 3 is considered a scratch register, if IMPSCRATCH is defined.
                     50: **
                     51: ** Next registers r8 through r4 are assigned (and r3, if it has not been used
                     52: ** as a scratch register).
                     53: **
                     54: ** Register variables assigned by the compiler are assigned first.  A variable
                     55: ** the compiler assigned to a user register may get assigned to a scratch 
                     56: ** register by the optimizer.
                     57: ** 
                     58: ** Variables in the list of autos and args are assigned next.
                     59: ** 
                     60: ** The cumulative cost for puting all variables up to a given variable
                     61: ** into registers is computed and used to select a cutoff.
                     62: ** All register variables assigned by the compiler remain in 
                     63: ** registers.  Other variables are assigned only if the
                     64: ** estimated payoff os positive.
                     65: ** 
                     66: ** Instruction operands are modified to reflect the additional assignments.
                     67: **
                     68: */
                     69: 
                     70: #define MAXREGS 10
                     71: #define MAXVARS 20
                     72: 
                     73: /* variable storage classes */
                     74: 
                     75: #define SCLNULL 0
                     76: #define AUTO 1
                     77: #define REGISTER 4
                     78: #define PARAM 9
                     79: 
                     80: /* register types */
                     81: 
                     82: #define SCRATCH 0
                     83: #define USER 1
                     84: 
                     85: /* register status */
                     86: 
                     87: #define AVAIL 0
                     88: #define NOTAVAIL 1
                     89: 
                     90: /* cycle estimates for BELLMAC-32B instructions */
                     91: 
                     92: #define CYCSAVE 39     /* SAVE and RESTORE with 0 user registers */
                     93: #define CYCDELTA 5     /* delta to save and restore an additional register */
                     94: #define CYCADD 6       /* ADD small literal to stack pointer */
                     95: #define CYCMOVS 16     /* MOVW from register to register offset and back */
                     96: #define CYCAWORD 7     /* MOVAW of register offset to frame pointer */
                     97: #define CYCPUSH 10     /* PUSH a regsiter */
                     98: #define CYCPOP 10      /* POPW a value into a register */
                     99: 
                    100: struct hinode { /* ordered table of variables with highest estimators */
                    101:        int     hiestim;                /* estimator of cycle payoff */
                    102:        int     hiscl;                  /* scl of quant to put in reg */
                    103:        char*   hiname;                 /* name of quantity:
                    104:                                         *      local           offset 
                    105:                                         *      argument        offset*/
                    106:        int     hilen;                  /* length in bytes of quantity */
                    107: } high[MAXVARS];
                    108: 
                    109: int vars = 0;          /* number of variables stored in 'high' array */
                    110: int nodblflg = 0;      /* flag indicating absence of doubles */
                    111: 
                    112: struct assign {
                    113:        char *asrname;  /* register name */
                    114:        char *asrind;   /* indirect reference through register */
                    115:        int asrtype;    /* register type */
                    116:        int asrsave;    /* number of user registers saved */
                    117:        int asavail;    /* availabilty of register */
                    118:        int asestim;    /* estimator of cycle payoff of assigned variable */
                    119:        int asvscl;     /* storage class of variable assigned */
                    120:        char *asvname;  /* variable name */
                    121:        int asvlen;     /* variable lenggth in bytes */
                    122: } asreg[MAXREGS] = {
                    123:        { "%r0", "0(%r0)", SCRATCH, 0 },
                    124:        { "%r1", "0(%r1)", SCRATCH, 0 },
                    125:        { "%r2", "0(%r2)", SCRATCH, 0 },
                    126:        { "%r3", "0(%r3)", SCRATCH, 0 },
                    127:        { "%r8", "0(%r8)", USER, 1 },
                    128:        { "%r7", "0(%r7)", USER, 2 },
                    129:        { "%r6", "0(%r6)", USER, 3 },
                    130:        { "%r5", "0(%r5)", USER, 4 },
                    131:        { "%r4", "0(%r4)", USER, 5 },
                    132:        { "%r3", "0(%r3)", USER, 6 }
                    133: };
                    134: 
                    135: /* Note that register 3 appears twice.  It is used as a scratch register if 
                    136: ** possible and as a user register otherwise. 
                    137: */
                    138: 
                    139: char* rnames[] = { "%r8", "%r7", "%r6", "%r5", "%r4", "%r3" };
                    140: 
                    141: 
                    142: /* routine to read in table of variables stored in high[] */
                    143: 
                    144: void
                    145: ratable( p )
                    146: register char *p;
                    147: 
                    148: {
                    149:        extern int atoi();
                    150:        register char *q, *r;
                    151: 
                    152:        /* check for table overflow */
                    153:        if( vars >= MAXVARS ) return;
                    154: 
                    155:        /* scan to estimator and read it */
                    156:        while( *p++ != '\t' );
                    157:        high[vars].hiestim = atoi( p );
                    158: 
                    159:        /* scan to storage class and read it */
                    160:        while( *p++ != '\t' );
                    161:        switch (*p) {
                    162:        case 'A': high[vars].hiscl = AUTO; break;
                    163:        case 'P': high[vars].hiscl = PARAM; break;
                    164:        /* set doubles flag */
                    165:        case 'N': nodblflg = 1; return;
                    166:        }
                    167: 
                    168:        /* scan to name and read it */
                    169:        while( *p++ != '\t' );
                    170:        q = p;
                    171:        while( *q++ != '\t' );
                    172:        high[vars].hiname = r = getspace( q - p );
                    173:        while( p < ( q - 1 ) ) *r++ = *p++;
                    174:        *r = '\0';
                    175: 
                    176:        /* read length */
                    177:        high[vars].hilen = atoi(q);
                    178: 
                    179:        /* increment table index */
                    180:        vars++;
                    181:        return;
                    182: }
                    183: 
                    184: 
                    185: /* main routine for register allocation optimization */
                    186: 
                    187: int
                    188: raoptim( numnreg, numauto )
                    189: register int numnreg;  /* input number of registers saved/restored */
                    190: register int numauto;  /* number of words of automatic variables */
                    191: 
                    192: {
                    193:        void raavail(), ravassign(), raremove(), raopn(), raparam(), radef();
                    194:        void rainsld(), raremld();
                    195:        int rarassign(), racut();
                    196:        int iascut;     /* index for assignment cutoff */
                    197:        int iasrlast;   /* index of the last register variable assigned */
                    198:        int newnreg;    /* new number of registers to be saved */
                    199:        register int ias;
                    200: 
                    201:        /* check for doubles */
                    202:        if( nodblflg == 0 ) {
                    203:                vars = 0;
                    204:                return( numnreg );
                    205:        }
                    206: 
                    207:        /* initialize assignment table */
                    208:        for( ias = 0; ias < MAXREGS; ias++ ) {
                    209:                asreg[ias].asavail = AVAIL;
                    210:                asreg[ias].asvscl = SCLNULL;
                    211:                asreg[ias].asvlen = 0;
                    212:        }
                    213: 
                    214:        /* determine availability of scratch registers */
                    215:        raavail( numnreg );
                    216: 
                    217:        /* insert branch pointers for live/dead analysis */
                    218:        rainsld();
                    219:        
                    220:        /* assign register variables */
                    221:        iasrlast = rarassign( numnreg );
                    222: 
                    223:        /* assign non-register variables */
                    224:        ravassign();
                    225: 
                    226:        /* remove remove branch pointers from live/dead analysis */
                    227:        raremld();
                    228: 
                    229:        /* compute cutoff from cumulative payoff */
                    230:        iascut = racut( numnreg, numauto, iasrlast );
                    231:        if( iascut < 0 ) { /* if no payoff for this optimization */
                    232:                vars = 0;
                    233:                return( numnreg );      
                    234:        }
                    235:        newnreg = asreg[iascut].asrsave;
                    236: 
                    237:        /* modify the instruction operands */
                    238:        raopn( iascut, newnreg );
                    239: 
                    240:        /* insert moves for parameters */
                    241:        raparam( iascut );
                    242: 
                    243:        /* modify def statements */
                    244:        radef( iascut );
                    245: 
                    246:        /* re-initailize for next procedure */
                    247:        vars = 0;
                    248:        return( newnreg );
                    249: }
                    250: 
                    251: /* determine availability of scratch registers */
                    252: void
                    253: raavail( numnreg )
                    254: int numnreg;   /* input number of registers to be saved/restored */
                    255: {
                    256:        register NODE *pn;
                    257:        register struct assign *pa;
                    258:        register int iop, i;
                    259:        register char *p;
                    260:        struct assign *map[MAXREGS];
                    261: 
                    262:        /* check availability of scratch %r3 */
                    263:        if( numnreg == 6 ) asreg[3].asavail = NOTAVAIL;
                    264:        else asreg[9].asavail = NOTAVAIL;
                    265: #ifndef IMPSCRATCH
                    266:        asreg[3].asavail = NOTAVAIL;
                    267:        asreg[9].asavail = AVAIL;
                    268: #endif /* IMPSCRATCH */
                    269: 
                    270:        /* set up mapping for scratch registers */
                    271:        for( i = 0; i < MAXREGS; i++ ) map[i] = NULL;
                    272:        for( i = 0; i < MAXREGS; i++ ) {
                    273:                pa = &asreg[i];
                    274:                if( pa->asrtype == SCRATCH && pa->asavail == AVAIL )
                    275:                        map[*( pa-> asrname + 2 ) - '0'] = pa;
                    276:        }
                    277:        
                    278:        /* scan for uses */
                    279:        for( ALLN( pn ) ) { /* scan nodes */
                    280:                if( pn->op == FILTER ) continue;
                    281:                /* check for use of scratch registers */
                    282:                for( iop = 1; iop < MAXOPS + 1; iop++ ) { /* scan operands */
                    283:                        if( ( p = pn->ops[iop] ) == NULL ) continue;
                    284:                        while( *p != '\0' ) {
                    285:                                if( *p++ != '%' ) continue; 
                    286:                                if( *p++ != 'r' ) break;
                    287:                                pa = map[*p - '0'];
                    288:                                if( pa != NULL ) pa->asavail = NOTAVAIL;
                    289:                                break;
                    290:                        }
                    291:                }
                    292:        }
                    293: }
                    294: 
                    295: /* insert pointers for live/dead analysis */
                    296: void
                    297: rainsld()
                    298: {
                    299:        register NODE *pn, *qn;
                    300:        register char *ppn;
                    301: 
                    302:        for( ALLN( pn ) ) {
                    303:                if( isbr( pn ) && !isret( pn ) ) {
                    304:                        ppn = getp( pn );
                    305:                        /* use wraparound scan when looking for label */
                    306:                        for( qn = ( pn->forw != &ntail ) ? pn->forw : n0.forw; 
                    307:                                qn != pn; qn = ( qn->forw != &ntail ) ?
                    308:                                qn->forw : n0.forw ) {
                    309:                                if( islabel( qn ) ) {
                    310:                                        if(*(ppn + 2) != *(qn->ops[0] + 2) &&
                    311:                                                *(ppn + 1) != '\0' ) 
                    312:                                                continue; /* for speed */
                    313:                                        if( strcmp( ppn, qn->ops[0] ) == 0 ){
                    314:                                                pn -> opm = (char *) qn;
                    315:                                                break;
                    316:                                        }
                    317:                                }
                    318:                        }
                    319:                }
                    320:        }
                    321: }
                    322: 
                    323: /* assign register variables */
                    324: int
                    325: rarassign( numnreg ) 
                    326: register int numnreg;  /* input number of registers to be saved/restored */
                    327: {
                    328:        register struct assign *pa;
                    329:        register int ias, ireg, ok;
                    330:        int iasrlast;
                    331: 
                    332:        iasrlast = -1;
                    333: 
                    334:        /* assign to first available register, and mark unavailable  */
                    335:        for( ireg = 0; ireg < numnreg; ireg++ ) {
                    336:                /* check whether is dead at CALL's etc. */
                    337:                ok = raregok( rnames[ireg], 0 );
                    338:                for( ias = 0; ias < MAXREGS; ias++ ) {
                    339:                        pa = &asreg[ias];
                    340:                        if( pa->asavail == NOTAVAIL ) continue;
                    341:                        if( pa->asrtype == SCRATCH && !ok ) continue;
                    342: 
                    343:                        /* assign it */
                    344:                        pa->asavail = NOTAVAIL;
                    345:                        pa->asestim = 0;
                    346:                        pa->asvscl = REGISTER;
                    347:                        pa->asvname = rnames[ireg];
                    348:                        pa->asvlen = 4;
                    349:                        if( iasrlast < ias ) iasrlast = ias;
                    350:                        break;
                    351:                }
                    352:        }
                    353:        return( iasrlast );
                    354: }
                    355: 
                    356: /* assign non-register variables */
                    357: void
                    358: ravassign()
                    359: {
                    360:        register int ivar, ias, ok;
                    361:        register struct assign *pa;
                    362:        register struct hinode *ph;
                    363: 
                    364:        /* go through variables */
                    365:        for( ivar = 0; ivar < vars; ivar++ ) {
                    366:                ph = &high[ivar];
                    367:                /* check to see if dead at CALL's etc. */
                    368:                ok = raregok(ph->hiname, ph->hilen);
                    369:                /* assign to first register that qualifies */
                    370:                for( ias = 0; ias < MAXREGS; ias++ ) {
                    371:                        pa = &asreg[ias];
                    372:                        if( pa->asavail == NOTAVAIL ) continue;
                    373:                        if( pa->asrtype == SCRATCH && !ok ) continue;
                    374: 
                    375:                        /* assign it */
                    376:                        pa->asavail = NOTAVAIL;
                    377:                        pa->asestim = ph->hiestim;
                    378:                        pa->asvscl = ph->hiscl;
                    379:                        pa->asvname = ph->hiname;
                    380:                        pa->asvlen = ph->hilen;
                    381:                        break;
                    382:                }
                    383:        }
                    384: }
                    385: 
                    386: /* check if dead at CALL's etc. */
                    387: int
                    388: raregok( name, len )
                    389: register char *name;   /* pointer to register or variable name */
                    390: register int len;      /* length of variable (0 for register) */
                    391: {
                    392:        register NODE *pn;
                    393:        NODE *rald();
                    394: 
                    395:        for( pn = n0.forw; pn != 0; pn = pn->forw ) { /* scan nodes */
                    396:                switch( pn->op ) {
                    397:                default: continue;
                    398:                case CALL:
                    399:                case JSB:
                    400:                case MOVBLB:
                    401:                case MOVBLH:
                    402:                case MOVBLW:
                    403:                        /* check if 'name' is live */
                    404:                        if( rald( pn->forw, name, len ) != NULL ) return( 0 );
                    405:                }
                    406:        }
                    407:        /* dead */
                    408:        return( 1 );
                    409: }
                    410: 
                    411: /* check for register or variable dead in a block */
                    412: /* Note that this routine may visit a block more than
                    413:  * once, but that it cannot loop because any closed path
                    414:  * in the program contains at least one label, and the
                    415:  * routine will not scan a block beginning with a given
                    416:  * label more than once. 
                    417:  */
                    418: NODE *
                    419: rald( pn, name, len )
                    420: register NODE *pn;     /* pointer to block to be searched */
                    421: register char *name;   /* pointer to register or variable name */
                    422: register int len;      /* length of variable (0 for register) */
                    423: {
                    424:        NODE *qn;
                    425:        register int iop;
                    426:        register char *p;
                    427:        int srcsize, dstsize;
                    428: 
                    429:        /* scan block */
                    430:        for( ; pn != 0; pn = pn->forw ) {
                    431:                if( pn->op == FILTER ) continue;
                    432:                /*control recursion */
                    433:                if( islabel( pn ) ) {
                    434:                        /* terminate recursion if this block has been visited */
                    435:                        if( pn->opm == name ) return( NULL );
                    436:                        /* mark block as visited */
                    437:                        pn->opm = name;
                    438:                        continue;
                    439:                }
                    440:                /* if no references, its dead */
                    441:                if( isret( pn ) ) return( NULL );
                    442:                /* end of block */
                    443:                if( isbr( pn ) ) break;
                    444:                /* check operands of remaining instructions */
                    445:                for( iop = 1; iop < MAXOPS + 1; iop++ ) {
                    446:                        p = pn->ops[iop];
                    447:                        if( p == NULL ) continue;
                    448:                        /* look for register or variable */
                    449:                        if( ( *name == '%' && usesreg( p, name ) ) ||
                    450:                                rausesoff( p, name, len ) ) {
                    451:                                /* see if it's a destination */
                    452:                                if( iop==2 && ( length(name) == length(p) )
                    453:                                        && ismove( pn, &srcsize, &dstsize )) 
                    454:                                        return( NULL );
                    455:                                if( iop==3 && ( length(name) == length(p) )) {
                    456:                                        switch ( pn->op ) {
                    457:                                        case ANDB3: case ANDH3: case ANDW3:
                    458:                                        case ORB3: case ORH3: case ORW3:
                    459:                                        case XORB3: case XORH3: case XORW3:
                    460:                                        case LLSW3: case LRSW3:
                    461:                                        case ADDB3: case ADDH3: case ADDW3:
                    462:                                        case SUBB3: case SUBH3: case SUBW3:
                    463:                                        case MULW3: case UMULW3:
                    464:                                        case DIVW3: case UDIVW3:
                    465:                                        case MODW3: case UMODW3:
                    466:                                        case ALSW3: case ARSW3:
                    467:                                                return( NULL );
                    468:                                        }
                    469:                                }
                    470:                                /* nope, it's live */
                    471:                                return( pn );
                    472:                        }
                    473:                }
                    474:        }
                    475:        /* examine next block(s) recursively */
                    476:        if( pn->opm == NULL ) return( pn ); /* dst not a simple label */
                    477:        
                    478:        if( ( qn = rald( (NODE *) pn->opm, name, len ) ) != NULL ) return( qn );
                    479:        if( isuncbr( pn ) ) return( NULL );
                    480:        qn = rald( pn->forw, name, len );
                    481:        return( qn );
                    482: }
                    483: 
                    484: /* remove branch information from live/dead analysis */
                    485: void
                    486: raremld()
                    487: {
                    488:        register NODE *pn;
                    489: 
                    490:        for( pn = n0.forw; pn != 0; pn = pn->forw ) {
                    491:                if( isbr( pn ) || islabel( pn ) ) pn->opm = NULL;
                    492:        }
                    493: }
                    494: 
                    495: /* compute cutoff from cumulative payoff */
                    496: int
                    497: racut( numnreg, numauto, iasrlast ) 
                    498: int numnreg;   /* input number of registers saved */
                    499: int numauto;   /* number of autos */
                    500: int iasrlast;  /* index of last assigned register variable */
                    501: {
                    502:        int rsave(), rsaveo();
                    503:        int vcumul;     /* cumulative payoff for variables */
                    504:        int rcumul;     /* cumulative payoff for reg save/restore */
                    505:        int cumul;      /* cumulative total payoff */
                    506:        int paycut;     /* payoff for cutoff register */
                    507:        int oldsave;    /* cycles to save and restore */
                    508:        int oldsaveo;   /* cycles to save and restore with func call opt */
                    509:        int ias, iascut;
                    510:        struct assign *pa;
                    511: 
                    512:        vcumul = 0;
                    513:        iascut = iasrlast;
                    514:        paycut = 0;
                    515:        oldsave = rsave( numnreg, numauto );
                    516: 
                    517:        for( ias = 0; ias < MAXREGS; ias ++ ) {
                    518: 
                    519:                /* skip if no assignment */
                    520:                pa = &asreg[ias];
                    521:                if( pa->asvscl == SCLNULL ) continue;
                    522: 
                    523:                /* compute cumulative variable payoff */
                    524:                vcumul += pa->asestim;
                    525: 
                    526:                /* compute cost/payoff from save and restore */
                    527:                rcumul = oldsave - rsave( pa->asrsave, numauto );
                    528: 
                    529:                /* add cumulative payoffs, find max of last reg and all var */
                    530:                cumul = vcumul + rcumul;
                    531:                if( ias >= iasrlast && cumul >= paycut ) { 
                    532:                        paycut = cumul; 
                    533:                        iascut = ias; 
                    534:                }
                    535: /*
                    536:                printf( "#ias=%d %s asestim=%d %s vcumul=%d rcumul=%d cumul=%d iascut=%d\n",
                    537:                        ias,pa->asrname,pa->asestim,pa->asvname,vcumul,rcumul,cumul,iascut );
                    538: */
                    539:        }
                    540:        return( iascut );
                    541: }
                    542: /* compute estimated save/restore cycles without func call optimization */
                    543: int
                    544: rsave( n, numauto )
                    545: int n; /* number of registers to save/restore, not including frame pointer */
                    546: int numauto; /* number of autos */
                    547: 
                    548: {
                    549:        int e;
                    550: 
                    551:        if( numauto ) e = CYCSAVE + n * CYCDELTA + CYCADD ;
                    552:        else e = CYCSAVE + n * CYCDELTA ;
                    553:        return e;
                    554: }
                    555: 
                    556: /* modify the operands */
                    557: void
                    558: raopn( iascut, newnreg )
                    559: int iascut;    /* index for assignment cutoff */
                    560: int newnreg;   /* new number of registers to be saved/restored */
                    561: {
                    562:        register char *p, *q, *q2;
                    563:        NODE *pn;
                    564:        register struct assign *pa, *pacut;
                    565:        struct assign *pamin;
                    566:        int iop;
                    567:        static char* numbers[] = { "&0", "&1", "&2", "&3", "&4", "&5", "&6" };
                    568:        struct assign *map[MAXREGS];
                    569:        int i;
                    570: 
                    571:        /* suppress changes for registers assigned to themselves */
                    572:        pamin = &asreg[0];
                    573:        pacut = &asreg[iascut];
                    574:        for( pa = pamin; pa <= pacut; pa++ ) {
                    575:                if( strcmp( pa->asvname, pa->asrname ) == 0 )
                    576:                        pa->asvscl = SCLNULL;
                    577:        }
                    578: 
                    579:        /* set up mapping for registers */
                    580:        for( i = 0; i < MAXREGS; i++ ) map[i] = NULL;
                    581:        for( pa = pamin; pa <= pacut; pa++ )
                    582:                if( pa->asvscl == REGISTER )
                    583:                        map[ *( pa->asvname + 2 ) - '0'] = pa;
                    584: 
                    585:        /* make changes on the rest */
                    586:        for( ALLN( pn ) ) {
                    587:                if( pn->op == FILTER ) continue;
                    588:                for( iop = 1; iop <= MAXOPS; iop++ ) { /* scan operands */
                    589:                        if( ( q = pn->ops[iop] ) == NULL ) continue;
                    590:                        /* check for address arithmetic */
                    591:                        if( ( ( pn->op == MOVAW ) || ( pn->op == PUSHAW ) ) &&
                    592:                                ( iop == 1 ) ) continue;
                    593:                        /* find operands that use registers */
                    594:                        for( p = q; *p != '%' && *p != '\0'; p++ );
                    595:                        if( *p == '\0' ) continue;
                    596:                        p++;
                    597:                        switch( *p ) {
                    598:                        case 'r':       /* %r0 through %r8 */
                    599:                                /* change register, if appropriate */
                    600:                                if( ( pa = map[*++p - '0'] ) != NULL ) {
                    601:                                        if( *q == '%' )
                    602:                                                pn->ops[iop] = pa->asrname;
                    603:                                        else {
                    604:                                                for( q2=q; *q2!='\0'; q2++ );
                    605:                                                q2 = getspace( q2 - q + 1 );
                    606:                                                pn->ops[iop] = q2;
                    607:                                                p = q2 + ( p - q );
                    608:                                                while((*q2++ = *q++) != '\0');
                    609:                                                *p = *(pa->asrname + 2);
                    610:                                        }
                    611:                                }
                    612:                                break;
                    613:                        case 'f':       /* auto */
                    614:                        case 'a':       /* parameter */
                    615:                                /* convert to register, if apropriate */
                    616:                                for( pa = pamin; pa <= pacut; pa++ ) {
                    617:                                        if( ( *p=='f' && pa->asvscl!=AUTO ) ||
                    618:                                                (*p=='a'&&pa->asvscl!=PARAM )) 
                    619:                                                continue; /* for speed */
                    620:                                        if( !rausesoff( q, pa->asvname,
                    621:                                                pa->asvlen ) ) continue;
                    622:                                        if( *q == '*' )
                    623:                                                pn->ops[iop] = pa->asrind;
                    624:                                        else    pn->ops[iop] = pa->asrname;
                    625:                                        break;
                    626:                                }
                    627:                                break;
                    628:                        }
                    629:                }
                    630: 
                    631:                /* change number of registers saved and restored */
                    632:                if( pn->op==SAVE || pn->op==RET ) pn->op1 = numbers[newnreg];
                    633:        }
                    634: }
                    635: 
                    636: /* uses offset addressed variable */
                    637: int
                    638: rausesoff( oper, var, len )
                    639: char* oper;    /* pointer to operand */
                    640: char* var;     /* pointer to offset addressed variable */
                    641: int len;       /* length of the variable in bytes */
                    642: {
                    643:        register int io, iv;
                    644: 
                    645:        if( *oper == '*' ) oper++;
                    646:        io = strtol( oper, &oper, 10 );
                    647:        iv = strtol( var, &var, 10 );
                    648:        if( *oper != '(' || *var != '(' || *(oper + 2) != *(var + 2) )
                    649:                return( 0 );
                    650:        if( io < iv || io > ( iv + len - 1 ) ) return( 0 );
                    651:        return( 1 );
                    652: }
                    653: 
                    654: /* insert moves for parameters */
                    655: void
                    656: raparam( iascut )
                    657: register int iascut;   /* index for assignment cutoff */
                    658: {
                    659:        register NODE *pn;
                    660:        register int ias;
                    661:        register struct assign *pa;
                    662: 
                    663:        /* find save instruction */
                    664:        for( pn = n0.forw; pn != 0; pn = pn->forw ) { /* scan nodes */
                    665:                if( pn->op == SAVE ) {
                    666: 
                    667:                        /* skip over stack pointer increment for locals */
                    668:                        if( *( pn->forw->ops[1] + 2 ) == 'F' ) pn = pn->forw;
                    669: 
                    670:                        /* insert move for each parameter assigned to reg */
                    671:                        for( ias = 0; ias <= iascut;  ias++ ) {
                    672:                                pa = &asreg[ias];
                    673:                                if( pa->asvscl != PARAM ) continue;
                    674:                                switch( atoi( pa->asvname ) % 4 ) {
                    675:                                case 0:
                    676:                                        addi( MOVW, "movw", pa->asvname, 
                    677:                                                pa->asrname );
                    678:                                        break;
                    679:                                case 1:
                    680:                                case 3:
                    681:                                        addi( MOVB, "movb", pa->asvname,
                    682:                                                pa->asrname );
                    683:                                        break;
                    684:                                case 2:
                    685:                                        addi( MOVH, "movh", pa->asvname,
                    686:                                                pa->asrname );
                    687:                                        break;
                    688:                                }
                    689:                        }
                    690:                        break;
                    691:                }
                    692:        }
                    693: }
                    694: 
                    695: /* modify def statements */
                    696: void
                    697: radef( iascut )
                    698: int iascut;    /* index for assignment cutoff */
                    699: {
                    700:        register NODE *pn;
                    701:        int ias;
                    702:        register struct assign *pa;
                    703:        register int scl;
                    704:        int val, vval, dscl;
                    705:        register char *p, *q;
                    706:        char *pv, *ps, *s;
                    707: 
                    708:        for( pn = n0.forw; pn != 0; pn = pn->forw ) { /* scan nodes */
                    709:                if( pn->op != FILTER ) continue;
                    710:                p = pn->opcode;
                    711:                if( ! ( p = strchr( p, '.' ) ) || *++p != 'd' ) continue;
                    712:                if( ! ( p = strchr( p, '.' ) ) || *++p != 'v' ) continue;
                    713:                val = atoi( pv = p += 3 );
                    714:                if( ! ( p = strchr( p, '.' ) ) || *++p != 's' ) continue;
                    715:                scl = atoi( ps = p += 3 );
                    716:                switch( scl ) {
                    717:                case C_AUTO: dscl = AUTO; break;
                    718:                case C_ARG: dscl = PARAM; break;
                    719:                case C_REG:
                    720:                case C_REGPARM: dscl = REGISTER; break;
                    721:                default: continue;
                    722:                }
                    723:                for( ias = 0; ias <= iascut; ias++ ) {
                    724:                        pa = &asreg[ias];
                    725:                        if( dscl != pa->asvscl ) continue;
                    726:                        vval = ( scl == C_AUTO || scl == C_ARG ) ?
                    727:                                atoi( pa->asvname ) : 
                    728:                                *( pa->asvname + 2 ) - '0' ;
                    729:                        if( val != vval ) continue;
                    730:                        q = s = getspace( length( p = pn->opcode ) + 5 );
                    731:                        while( p != pv ) *q++ = *p++;           /* thru .val */
                    732:                        *q++ = *p++;                            /* tab */
                    733:                        *q++ = *( pa->asrname + 2 );            /* reg no */
                    734:                        while( *++p != ';' );
                    735:                        while( p != ps ) *q++ = *p++;           /* thru .scl */
                    736:                        *q++ = *p++;                            /* tab */
                    737:                        q += sprintf( q, "%d",                  /* scl value */
                    738:                                ( scl == C_AUTO || scl == C_REG ) ? 
                    739:                                C_REG : C_REGPARM );
                    740:                        while( *++p != ';' );
                    741:                        while( *q++ = *p++ );                   /* the rest */
                    742:                        pn->opcode = s;
                    743:                }
                    744:        }
                    745: }
                    746: 
                    747: /* eliminate auto area if no more autos */
                    748: int
                    749: raautos( numauto )
                    750: int numauto;   /* number of bytes of automatic variables */
                    751: {
                    752:        register NODE *pn, *qn;
                    753:        register int iop;
                    754:        register char *p;
                    755: 
                    756:        for( pn = n0.forw; pn != 0; pn = pn->forw ) { /* scan nodes */
                    757:                if( pn->op == FILTER ) continue;
                    758:                if( pn->op == SAVE ) qn = pn->forw;
                    759:                for( iop = 1; iop < MAXOPS + 1; iop++ ) { /* scan operands */
                    760:                        p = pn->ops[iop];
                    761:                        if( p == NULL ) continue;
                    762:                        /* look for uses of frame pointer */
                    763:                        if( usesreg( p, "%fp" ) ) return( numauto );
                    764:                }
                    765:        }
                    766:        /* remove allocation of auto area */
                    767:        if( *( qn->op1 + 2 ) == 'F' ) {
                    768:                DELNODE( qn );
                    769:                numauto = 0;
                    770:        }
                    771:        return( numauto );
                    772: }
                    773: #endif /* IMPREGAL */
                    774: 
                    775: 
                    776: #ifdef IMPIL
                    777: /* in-line substitution optimization
                    778: **
                    779: ** F.B. Wolverton 8/12/83
                    780: **
                    781: */
                    782: 
                    783: #define        MAXINSTR        22      /* = 20 * (cost/benefit) + 2 */
                    784: 
                    785: struct procnode {
                    786:        struct procnode *pnforw;        /* forward pointer for list of procs */
                    787:        struct procnode *pnback;        /* backward pointer for list of procs */
                    788:        char            *pnname;        /* procedure name */
                    789:        int             pncalls;        /* num of times procedure is called */
                    790:        int             pnni;           /* num of instr in procedure */
                    791:        struct node     *pnhead;        /* proc head pointer */
                    792:        struct node     *pntail;        /* proc tail pointer */
                    793: } prochead, proctail;
                    794: int    proccnt;        /* number of procs in table */
                    795: int    totalni = 0;    /* total number of instructions in file */
                    796: #define PNODE          struct procnode
                    797: #define        ALLPN( prn )    prn = prochead.pnforw; prn != &proctail; prn=prn->pnforw
                    798: #define ALLPNB( prn )  prn = proctail.pnback; prn != &prochead; prn=prn->pnback
                    799: #define PNALLN(prn,pn)  pn = prn->pnhead->forw; pn != prn->pntail; pn=pn->forw
                    800: #define PNALLNB(prn,pn) pn = prn->pntail->back; pn != prn->pnhead; pn=pn->back
                    801: extern char *mktemp();
                    802: char   itmpname[50]; /* name of file for output before in-line subst */
                    803: int    outfd;          /* descriptor for output file after in-line subst */
                    804: FILE   *outfp;         /* pointer for output file after in-line subst */
                    805: void   iledit(), ilinsert();
                    806: struct procnode *ilalloc();
                    807: #define        LINELEN 400
                    808: char   linebuf[LINELEN];
                    809: int    intpc = -3; /* persent limit on in-line expansion */
                    810: char   defltpc[] = MAXPC;
                    811: char   *pcdecode();
                    812: extern int zflag;      /* debug flag for in-line expansion */
                    813: extern boolean swflag;
                    814: 
                    815: /* initialization for in-line substitution */
                    816: void
                    817: ilinit()
                    818: {
                    819:        /* initialize procedure list */
                    820:        prochead.pnforw = &proctail;
                    821:        prochead.pnback = NULL;
                    822:        proctail.pnforw = NULL;
                    823:        proctail.pnback = &prochead;
                    824:        proccnt = 0;
                    825: 
                    826:        /* default the in-line expansion limit if not set */
                    827:        if( intpc == -3 && *( pcdecode( defltpc )+1 ) != '\0' ) pcdecode( "" );
                    828: 
                    829:        /* redirect stdout to tempfile to hold output before in-line subst */
                    830:        strcpy( itmpname, TMPDIR );
                    831:        strcat( itmpname, "/ccilXXXXXX" );
                    832:        mktemp( itmpname );
                    833:        if( ( outfd = dup( 1 ) ) == -1 ) 
                    834:                fatal( "can't get file descriptor\n", 0 );
                    835:        outfp = fdopen( outfd, "w" );
                    836:        if( freopen( itmpname, "w", stdout ) == NULL )
                    837:                fatal( "can't open file %s\n", itmpname );
                    838: }
                    839: /* routine to decode the limit on percent in-line expansion */
                    840: char *
                    841: pcdecode( flags )
                    842: char *flags; /* pointer to first character of suboption for 'y' */
                    843: {
                    844:        char *p;
                    845:        switch( *flags ) {
                    846:        case 'u': intpc = -1; break;
                    847:        case 's': intpc = -2; break;
                    848:        case '\n':
                    849:        case '\0': 
                    850:                fprintf( stderr, "Optimizer: in-line option missing, " );
                    851:                fprintf( stderr, "expansion suppressed\n");
                    852:                flags--;
                    853:                intpc = -2;
                    854:                break;
                    855:        default:
                    856:                intpc = ( int ) strtol( p = flags, &flags, 10 );
                    857:                flags--;
                    858:                if( flags >= p ) break; /* break if found an integer */
                    859:                fprintf( stderr, "Optimizer: invalid in-line option " );
                    860:                fprintf( stderr, "starting with '%c', ", *p );
                    861:                fprintf( stderr, "expansion suppressed\n" );
                    862:                intpc = -2;
                    863:        }
                    864:        return( flags ); /* returns pointer to last character of suboption */
                    865: }
                    866: /* routine to mark calls with bytes pushed on stack at time of call */
                    867: 
                    868: /* The purpose of this routine is to permit nested calls to be expanded
                    869: ** in-line.  This routine routine does static analysis of the stack
                    870: ** size and should, therefore, precede the branch optimization. */
                    871: 
                    872: void
                    873: ilmark()
                    874: 
                    875: {
                    876:        register int npush = 0;         /* number of bytes of
                    877:                                   arguments pushed or moved onto the stack */
                    878:        register NODE *pn;              /* pointer to instruction node being
                    879:                                   processed */
                    880:        
                    881:        /* check whether in-line expansion is being suppressed */
                    882:        if( intpc == -2 ) return;
                    883: 
                    884:        /* mark calls */
                    885:        for( ALLN( pn ) ) {
                    886:                if( pn->op == FILTER ) continue;
                    887:                switch(pn->op) {
                    888:                case PUSHZB:
                    889:                case PUSHZH:
                    890:                case PUSHAW:
                    891:                case PUSHBB:
                    892:                case PUSHBH:
                    893:                case PUSHW:
                    894:                case PUSHD:
                    895:                        npush += 4;
                    896:                        break;
                    897:                case ADDW2:
                    898:                        if( strncmp( pn->op2, "%sp", 3 ) != 0 ) break;
                    899:                        if( strncmp( pn->op1, "&.F", 3 ) == 0 ) break;
                    900:                        npush += atoi( pn->op1 + 1 );
                    901:                        break;
                    902:                case SUBW2:
                    903:                        if( strncmp( pn->op2, "%sp", 3 ) != 0 ) break;
                    904:                        npush -= atoi( pn->op1 + 1 );
                    905:                        break;
                    906:                case CALL:
                    907:                        npush -= 4 * atoi( pn->op1 + 1 );
                    908:                        pn->opm = (char * ) npush;
                    909:                        break;
                    910:                }
                    911:        }
                    912: }
                    913: 
                    914: /* gather statistics for in-line substitution */
                    915: void
                    916: ilstat( numnreg, numauto )
                    917: int numnreg;   /* number of registers to save and restore */
                    918: int numauto;   /* number of words of autos */
                    919: {
                    920:        register NODE *pn, *p;
                    921:        PNODE *prn, *pp;
                    922:        int nn, ni, iop, nc, lastop;
                    923:        char *ncp;
                    924: 
                    925:        /* check whether in-line expansion is being suppressed */
                    926:        if( intpc == -2 ) return;
                    927: 
                    928:        /* count CALL's and total number of instructions */
                    929:        lastop = 0;
                    930:        for( ALLN( pn ) ) {
                    931:                if( pn->op == CALL ) {
                    932:                        if( ( prn = ilalloc( pn->op2 ) ) == NULL ) return;
                    933:                        prn->pncalls++;
                    934:                }
                    935:                if( !islabel( pn ) && pn->op != MISC &&
                    936:                        ( pn->op != RET || 
                    937:                        ( lastop != RET && lastop != JMP ) ) ) {
                    938:                        totalni++;
                    939:                        lastop = pn->op;
                    940: /*
                    941:                        printf( "%d %s\n", totalni, pn->ops[0] );
                    942: */
                    943:                }
                    944:        }
                    945: 
                    946:        /* allocate a node for this proc if one does not exist */
                    947:        for( ALLN( pn ) ) {
                    948:                if( islabel( pn ) ) {
                    949:                        if( ( prn = ilalloc( pn->opcode ) ) == NULL ) return; 
                    950:                        break;
                    951:                }
                    952:        }
                    953:        if( pn == 0 ) return;
                    954: 
                    955:        /* check conditions for being substituted in line */
                    956:        /* check for locals or saved registers */
                    957:        if( numnreg != 0 || numauto != 0 ) return;
                    958:        /* check procedure size and compute total length of strings */
                    959:        nn = ni = nc = lastop = 0;
                    960:        for( ALLN( pn ) ) {
                    961:                register char *cp;
                    962:                nn++;
                    963:                for( iop = 0; iop <= MAXOPS; iop++ ) {
                    964:                        if( (cp = pn->ops[iop] ) != NULL ) nc += length( cp );
                    965:                }
                    966:                if( !islabel( pn ) && pn->op != MISC &&
                    967:                        ( pn->op != RET || 
                    968:                        ( lastop != RET && lastop != JMP ) ) ) {
                    969:                        if( ++ni > MAXINSTR ) return;
                    970:                        lastop = pn->op;
                    971: /*
                    972:                        printf( "%d %s\n", ni, pn->ops[0] );
                    973: */
                    974:                }
                    975:        }
                    976:        /* check for label expressions */
                    977:        for( ALLN( pn ) ) {
                    978:                if( !islabel( pn ) ) continue;
                    979:                for( ALLN( p ) ) {
                    980:                        register int i;
                    981:                        for( i = 0; i <= MAXOPS; i++ ) {
                    982:                                register char *cp;
                    983:                                cp = p->ops[i];
                    984:                                if( cp == NULL ) continue;
                    985:                                if( *cp == *( pn->opcode ) &&/*speed*/
                    986:                                        strcmp(cp, pn->opcode ) == 0) continue;
                    987:                                while( *cp != '\0' ) {
                    988:                                        cp++;
                    989:                                        if( *cp == *( pn->opcode )&&/* speed */
                    990:                                                strcmp( cp, pn->opcode ) == 0 )
                    991:                                                return;
                    992:                                }
                    993:                        }
                    994:                }
                    995:        }
                    996: 
                    997:        /* check for switch tables */
                    998:        if( swflag ) { swflag = false; return; }
                    999: 
                   1000:        /* save the code */
                   1001:        prn->pnni = ni;
                   1002:        if( ( p = (NODE *)malloc( ( nn + 2 ) * sizeof( NODE ) + nc ) ) == NULL )
                   1003:                return;
                   1004:        ncp = (char *) p + ( nn + 2 ) * sizeof( NODE );
                   1005:        prn->pnhead = p;
                   1006:        p->forw = p + 1;
                   1007:        p->back = NULL;
                   1008:        for( ALLN( pn ) ) {
                   1009:                register int i;
                   1010:                p++;
                   1011:                p->forw = p + 1;
                   1012:                p->back = p - 1;
                   1013:                for( i = 0; i <= MAXOPS; i++ ) {
                   1014:                        if( ( p->ops[i] = pn->ops[i] ) == NULL ) continue;
                   1015:                        strcpy( ncp, pn->ops[i] );
                   1016:                        p->ops[i] = ncp;
                   1017:                        ncp += length( ncp );
                   1018:                }
                   1019:                p->op = pn->op;
                   1020:        }
                   1021:        p++;    
                   1022:        p->forw = NULL;
                   1023:        p->back = p - 1;
                   1024:        prn->pntail = p;
                   1025: 
                   1026:        /* reposition in list by increasing size */
                   1027:        /* remove from list */
                   1028:        prn->pnforw->pnback = prn->pnback;
                   1029:        prn->pnback->pnforw = prn->pnforw;
                   1030:        /* locate proper position */
                   1031:        for( ALLPNB( pp ) ) {
                   1032:                if( prn->pnni >= pp->pnni ) break;
                   1033:        }
                   1034:        /* reinsert it */
                   1035:        prn->pnforw = pp->pnforw;
                   1036:        prn->pnback = pp;
                   1037:        prn->pnforw->pnback = prn;
                   1038:        prn->pnback->pnforw = prn;
                   1039: }
                   1040: 
                   1041: /* perform the in-line substitution for whole file */
                   1042: void
                   1043: ilfile()
                   1044: {
                   1045:        register struct procnode *prn;
                   1046:        int fpc, delta;
                   1047:        register char *linptr;
                   1048: 
                   1049:        /* eliminate nodes for progs not in the file or not called */
                   1050:        for( ALLPN( prn  ) ) {
                   1051:                if( prn->pnni == 0 || prn->pncalls ==0 ) {
                   1052:                        prn->pnforw->pnback = prn->pnback;
                   1053:                        prn->pnback->pnforw = prn->pnforw;
                   1054:                }
                   1055:        }
                   1056: 
                   1057:        /* apply percent limit unless no limit */
                   1058:        if( intpc != -1 ) {
                   1059:                /* apply percent text increase constraint */
                   1060:                fpc = 100 * intpc;
                   1061:                for( ALLPN( prn ) ) {
                   1062:                        delta = 100 * ( prn->pnni - 2 ) * 100 / totalni;
                   1063:                        fpc -= prn->pncalls * delta;
                   1064:                        if( fpc < 0 ) {
                   1065:                                while( fpc < 0 && prn->pncalls > 0 ) { 
                   1066:                                        fpc += delta;
                   1067:                                        prn->pncalls--;
                   1068:                                }
                   1069:                                break;
                   1070:                        }
                   1071:                }
                   1072:                if( prn != &proctail ) {
                   1073:                        if( ( prn->pncalls ) == 0 ) prn = prn -> pnback;
                   1074:                        prn->pnforw = &proctail;
                   1075:                        prn->pnforw->pnback = prn;
                   1076:                }
                   1077:        }
                   1078: 
                   1079:        /* analytic printout */
                   1080:        if( zflag ) {
                   1081:                int size, sumsize;
                   1082:                sumsize = 0;
                   1083:                if( zflag ) fprintf(stderr, "in-line expansion limit = %d\n",
                   1084:                        intpc );
                   1085:                for( ALLPN( prn ) ) {
                   1086:                        size = prn->pncalls * 
                   1087:                                ( prn->pnni -2 ) * 100 / totalni;
                   1088:                        sumsize += size;
                   1089:                        fprintf( stderr,
                   1090:                                "%s calls=%d inst=%d sz=%d%% t_sz=%d%% \n",
                   1091:                                prn->pnname,prn->pncalls,prn->pnni,size,
                   1092:                                sumsize );
                   1093:                }
                   1094:        }
                   1095: 
                   1096:        /* edit routines before inserting */
                   1097:        iledit();
                   1098: 
                   1099:        /* read temp file and write output with inserted procedures */
                   1100:        fclose( stdout );
                   1101:        if( freopen( itmpname, "r", stdin ) == NULL )
                   1102:                fatal( "can't open file %s\n", itmpname );
                   1103:        while( ( linptr = fgets( linebuf, LINELEN, stdin ) ) != NULL ){
                   1104:                register int numauto, nargs;
                   1105:                register char *cp;
                   1106:                char *linp;
                   1107: 
                   1108:                if( *linptr == '!' ) continue;
                   1109:                if( *linptr == '*' ) {
                   1110:                        /* insert .il flag to indicate in-line expansion */
                   1111:                        if( ( linptr = fgets( linebuf, LINELEN, stdin ) )
                   1112:                                == NULL ) break;
                   1113:                        for( cp = linebuf; *cp != '\n'; cp++ );
                   1114:                        *cp = '\0';
                   1115:                        for( ALLPN( prn ) ) {
                   1116:                                if( strcmp( linebuf, prn->pnname ) == 0 ) {
                   1117:                                        linptr = fgets( linebuf, LINELEN,
                   1118:                                                stdin );
                   1119:                                        for(cp=linebuf; *cp != '\n'; cp++)
                   1120:                                                if(*cp == ';') linptr = cp;
                   1121:                                        *linptr = '\0';
                   1122:                                        fprintf( outfp, "%s;\t.il;\t.endef\n",
                   1123:                                                linebuf );
                   1124:                                        break;
                   1125:                                }
                   1126:                        }
                   1127:                        continue;
                   1128:                }
                   1129:                /* default */
                   1130:                if( *linptr != '@' ) {
                   1131:                        fprintf( outfp, "%s", linptr );
                   1132:                        continue;
                   1133:                }
                   1134:                /* expand the call */
                   1135:                linp = linptr;
                   1136:                numauto = (int) strtol( ++linp, &linp, 10 );
                   1137:                nargs = (int) strtol( ++linp, &linp, 10 );
                   1138:                linptr = linp;
                   1139:                cp = ++linptr;
                   1140:                while( *cp != '\n' ) cp++;
                   1141:                *cp = '\0';
                   1142:                for( ALLPNB( prn ) ) {
                   1143:                        if( strcmp( linptr, prn->pnname ) == 0 ) {
                   1144:                                if( prn->pncalls <= 0 ) break;
                   1145:                                ilinsert( numauto, nargs, prn );
                   1146:                                prn->pncalls--;
                   1147:                                fgets( linebuf, LINELEN, stdin );
                   1148:                                break;
                   1149:                        }
                   1150:                }
                   1151:        }
                   1152:        (void) fclose( stdin );
                   1153:        unlink( itmpname );
                   1154: }
                   1155: 
                   1156: 
                   1157: /* edit routines before substitution */
                   1158: void
                   1159: iledit()
                   1160: {
                   1161:        register NODE *pn;
                   1162:        register PNODE *prn;
                   1163: 
                   1164:        for( ALLPN( prn ) ) {
                   1165:                /* replace entry label with new label */
                   1166:                for( PNALLN( prn, pn ) ) {
                   1167:                        if( islabel( pn ) ) {
                   1168:                                prn->pnhead->forw = pn;
                   1169:                                pn->back = prn->pnhead;
                   1170:                                pn->opcode = "EL";
                   1171:                                break;
                   1172:                        }
                   1173:                }
                   1174:                /* replace last return with lab or follow last jump with lab */
                   1175:                for( PNALLNB( prn, pn ) ) {
                   1176:                        if( pn->op == RET ) {
                   1177:                                pn->op = LABEL;
                   1178:                                pn->opcode = "RL";
                   1179:                                prn->pntail->back = pn;
                   1180:                                pn->forw = prn->pntail;
                   1181:                                /* remove duplicate return, if any */
                   1182:                                while( islabel( pn ) ) pn = pn ->back;
                   1183:                                if( pn->op == RET ) DELNODE( pn );
                   1184:                                break;
                   1185:                        }
                   1186:                        if( pn->op == JMP ) {
                   1187:                                addi( LABEL, "RL", 0, 0 );
                   1188:                                prn->pntail->back = pn;
                   1189:                                pn->forw = prn->pntail;
                   1190:                                break;
                   1191:                        }
                   1192:                }
                   1193:                /* replace other returns with jump to new label */
                   1194:                for( PNALLN( prn, pn ) ) {
                   1195:                        if( pn->op == RET ) {
                   1196:                                pn->op = JMP;
                   1197:                                pn->opcode = "jmp";
                   1198:                                pn->op1 = "RL";
                   1199:                        }
                   1200:                }
                   1201:        }
                   1202: }
                   1203: 
                   1204: 
                   1205: /* insert a procedure */
                   1206: void
                   1207: ilinsert( numauto, nargs, prn )
                   1208: int numauto;   /* numbers of words of autos in calling procedure */
                   1209: int nargs;     /* number of arguments procedure is called with */
                   1210: PNODE *prn;    /* procedure to be inserted */
                   1211: {
                   1212:        register NODE *pn, *p;
                   1213:        static int ilabel = 0;
                   1214:        register int i;
                   1215:        register char *cp, *cpn;
                   1216:        char *lab;
                   1217: 
                   1218:        /* rewrite labels */
                   1219:        for( PNALLN( prn, pn ) ) {
                   1220:                if( !islabel( pn ) ) continue;
                   1221:                cpn = pn->opcode;
                   1222:                ilabel++;
                   1223:                lab = getspace( 9 );
                   1224:                sprintf( lab, ".I%d\0", ilabel );
                   1225:                for( PNALLN( prn, p ) ) {
                   1226:                        for( i = 0; i <= MAXOPS; i++ ) {
                   1227:                                cp = p->ops[i]; 
                   1228:                                if( cp == NULL ) continue;
                   1229:                                if( *cp == *cpn &&
                   1230:                                        strcmp( cp, cpn ) == 0 )
                   1231:                                        p->ops[i] = lab;
                   1232:                        }
                   1233:                }
                   1234:        }
                   1235: 
                   1236:        /* write out instructions, rewriting args and omitting save */
                   1237:        for( PNALLN( prn, pn ) ) {
                   1238:                switch( pn->op ) {
                   1239:                case SAVE: continue;
                   1240:                case LABEL:
                   1241:                        fprintf( outfp, "%s:\n", pn->opcode );
                   1242:                        break;
                   1243:                case HLABEL:
                   1244:                        fprintf( outfp, "%s:\n", pn->opcode );
                   1245:                        break;
                   1246:                case MISC:
                   1247:                        fprintf( outfp, "       %s\n", pn->opcode );
                   1248:                        break;
                   1249:                case CALL:
                   1250:                        pn->opm = NULL;
                   1251:                        /* fall through */
                   1252:                default:
                   1253:                        fprintf( outfp, "       %s      ", pn->opcode );
                   1254:                        for( i = 1; i < MAXOPS + 1; i++ ) {
                   1255:                                if( (cp=pn->ops[i]) == NULL ) continue;
                   1256:                                if( i > 1 ) fprintf( outfp, "," );
                   1257:                                if( usesreg( cp, "%ap" ) ) {
                   1258:                                        if( *cp == '*') {
                   1259:                                                fprintf( outfp, "*" );
                   1260:                                                cp++;
                   1261:                                        }
                   1262:                                        fprintf( outfp, "%d(%%fp)",
                   1263:                                                atoi( cp ) +  numauto );
                   1264:                                }
                   1265:                                else fprintf( outfp, "%s", cp );
                   1266:                        }
                   1267:                        fprintf( outfp, "\n" );
                   1268:                        break;
                   1269:                }
                   1270:        }
                   1271: 
                   1272:        /* reset stack pointer if necessary */
                   1273:        if( nargs != 0 ) 
                   1274:                fprintf( outfp, "       subw2   &%d,%%sp\n", 4 * nargs );
                   1275: }
                   1276: 
                   1277: /* allocate procedure nodes */
                   1278: struct procnode *
                   1279: ilalloc( name )
                   1280: char   *name;  /* procedure name */
                   1281: {
                   1282:        register PNODE *prn;
                   1283: 
                   1284:        /* check whether node already exists */
                   1285:        for( ALLPN( prn ) ) {
                   1286:                if( strcmp( name, prn->pnname ) == 0 ) 
                   1287:                        return( prn );
                   1288:        }
                   1289: 
                   1290:        /* allocate node */
                   1291:        if( ( prn = ( PNODE * ) 
                   1292:                malloc( sizeof( PNODE ) + length( name ) ) ) == NULL ) 
                   1293:                return( prn );
                   1294:        prn->pnforw = prochead.pnforw;  
                   1295:        prn->pnback = &prochead;
                   1296:        prn->pnforw->pnback = prn;
                   1297:        prn->pnback->pnforw = prn;
                   1298:        prn->pnname = (char *) prn + sizeof( PNODE );
                   1299:        strcpy( prn->pnname, name );
                   1300:        prn->pncalls = 0;
                   1301:        prn->pnni = 0;
                   1302:        prn->pnhead = NULL;
                   1303:        return( prn );
                   1304: }
                   1305: #endif /* IMPIL */

unix.superglobalmegacorp.com

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