1750Speter /* Copyright (c) 1979 Regents of the University of California */ 2750Speter 3*3170Smckusic static char sccsid[] = "@(#)cset.c 1.5 03/10/81"; 4750Speter 5750Speter #include "whoami.h" 6750Speter #include "0.h" 7750Speter #include "tree.h" 8750Speter #include "opcode.h" 9750Speter #include "objfmt.h" 103072Smckusic #ifdef PC 11750Speter #include "pc.h" 12750Speter #include "pcops.h" 133072Smckusic #endif PC 14750Speter 15750Speter /* 163072Smckusic * CONSETS causes compile time constant sets to be constructed here. 173072Smckusic * 183072Smckusic * COMPSETSZE defines the maximum number of longs to be used in 193072Smckusic * constant set construction 203072Smckusic */ 213072Smckusic #define CONSETS 223072Smckusic #define COMPSETSZE 10 233072Smckusic 243072Smckusic #define BITSPERBYTE 8 253072Smckusic #define BITSPERLONG 32 263072Smckusic #define LG2BITSBYTE 3 273072Smckusic #define MSKBITSBYTE 0x07 283072Smckusic #define LG2BITSLONG 5 293072Smckusic #define MSKBITSLONG 0x1f 303072Smckusic 313072Smckusic /* 32750Speter * rummage through a `constant' set (i.e. anything within [ ]'s) tree 33750Speter * and decide if this is a compile time constant set or a runtime set. 34750Speter * this information is returned in a structure passed from the caller. 35750Speter * while rummaging, this also reorders the tree so that all ranges 36750Speter * preceed all singletons. 37750Speter */ 38750Speter bool 39750Speter precset( r , settype , csetp ) 40750Speter int *r; 41750Speter struct nl *settype; 42750Speter struct csetstr *csetp; 43750Speter { 44750Speter register int *e; 45750Speter register struct nl *t; 46750Speter register struct nl *exptype; 47750Speter register int *el; 48750Speter register int *pairp; 49750Speter register int *singp; 50750Speter int *ip; 513072Smckusic int lower; 523072Smckusic int upper; 53750Speter bool setofint; 54750Speter 55750Speter csetp -> csettype = NIL; 56750Speter csetp -> paircnt = 0; 57750Speter csetp -> singcnt = 0; 58750Speter csetp -> comptime = TRUE; 59750Speter setofint = FALSE; 60750Speter if ( settype != NIL ) { 61750Speter if ( settype -> class == SET ) { 62750Speter /* 63750Speter * the easy case, we are told the type of the set. 64750Speter */ 65750Speter exptype = settype -> type; 66750Speter } else { 67750Speter /* 68750Speter * we are told the type, but it's not a set 69750Speter * supposedly possible if someone tries 70750Speter * e.g string context [1,2] = 'abc' 71750Speter */ 72750Speter error("Constant set involved in non set context"); 73750Speter return csetp -> comptime; 74750Speter } 75750Speter } else { 76750Speter /* 77750Speter * So far we have no indication 78750Speter * of what the set type should be. 79750Speter * We "look ahead" and try to infer 80750Speter * The type of the constant set 81750Speter * by evaluating one of its members. 82750Speter */ 83750Speter e = r[2]; 84750Speter if (e == NIL) { 85750Speter /* 861552Speter * tentative for [], return type of `intset' 87750Speter */ 881552Speter settype = lookup( intset ); 891552Speter if ( settype == NIL ) { 901552Speter panic( "empty set" ); 911552Speter } 921552Speter settype = settype -> type; 931552Speter if ( settype == NIL ) { 941552Speter return csetp -> comptime; 951552Speter } 961552Speter if ( isnta( settype , "t" ) ) { 971552Speter error("Set default type \"intset\" is not a set"); 981552Speter return csetp -> comptime; 991552Speter } 1001552Speter csetp -> csettype = settype; 101*3170Smckusic setran( settype -> type ); 1023072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1033072Smckusic csetp -> comptime = FALSE; 104750Speter return csetp -> comptime; 105750Speter } 106750Speter e = e[1]; 107750Speter if (e == NIL) { 108750Speter return csetp -> comptime; 109750Speter } 110750Speter if (e[0] == T_RANG) { 111750Speter e = e[1]; 112750Speter } 113750Speter codeoff(); 114750Speter t = rvalue(e, NIL , RREQ ); 115750Speter codeon(); 116750Speter if (t == NIL) { 117750Speter return csetp -> comptime; 118750Speter } 119750Speter /* 120750Speter * The type of the set, settype, is 121750Speter * deemed to be a set of the base type 122750Speter * of t, which we call exptype. If, 123750Speter * however, this would involve a 124750Speter * "set of integer", we cop out 125750Speter * and use "intset"'s current scoped 126750Speter * type instead. 127750Speter */ 128750Speter if (isa(t, "r")) { 129750Speter error("Sets may not have 'real' elements"); 130750Speter return csetp -> comptime; 131750Speter } 132750Speter if (isnta(t, "bcsi")) { 133750Speter error("Set elements must be scalars, not %ss", nameof(t)); 134750Speter return csetp -> comptime; 135750Speter } 136750Speter if (isa(t, "i")) { 137750Speter settype = lookup(intset); 138750Speter if (settype == NIL) 139750Speter panic("intset"); 140750Speter settype = settype->type; 141750Speter if (settype == NIL) 142750Speter return csetp -> comptime; 143750Speter if (isnta(settype, "t")) { 144750Speter error("Set default type \"intset\" is not a set"); 145750Speter return csetp -> comptime; 146750Speter } 147750Speter exptype = settype->type; 148750Speter /* 149750Speter * say we are doing an intset 150750Speter * but, if we get out of range errors for intset 151750Speter * we punt constructing the set at compile time. 152750Speter */ 153750Speter setofint = TRUE; 154750Speter } else { 155750Speter exptype = t->type; 156750Speter if (exptype == NIL) 157750Speter return csetp -> comptime; 158750Speter if (exptype->class != RANGE) 159750Speter exptype = exptype->type; 160750Speter settype = defnl(0, SET, exptype, 0); 161750Speter } 162750Speter } 163750Speter csetp -> csettype = settype; 1643072Smckusic # ifndef CONSETS 1653072Smckusic csetp -> comptime = FALSE; 1663072Smckusic # endif CONSETS 167750Speter setran( exptype ); 1683072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1693072Smckusic csetp -> comptime = FALSE; 170750Speter lower = set.lwrb; 171750Speter upper = set.lwrb + set.uprbp; 172750Speter pairp = NIL; 173750Speter singp = NIL; 174750Speter codeoff(); 175750Speter while ( el = r[2] ) { 176750Speter e = el[1]; 177750Speter if (e == NIL) { 178750Speter /* 179750Speter * don't hang this one anywhere. 180750Speter */ 181750Speter csetp -> csettype = NIL; 182750Speter r[2] = el[2]; 183750Speter continue; 184750Speter } 185750Speter if (e[0] == T_RANG) { 186750Speter if ( csetp -> comptime && constval( e[2] ) ) { 1873072Smckusic #ifdef CONSETS 188750Speter t = con.ctype; 1893072Smckusic if ( con.crval < lower || con.crval > upper ) { 190750Speter if ( setofint ) { 191750Speter csetp -> comptime = FALSE; 192750Speter } else { 1933072Smckusic error("Range upper bound of %D out of set bounds" , ((long)con.crval) ); 194750Speter csetp -> csettype = NIL; 195750Speter } 196750Speter } 1973072Smckusic #endif CONSETS 198750Speter } else { 199750Speter csetp -> comptime = FALSE; 200750Speter t = rvalue(e[2], NIL , RREQ ); 201750Speter if (t == NIL) { 202750Speter rvalue(e[1], NIL , RREQ ); 203750Speter goto pairhang; 204750Speter } 205750Speter } 206750Speter if (incompat(t, exptype, e[2])) { 207750Speter cerror("Upper bound of element type clashed with set type in constant set"); 208750Speter } 209750Speter if ( csetp -> comptime && constval( e[1] ) ) { 2103072Smckusic #ifdef CONSETS 211750Speter t = con.ctype; 2123072Smckusic if ( con.crval < lower || con.crval > upper ) { 213750Speter if ( setofint ) { 214750Speter csetp -> comptime = FALSE; 215750Speter } else { 2163072Smckusic error("Range lower bound of %D out of set bounds" , ((long)con.crval) ); 217750Speter csetp -> csettype = NIL; 218750Speter } 219750Speter } 2203072Smckusic #endif CONSETS 221750Speter } else { 222750Speter csetp -> comptime = FALSE; 223750Speter t = rvalue(e[1], NIL , RREQ ); 224750Speter if (t == NIL) { 225750Speter goto pairhang; 226750Speter } 227750Speter } 228750Speter if (incompat(t, exptype, e[1])) { 229750Speter cerror("Lower bound of element type clashed with set type in constant set"); 230750Speter } 231750Speter pairhang: 232750Speter /* 233750Speter * remove this range from the tree list and 234750Speter * hang it on the pairs list. 235750Speter */ 236750Speter ip = el[2]; 237750Speter el[2] = pairp; 238750Speter pairp = r[2]; 239750Speter r[2] = ip; 240750Speter csetp -> paircnt++; 241750Speter } else { 242750Speter if ( csetp -> comptime && constval( e ) ) { 2433072Smckusic #ifdef CONSETS 244750Speter t = con.ctype; 2453072Smckusic if ( con.crval < lower || con.crval > upper ) { 246750Speter if ( setofint ) { 247750Speter csetp -> comptime = FALSE; 248750Speter } else { 2493072Smckusic error("Value of %D out of set bounds" , ((long)con.crval) ); 250750Speter csetp -> csettype = NIL; 251750Speter } 252750Speter } 2533072Smckusic #endif CONSETS 254750Speter } else { 255750Speter csetp -> comptime = FALSE; 256750Speter t = rvalue((int *) e, NLNIL , RREQ ); 257750Speter if (t == NIL) { 258750Speter goto singhang; 259750Speter } 260750Speter } 261750Speter if (incompat(t, exptype, e)) { 262750Speter cerror("Element type clashed with set type in constant set"); 263750Speter } 264750Speter singhang: 265750Speter /* 266750Speter * take this expression off the tree list and 267750Speter * hang it on the list of singletons. 268750Speter */ 269750Speter ip = el[2]; 270750Speter el[2] = singp; 271750Speter singp = r[2]; 272750Speter r[2] = ip; 273750Speter csetp -> singcnt++; 274750Speter } 275750Speter } 276750Speter codeon(); 277750Speter # ifdef PC 278750Speter if ( pairp != NIL ) { 279750Speter for ( el = pairp ; el[2] != NIL ; el = el[2] ) /* void */; 280750Speter el[2] = singp; 281750Speter r[2] = pairp; 282750Speter } else { 283750Speter r[2] = singp; 284750Speter } 285750Speter # endif PC 286750Speter # ifdef OBJ 287750Speter if ( singp != NIL ) { 288750Speter for ( el = singp ; el[2] != NIL ; el = el[2] ) /* void */; 289750Speter el[2] = pairp; 290750Speter r[2] = singp; 291750Speter } else { 292750Speter r[2] = pairp; 293750Speter } 294750Speter # endif OBJ 295750Speter if ( csetp -> csettype == NIL ) { 296750Speter csetp -> comptime = TRUE; 297750Speter } 298750Speter return csetp -> comptime; 299750Speter } 300750Speter 3013072Smckusic #ifdef CONSETS 302750Speter /* 303750Speter * mask[i] has the low i bits turned off. 304750Speter */ 305750Speter long mask[] = { 3063072Smckusic # ifdef DEC11 307750Speter 0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 , 308750Speter 0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 , 309750Speter 0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 , 310750Speter 0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 , 311750Speter 0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 , 312750Speter 0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 , 313750Speter 0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 , 314750Speter 0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 , 315750Speter 0x00000000 3163072Smckusic # else 3173072Smckusic 0xffffffff , 0xfeffffff , 0xfcffffff , 0xf8ffffff , 3183072Smckusic 0xf0ffffff , 0xe0ffffff , 0xc0ffffff , 0x80ffffff , 3193072Smckusic 0x00ffffff , 0x00feffff , 0x00fcffff , 0x00f8ffff , 3203072Smckusic 0x00f0ffff , 0x00e0ffff , 0x00c0ffff , 0x0080ffff , 3213072Smckusic 0x0000ffff , 0x0000feff , 0x0000fcff , 0x0000f8ff , 3223072Smckusic 0x0000f0ff , 0x0000e0ff , 0x0000c0ff , 0x000080ff , 3233072Smckusic 0x000000ff , 0x000000fe , 0x000000fc , 0x000000f8 , 3243072Smckusic 0x000000f0 , 0x000000e0 , 0x000000c0 , 0x00000080 , 3253072Smckusic 0x00000000 3263072Smckusic # endif DEC11 3273072Smckusic }; 328750Speter /* 329750Speter * given a csetstr, either 330750Speter * put out a compile time constant set and an lvalue to it. 331750Speter * or 332750Speter * put out rvalues for the singletons and the pairs 333750Speter * and counts of each. 334750Speter */ 3353072Smckusic #endif CONSETS 336750Speter postcset( r , csetp ) 337750Speter int *r; 338750Speter struct csetstr *csetp; 339750Speter { 340750Speter register int *el; 341750Speter register int *e; 342750Speter int lower; 343750Speter int upper; 344750Speter int lowerdiv; 345750Speter int lowermod; 346750Speter int upperdiv; 347750Speter int uppermod; 348750Speter int label; 349750Speter long *lp; 350750Speter long *limit; 3513072Smckusic long tempset[ COMPSETSZE ]; 352750Speter long temp; 3533072Smckusic char *cp; 3543072Smckusic # ifdef PC 3553072Smckusic char labelname[ BUFSIZ ]; 3563072Smckusic # endif PC 357750Speter 358750Speter if ( csetp -> comptime ) { 3593072Smckusic #ifdef CONSETS 360750Speter setran( ( csetp -> csettype ) -> type ); 3613072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 362750Speter for ( lp = &tempset[0] ; lp < limit ; lp++ ) { 363750Speter *lp = 0; 364750Speter } 365750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 366750Speter e = el[1]; 367750Speter if ( e[0] == T_RANG ) { 368750Speter constval( e[1] ); 3693072Smckusic lower = con.crval; 370750Speter constval( e[2] ); 3713072Smckusic upper = con.crval; 372750Speter if ( upper < lower ) { 373750Speter continue; 374750Speter } 3753072Smckusic lowerdiv = ( lower - set.lwrb ) >> LG2BITSLONG; 3763072Smckusic lowermod = ( lower - set.lwrb ) & MSKBITSLONG; 3773072Smckusic upperdiv = ( upper - set.lwrb ) >> LG2BITSLONG; 3783072Smckusic uppermod = ( upper - set.lwrb ) & MSKBITSLONG; 379750Speter temp = mask[ lowermod ]; 380750Speter if ( lowerdiv == upperdiv ) { 381750Speter temp &= ~mask[ uppermod + 1 ]; 382750Speter } 383750Speter tempset[ lowerdiv ] |= temp; 384750Speter limit = &tempset[ upperdiv-1 ]; 385750Speter for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) { 3863072Smckusic *lp |= 0xffffffff; 387750Speter } 388750Speter if ( lowerdiv != upperdiv ) { 389750Speter tempset[ upperdiv ] |= ~mask[ uppermod + 1 ]; 390750Speter } 391750Speter } else { 392750Speter constval( e ); 3933072Smckusic temp = con.crval - set.lwrb; 3943072Smckusic cp = (char *)tempset; 3953072Smckusic cp[temp >> LG2BITSBYTE] |= (1 << (temp & MSKBITSBYTE)); 396750Speter } 397750Speter } 398750Speter if ( cgenflg ) 399750Speter return; 400750Speter # ifdef PC 401750Speter putprintf( " .data" , 0 ); 402750Speter putprintf( " .align 2" , 0 ); 403750Speter label = getlab(); 404750Speter putlab( label ); 405750Speter lp = &( tempset[0] ); 4063072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 407750Speter while ( lp < limit ) { 408750Speter putprintf( " .long 0x%x" , 1 , *lp ++ ); 409750Speter for ( temp = 2 ; ( temp <= 8 ) && lp < limit ; temp ++ ) { 410750Speter putprintf( ",0x%x" , 1 , *lp++ ); 411750Speter } 412750Speter putprintf( "" , 0 ); 413750Speter } 414750Speter putprintf( " .text" , 0 ); 415750Speter sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 416750Speter putleaf( P2ICON , 0 , 0 , P2PTR | P2STRTY , labelname ); 417750Speter # endif PC 418750Speter # ifdef OBJ 4193072Smckusic put(2, O_CON, (int)(((set.uprbp >> LG2BITSLONG) + 1) * 4203072Smckusic (BITSPERLONG >> LG2BITSBYTE))); 421750Speter lp = &( tempset[0] ); 4223072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 423750Speter while ( lp < limit ) { 4243072Smckusic put(2, O_CASE4, *lp ++); 425750Speter } 426750Speter # endif OBJ 4273072Smckusic #else 4283072Smckusic panic("const cset"); 4293072Smckusic #endif CONSETS 430750Speter } else { 431750Speter # ifdef PC 432750Speter putleaf( P2ICON , csetp -> paircnt , 0 , P2INT , 0 ); 433750Speter putop( P2LISTOP , P2INT ); 434750Speter putleaf( P2ICON , csetp -> singcnt , 0 , P2INT , 0 ); 435750Speter putop( P2LISTOP , P2INT ); 436750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 437750Speter e = el[1]; 438750Speter if ( e[0] == T_RANG ) { 439750Speter rvalue( e[2] , NIL , RREQ ); 440750Speter putop( P2LISTOP , P2INT ); 441750Speter rvalue( e[1] , NIL , RREQ ); 442750Speter putop( P2LISTOP , P2INT ); 443750Speter } else { 444750Speter rvalue( e , NIL , RREQ ); 445750Speter putop( P2LISTOP , P2INT ); 446750Speter } 447750Speter } 448750Speter # endif PC 449750Speter # ifdef OBJ 450750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 451750Speter e = el[1]; 452750Speter if ( e[0] == T_RANG ) { 4531884Speter stkrval( e[1] , NIL , RREQ ); 454750Speter stkrval( e[2] , NIL , RREQ ); 455750Speter } else { 456750Speter stkrval( e , NIL , RREQ ); 457750Speter } 458750Speter } 4593072Smckusic put(2 , O_CON24 , (int)csetp -> singcnt ); 4603072Smckusic put(2 , O_CON24 , (int)csetp -> paircnt ); 461750Speter # endif OBJ 462750Speter } 463750Speter } 464