Annotation of 43BSDReno/pgrm/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.2 (Berkeley) 11/12/86";
                      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: #if defined(vax) || defined(tahoe)
                     40: #   define     FORCENAME       "r0"
                     41: #endif vax || tahoe
                     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: 
                    296: #   ifdef tahoe
                    297:        if (opt('J')) {
                    298:            /*
                    299:             *  We have a table of absolute addresses.
                    300:             *
                    301:             *  subl2   to make r0 a 0-origin byte offset.
                    302:             *  cmpl    check against upper limit.
                    303:             *  jlssu   error if out of bounds.
                    304:             *  shal    to make r0 a 0-origin long offset,
                    305:             *  jmp     and indirect through it.
                    306:             */
                    307:            putprintf(" subl2   $%d,%s", 0, (int) ctab[1].cconst, (int) FORCENAME);
                    308:            putprintf(" cmpl    $%d,%s", 0,
                    309:                        (int) (ctab[count].cconst - ctab[1].cconst),
                    310:                        (int) FORCENAME);
                    311:            putprintf(" jlssu   %s%d", 0, (int) LABELPREFIX, ctab[0].clabel);
                    312:            putprintf(" shal    $2,%s,%s", 0, (int) FORCENAME, (int) FORCENAME);
                    313:            putprintf(" jmp     *%s%d(%s)", 0,
                    314:                    (int) LABELPREFIX, fromlabel, (int) FORCENAME);
                    315:        } else {
                    316:            /*
                    317:             *  We can use the TAHOE casel instruction with a table
                    318:             *  of short relative offsets.
                    319:             */
                    320:            putprintf(" casel   %s,$%d,$%d" , 0 , (int) FORCENAME ,
                    321:                    (int) ctab[1].cconst ,
                    322:                    (int) (ctab[ count ].cconst - ctab[1].cconst ));
                    323:            putprintf(" .align 1", 0);
                    324:        }
                    325: #   endif tahoe
                    326: 
                    327: #   ifdef mc68000
                    328:        /*
                    329:         *      subl    to make d0 a 0-origin byte offset.
                    330:         *      cmpl    check against upper limit.
                    331:         *      bhi     error if out of bounds.
                    332:         */
                    333:        putprintf("     subl    #%d,%s", 0, ctab[1].cconst, FORCENAME);
                    334:        putprintf("     cmpl    #%d,%s", 0,
                    335:                ctab[count].cconst - ctab[1].cconst, FORCENAME);
                    336:        putprintf("     bhi     %s%d", 0, LABELPREFIX, ctab[0].clabel);
                    337:        if (opt('J')) {
                    338:            /*
                    339:             *  We have a table of absolute addresses.
                    340:             *
                    341:             *  asll    to make d0 a 0-origin long offset.
                    342:             *  movl    pick up a jump-table entry
                    343:             *  jmp     and indirect through it.
                    344:             */
                    345:            putprintf(" asll    #2,%s", 0, FORCENAME, FORCENAME);
                    346:            putprintf(" movl    pc@(4,%s:l),%s", 0, FORCENAME, ADDRTEMP);
                    347:            putprintf(" jmp     %s@", 0, ADDRTEMP);
                    348:        } else {
                    349:            /*
                    350:             *  We have a table of relative addresses.
                    351:             *
                    352:             *  addw    to make d0 a 0-origin word offset.
                    353:             *  movw    pick up a jump-table entry
                    354:             *  jmp     and indirect through it.
                    355:             */
                    356:            putprintf(" addw    %s,%s", 0, FORCENAME, FORCENAME);
                    357:            putprintf(" movw    pc@(6,%s:w),%s", 0, FORCENAME, FORCENAME);
                    358:            putprintf(" jmp     pc@(2,%s:w)", 0, FORCENAME);
                    359:        }
                    360: #   endif mc68000
                    361:     (void) putlab( (char *) fromlabel );
                    362:     i = 1;
                    363:     j = ctab[1].cconst;
                    364:     while ( i <= count ) {
                    365:        if ( j == ctab[ i ].cconst ) {
                    366:            if (opt('J')) {
                    367:                putprintf( "    .long   " , 1 );
                    368:                putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , ctab[ i ].clabel );
                    369:            } else {
                    370:                putprintf( "    .word   " , 1 );
                    371:                putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , ctab[ i ].clabel );
                    372:                putprintf( "-" , 1 );
                    373:                putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , fromlabel );
                    374:            }
                    375:            i++;
                    376:        } else {
                    377:            if (opt('J')) {
                    378:                putprintf( "    .long   " , 1 );
                    379:                putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , ctab[ 0 ].clabel );
                    380:            } else {
                    381:                putprintf( "    .word   " , 1 );
                    382:                putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , ctab[ 0 ].clabel );
                    383:                putprintf( "-" , 1 );
                    384:                putprintf( PREFIXFORMAT , 0 , (int) LABELPREFIX , fromlabel );
                    385:            }
                    386:        }
                    387:        j++;
                    388:     }
                    389: #   if defined(vax) || defined(tahoe)
                    390:            /*
                    391:             *  execution continues here if value not in range of case.
                    392:             */
                    393:        if (!opt('J'))
                    394:            putjbr( (long) ctab[0].clabel );
                    395: #   endif vax || tahoe
                    396: }
                    397: 
                    398:     /*
                    399:      * binary switch
                    400:      * special case out default label and start recursion.
                    401:      */
                    402: binarysw( ctab , count )
                    403:     struct ct  *ctab;
                    404:     int                count;
                    405: {
                    406:     
                    407:     bsrecur( ctab[0].clabel , &ctab[0] , count );
                    408: }
                    409: 
                    410:     /*
                    411:      * recursive log( count ) search.
                    412:      */
                    413: bsrecur( deflabel , ctab , count )
                    414:     int                deflabel;
                    415:     struct ct  *ctab;
                    416:     int                count;
                    417: {
                    418: 
                    419:     if ( count <= 0 ) {
                    420:        putjbr((long) deflabel);
                    421:        return;
                    422:     } else if ( count == 1 ) {
                    423: #      if defined(vax) || defined(tahoe)
                    424:            putprintf(" cmpl    %s,$%d", 0, (int) FORCENAME, (int) ctab[1].cconst);
                    425:            putprintf(" jeql    %s%d", 0, (int) LABELPREFIX, ctab[1].clabel);
                    426:            putjbr((long) deflabel);
                    427: #      endif vax || tahoe
                    428: #      ifdef mc68000
                    429:            putprintf(" cmpl    #%d,%s", 0, ctab[1].cconst, (int) FORCENAME);
                    430:            putprintf(" jeq     L%d", 0, (int) LABELPREFIX, ctab[1].clabel);
                    431:            putjbr((long) deflabel);
                    432: #      endif mc68000
                    433:        return;
                    434:     } else {
                    435:        int     half = ( count + 1 ) / 2;
                    436:        int     gtrlabel = (int) getlab();
                    437: 
                    438: #      if defined(vax) || defined(tahoe)
                    439:            putprintf(" cmpl    %s,$%d", 0, (int) FORCENAME, (int) ctab[half].cconst);
                    440:            putprintf(" jgtr    %s%d", 0, (int) LABELPREFIX, gtrlabel);
                    441:            putprintf(" jeql    %s%d", 0, (int) LABELPREFIX, ctab[half].clabel);
                    442: #      endif vax || tahoe
                    443: #      ifdef mc68000
                    444:            putprintf(" cmpl    #%d,%s", 0, (int) ctab[half].cconst, (int) FORCENAME);
                    445:            putprintf(" jgt     %s%d", 0, (int) LABELPREFIX, gtrlabel);
                    446:            putprintf(" jeq     %s%d", 0, (int) LABELPREFIX, ctab[half].clabel);
                    447: #      endif mc68000
                    448:        bsrecur( deflabel , &ctab[0] , half - 1 );
                    449:        (void) putlab((char *) gtrlabel);
                    450:        bsrecur( deflabel , &ctab[ half ] , count - half );
                    451:        return;
                    452:     }
                    453: }
                    454: 
                    455: itesw( ctab , count )
                    456:     struct ct  *ctab;
                    457:     int                count;
                    458: {
                    459:     int        i;
                    460: 
                    461:     for ( i = 1 ; i <= count ; i++ ) {
                    462: #      if defined(vax) || defined(tahoe)
                    463:            putprintf(" cmpl    %s,$%d", 0, (int) FORCENAME, (int) ctab[i].cconst);
                    464:            putprintf(" jeql    %s%d", 0, (int) LABELPREFIX, ctab[i].clabel);
                    465: #      endif vax || tahoe
                    466: #      ifdef mc68000
                    467:            putprintf(" cmpl    #%d,%s", 0, (int) ctab[i].cconst, (int) FORCENAME);
                    468:            putprintf(" jeq     %s%d", 0, (int) LABELPREFIX, ctab[i].clabel);
                    469: #      endif mc68000
                    470:     }
                    471:     putjbr((long) ctab[0].clabel);
                    472:     return;
                    473: }
                    474: int
                    475: casecmp( this , that )
                    476:     struct ct  *this;
                    477:     struct ct  *that;
                    478: {
                    479:     if ( this -> cconst < that -> cconst ) {
                    480:        return -1;
                    481:     } else if ( this -> cconst > that -> cconst ) {
                    482:        return 1;
                    483:     } else {
                    484:        return 0;
                    485:     }
                    486: }
                    487: #endif PC

unix.superglobalmegacorp.com

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