1750Speter /* Copyright (c) 1979 Regents of the University of California */ 2750Speter 3*1884Speter static char sccsid[] = "@(#)cset.c 1.3 12/12/80"; 4750Speter 5750Speter #include "whoami.h" 6750Speter #include "0.h" 7750Speter #include "tree.h" 8750Speter #include "opcode.h" 9750Speter #include "objfmt.h" 10750Speter #include "pc.h" 11750Speter #include "pcops.h" 12750Speter 13750Speter /* 14750Speter * rummage through a `constant' set (i.e. anything within [ ]'s) tree 15750Speter * and decide if this is a compile time constant set or a runtime set. 16750Speter * this information is returned in a structure passed from the caller. 17750Speter * while rummaging, this also reorders the tree so that all ranges 18750Speter * preceed all singletons. 19750Speter */ 20750Speter bool 21750Speter precset( r , settype , csetp ) 22750Speter int *r; 23750Speter struct nl *settype; 24750Speter struct csetstr *csetp; 25750Speter { 26750Speter register int *e; 27750Speter register struct nl *t; 28750Speter register struct nl *exptype; 29750Speter register int *el; 30750Speter register int *pairp; 31750Speter register int *singp; 32750Speter int *ip; 33750Speter long lower; 34750Speter long upper; 35750Speter long rangeupper; 36750Speter bool setofint; 37750Speter 38750Speter csetp -> csettype = NIL; 39750Speter csetp -> paircnt = 0; 40750Speter csetp -> singcnt = 0; 41750Speter csetp -> comptime = TRUE; 42750Speter setofint = FALSE; 43750Speter if ( settype != NIL ) { 44750Speter if ( settype -> class == SET ) { 45750Speter /* 46750Speter * the easy case, we are told the type of the set. 47750Speter */ 48750Speter exptype = settype -> type; 49750Speter } else { 50750Speter /* 51750Speter * we are told the type, but it's not a set 52750Speter * supposedly possible if someone tries 53750Speter * e.g string context [1,2] = 'abc' 54750Speter */ 55750Speter error("Constant set involved in non set context"); 56750Speter return csetp -> comptime; 57750Speter } 58750Speter } else { 59750Speter /* 60750Speter * So far we have no indication 61750Speter * of what the set type should be. 62750Speter * We "look ahead" and try to infer 63750Speter * The type of the constant set 64750Speter * by evaluating one of its members. 65750Speter */ 66750Speter e = r[2]; 67750Speter if (e == NIL) { 68750Speter /* 691552Speter * tentative for [], return type of `intset' 70750Speter */ 711552Speter settype = lookup( intset ); 721552Speter if ( settype == NIL ) { 731552Speter panic( "empty set" ); 741552Speter } 751552Speter settype = settype -> type; 761552Speter if ( settype == NIL ) { 771552Speter return csetp -> comptime; 781552Speter } 791552Speter if ( isnta( settype , "t" ) ) { 801552Speter error("Set default type \"intset\" is not a set"); 811552Speter return csetp -> comptime; 821552Speter } 831552Speter csetp -> csettype = settype; 84750Speter return csetp -> comptime; 85750Speter } 86750Speter e = e[1]; 87750Speter if (e == NIL) { 88750Speter return csetp -> comptime; 89750Speter } 90750Speter if (e[0] == T_RANG) { 91750Speter e = e[1]; 92750Speter } 93750Speter codeoff(); 94750Speter t = rvalue(e, NIL , RREQ ); 95750Speter codeon(); 96750Speter if (t == NIL) { 97750Speter return csetp -> comptime; 98750Speter } 99750Speter /* 100750Speter * The type of the set, settype, is 101750Speter * deemed to be a set of the base type 102750Speter * of t, which we call exptype. If, 103750Speter * however, this would involve a 104750Speter * "set of integer", we cop out 105750Speter * and use "intset"'s current scoped 106750Speter * type instead. 107750Speter */ 108750Speter if (isa(t, "r")) { 109750Speter error("Sets may not have 'real' elements"); 110750Speter return csetp -> comptime; 111750Speter } 112750Speter if (isnta(t, "bcsi")) { 113750Speter error("Set elements must be scalars, not %ss", nameof(t)); 114750Speter return csetp -> comptime; 115750Speter } 116750Speter if (isa(t, "i")) { 117750Speter settype = lookup(intset); 118750Speter if (settype == NIL) 119750Speter panic("intset"); 120750Speter settype = settype->type; 121750Speter if (settype == NIL) 122750Speter return csetp -> comptime; 123750Speter if (isnta(settype, "t")) { 124750Speter error("Set default type \"intset\" is not a set"); 125750Speter return csetp -> comptime; 126750Speter } 127750Speter exptype = settype->type; 128750Speter /* 129750Speter * say we are doing an intset 130750Speter * but, if we get out of range errors for intset 131750Speter * we punt constructing the set at compile time. 132750Speter */ 133750Speter setofint = TRUE; 134750Speter } else { 135750Speter exptype = t->type; 136750Speter if (exptype == NIL) 137750Speter return csetp -> comptime; 138750Speter if (exptype->class != RANGE) 139750Speter exptype = exptype->type; 140750Speter settype = defnl(0, SET, exptype, 0); 141750Speter } 142750Speter } 143750Speter csetp -> csettype = settype; 144750Speter setran( exptype ); 145750Speter lower = set.lwrb; 146750Speter upper = set.lwrb + set.uprbp; 147750Speter pairp = NIL; 148750Speter singp = NIL; 149750Speter codeoff(); 150750Speter while ( el = r[2] ) { 151750Speter e = el[1]; 152750Speter if (e == NIL) { 153750Speter /* 154750Speter * don't hang this one anywhere. 155750Speter */ 156750Speter csetp -> csettype = NIL; 157750Speter r[2] = el[2]; 158750Speter continue; 159750Speter } 160750Speter if (e[0] == T_RANG) { 161750Speter if ( csetp -> comptime && constval( e[2] ) ) { 162750Speter t = con.ctype; 163750Speter if ( ((long)con.crval) < lower || ((long)con.crval) > upper ) { 164750Speter if ( setofint ) { 165750Speter csetp -> comptime = FALSE; 166750Speter } else { 167750Speter error("Range upper bound of %d out of set bounds" , ((long)con.crval) ); 168750Speter csetp -> csettype = NIL; 169750Speter } 170750Speter } 171750Speter rangeupper = ((long)con.crval); 172750Speter } else { 173750Speter csetp -> comptime = FALSE; 174750Speter t = rvalue(e[2], NIL , RREQ ); 175750Speter if (t == NIL) { 176750Speter rvalue(e[1], NIL , RREQ ); 177750Speter goto pairhang; 178750Speter } 179750Speter } 180750Speter if (incompat(t, exptype, e[2])) { 181750Speter cerror("Upper bound of element type clashed with set type in constant set"); 182750Speter } 183750Speter if ( csetp -> comptime && constval( e[1] ) ) { 184750Speter t = con.ctype; 185750Speter if ( ((long)con.crval) < lower || ((long)con.crval) > upper ) { 186750Speter if ( setofint ) { 187750Speter csetp -> comptime = FALSE; 188750Speter } else { 189750Speter error("Range lower bound of %d out of set bounds" , ((long)con.crval) ); 190750Speter csetp -> csettype = NIL; 191750Speter } 192750Speter } 193750Speter } else { 194750Speter csetp -> comptime = FALSE; 195750Speter t = rvalue(e[1], NIL , RREQ ); 196750Speter if (t == NIL) { 197750Speter goto pairhang; 198750Speter } 199750Speter } 200750Speter if (incompat(t, exptype, e[1])) { 201750Speter cerror("Lower bound of element type clashed with set type in constant set"); 202750Speter } 203750Speter pairhang: 204750Speter /* 205750Speter * remove this range from the tree list and 206750Speter * hang it on the pairs list. 207750Speter */ 208750Speter ip = el[2]; 209750Speter el[2] = pairp; 210750Speter pairp = r[2]; 211750Speter r[2] = ip; 212750Speter csetp -> paircnt++; 213750Speter } else { 214750Speter if ( csetp -> comptime && constval( e ) ) { 215750Speter t = con.ctype; 216750Speter if ( ((long)con.crval) < lower || ((long)con.crval) > upper ) { 217750Speter if ( setofint ) { 218750Speter csetp -> comptime = FALSE; 219750Speter } else { 220750Speter error("Value of %d out of set bounds" , ((long)con.crval) ); 221750Speter csetp -> csettype = NIL; 222750Speter } 223750Speter } 224750Speter } else { 225750Speter csetp -> comptime = FALSE; 226750Speter t = rvalue((int *) e, NLNIL , RREQ ); 227750Speter if (t == NIL) { 228750Speter goto singhang; 229750Speter } 230750Speter } 231750Speter if (incompat(t, exptype, e)) { 232750Speter cerror("Element type clashed with set type in constant set"); 233750Speter } 234750Speter singhang: 235750Speter /* 236750Speter * take this expression off the tree list and 237750Speter * hang it on the list of singletons. 238750Speter */ 239750Speter ip = el[2]; 240750Speter el[2] = singp; 241750Speter singp = r[2]; 242750Speter r[2] = ip; 243750Speter csetp -> singcnt++; 244750Speter } 245750Speter } 246750Speter codeon(); 247750Speter # ifdef PC 248750Speter if ( pairp != NIL ) { 249750Speter for ( el = pairp ; el[2] != NIL ; el = el[2] ) /* void */; 250750Speter el[2] = singp; 251750Speter r[2] = pairp; 252750Speter } else { 253750Speter r[2] = singp; 254750Speter } 255750Speter # endif PC 256750Speter # ifdef OBJ 257750Speter if ( singp != NIL ) { 258750Speter for ( el = singp ; el[2] != NIL ; el = el[2] ) /* void */; 259750Speter el[2] = pairp; 260750Speter r[2] = singp; 261750Speter } else { 262750Speter r[2] = pairp; 263750Speter } 264750Speter # endif OBJ 265750Speter if ( csetp -> csettype == NIL ) { 266750Speter csetp -> comptime = TRUE; 267750Speter } 268750Speter return csetp -> comptime; 269750Speter } 270750Speter 271750Speter #define BITSPERLONG ( sizeof( long ) * BITSPERBYTE ) 272750Speter /* 273750Speter * mask[i] has the low i bits turned off. 274750Speter */ 275750Speter long mask[] = { 276750Speter 0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 , 277750Speter 0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 , 278750Speter 0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 , 279750Speter 0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 , 280750Speter 0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 , 281750Speter 0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 , 282750Speter 0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 , 283750Speter 0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 , 284750Speter 0x00000000 285750Speter }; 286750Speter /* 287750Speter * given a csetstr, either 288750Speter * put out a compile time constant set and an lvalue to it. 289750Speter * or 290750Speter * put out rvalues for the singletons and the pairs 291750Speter * and counts of each. 292750Speter */ 293750Speter postcset( r , csetp ) 294750Speter int *r; 295750Speter struct csetstr *csetp; 296750Speter { 297750Speter register int *el; 298750Speter register int *e; 299750Speter int lower; 300750Speter int upper; 301750Speter int lowerdiv; 302750Speter int lowermod; 303750Speter int upperdiv; 304750Speter int uppermod; 305750Speter int label; 306750Speter long *lp; 307750Speter long *limit; 308750Speter long tempset[ ( MAXSET / BITSPERLONG ) + 1 ]; 309750Speter long temp; 310750Speter char labelname[ BUFSIZ ]; 311750Speter 312750Speter if ( csetp -> comptime ) { 313750Speter setran( ( csetp -> csettype ) -> type ); 314750Speter limit = &tempset[ ( set.uprbp / BITSPERLONG ) + 1 ]; 315750Speter for ( lp = &tempset[0] ; lp < limit ; lp++ ) { 316750Speter *lp = 0; 317750Speter } 318750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 319750Speter e = el[1]; 320750Speter if ( e[0] == T_RANG ) { 321750Speter constval( e[1] ); 322750Speter lower = (long) con.crval; 323750Speter constval( e[2] ); 324750Speter upper = (long) con.crval; 325750Speter if ( upper < lower ) { 326750Speter continue; 327750Speter } 328750Speter lowerdiv = ( lower - set.lwrb ) / BITSPERLONG; 329750Speter lowermod = ( lower - set.lwrb ) % BITSPERLONG; 330750Speter upperdiv = ( upper - set.lwrb ) / BITSPERLONG; 331750Speter uppermod = ( upper - set.lwrb ) % BITSPERLONG; 332750Speter temp = mask[ lowermod ]; 333750Speter if ( lowerdiv == upperdiv ) { 334750Speter temp &= ~mask[ uppermod + 1 ]; 335750Speter } 336750Speter tempset[ lowerdiv ] |= temp; 337750Speter limit = &tempset[ upperdiv-1 ]; 338750Speter for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) { 339750Speter *lp |= ~0; 340750Speter } 341750Speter if ( lowerdiv != upperdiv ) { 342750Speter tempset[ upperdiv ] |= ~mask[ uppermod + 1 ]; 343750Speter } 344750Speter } else { 345750Speter constval( e ); 346750Speter lowerdiv = ( ((long)con.crval) - set.lwrb ) / BITSPERLONG; 347750Speter lowermod = ( ((long)con.crval) - set.lwrb ) % BITSPERLONG; 348750Speter tempset[ lowerdiv ] |= ( 1 << lowermod ); 349750Speter } 350750Speter } 351750Speter if ( cgenflg ) 352750Speter return; 353750Speter # ifdef PC 354750Speter putprintf( " .data" , 0 ); 355750Speter putprintf( " .align 2" , 0 ); 356750Speter label = getlab(); 357750Speter putlab( label ); 358750Speter lp = &( tempset[0] ); 359750Speter limit = &tempset[ ( set.uprbp / BITSPERLONG ) + 1 ]; 360750Speter while ( lp < limit ) { 361750Speter putprintf( " .long 0x%x" , 1 , *lp ++ ); 362750Speter for ( temp = 2 ; ( temp <= 8 ) && lp < limit ; temp ++ ) { 363750Speter putprintf( ",0x%x" , 1 , *lp++ ); 364750Speter } 365750Speter putprintf( "" , 0 ); 366750Speter } 367750Speter putprintf( " .text" , 0 ); 368750Speter sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 369750Speter putleaf( P2ICON , 0 , 0 , P2PTR | P2STRTY , labelname ); 370750Speter # endif PC 371750Speter # ifdef OBJ 372750Speter put( 2, O_CON, (set.uprbp / BITSPERLONG + 1) * 373750Speter (BITSPERLONG / BITSPERBYTE)); 374750Speter lp = &( tempset[0] ); 375750Speter limit = &tempset[ ( set.uprbp / BITSPERLONG ) + 1 ]; 376750Speter while ( lp < limit ) { 377750Speter put( 2, O_CASE4, *lp ++); 378750Speter } 379750Speter # endif OBJ 380750Speter } else { 381750Speter # ifdef PC 382750Speter putleaf( P2ICON , csetp -> paircnt , 0 , P2INT , 0 ); 383750Speter putop( P2LISTOP , P2INT ); 384750Speter putleaf( P2ICON , csetp -> singcnt , 0 , P2INT , 0 ); 385750Speter putop( P2LISTOP , P2INT ); 386750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 387750Speter e = el[1]; 388750Speter if ( e[0] == T_RANG ) { 389750Speter rvalue( e[2] , NIL , RREQ ); 390750Speter putop( P2LISTOP , P2INT ); 391750Speter rvalue( e[1] , NIL , RREQ ); 392750Speter putop( P2LISTOP , P2INT ); 393750Speter } else { 394750Speter rvalue( e , NIL , RREQ ); 395750Speter putop( P2LISTOP , P2INT ); 396750Speter } 397750Speter } 398750Speter # endif PC 399750Speter # ifdef OBJ 400750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 401750Speter e = el[1]; 402750Speter if ( e[0] == T_RANG ) { 403*1884Speter stkrval( e[1] , NIL , RREQ ); 404750Speter stkrval( e[2] , NIL , RREQ ); 405750Speter } else { 406750Speter stkrval( e , NIL , RREQ ); 407750Speter } 408750Speter } 409750Speter put( 2 , O_CON24 , csetp -> singcnt ); 410750Speter put( 2 , O_CON24 , csetp -> paircnt ); 411750Speter # endif OBJ 412750Speter } 413750Speter } 414