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[] = "@(#)cset.c 5.1 (Berkeley) 6/5/85"; 9: #endif not lint 10: 11: #include "whoami.h" 12: #include "0.h" 13: #include "tree.h" 14: #include "opcode.h" 15: #include "objfmt.h" 16: #include "tree_ty.h" 17: #ifdef PC 18: #include "pc.h" 19: #include <pcc.h> 20: #include "align.h" 21: #endif PC 22: 23: /* 24: * CONSETS causes compile time constant sets to be constructed here. 25: * 26: * COMPSETSZE defines the maximum number of longs to be used in 27: * constant set construction 28: */ 29: #define CONSETS 30: #define COMPSETSZE 10 31: 32: #define BITSPERBYTE 8 33: #define BITSPERLONG 32 34: #define LG2BITSBYTE 3 35: #define MSKBITSBYTE 0x07 36: #define LG2BITSLONG 5 37: #define MSKBITSLONG 0x1f 38: 39: /* 40: * rummage through a `constant' set (i.e. anything within [ ]'s) tree 41: * and decide if this is a compile time constant set or a runtime set. 42: * this information is returned in a structure passed from the caller. 43: * while rummaging, this also reorders the tree so that all ranges 44: * preceed all singletons. 45: */ 46: bool 47: precset( r , settype , csetp ) 48: struct tnode *r; 49: struct nl *settype; 50: struct csetstr *csetp; 51: { 52: register struct tnode *e; 53: register struct nl *t; 54: register struct nl *exptype; 55: register struct tnode *el; 56: register struct tnode *pairp; 57: register struct tnode *singp; 58: struct tnode *ip; 59: int lower; 60: int upper; 61: bool setofint; 62: 63: csetp -> csettype = NIL; 64: csetp -> paircnt = 0; 65: csetp -> singcnt = 0; 66: csetp -> comptime = TRUE; 67: setofint = FALSE; 68: if ( settype != NIL ) { 69: if ( settype -> class == SET ) { 70: /* 71: * the easy case, we are told the type of the set. 72: */ 73: exptype = settype -> type; 74: } else { 75: /* 76: * we are told the type, but it's not a set 77: * supposedly possible if someone tries 78: * e.g string context [1,2] = 'abc' 79: */ 80: error("Constant set involved in non set context"); 81: return csetp -> comptime; 82: } 83: } else { 84: /* 85: * So far we have no indication 86: * of what the set type should be. 87: * We "look ahead" and try to infer 88: * The type of the constant set 89: * by evaluating one of its members. 90: */ 91: e = r->cset_node.el_list; 92: if (e == NIL) { 93: /* 94: * tentative for [], return type of `intset' 95: */ 96: settype = lookup( (char *) intset ); 97: if ( settype == NIL ) { 98: panic( "empty set" ); 99: } 100: settype = settype -> type; 101: if ( settype == NIL ) { 102: return csetp -> comptime; 103: } 104: if ( isnta( settype , "t" ) ) { 105: error("Set default type \"intset\" is not a set"); 106: return csetp -> comptime; 107: } 108: csetp -> csettype = settype; 109: setran( settype -> type ); 110: if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 111: csetp -> comptime = FALSE; 112: return csetp -> comptime; 113: } 114: e = e->list_node.list; 115: if (e == NIL) { 116: return csetp -> comptime; 117: } 118: if (e->tag == T_RANG) { 119: e = e->rang.expr1; 120: } 121: codeoff(); 122: t = rvalue(e, NLNIL , RREQ ); 123: codeon(); 124: if (t == NIL) { 125: return csetp -> comptime; 126: } 127: /* 128: * The type of the set, settype, is 129: * deemed to be a set of the base type 130: * of t, which we call exptype. If, 131: * however, this would involve a 132: * "set of integer", we cop out 133: * and use "intset"'s current scoped 134: * type instead. 135: */ 136: if (isa(t, "r")) { 137: error("Sets may not have 'real' elements"); 138: return csetp -> comptime; 139: } 140: if (isnta(t, "bcsi")) { 141: error("Set elements must be scalars, not %ss", nameof(t)); 142: return csetp -> comptime; 143: } 144: if (isa(t, "i")) { 145: settype = lookup((char *) intset); 146: if (settype == NIL) 147: panic("intset"); 148: settype = settype->type; 149: if (settype == NIL) 150: return csetp -> comptime; 151: if (isnta(settype, "t")) { 152: error("Set default type \"intset\" is not a set"); 153: return csetp -> comptime; 154: } 155: exptype = settype->type; 156: /* 157: * say we are doing an intset 158: * but, if we get out of range errors for intset 159: * we punt constructing the set at compile time. 160: */ 161: setofint = TRUE; 162: } else { 163: exptype = t->type; 164: if (exptype == NIL) 165: return csetp -> comptime; 166: if (exptype->class != RANGE) 167: exptype = exptype->type; 168: settype = defnl((char *) 0, SET, exptype, 0); 169: } 170: } 171: csetp -> csettype = settype; 172: # ifndef CONSETS 173: csetp -> comptime = FALSE; 174: # endif CONSETS 175: setran( exptype ); 176: if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 177: csetp -> comptime = FALSE; 178: lower = set.lwrb; 179: upper = set.lwrb + set.uprbp; 180: pairp = NIL; 181: singp = NIL; 182: codeoff(); 183: while ( el = r->cset_node.el_list ) { 184: e = el->list_node.list; 185: if (e == NIL) { 186: /* 187: * don't hang this one anywhere. 188: */ 189: csetp -> csettype = NIL; 190: r->cset_node.el_list = el->list_node.next; 191: continue; 192: } 193: if (e->tag == T_RANG) { 194: if ( csetp -> comptime && constval( e->rang.expr2 ) ) { 195: #ifdef CONSETS 196: t = con.ctype; 197: if ( con.crval < lower || con.crval > upper ) { 198: if ( setofint ) { 199: csetp -> comptime = FALSE; 200: } else { 201: error("Range upper bound of %D out of set bounds" , ((long)con.crval) ); 202: csetp -> csettype = NIL; 203: } 204: } 205: #endif CONSETS 206: } else { 207: csetp -> comptime = FALSE; 208: t = rvalue(e->rang.expr2, NLNIL , RREQ ); 209: if (t == NIL) { 210: (void) rvalue(e->rang.expr1, NLNIL , RREQ ); 211: goto pairhang; 212: } 213: } 214: if (incompat(t, exptype, e->rang.expr2)) { 215: cerror("Upper bound of element type clashed with set type in constant set"); 216: } 217: if ( csetp -> comptime && constval( e->rang.expr1 ) ) { 218: #ifdef CONSETS 219: t = con.ctype; 220: if ( con.crval < lower || con.crval > upper ) { 221: if ( setofint ) { 222: csetp -> comptime = FALSE; 223: } else { 224: error("Range lower bound of %D out of set bounds" , ((long)con.crval) ); 225: csetp -> csettype = NIL; 226: } 227: } 228: #endif CONSETS 229: } else { 230: csetp -> comptime = FALSE; 231: t = rvalue(e->rang.expr1, NLNIL , RREQ ); 232: if (t == NIL) { 233: goto pairhang; 234: } 235: } 236: if (incompat(t, exptype, e->rang.expr1)) { 237: cerror("Lower bound of element type clashed with set type in constant set"); 238: } 239: pairhang: 240: /* 241: * remove this range from the tree list and 242: * hang it on the pairs list. 243: */ 244: ip = el->list_node.next; 245: el->list_node.next = pairp; 246: pairp = r->cset_node.el_list; 247: r->cset_node.el_list = ip; 248: csetp -> paircnt++; 249: } else { 250: if ( csetp -> comptime && constval( e ) ) { 251: #ifdef CONSETS 252: t = con.ctype; 253: if ( con.crval < lower || con.crval > upper ) { 254: if ( setofint ) { 255: csetp -> comptime = FALSE; 256: } else { 257: error("Value of %D out of set bounds" , ((long)con.crval) ); 258: csetp -> csettype = NIL; 259: } 260: } 261: #endif CONSETS 262: } else { 263: csetp -> comptime = FALSE; 264: t = rvalue( e, NLNIL , RREQ ); 265: if (t == NIL) { 266: goto singhang; 267: } 268: } 269: if (incompat(t, exptype, e)) { 270: cerror("Element type clashed with set type in constant set"); 271: } 272: singhang: 273: /* 274: * take this expression off the tree list and 275: * hang it on the list of singletons. 276: */ 277: ip = el->list_node.next; 278: el->list_node.next = singp; 279: singp = r->cset_node.el_list; 280: r->cset_node.el_list = ip; 281: csetp -> singcnt++; 282: } 283: } 284: codeon(); 285: # ifdef PC 286: if ( pairp != NIL ) { 287: for ( el = pairp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */; 288: el->list_node.next = singp; 289: r->cset_node.el_list = pairp; 290: } else { 291: r->cset_node.el_list = singp; 292: } 293: # endif PC 294: # ifdef OBJ 295: if ( singp != NIL ) { 296: for ( el = singp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */; 297: el->list_node.next = pairp; 298: r->cset_node.el_list = singp; 299: } else { 300: r->cset_node.el_list = pairp; 301: } 302: # endif OBJ 303: if ( csetp -> csettype == NIL ) { 304: csetp -> comptime = TRUE; 305: } 306: return csetp -> comptime; 307: } 308: 309: #ifdef CONSETS 310: /* 311: * mask[i] has the low i bits turned off. 312: */ 313: long mask[] = { 314: # ifdef DEC11 315: 0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 , 316: 0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 , 317: 0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 , 318: 0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 , 319: 0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 , 320: 0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 , 321: 0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 , 322: 0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 , 323: 0x00000000 324: # else 325: 0xffffffff , 0xfeffffff , 0xfcffffff , 0xf8ffffff , 326: 0xf0ffffff , 0xe0ffffff , 0xc0ffffff , 0x80ffffff , 327: 0x00ffffff , 0x00feffff , 0x00fcffff , 0x00f8ffff , 328: 0x00f0ffff , 0x00e0ffff , 0x00c0ffff , 0x0080ffff , 329: 0x0000ffff , 0x0000feff , 0x0000fcff , 0x0000f8ff , 330: 0x0000f0ff , 0x0000e0ff , 0x0000c0ff , 0x000080ff , 331: 0x000000ff , 0x000000fe , 0x000000fc , 0x000000f8 , 332: 0x000000f0 , 0x000000e0 , 0x000000c0 , 0x00000080 , 333: 0x00000000 334: # endif DEC11 335: }; 336: /* 337: * given a csetstr, either 338: * put out a compile time constant set and an lvalue to it. 339: * or 340: * put out rvalues for the singletons and the pairs 341: * and counts of each. 342: */ 343: #endif CONSETS 344: postcset( r , csetp ) 345: struct tnode *r; 346: struct csetstr *csetp; 347: { 348: register struct tnode *el; 349: register struct tnode *e; 350: int lower; 351: int upper; 352: int lowerdiv; 353: int lowermod; 354: int upperdiv; 355: int uppermod; 356: long *lp; 357: long *limit; 358: long tempset[ COMPSETSZE ]; 359: long temp; 360: char *cp; 361: # ifdef PC 362: int label; 363: char labelname[ BUFSIZ ]; 364: # endif PC 365: 366: if ( csetp -> comptime ) { 367: #ifdef CONSETS 368: setran( ( csetp -> csettype ) -> type ); 369: limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 370: for ( lp = &tempset[0] ; lp < limit ; lp++ ) { 371: *lp = 0; 372: } 373: for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 374: e = el->list_node.list; 375: if ( e->tag == T_RANG ) { 376: (void) constval( e->rang.expr1 ); 377: lower = con.crval; 378: (void) constval( e->rang.expr2 ); 379: upper = con.crval; 380: if ( upper < lower ) { 381: continue; 382: } 383: lowerdiv = ( lower - set.lwrb ) >> LG2BITSLONG; 384: lowermod = ( lower - set.lwrb ) & MSKBITSLONG; 385: upperdiv = ( upper - set.lwrb ) >> LG2BITSLONG; 386: uppermod = ( upper - set.lwrb ) & MSKBITSLONG; 387: temp = mask[ lowermod ]; 388: if ( lowerdiv == upperdiv ) { 389: temp &= ~mask[ uppermod + 1 ]; 390: } 391: tempset[ lowerdiv ] |= temp; 392: limit = &tempset[ upperdiv-1 ]; 393: for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) { 394: *lp |= 0xffffffff; 395: } 396: if ( lowerdiv != upperdiv ) { 397: tempset[ upperdiv ] |= ~mask[ uppermod + 1 ]; 398: } 399: } else { 400: (void) constval( e ); 401: temp = con.crval - set.lwrb; 402: cp = (char *)tempset; 403: cp[temp >> LG2BITSBYTE] |= (1 << (temp & MSKBITSBYTE)); 404: } 405: } 406: if ( !CGENNING ) 407: return; 408: # ifdef PC 409: label = (int) getlab(); 410: putprintf(" .data" , 0 ); 411: aligndot(A_SET); 412: (void) putlab( (char *) label ); 413: lp = &( tempset[0] ); 414: limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 415: while (lp < limit) { 416: putprintf(" .long 0x%x", 1, (int) (*lp++)); 417: for (temp = 2 ; temp <= 8 && lp < limit ; temp++) { 418: putprintf(",0x%x", 1, (int) (*lp++)); 419: } 420: putprintf("", 0); 421: } 422: putprintf(" .text", 0); 423: sprintf( labelname , PREFIXFORMAT , LABELPREFIX , (char *) label ); 424: putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR | PCCT_STRTY , labelname ); 425: # endif PC 426: # ifdef OBJ 427: (void) put(2, O_CON, (int)(((set.uprbp >> LG2BITSLONG) + 1) * 428: (BITSPERLONG >> LG2BITSBYTE))); 429: lp = &( tempset[0] ); 430: limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 431: while ( lp < limit ) { 432: (void) put(2, O_CASE4, (int) (*lp ++)); 433: } 434: # endif OBJ 435: #else 436: panic("const cset"); 437: #endif CONSETS 438: } else { 439: # ifdef PC 440: putleaf( PCC_ICON , (int) csetp -> paircnt , 0 , PCCT_INT , (char *) 0 ); 441: putop( PCC_CM , PCCT_INT ); 442: putleaf( PCC_ICON , (int) csetp -> singcnt , 0 , PCCT_INT , (char *) 0 ); 443: putop( PCC_CM , PCCT_INT ); 444: for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 445: e = el->list_node.list; 446: if ( e->tag == T_RANG ) { 447: (void) rvalue( e->rang.expr2 , NLNIL , RREQ ); 448: putop( PCC_CM , PCCT_INT ); 449: (void) rvalue( e->rang.expr1 , NLNIL , RREQ ); 450: putop( PCC_CM , PCCT_INT ); 451: } else { 452: (void) rvalue( e , NLNIL , RREQ ); 453: putop( PCC_CM , PCCT_INT ); 454: } 455: } 456: # endif PC 457: # ifdef OBJ 458: for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 459: e = el->list_node.list; 460: if ( e->tag == T_RANG ) { 461: (void) stkrval( e->rang.expr1 , NLNIL , (long) RREQ ); 462: (void) stkrval( e->rang.expr2 , NLNIL , (long) RREQ ); 463: } else { 464: (void) stkrval( e , NLNIL , (long) RREQ ); 465: } 466: } 467: (void) put(2 , O_CON24 , (int)csetp -> singcnt ); 468: (void) put(2 , O_CON24 , (int)csetp -> paircnt ); 469: # endif OBJ 470: } 471: }