# 2.11BSD#431 - /usr/src/ucb/PORT/pascal/src/pccaseop.c

##### Functions

    binarysw          X
    bsrecur           X
    casecmp           X
    directsw          X
    itesw             X
    pccaseop          X

##### Macros

    ADDRTEMP          X
    FORCENAME         X

##### struct's

    ct                X

       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

#### Defined functions

binarysw defined in line 370; used 1 times

- in line 245

bsrecur defined in line 381; used 3 times

- in line 375, 416-418(2)

casecmp defined in line 442; used 2 times

- in line 81, 220

directsw defined in line 258; used 1 times

- in line 243

itesw defined in line 423; used 1 times

- in line 247

pccaseop defined in line 61; used 1 times

- in /usr/src/ucb/PORT/pascal/src/stat.c line 121

#### Defined variables

sccsid defined in line 8; never used

#### Defined struct's

ct defined in line 29; used 24 times

- in line 77-78(4), 148-149(6), 220(2), 259(2), 371(2), 383(2), 424(2), 444-445(4)

#### Defined macros

ADDRTEMP defined in line 44; used 2 times

- in line 314-315(2)

FORCENAME defined in line 43; used 22 times

- in line 277-284(5), 290, 301-303(2), 313-314(3), 324-326(5), 392-397(2), 407-412(2), 431-435(2)

Last modified: 1985-06-05 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1607 |