Annotation of 43BSD/ucb/pascal/src/pccaseop.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)pccaseop.c 5.1 (Berkeley) 6/5/85";
                      9: #endif not lint
                     10: 
                     11: 
                     12: #include "whoami.h"
                     13: #ifdef PC
                     14:     /*
                     15:      * and the rest of the file
                     16:      */
                     17: #include "0.h"
                     18: #include "tree.h"
                     19: #include "objfmt.h"
                     20: #include <pcc.h>
                     21: #include "pc.h"
                     22: #include "tmps.h"
                     23: #include "tree_ty.h"
                     24: 
                     25:     /*
                     26:      * structure for a case: 
                     27:      *     its constant label, line number (for errors), and location label.
                     28:      */
                     29: struct ct {
                     30:     long       cconst;
                     31:     int                cline;
                     32:     int                clabel;
                     33: };
                     34: 
                     35:     /*
                     36:      * the PCC_FORCE operator puts its operand into a register.
                     37:      * these to keep from thinking of it as r0 all over.
                     38:      */
                     39: #ifdef vax
                     40: #   define     FORCENAME       "r0"
                     41: #endif vax
                     42: #ifdef mc68000
                     43: #   define     FORCENAME       "d0"
                     44: #   define     ADDRTEMP        "a0"
                     45: #endif mc68000
                     46: 
                     47:     /*
                     48:      * given a tree for a case statement, generate code for it.
                     49:      * this computes the expression into a register,
                     50:      * puts down the code for each of the cases,
                     51:      * and then decides how to do the case switching.
                     52:      * tcase   [0]     T_CASE
                     53:      *         [1]     lineof "case"
                     54:      *         [2]     expression
                     55:      *         [3]     list of cased statements:
                     56:      *                 cstat   [0]     T_CSTAT
                     57:      *                         [1]     lineof ":"
                     58:      *                         [2]     list of constant labels
                     59:      *                         [3]     statement
                     60:      */
                     61: pccaseop( tcase )
                     62:     WHI_CAS *tcase;
                     63: {
                     64:     struct nl  *exprtype;
                     65:     struct nl  *exprnlp;
                     66:     struct nl  *rangetype;
                     67:     long       low;
                     68:     long       high;
                     69:     long       exprctype;
                     70:     char       *swlabel;
                     71:     char       *endlabel;
                     72:     char       *label;
                     73:     int                count;
                     74:     struct tnode *cstatlp;
                     75:     struct tnode *cstatp;
                     76:     struct tnode *casep;
                     77:     struct ct  *ctab;
                     78:     struct ct  *ctp;
                     79:     bool       nr;
                     80:     long       goc;
                     81:     int                casecmp();
                     82:     bool       dupcases;
                     83: 
                     84:     goc = gocnt;
                     85:        /*
                     86:         *  find out the type of the case expression
                     87:         *  even if the expression has errors (exprtype == NIL), continue.
                     88:         */
                     89:     line = tcase->line_no;
                     90:     codeoff();
                     91:     exprtype = rvalue( tcase->expr , NLNIL  , RREQ );
                     92:     codeon();
                     93:     if ( exprtype != NLNIL ) {
                     94:        if ( isnta( exprtype , "bcsi" ) ) {
                     95:            error("Case selectors cannot be %ss" , nameof( exprtype ) );
                     96:            exprtype = NLNIL;
                     97:        } else {
                     98:            if ( exprtype -> class != RANGE ) {
                     99:                rangetype = exprtype -> type;
                    100:            } else {
                    101:                rangetype = exprtype;
                    102:            }
                    103:            if ( rangetype == NLNIL ) {
                    104:                exprtype = NLNIL;
                    105:            } else {
                    106:                low = rangetype -> range[0];
                    107:                high = rangetype -> range[1];
                    108:            }
                    109:        }
                    110:     }
                    111:     if ( exprtype != NLNIL ) {
                    112:            /*
                    113:             *  compute and save the case expression.
                    114:             *  also, put expression into a register
                    115:             *  save its c-type and jump to the code to do the switch.
                    116:             */
                    117:        exprctype = p2type( exprtype );
                    118:        exprnlp = tmpalloc( (long) (sizeof (long)), nl + T4INT , NOREG );
                    119:        putRV((char *) 0 , cbn , exprnlp -> value[ NL_OFFS ] ,
                    120:                        exprnlp -> extra_flags , PCCT_INT );
                    121:        (void) rvalue( tcase->expr , NLNIL , RREQ );
                    122:        sconv((int) exprctype, (int) PCCT_INT);
                    123:        putop( PCC_ASSIGN , PCCT_INT );
                    124:        putop( PCC_FORCE , PCCT_INT );
                    125:        putdot( filename , line );
                    126:        swlabel = getlab();
                    127:        putjbr( (long) swlabel );
                    128:     }
                    129:        /*
                    130:         *  count the number of cases
                    131:         *  and allocate table for cases, lines, and labels
                    132:         *  default case goes in ctab[0].
                    133:         */
                    134:     count = 1;
                    135:     for ( cstatlp = tcase->stmnt_list ; cstatlp != TR_NIL ;
                    136:                cstatlp = cstatlp->list_node.next ) {
                    137:        cstatp = cstatlp->list_node.list;
                    138:        if ( cstatp == TR_NIL ) {
                    139:            continue;
                    140:        }
                    141:        for ( casep = cstatp->c_stmnt.const_list ; casep != TR_NIL ;
                    142:                        casep = casep->list_node.next ) {
                    143:            count++;
                    144:        }
                    145:     }
                    146:        /*
                    147:         */
                    148:     ctab = (struct ct *) malloc( count * sizeof( struct ct ) );
                    149:     if ( ctab == (struct ct *) 0 ) {
                    150:        error("Ran out of memory (case)");
                    151:        pexit( DIED );
                    152:     }
                    153:        /*
                    154:         *  pick up default label and label for after case statement.
                    155:         */
                    156:     ctab[0].clabel = (int) getlab();
                    157:     endlabel = getlab();
                    158:        /*
                    159:         *  generate code for each case
                    160:         *  filling in ctab for each.
                    161:         *  nr is for error if no case falls out bottom.
                    162:         */
                    163:     nr = TRUE;;
                    164:     count = 0;
                    165:     for ( cstatlp = tcase->stmnt_list ; cstatlp != TR_NIL ;
                    166:                cstatlp = cstatlp->list_node.next ) {
                    167:        cstatp = cstatlp->list_node.list;
                    168:        if ( cstatp == TR_NIL ) {
                    169:            continue;
                    170:        }
                    171:        line = cstatp->c_stmnt.line_no;
                    172:        label = getlab();
                    173:        for ( casep = cstatp->c_stmnt.const_list ; casep != TR_NIL ;
                    174:                        casep = casep->list_node.next ) {
                    175:            gconst( casep->list_node.list );
                    176:            if( exprtype == NLNIL || con.ctype == NIL ) {
                    177:                continue;
                    178:            }
                    179:            if ( incompat( con.ctype , exprtype , TR_NIL ) ) {
                    180:                cerror("Case label type clashed with case selector expression type");
                    181:                continue;
                    182:            }
                    183:            if ( con.crval < low || con.crval > high ) {
                    184:                error("Case label out of range");
                    185:                continue;
                    186:            }
                    187:            count++;
                    188:            ctab[ count ].cconst = con.crval;
                    189:            ctab[ count ].cline = line;
                    190:            ctab[ count ].clabel = (int) label;
                    191:        }
                    192:            /*
                    193:             *  put out the statement
                    194:             */
                    195:        (void) putlab( label );
                    196:        putcnt();
                    197:        level++;
                    198:        statement( cstatp->c_stmnt.stmnt );
                    199:        nr = (nr && noreach)?TRUE:FALSE;
                    200:        noreach = FALSE;
                    201:        level--;
                    202:        if (gotos[cbn]) {
                    203:                ungoto();
                    204:        }
                    205:        putjbr( (long) endlabel );
                    206:     }
                    207:     noreach = nr;
                    208:        /*
                    209:         *      default action is to call error
                    210:         */
                    211:     (void) putlab( (char *) ctab[0].clabel );
                    212:     putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_CASERNG" );
                    213:     putRV((char *) 0 , cbn , exprnlp -> value[ NL_OFFS ] ,
                    214:                    exprnlp -> extra_flags , PCCT_INT );
                    215:     putop( PCC_CALL , PCCT_INT );
                    216:     putdot( filename , line );
                    217:        /*
                    218:         *  sort the cases
                    219:         */
                    220:     qsort( &ctab[1] , count , sizeof (struct ct) , casecmp );
                    221:        /*
                    222:         *  check for duplicates
                    223:         */
                    224:     dupcases = FALSE;
                    225:     for ( ctp = &ctab[1] ; ctp < &ctab[ count ] ; ctp++ ) {
                    226:        if ( ctp[0].cconst == ctp[1].cconst ) {
                    227:            error("Multiply defined label in case, lines %d and %d" ,
                    228:                    (char *) ctp[0].cline , (char *) ctp[1].cline );
                    229:            dupcases = TRUE;
                    230:        }
                    231:     }
                    232:     if ( dupcases ) {
                    233:        return;
                    234:     }
                    235:        /*
                    236:         *  choose a switch algorithm and implement it:
                    237:         *      direct switch   >= 1/3 full and >= 4 cases.
                    238:         *      binary switch   not direct switch and > 8 cases.
                    239:         *      ifthenelse      not direct or binary switch.
                    240:         */
                    241:     (void) putlab( swlabel );
                    242:     if ( ctab[ count ].cconst - ctab[1].cconst < 3 * count && count >= 4 ) {
                    243:        directsw( ctab , count );
                    244:     } else if ( count > 8 ) {
                    245:        binarysw( ctab , count );
                    246:     } else {
                    247:        itesw( ctab , count );
                    248:     }
                    249:     (void) putlab( endlabel );
                    250:     if ( goc != gocnt ) {
                    251:            putcnt();
                    252:     }
                    253: }
                    254: 
                    255:     /*
                    256:      * direct switch
                    257:      */
                    258: directsw( ctab , count )
                    259:     struct ct  *ctab;
                    260:     int                count;
                    261: {
                    262:     int                fromlabel = (int) getlab();
                    263:     long       i;
                    264:     long       j;
                    265: 
                    266: #   ifdef vax
                    267:        if (opt('J')) {
                    268:            /*
                    269:             *  We have a table of absolute addresses.
                    270:             *
                    271:             *  subl2   to make r0 a 0-origin byte offset.
                    272:             *  cmpl    check against upper limit.
                    273:             *  jlssu   error if out of bounds.
                    274:             *  ashl    to make r0 a 0-origin long offset,
                    275:             *  jmp     and indirect through it.
                    276:             */
                    277:            putprintf(" subl2   $%d,%s", 0, (int) ctab[1].cconst, (int) FORCENAME);
                    278:            putprintf(" cmpl    $%d,%s", 0,
                    279:                        (int) (ctab[count].cconst - ctab[1].cconst),
                    280:                        (int) FORCENAME);
                    281:            putprintf(" jlssu   %s%d", 0, (int) LABELPREFIX, ctab[0].clabel);
                    282:            putprintf(" ashl    $2,%s,%s", 0, (int) FORCENAME, (int) FORCENAME);
                    283:            putprintf(" jmp     *%s%d(%s)", 0,
                    284:                    (int) LABELPREFIX, fromlabel, (int) FORCENAME);
                    285:        } else {
                    286:            /*
                    287:             *  We can use the VAX casel instruction with a table
                    288:             *  of short relative offsets.
                    289:             */
                    290:            putprintf(" casel   %s,$%d,$%d" , 0 , (int) FORCENAME ,
                    291:                    (int) ctab[1].cconst ,
                    292:                    (int) (ctab[ count ].cconst - ctab[1].cconst ));
                    293:        }
                    294: #   endif vax
                    295: #   ifdef mc68000
                    296:        /*
                    297:         *      subl    to make d0 a 0-origin byte offset.
                    298:         *      cmpl    check against upper limit.
                    299:         *      bhi     error if out of bounds.
                    300:         */
                    301:        putprintf("     subl    #%d,%s", 0, ctab[1].cconst, FORCENAME);
                    302:        putprintf("     cmpl    #%d,%s", 0,
                    303:                ctab[count].cconst - ctab[1].cconst, FORCENAME);
                    304:        putprintf("     bhi     %s%d", 0, LABELPREFIX, ctab[0].clabel);
                    305:        if (opt('J')) {
                    306:            /*
                    307:             *  We have a table of absolute addresses.
                    308:             *
                    309:             *  asll    to make d0 a 0-origin long offset.
                    310:             *  movl    pick up a jump-table entry
                    311:             *  jmp     and indirect through it.
                    312:             */
                    313:            putprintf(" asll    #2,%s", 0, FORCENAME, FORCENAME);
                    314:            putprintf(" movl    pc@(4,%s:l),%s", 0, FORCENAME, ADDRTEMP);
                    315:            putprintf(" jmp     %s@", 0, ADDRTEMP);
                    316:        } else {
                    317:            /*
                    318:             *  We have a table of relative addresses.
                    319:             *
                    320:             *  addw    to make d0 a 0-origin word offset.
                    321:             *  movw    pick up a jump-table entry
                    322:             *  jmp     and indirect through it.
                    323:             */
                    324:            putprintf(" addw    %s,%s", 0, FORCENAME, FORCENAME);
                    325:            putprintf(" movw    pc@(6,%s:w),%s", 0, FORCENAME, FORCENAME);
                    326:            putprintf(" jmp     pc@(2,%s:w)", 0, FORCENAME);
                    327:        }
                    328: #   endif mc68000
                    329:     (void) putlab( (char *) fromlabel );
                    330:     i = 1;
                    331:     j = ctab[1].cconst;
                    332:     while ( i <= count ) {
                    333:        if ( j == ctab[ i ].cconst ) {
                    334:            if (opt('J')) {
                    335:                putprintf( "    .long   " , 1 );
                    336:                putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , ctab[ i ].clabel );
                    337:            } else {
                    338:                putprintf( "    .word   " , 1 );
                    339:                putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , ctab[ i ].clabel );
                    340:                putprintf( "-" , 1 );
                    341:                putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , fromlabel );
                    342:            }
                    343:            i++;
                    344:        } else {
                    345:            if (opt('J')) {
                    346:                putprintf( "    .long   " , 1 );
                    347:                putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , ctab[ 0 ].clabel );
                    348:            } else {
                    349:                putprintf( "    .word   " , 1 );
                    350:                putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , ctab[ 0 ].clabel );
                    351:                putprintf( "-" , 1 );
                    352:                putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , fromlabel );
                    353:            }
                    354:        }
                    355:        j++;
                    356:     }
                    357: #   ifdef vax
                    358:            /*
                    359:             *  execution continues here if value not in range of case.
                    360:             */
                    361:        if (!opt('J'))
                    362:            putjbr( (long) ctab[0].clabel );
                    363: #   endif vax
                    364: }
                    365: 
                    366:     /*
                    367:      * binary switch
                    368:      * special case out default label and start recursion.
                    369:      */
                    370: binarysw( ctab , count )
                    371:     struct ct  *ctab;
                    372:     int                count;
                    373: {
                    374:     
                    375:     bsrecur( ctab[0].clabel , &ctab[0] , count );
                    376: }
                    377: 
                    378:     /*
                    379:      * recursive log( count ) search.
                    380:      */
                    381: bsrecur( deflabel , ctab , count )
                    382:     int                deflabel;
                    383:     struct ct  *ctab;
                    384:     int                count;
                    385: {
                    386: 
                    387:     if ( count <= 0 ) {
                    388:        putjbr((long) deflabel);
                    389:        return;
                    390:     } else if ( count == 1 ) {
                    391: #      ifdef vax
                    392:            putprintf(" cmpl    %s,$%d", 0, (int) FORCENAME, (int) ctab[1].cconst);
                    393:            putprintf(" jeql    %s%d", 0, (int) LABELPREFIX, ctab[1].clabel);
                    394:            putjbr((long) deflabel);
                    395: #      endif vax
                    396: #      ifdef mc68000
                    397:            putprintf(" cmpl    #%d,%s", 0, ctab[1].cconst, (int) FORCENAME);
                    398:            putprintf(" jeq     L%d", 0, (int) LABELPREFIX, ctab[1].clabel);
                    399:            putjbr((long) deflabel);
                    400: #      endif mc68000
                    401:        return;
                    402:     } else {
                    403:        int     half = ( count + 1 ) / 2;
                    404:        int     gtrlabel = (int) getlab();
                    405: 
                    406: #      ifdef vax
                    407:            putprintf(" cmpl    %s,$%d", 0, (int) FORCENAME, (int) ctab[half].cconst);
                    408:            putprintf(" jgtr    %s%d", 0, (int) LABELPREFIX, gtrlabel);
                    409:            putprintf(" jeql    %s%d", 0, (int) LABELPREFIX, ctab[half].clabel);
                    410: #      endif vax
                    411: #      ifdef mc68000
                    412:            putprintf(" cmpl    #%d,%s", 0, (int) ctab[half].cconst, (int) FORCENAME);
                    413:            putprintf(" jgt     %s%d", 0, (int) LABELPREFIX, gtrlabel);
                    414:            putprintf(" jeq     %s%d", 0, (int) LABELPREFIX, ctab[half].clabel);
                    415: #      endif mc68000
                    416:        bsrecur( deflabel , &ctab[0] , half - 1 );
                    417:        (void) putlab((char *) gtrlabel);
                    418:        bsrecur( deflabel , &ctab[ half ] , count - half );
                    419:        return;
                    420:     }
                    421: }
                    422: 
                    423: itesw( ctab , count )
                    424:     struct ct  *ctab;
                    425:     int                count;
                    426: {
                    427:     int        i;
                    428: 
                    429:     for ( i = 1 ; i <= count ; i++ ) {
                    430: #      ifdef vax
                    431:            putprintf(" cmpl    %s,$%d", 0, (int) FORCENAME, (int) ctab[i].cconst);
                    432:            putprintf(" jeql    %s%d", 0, (int) LABELPREFIX, ctab[i].clabel);
                    433: #      endif vax
                    434: #      ifdef mc68000
                    435:            putprintf(" cmpl    #%d,%s", 0, (int) ctab[i].cconst, (int) FORCENAME);
                    436:            putprintf(" jeq     %s%d", 0, (int) LABELPREFIX, ctab[i].clabel);
                    437: #      endif mc68000
                    438:     }
                    439:     putjbr((long) ctab[0].clabel);
                    440:     return;
                    441: }
                    442: int
                    443: casecmp( this , that )
                    444:     struct ct  *this;
                    445:     struct ct  *that;
                    446: {
                    447:     if ( this -> cconst < that -> cconst ) {
                    448:        return -1;
                    449:     } else if ( this -> cconst > that -> cconst ) {
                    450:        return 1;
                    451:     } else {
                    452:        return 0;
                    453:     }
                    454: }
                    455: #endif PC

unix.superglobalmegacorp.com

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