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