Annotation of 40BSD/cmd/pi/pccaseop.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1980 Regents of the University of California */
                      2: 
                      3: static char sccsid[] = "@(#)pccaseop.c 1.4 10/8/80";
                      4: 
                      5: #include "whoami.h"
                      6: #ifdef PC
                      7:     /*
                      8:      * and the rest of the file
                      9:      */
                     10: #include "0.h"
                     11: #include "tree.h"
                     12: #include "objfmt.h"
                     13: #include "pcops.h"
                     14: #include "pc.h"
                     15: 
                     16:     /*
                     17:      * structure for a case: 
                     18:      *     its constant label, line number (for errors), and location label.
                     19:      */
                     20: struct ct {
                     21:     long       cconst;
                     22:     int                cline;
                     23:     int                clabel;
                     24: };
                     25: 
                     26:     /*
                     27:      * the P2FORCE operator puts its operand into a register.
                     28:      * these to keep from thinking of it as r0 all over.
                     29:      */
                     30: #define        FORCENAME       "r0"
                     31: #define        FORCENUMBER     0
                     32: 
                     33:     /*
                     34:      * given a tree for a case statement, generate code for it.
                     35:      * this computes the expression into a register,
                     36:      * puts down the code for each of the cases,
                     37:      * and then decides how to do the case switching.
                     38:      * tcase   [0]     T_CASE
                     39:      *         [1]     lineof "case"
                     40:      *         [2]     expression
                     41:      *         [3]     list of cased statements:
                     42:      *                 cstat   [0]     T_CSTAT
                     43:      *                         [1]     lineof ":"
                     44:      *                         [2]     list of constant labels
                     45:      *                         [3]     statement
                     46:      */
                     47: pccaseop( tcase )
                     48:     int        *tcase;
                     49: {
                     50:     struct nl  *exprtype;
                     51:     struct nl  *rangetype;
                     52:     long       low;
                     53:     long       high;
                     54:     long       exprctype;
                     55:     long       swlabel;
                     56:     long       endlabel;
                     57:     long       label;
                     58:     long       count;
                     59:     long       *cstatlp;
                     60:     long       *cstatp;
                     61:     long       *casep;
                     62:     struct ct  *ctab;
                     63:     struct ct  *ctp;
                     64:     long       i;
                     65:     long       nr;
                     66:     long       goc;
                     67:     int                casecmp();
                     68:     bool       dupcases;
                     69: 
                     70:     goc = gocnt;
                     71:        /*
                     72:         *  find out the type of the case expression
                     73:         *  even if the expression has errors (exprtype == NIL), continue.
                     74:         */
                     75:     line = tcase[1];
                     76:     exprtype = rvalue( (int *) tcase[2] , NIL  , RREQ );
                     77:     if ( exprtype != NIL ) {
                     78:        if ( isnta( exprtype , "bcsi" ) ) {
                     79:            error("Case selectors cannot be %ss" , nameof( exprtype ) );
                     80:            exprtype = NIL;
                     81:        } else {
                     82:            if ( exprtype -> class != RANGE ) {
                     83:                rangetype = exprtype -> type;
                     84:            } else {
                     85:                rangetype = exprtype;
                     86:            }
                     87:            if ( rangetype == NIL ) {
                     88:                exprtype = NIL;
                     89:            } else {
                     90:                low = rangetype -> range[0];
                     91:                high = rangetype -> range[1];
                     92:            }
                     93:        }
                     94:     }
                     95:     if ( exprtype != NIL ) {
                     96:            /*
                     97:             *  put expression into a register
                     98:             *  save its c-type and jump to the code to do the switch.
                     99:             */
                    100:        putop( P2FORCE , P2INT );
                    101:        putdot( filename , line );
                    102:        exprctype = p2type( exprtype );
                    103:        swlabel = getlab();
                    104:        putjbr( swlabel );
                    105:     }
                    106:        /*
                    107:         *  count the number of cases
                    108:         *  and allocate table for cases, lines, and labels
                    109:         *  default case goes in ctab[0].
                    110:         */
                    111:     count = 1;
                    112:     for ( cstatlp = tcase[3] ; cstatlp != NIL ; cstatlp = cstatlp[2] ) {
                    113:        cstatp = cstatlp[1];
                    114:        if ( cstatp == NIL ) {
                    115:            continue;
                    116:        }
                    117:        for ( casep = cstatp[2] ; casep != NIL ; casep = casep[2] ) {
                    118:            count++;
                    119:        }
                    120:     }
                    121:        /*
                    122:         */
                    123:     ctab = (struct ct *) malloc( count * sizeof( struct ct ) );
                    124:     if ( ctab == (struct ct *) 0 ) {
                    125:        error("Ran out of memory (case)");
                    126:        pexit( DIED );
                    127:     }
                    128:        /*
                    129:         *  pick up default label and label for after case statement.
                    130:         */
                    131:     ctab[0].clabel = getlab();
                    132:     endlabel = getlab();
                    133:        /*
                    134:         *  generate code for each case
                    135:         *  filling in ctab for each.
                    136:         *  nr is for error if no case falls out bottom.
                    137:         */
                    138:     nr = 1;
                    139:     count = 0;
                    140:     for ( cstatlp = tcase[3] ; cstatlp != NIL ; cstatlp = cstatlp[2] ) {
                    141:        cstatp = cstatlp[1];
                    142:        if ( cstatp == NIL ) {
                    143:            continue;
                    144:        }
                    145:        line = cstatp[1];
                    146:        label = getlab();
                    147:        for ( casep = cstatp[2] ; casep != NIL ; casep = casep[2] ) {
                    148:            gconst( casep[1] );
                    149:            if( exprtype == NIL || con.ctype == NIL ) {
                    150:                continue;
                    151:            }
                    152:            if ( incompat( con.ctype , exprtype , NIL ) ) {
                    153:                cerror("Case label type clashed with case selector expression type");
                    154:                continue;
                    155:            }
                    156:            if ( con.crval < low || con.crval > high ) {
                    157:                error("Case label out of range");
                    158:                continue;
                    159:            }
                    160:            count++;
                    161:            ctab[ count ].cconst = con.crval;
                    162:            ctab[ count ].cline = line;
                    163:            ctab[ count ].clabel = label;
                    164:        }
                    165:            /*
                    166:             *  put out the statement
                    167:             */
                    168:        putlab( label );
                    169:        putcnt();
                    170:        level++;
                    171:        statement( cstatp[3] );
                    172:        nr &= noreach;
                    173:        noreach = 0;
                    174:        level--;
                    175:        if (gotos[cbn]) {
                    176:                ungoto();
                    177:        }
                    178:        putjbr( endlabel );
                    179:     }
                    180:     noreach = nr;
                    181:        /*
                    182:         *      default action is to call error
                    183:         */
                    184:     putlab( ctab[0].clabel );
                    185:     putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_ERROR" );
                    186:     putleaf( P2ICON , ECASE , 0 , P2INT , 0 );
                    187:     putleaf( P2REG , FORCENUMBER , 0 , P2INT , 0 );
                    188:     putop( P2LISTOP , P2INT );
                    189:     putop( P2CALL , P2INT );
                    190:     putdot( filename , line );
                    191:        /*
                    192:         *  sort the cases
                    193:         */
                    194:     qsort( &ctab[1] , count , sizeof (struct ct) , casecmp );
                    195:        /*
                    196:         *  check for duplicates
                    197:         */
                    198:     dupcases = FALSE;
                    199:     for ( ctp = &ctab[1] ; ctp < &ctab[ count ] ; ctp++ ) {
                    200:        if ( ctp[0].cconst == ctp[1].cconst ) {
                    201:            error("Multiply defined label in case, lines %d and %d" ,
                    202:                    ctp[0].cline , ctp[1].cline );
                    203:            dupcases = TRUE;
                    204:        }
                    205:     }
                    206:     if ( dupcases ) {
                    207:        return;
                    208:     }
                    209:        /*
                    210:         *  choose a switch algorithm and implement it:
                    211:         *      direct switch   >= 1/3 full and >= 4 cases.
                    212:         *      binary switch   not direct switch and > 8 cases.
                    213:         *      ifthenelse      not direct or binary switch.
                    214:         */
                    215:     putlab( swlabel );
                    216:     if ( ctab[ count ].cconst - ctab[1].cconst < 3 * count && count >= 4 ) {
                    217:        directsw( ctab , count );
                    218:     } else if ( count > 8 ) {
                    219:        binarysw( ctab , count );
                    220:     } else {
                    221:        itesw( ctab , count );
                    222:     }
                    223:     putlab( endlabel );
                    224:     if ( goc != gocnt ) {
                    225:            putcnt();
                    226:     }
                    227: }
                    228: 
                    229:     /*
                    230:      * direct switch
                    231:      */
                    232: directsw( ctab , count )
                    233:     struct ct  *ctab;
                    234:     int                count;
                    235: {
                    236:     int                fromlabel = getlab();
                    237:     long       i;
                    238:     long       j;
                    239: 
                    240:     putprintf( "       casel   %s,$%d,$%d" , 0 , FORCENAME ,
                    241:            ctab[1].cconst , ctab[ count ].cconst - ctab[1].cconst );
                    242:     putlab( fromlabel );
                    243:     i = 1;
                    244:     j = ctab[1].cconst;
                    245:     while ( i <= count ) {
                    246:        if ( j == ctab[ i ].cconst ) {
                    247:            putprintf( "        .word   " , 1 );
                    248:            putprintf( PREFIXFORMAT , 1 , LABELPREFIX , ctab[ i ].clabel );
                    249:            putprintf( "-" , 1 );
                    250:            putprintf( PREFIXFORMAT , 0 , LABELPREFIX , fromlabel );
                    251:            i++;
                    252:        } else {
                    253:            putprintf( "        .word   " , 1 );
                    254:            putprintf( PREFIXFORMAT , 1 , LABELPREFIX , ctab[ 0 ].clabel );
                    255:            putprintf( "-" , 1 );
                    256:            putprintf( PREFIXFORMAT , 0 , LABELPREFIX , fromlabel );
                    257:        }
                    258:        j++;
                    259:     }
                    260:     putjbr( ctab[0].clabel );
                    261: }
                    262: 
                    263:     /*
                    264:      * binary switch
                    265:      * special case out default label and start recursion.
                    266:      */
                    267: binarysw( ctab , count )
                    268:     struct ct  *ctab;
                    269:     int                count;
                    270: {
                    271:     
                    272:     bsrecur( ctab[0].clabel , &ctab[0] , count );
                    273: }
                    274: 
                    275:     /*
                    276:      * recursive log( count ) search.
                    277:      */
                    278: bsrecur( deflabel , ctab , count )
                    279:     int                deflabel;
                    280:     struct ct  *ctab;
                    281:     int                count;
                    282: {
                    283: 
                    284:     if ( count <= 0 ) {
                    285:        putprintf( "    jbr     L%d" , 0 , deflabel );
                    286:        return;
                    287:     } else if ( count == 1 ) {
                    288:        putprintf( "    cmpl    %s,$%d" , 0 , FORCENAME , ctab[1].cconst );
                    289:        putprintf( "    jeql    L%d" , 0 , ctab[1].clabel );
                    290:        putprintf( "    jbr     L%d" , 0 , deflabel );
                    291:        return;
                    292:     } else {
                    293:        int     half = ( count + 1 ) / 2;
                    294:        int     gtrlabel = getlab();
                    295: 
                    296:        putprintf( "    cmpl    %s,$%d" , 0 , FORCENAME , ctab[ half ].cconst );
                    297:        putprintf( "    jgtr    L%d" , 0 , gtrlabel );
                    298:        putprintf( "    jeql    L%d" , 0 , ctab[ half ].clabel );
                    299:        bsrecur( deflabel , &ctab[0] , half - 1 );
                    300:        putprintf( "L%d:" , 0 , gtrlabel );
                    301:        bsrecur( deflabel , &ctab[ half ] , count - half );
                    302:        return;
                    303:     }
                    304: }
                    305: 
                    306: itesw( ctab , count )
                    307:     struct ct  *ctab;
                    308:     int                count;
                    309: {
                    310:     int        i;
                    311: 
                    312:     for ( i = 1 ; i <= count ; i++ ) {
                    313:        putprintf( "    cmpl    %s,$%d" , 0 , FORCENAME , ctab[ i ].cconst );
                    314:        putprintf( "    jeql    L%d" , 0 , ctab[ i ].clabel );
                    315:     }
                    316:     putprintf( "       jbr     L%d" , 0 , ctab[0].clabel );
                    317:     return;
                    318: }
                    319: int
                    320: casecmp( this , that )
                    321:     struct ct  *this;
                    322:     struct ct  *that;
                    323: {
                    324:     if ( this -> cconst < that -> cconst ) {
                    325:        return -1;
                    326:     } else if ( this -> cconst > that -> cconst ) {
                    327:        return 1;
                    328:     } else {
                    329:        return 0;
                    330:     }
                    331: }
                    332: #endif PC

unix.superglobalmegacorp.com

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