1750Speter /* Copyright (c) 1979 Regents of the University of California */ 2750Speter 3*10652Speter static char sccsid[] = "@(#)cset.c 1.7 02/01/83"; 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" 13*10652Speter #include "align.h" 143072Smckusic #endif PC 15750Speter 16750Speter /* 173072Smckusic * CONSETS causes compile time constant sets to be constructed here. 183072Smckusic * 193072Smckusic * COMPSETSZE defines the maximum number of longs to be used in 203072Smckusic * constant set construction 213072Smckusic */ 223072Smckusic #define CONSETS 233072Smckusic #define COMPSETSZE 10 243072Smckusic 253072Smckusic #define BITSPERBYTE 8 263072Smckusic #define BITSPERLONG 32 273072Smckusic #define LG2BITSBYTE 3 283072Smckusic #define MSKBITSBYTE 0x07 293072Smckusic #define LG2BITSLONG 5 303072Smckusic #define MSKBITSLONG 0x1f 313072Smckusic 323072Smckusic /* 33750Speter * rummage through a `constant' set (i.e. anything within [ ]'s) tree 34750Speter * and decide if this is a compile time constant set or a runtime set. 35750Speter * this information is returned in a structure passed from the caller. 36750Speter * while rummaging, this also reorders the tree so that all ranges 37750Speter * preceed all singletons. 38750Speter */ 39750Speter bool 40750Speter precset( r , settype , csetp ) 41750Speter int *r; 42750Speter struct nl *settype; 43750Speter struct csetstr *csetp; 44750Speter { 45750Speter register int *e; 46750Speter register struct nl *t; 47750Speter register struct nl *exptype; 48750Speter register int *el; 49750Speter register int *pairp; 50750Speter register int *singp; 51750Speter int *ip; 523072Smckusic int lower; 533072Smckusic int upper; 54750Speter bool setofint; 55750Speter 56750Speter csetp -> csettype = NIL; 57750Speter csetp -> paircnt = 0; 58750Speter csetp -> singcnt = 0; 59750Speter csetp -> comptime = TRUE; 60750Speter setofint = FALSE; 61750Speter if ( settype != NIL ) { 62750Speter if ( settype -> class == SET ) { 63750Speter /* 64750Speter * the easy case, we are told the type of the set. 65750Speter */ 66750Speter exptype = settype -> type; 67750Speter } else { 68750Speter /* 69750Speter * we are told the type, but it's not a set 70750Speter * supposedly possible if someone tries 71750Speter * e.g string context [1,2] = 'abc' 72750Speter */ 73750Speter error("Constant set involved in non set context"); 74750Speter return csetp -> comptime; 75750Speter } 76750Speter } else { 77750Speter /* 78750Speter * So far we have no indication 79750Speter * of what the set type should be. 80750Speter * We "look ahead" and try to infer 81750Speter * The type of the constant set 82750Speter * by evaluating one of its members. 83750Speter */ 84750Speter e = r[2]; 85750Speter if (e == NIL) { 86750Speter /* 871552Speter * tentative for [], return type of `intset' 88750Speter */ 891552Speter settype = lookup( intset ); 901552Speter if ( settype == NIL ) { 911552Speter panic( "empty set" ); 921552Speter } 931552Speter settype = settype -> type; 941552Speter if ( settype == NIL ) { 951552Speter return csetp -> comptime; 961552Speter } 971552Speter if ( isnta( settype , "t" ) ) { 981552Speter error("Set default type \"intset\" is not a set"); 991552Speter return csetp -> comptime; 1001552Speter } 1011552Speter csetp -> csettype = settype; 1023170Smckusic setran( settype -> type ); 1033072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1043072Smckusic csetp -> comptime = FALSE; 105750Speter return csetp -> comptime; 106750Speter } 107750Speter e = e[1]; 108750Speter if (e == NIL) { 109750Speter return csetp -> comptime; 110750Speter } 111750Speter if (e[0] == T_RANG) { 112750Speter e = e[1]; 113750Speter } 114750Speter codeoff(); 115750Speter t = rvalue(e, NIL , RREQ ); 116750Speter codeon(); 117750Speter if (t == NIL) { 118750Speter return csetp -> comptime; 119750Speter } 120750Speter /* 121750Speter * The type of the set, settype, is 122750Speter * deemed to be a set of the base type 123750Speter * of t, which we call exptype. If, 124750Speter * however, this would involve a 125750Speter * "set of integer", we cop out 126750Speter * and use "intset"'s current scoped 127750Speter * type instead. 128750Speter */ 129750Speter if (isa(t, "r")) { 130750Speter error("Sets may not have 'real' elements"); 131750Speter return csetp -> comptime; 132750Speter } 133750Speter if (isnta(t, "bcsi")) { 134750Speter error("Set elements must be scalars, not %ss", nameof(t)); 135750Speter return csetp -> comptime; 136750Speter } 137750Speter if (isa(t, "i")) { 138750Speter settype = lookup(intset); 139750Speter if (settype == NIL) 140750Speter panic("intset"); 141750Speter settype = settype->type; 142750Speter if (settype == NIL) 143750Speter return csetp -> comptime; 144750Speter if (isnta(settype, "t")) { 145750Speter error("Set default type \"intset\" is not a set"); 146750Speter return csetp -> comptime; 147750Speter } 148750Speter exptype = settype->type; 149750Speter /* 150750Speter * say we are doing an intset 151750Speter * but, if we get out of range errors for intset 152750Speter * we punt constructing the set at compile time. 153750Speter */ 154750Speter setofint = TRUE; 155750Speter } else { 156750Speter exptype = t->type; 157750Speter if (exptype == NIL) 158750Speter return csetp -> comptime; 159750Speter if (exptype->class != RANGE) 160750Speter exptype = exptype->type; 161750Speter settype = defnl(0, SET, exptype, 0); 162750Speter } 163750Speter } 164750Speter csetp -> csettype = settype; 1653072Smckusic # ifndef CONSETS 1663072Smckusic csetp -> comptime = FALSE; 1673072Smckusic # endif CONSETS 168750Speter setran( exptype ); 1693072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1703072Smckusic csetp -> comptime = FALSE; 171750Speter lower = set.lwrb; 172750Speter upper = set.lwrb + set.uprbp; 173750Speter pairp = NIL; 174750Speter singp = NIL; 175750Speter codeoff(); 176750Speter while ( el = r[2] ) { 177750Speter e = el[1]; 178750Speter if (e == NIL) { 179750Speter /* 180750Speter * don't hang this one anywhere. 181750Speter */ 182750Speter csetp -> csettype = NIL; 183750Speter r[2] = el[2]; 184750Speter continue; 185750Speter } 186750Speter if (e[0] == T_RANG) { 187750Speter if ( csetp -> comptime && constval( e[2] ) ) { 1883072Smckusic #ifdef CONSETS 189750Speter t = con.ctype; 1903072Smckusic if ( con.crval < lower || con.crval > upper ) { 191750Speter if ( setofint ) { 192750Speter csetp -> comptime = FALSE; 193750Speter } else { 1943072Smckusic error("Range upper bound of %D out of set bounds" , ((long)con.crval) ); 195750Speter csetp -> csettype = NIL; 196750Speter } 197750Speter } 1983072Smckusic #endif CONSETS 199750Speter } else { 200750Speter csetp -> comptime = FALSE; 201750Speter t = rvalue(e[2], NIL , RREQ ); 202750Speter if (t == NIL) { 203750Speter rvalue(e[1], NIL , RREQ ); 204750Speter goto pairhang; 205750Speter } 206750Speter } 207750Speter if (incompat(t, exptype, e[2])) { 208750Speter cerror("Upper bound of element type clashed with set type in constant set"); 209750Speter } 210750Speter if ( csetp -> comptime && constval( e[1] ) ) { 2113072Smckusic #ifdef CONSETS 212750Speter t = con.ctype; 2133072Smckusic if ( con.crval < lower || con.crval > upper ) { 214750Speter if ( setofint ) { 215750Speter csetp -> comptime = FALSE; 216750Speter } else { 2173072Smckusic error("Range lower bound of %D out of set bounds" , ((long)con.crval) ); 218750Speter csetp -> csettype = NIL; 219750Speter } 220750Speter } 2213072Smckusic #endif CONSETS 222750Speter } else { 223750Speter csetp -> comptime = FALSE; 224750Speter t = rvalue(e[1], NIL , RREQ ); 225750Speter if (t == NIL) { 226750Speter goto pairhang; 227750Speter } 228750Speter } 229750Speter if (incompat(t, exptype, e[1])) { 230750Speter cerror("Lower bound of element type clashed with set type in constant set"); 231750Speter } 232750Speter pairhang: 233750Speter /* 234750Speter * remove this range from the tree list and 235750Speter * hang it on the pairs list. 236750Speter */ 237750Speter ip = el[2]; 238750Speter el[2] = pairp; 239750Speter pairp = r[2]; 240750Speter r[2] = ip; 241750Speter csetp -> paircnt++; 242750Speter } else { 243750Speter if ( csetp -> comptime && constval( e ) ) { 2443072Smckusic #ifdef CONSETS 245750Speter t = con.ctype; 2463072Smckusic if ( con.crval < lower || con.crval > upper ) { 247750Speter if ( setofint ) { 248750Speter csetp -> comptime = FALSE; 249750Speter } else { 2503072Smckusic error("Value of %D out of set bounds" , ((long)con.crval) ); 251750Speter csetp -> csettype = NIL; 252750Speter } 253750Speter } 2543072Smckusic #endif CONSETS 255750Speter } else { 256750Speter csetp -> comptime = FALSE; 257750Speter t = rvalue((int *) e, NLNIL , RREQ ); 258750Speter if (t == NIL) { 259750Speter goto singhang; 260750Speter } 261750Speter } 262750Speter if (incompat(t, exptype, e)) { 263750Speter cerror("Element type clashed with set type in constant set"); 264750Speter } 265750Speter singhang: 266750Speter /* 267750Speter * take this expression off the tree list and 268750Speter * hang it on the list of singletons. 269750Speter */ 270750Speter ip = el[2]; 271750Speter el[2] = singp; 272750Speter singp = r[2]; 273750Speter r[2] = ip; 274750Speter csetp -> singcnt++; 275750Speter } 276750Speter } 277750Speter codeon(); 278750Speter # ifdef PC 279750Speter if ( pairp != NIL ) { 280750Speter for ( el = pairp ; el[2] != NIL ; el = el[2] ) /* void */; 281750Speter el[2] = singp; 282750Speter r[2] = pairp; 283750Speter } else { 284750Speter r[2] = singp; 285750Speter } 286750Speter # endif PC 287750Speter # ifdef OBJ 288750Speter if ( singp != NIL ) { 289750Speter for ( el = singp ; el[2] != NIL ; el = el[2] ) /* void */; 290750Speter el[2] = pairp; 291750Speter r[2] = singp; 292750Speter } else { 293750Speter r[2] = pairp; 294750Speter } 295750Speter # endif OBJ 296750Speter if ( csetp -> csettype == NIL ) { 297750Speter csetp -> comptime = TRUE; 298750Speter } 299750Speter return csetp -> comptime; 300750Speter } 301750Speter 3023072Smckusic #ifdef CONSETS 303750Speter /* 304750Speter * mask[i] has the low i bits turned off. 305750Speter */ 306750Speter long mask[] = { 3073072Smckusic # ifdef DEC11 308750Speter 0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 , 309750Speter 0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 , 310750Speter 0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 , 311750Speter 0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 , 312750Speter 0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 , 313750Speter 0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 , 314750Speter 0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 , 315750Speter 0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 , 316750Speter 0x00000000 3173072Smckusic # else 3183072Smckusic 0xffffffff , 0xfeffffff , 0xfcffffff , 0xf8ffffff , 3193072Smckusic 0xf0ffffff , 0xe0ffffff , 0xc0ffffff , 0x80ffffff , 3203072Smckusic 0x00ffffff , 0x00feffff , 0x00fcffff , 0x00f8ffff , 3213072Smckusic 0x00f0ffff , 0x00e0ffff , 0x00c0ffff , 0x0080ffff , 3223072Smckusic 0x0000ffff , 0x0000feff , 0x0000fcff , 0x0000f8ff , 3233072Smckusic 0x0000f0ff , 0x0000e0ff , 0x0000c0ff , 0x000080ff , 3243072Smckusic 0x000000ff , 0x000000fe , 0x000000fc , 0x000000f8 , 3253072Smckusic 0x000000f0 , 0x000000e0 , 0x000000c0 , 0x00000080 , 3263072Smckusic 0x00000000 3273072Smckusic # endif DEC11 3283072Smckusic }; 329750Speter /* 330750Speter * given a csetstr, either 331750Speter * put out a compile time constant set and an lvalue to it. 332750Speter * or 333750Speter * put out rvalues for the singletons and the pairs 334750Speter * and counts of each. 335750Speter */ 3363072Smckusic #endif CONSETS 337750Speter postcset( r , csetp ) 338750Speter int *r; 339750Speter struct csetstr *csetp; 340750Speter { 341750Speter register int *el; 342750Speter register int *e; 343750Speter int lower; 344750Speter int upper; 345750Speter int lowerdiv; 346750Speter int lowermod; 347750Speter int upperdiv; 348750Speter int uppermod; 349750Speter int label; 350750Speter long *lp; 351750Speter long *limit; 3523072Smckusic long tempset[ COMPSETSZE ]; 353750Speter long temp; 3543072Smckusic char *cp; 3553072Smckusic # ifdef PC 3563072Smckusic char labelname[ BUFSIZ ]; 3573072Smckusic # endif PC 358750Speter 359750Speter if ( csetp -> comptime ) { 3603072Smckusic #ifdef CONSETS 361750Speter setran( ( csetp -> csettype ) -> type ); 3623072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 363750Speter for ( lp = &tempset[0] ; lp < limit ; lp++ ) { 364750Speter *lp = 0; 365750Speter } 366750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 367750Speter e = el[1]; 368750Speter if ( e[0] == T_RANG ) { 369750Speter constval( e[1] ); 3703072Smckusic lower = con.crval; 371750Speter constval( e[2] ); 3723072Smckusic upper = con.crval; 373750Speter if ( upper < lower ) { 374750Speter continue; 375750Speter } 3763072Smckusic lowerdiv = ( lower - set.lwrb ) >> LG2BITSLONG; 3773072Smckusic lowermod = ( lower - set.lwrb ) & MSKBITSLONG; 3783072Smckusic upperdiv = ( upper - set.lwrb ) >> LG2BITSLONG; 3793072Smckusic uppermod = ( upper - set.lwrb ) & MSKBITSLONG; 380750Speter temp = mask[ lowermod ]; 381750Speter if ( lowerdiv == upperdiv ) { 382750Speter temp &= ~mask[ uppermod + 1 ]; 383750Speter } 384750Speter tempset[ lowerdiv ] |= temp; 385750Speter limit = &tempset[ upperdiv-1 ]; 386750Speter for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) { 3873072Smckusic *lp |= 0xffffffff; 388750Speter } 389750Speter if ( lowerdiv != upperdiv ) { 390750Speter tempset[ upperdiv ] |= ~mask[ uppermod + 1 ]; 391750Speter } 392750Speter } else { 393750Speter constval( e ); 3943072Smckusic temp = con.crval - set.lwrb; 3953072Smckusic cp = (char *)tempset; 3963072Smckusic cp[temp >> LG2BITSBYTE] |= (1 << (temp & MSKBITSBYTE)); 397750Speter } 398750Speter } 3993315Speter if ( !CGENNING ) 400750Speter return; 401750Speter # ifdef PC 402750Speter label = getlab(); 403*10652Speter putprintf(" .data" , 0 ); 404*10652Speter aligndot(A_SET); 405750Speter putlab( label ); 406750Speter lp = &( tempset[0] ); 4073072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 408*10652Speter while (lp < limit) { 409*10652Speter putprintf(" .long 0x%x", 1, *lp++); 410*10652Speter for (temp = 2 ; temp <= 8 && lp < limit ; temp++) { 411*10652Speter putprintf(",0x%x", 1, *lp++); 412750Speter } 413*10652Speter putprintf("", 0); 414750Speter } 415*10652Speter putprintf(" .text", 0); 416750Speter sprintf( labelname , PREFIXFORMAT , LABELPREFIX , label ); 417750Speter putleaf( P2ICON , 0 , 0 , P2PTR | P2STRTY , labelname ); 418750Speter # endif PC 419750Speter # ifdef OBJ 4203072Smckusic put(2, O_CON, (int)(((set.uprbp >> LG2BITSLONG) + 1) * 4213072Smckusic (BITSPERLONG >> LG2BITSBYTE))); 422750Speter lp = &( tempset[0] ); 4233072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 424750Speter while ( lp < limit ) { 4253072Smckusic put(2, O_CASE4, *lp ++); 426750Speter } 427750Speter # endif OBJ 4283072Smckusic #else 4293072Smckusic panic("const cset"); 4303072Smckusic #endif CONSETS 431750Speter } else { 432750Speter # ifdef PC 433750Speter putleaf( P2ICON , csetp -> paircnt , 0 , P2INT , 0 ); 434750Speter putop( P2LISTOP , P2INT ); 435750Speter putleaf( P2ICON , csetp -> singcnt , 0 , P2INT , 0 ); 436750Speter putop( P2LISTOP , P2INT ); 437750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 438750Speter e = el[1]; 439750Speter if ( e[0] == T_RANG ) { 440750Speter rvalue( e[2] , NIL , RREQ ); 441750Speter putop( P2LISTOP , P2INT ); 442750Speter rvalue( e[1] , NIL , RREQ ); 443750Speter putop( P2LISTOP , P2INT ); 444750Speter } else { 445750Speter rvalue( e , NIL , RREQ ); 446750Speter putop( P2LISTOP , P2INT ); 447750Speter } 448750Speter } 449750Speter # endif PC 450750Speter # ifdef OBJ 451750Speter for ( el = r[2] ; el != NIL ; el = el[2] ) { 452750Speter e = el[1]; 453750Speter if ( e[0] == T_RANG ) { 4541884Speter stkrval( e[1] , NIL , RREQ ); 455750Speter stkrval( e[2] , NIL , RREQ ); 456750Speter } else { 457750Speter stkrval( e , NIL , RREQ ); 458750Speter } 459750Speter } 4603072Smckusic put(2 , O_CON24 , (int)csetp -> singcnt ); 4613072Smckusic put(2 , O_CON24 , (int)csetp -> paircnt ); 462750Speter # endif OBJ 463750Speter } 464750Speter } 465