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
bsrecur defined in line 381; used 3 times
casecmp defined in line 442; used 2 times
directsw defined in line 258; used 1 times
itesw defined in line 423; used 1 times
pccaseop defined in line 61; used 1 times

Defined variables

sccsid defined in line 8; never used

Defined struct's

ct defined in line 29; used 24 times

Defined macros

ADDRTEMP defined in line 44; used 2 times
FORCENAME defined in line 43; used 22 times
Last modified: 1985-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3450
Valid CSS Valid XHTML 1.0 Strict