|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.