1750Speter /* Copyright (c) 1979 Regents of the University of California */ 2750Speter 315927Sthien #ifndef lint 4*18455Sralph static char sccsid[] = "@(#)cset.c 2.2 03/20/85"; 515927Sthien #endif 6750Speter 7750Speter #include "whoami.h" 8750Speter #include "0.h" 9750Speter #include "tree.h" 10750Speter #include "opcode.h" 11750Speter #include "objfmt.h" 1215927Sthien #include "tree_ty.h" 133072Smckusic #ifdef PC 14750Speter #include "pc.h" 15*18455Sralph #include <pcc.h> 1610652Speter #include "align.h" 173072Smckusic #endif PC 18750Speter 19750Speter /* 203072Smckusic * CONSETS causes compile time constant sets to be constructed here. 213072Smckusic * 223072Smckusic * COMPSETSZE defines the maximum number of longs to be used in 233072Smckusic * constant set construction 243072Smckusic */ 253072Smckusic #define CONSETS 263072Smckusic #define COMPSETSZE 10 273072Smckusic 283072Smckusic #define BITSPERBYTE 8 293072Smckusic #define BITSPERLONG 32 303072Smckusic #define LG2BITSBYTE 3 313072Smckusic #define MSKBITSBYTE 0x07 323072Smckusic #define LG2BITSLONG 5 333072Smckusic #define MSKBITSLONG 0x1f 343072Smckusic 353072Smckusic /* 36750Speter * rummage through a `constant' set (i.e. anything within [ ]'s) tree 37750Speter * and decide if this is a compile time constant set or a runtime set. 38750Speter * this information is returned in a structure passed from the caller. 39750Speter * while rummaging, this also reorders the tree so that all ranges 40750Speter * preceed all singletons. 41750Speter */ 42750Speter bool 43750Speter precset( r , settype , csetp ) 4415927Sthien struct tnode *r; 45750Speter struct nl *settype; 46750Speter struct csetstr *csetp; 47750Speter { 4815927Sthien register struct tnode *e; 49750Speter register struct nl *t; 50750Speter register struct nl *exptype; 5115927Sthien register struct tnode *el; 5215927Sthien register struct tnode *pairp; 5315927Sthien register struct tnode *singp; 5415927Sthien struct tnode *ip; 553072Smckusic int lower; 563072Smckusic int upper; 57750Speter bool setofint; 58750Speter 59750Speter csetp -> csettype = NIL; 60750Speter csetp -> paircnt = 0; 61750Speter csetp -> singcnt = 0; 62750Speter csetp -> comptime = TRUE; 63750Speter setofint = FALSE; 64750Speter if ( settype != NIL ) { 65750Speter if ( settype -> class == SET ) { 66750Speter /* 67750Speter * the easy case, we are told the type of the set. 68750Speter */ 69750Speter exptype = settype -> type; 70750Speter } else { 71750Speter /* 72750Speter * we are told the type, but it's not a set 73750Speter * supposedly possible if someone tries 74750Speter * e.g string context [1,2] = 'abc' 75750Speter */ 76750Speter error("Constant set involved in non set context"); 77750Speter return csetp -> comptime; 78750Speter } 79750Speter } else { 80750Speter /* 81750Speter * So far we have no indication 82750Speter * of what the set type should be. 83750Speter * We "look ahead" and try to infer 84750Speter * The type of the constant set 85750Speter * by evaluating one of its members. 86750Speter */ 8715927Sthien e = r->cset_node.el_list; 88750Speter if (e == NIL) { 89750Speter /* 901552Speter * tentative for [], return type of `intset' 91750Speter */ 9215927Sthien settype = lookup( (char *) intset ); 931552Speter if ( settype == NIL ) { 941552Speter panic( "empty set" ); 951552Speter } 961552Speter settype = settype -> type; 971552Speter if ( settype == NIL ) { 981552Speter return csetp -> comptime; 991552Speter } 1001552Speter if ( isnta( settype , "t" ) ) { 1011552Speter error("Set default type \"intset\" is not a set"); 1021552Speter return csetp -> comptime; 1031552Speter } 1041552Speter csetp -> csettype = settype; 1053170Smckusic setran( settype -> type ); 1063072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1073072Smckusic csetp -> comptime = FALSE; 108750Speter return csetp -> comptime; 109750Speter } 11015927Sthien e = e->list_node.list; 111750Speter if (e == NIL) { 112750Speter return csetp -> comptime; 113750Speter } 11415927Sthien if (e->tag == T_RANG) { 11515927Sthien e = e->rang.expr1; 116750Speter } 117750Speter codeoff(); 11815927Sthien t = rvalue(e, NLNIL , RREQ ); 119750Speter codeon(); 120750Speter if (t == NIL) { 121750Speter return csetp -> comptime; 122750Speter } 123750Speter /* 124750Speter * The type of the set, settype, is 125750Speter * deemed to be a set of the base type 126750Speter * of t, which we call exptype. If, 127750Speter * however, this would involve a 128750Speter * "set of integer", we cop out 129750Speter * and use "intset"'s current scoped 130750Speter * type instead. 131750Speter */ 132750Speter if (isa(t, "r")) { 133750Speter error("Sets may not have 'real' elements"); 134750Speter return csetp -> comptime; 135750Speter } 136750Speter if (isnta(t, "bcsi")) { 137750Speter error("Set elements must be scalars, not %ss", nameof(t)); 138750Speter return csetp -> comptime; 139750Speter } 140750Speter if (isa(t, "i")) { 14115927Sthien settype = lookup((char *) intset); 142750Speter if (settype == NIL) 143750Speter panic("intset"); 144750Speter settype = settype->type; 145750Speter if (settype == NIL) 146750Speter return csetp -> comptime; 147750Speter if (isnta(settype, "t")) { 148750Speter error("Set default type \"intset\" is not a set"); 149750Speter return csetp -> comptime; 150750Speter } 151750Speter exptype = settype->type; 152750Speter /* 153750Speter * say we are doing an intset 154750Speter * but, if we get out of range errors for intset 155750Speter * we punt constructing the set at compile time. 156750Speter */ 157750Speter setofint = TRUE; 158750Speter } else { 159750Speter exptype = t->type; 160750Speter if (exptype == NIL) 161750Speter return csetp -> comptime; 162750Speter if (exptype->class != RANGE) 163750Speter exptype = exptype->type; 16415927Sthien settype = defnl((char *) 0, SET, exptype, 0); 165750Speter } 166750Speter } 167750Speter csetp -> csettype = settype; 1683072Smckusic # ifndef CONSETS 1693072Smckusic csetp -> comptime = FALSE; 1703072Smckusic # endif CONSETS 171750Speter setran( exptype ); 1723072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1733072Smckusic csetp -> comptime = FALSE; 174750Speter lower = set.lwrb; 175750Speter upper = set.lwrb + set.uprbp; 176750Speter pairp = NIL; 177750Speter singp = NIL; 178750Speter codeoff(); 17915927Sthien while ( el = r->cset_node.el_list ) { 18015927Sthien e = el->list_node.list; 181750Speter if (e == NIL) { 182750Speter /* 183750Speter * don't hang this one anywhere. 184750Speter */ 185750Speter csetp -> csettype = NIL; 18615927Sthien r->cset_node.el_list = el->list_node.next; 187750Speter continue; 188750Speter } 18915927Sthien if (e->tag == T_RANG) { 19015927Sthien if ( csetp -> comptime && constval( e->rang.expr2 ) ) { 1913072Smckusic #ifdef CONSETS 192750Speter t = con.ctype; 1933072Smckusic if ( con.crval < lower || con.crval > upper ) { 194750Speter if ( setofint ) { 195750Speter csetp -> comptime = FALSE; 196750Speter } else { 1973072Smckusic error("Range upper bound of %D out of set bounds" , ((long)con.crval) ); 198750Speter csetp -> csettype = NIL; 199750Speter } 200750Speter } 2013072Smckusic #endif CONSETS 202750Speter } else { 203750Speter csetp -> comptime = FALSE; 20415927Sthien t = rvalue(e->rang.expr2, NLNIL , RREQ ); 205750Speter if (t == NIL) { 20615927Sthien (void) rvalue(e->rang.expr1, NLNIL , RREQ ); 207750Speter goto pairhang; 208750Speter } 209750Speter } 21015927Sthien if (incompat(t, exptype, e->rang.expr2)) { 211750Speter cerror("Upper bound of element type clashed with set type in constant set"); 212750Speter } 21315927Sthien if ( csetp -> comptime && constval( e->rang.expr1 ) ) { 2143072Smckusic #ifdef CONSETS 215750Speter t = con.ctype; 2163072Smckusic if ( con.crval < lower || con.crval > upper ) { 217750Speter if ( setofint ) { 218750Speter csetp -> comptime = FALSE; 219750Speter } else { 2203072Smckusic error("Range lower bound of %D out of set bounds" , ((long)con.crval) ); 221750Speter csetp -> csettype = NIL; 222750Speter } 223750Speter } 2243072Smckusic #endif CONSETS 225750Speter } else { 226750Speter csetp -> comptime = FALSE; 22715927Sthien t = rvalue(e->rang.expr1, NLNIL , RREQ ); 228750Speter if (t == NIL) { 229750Speter goto pairhang; 230750Speter } 231750Speter } 23215927Sthien if (incompat(t, exptype, e->rang.expr1)) { 233750Speter cerror("Lower bound of element type clashed with set type in constant set"); 234750Speter } 235750Speter pairhang: 236750Speter /* 237750Speter * remove this range from the tree list and 238750Speter * hang it on the pairs list. 239750Speter */ 24015927Sthien ip = el->list_node.next; 24115927Sthien el->list_node.next = pairp; 24215927Sthien pairp = r->cset_node.el_list; 24315927Sthien r->cset_node.el_list = ip; 244750Speter csetp -> paircnt++; 245750Speter } else { 246750Speter if ( csetp -> comptime && constval( e ) ) { 2473072Smckusic #ifdef CONSETS 248750Speter t = con.ctype; 2493072Smckusic if ( con.crval < lower || con.crval > upper ) { 250750Speter if ( setofint ) { 251750Speter csetp -> comptime = FALSE; 252750Speter } else { 2533072Smckusic error("Value of %D out of set bounds" , ((long)con.crval) ); 254750Speter csetp -> csettype = NIL; 255750Speter } 256750Speter } 2573072Smckusic #endif CONSETS 258750Speter } else { 259750Speter csetp -> comptime = FALSE; 26015927Sthien t = rvalue( e, NLNIL , RREQ ); 261750Speter if (t == NIL) { 262750Speter goto singhang; 263750Speter } 264750Speter } 265750Speter if (incompat(t, exptype, e)) { 266750Speter cerror("Element type clashed with set type in constant set"); 267750Speter } 268750Speter singhang: 269750Speter /* 270750Speter * take this expression off the tree list and 271750Speter * hang it on the list of singletons. 272750Speter */ 27315927Sthien ip = el->list_node.next; 27415927Sthien el->list_node.next = singp; 27515927Sthien singp = r->cset_node.el_list; 27615927Sthien r->cset_node.el_list = ip; 277750Speter csetp -> singcnt++; 278750Speter } 279750Speter } 280750Speter codeon(); 281750Speter # ifdef PC 282750Speter if ( pairp != NIL ) { 28315927Sthien for ( el = pairp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */; 28415927Sthien el->list_node.next = singp; 28515927Sthien r->cset_node.el_list = pairp; 286750Speter } else { 28715927Sthien r->cset_node.el_list = singp; 288750Speter } 289750Speter # endif PC 290750Speter # ifdef OBJ 291750Speter if ( singp != NIL ) { 29215927Sthien for ( el = singp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */; 29315927Sthien el->list_node.next = pairp; 29415927Sthien r->cset_node.el_list = singp; 295750Speter } else { 29615927Sthien r->cset_node.el_list = pairp; 297750Speter } 298750Speter # endif OBJ 299750Speter if ( csetp -> csettype == NIL ) { 300750Speter csetp -> comptime = TRUE; 301750Speter } 302750Speter return csetp -> comptime; 303750Speter } 304750Speter 3053072Smckusic #ifdef CONSETS 306750Speter /* 307750Speter * mask[i] has the low i bits turned off. 308750Speter */ 309750Speter long mask[] = { 3103072Smckusic # ifdef DEC11 311750Speter 0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 , 312750Speter 0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 , 313750Speter 0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 , 314750Speter 0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 , 315750Speter 0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 , 316750Speter 0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 , 317750Speter 0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 , 318750Speter 0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 , 319750Speter 0x00000000 3203072Smckusic # else 3213072Smckusic 0xffffffff , 0xfeffffff , 0xfcffffff , 0xf8ffffff , 3223072Smckusic 0xf0ffffff , 0xe0ffffff , 0xc0ffffff , 0x80ffffff , 3233072Smckusic 0x00ffffff , 0x00feffff , 0x00fcffff , 0x00f8ffff , 3243072Smckusic 0x00f0ffff , 0x00e0ffff , 0x00c0ffff , 0x0080ffff , 3253072Smckusic 0x0000ffff , 0x0000feff , 0x0000fcff , 0x0000f8ff , 3263072Smckusic 0x0000f0ff , 0x0000e0ff , 0x0000c0ff , 0x000080ff , 3273072Smckusic 0x000000ff , 0x000000fe , 0x000000fc , 0x000000f8 , 3283072Smckusic 0x000000f0 , 0x000000e0 , 0x000000c0 , 0x00000080 , 3293072Smckusic 0x00000000 3303072Smckusic # endif DEC11 3313072Smckusic }; 332750Speter /* 333750Speter * given a csetstr, either 334750Speter * put out a compile time constant set and an lvalue to it. 335750Speter * or 336750Speter * put out rvalues for the singletons and the pairs 337750Speter * and counts of each. 338750Speter */ 3393072Smckusic #endif CONSETS 340750Speter postcset( r , csetp ) 34115927Sthien struct tnode *r; 342750Speter struct csetstr *csetp; 343750Speter { 34415927Sthien register struct tnode *el; 34515927Sthien register struct tnode *e; 346750Speter int lower; 347750Speter int upper; 348750Speter int lowerdiv; 349750Speter int lowermod; 350750Speter int upperdiv; 351750Speter int uppermod; 352750Speter long *lp; 353750Speter long *limit; 3543072Smckusic long tempset[ COMPSETSZE ]; 355750Speter long temp; 3563072Smckusic char *cp; 3573072Smckusic # ifdef PC 35815927Sthien int label; 3593072Smckusic char labelname[ BUFSIZ ]; 3603072Smckusic # endif PC 361750Speter 362750Speter if ( csetp -> comptime ) { 3633072Smckusic #ifdef CONSETS 364750Speter setran( ( csetp -> csettype ) -> type ); 3653072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 366750Speter for ( lp = &tempset[0] ; lp < limit ; lp++ ) { 367750Speter *lp = 0; 368750Speter } 36915927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 37015927Sthien e = el->list_node.list; 37115927Sthien if ( e->tag == T_RANG ) { 37215927Sthien (void) constval( e->rang.expr1 ); 3733072Smckusic lower = con.crval; 37415927Sthien (void) constval( e->rang.expr2 ); 3753072Smckusic upper = con.crval; 376750Speter if ( upper < lower ) { 377750Speter continue; 378750Speter } 3793072Smckusic lowerdiv = ( lower - set.lwrb ) >> LG2BITSLONG; 3803072Smckusic lowermod = ( lower - set.lwrb ) & MSKBITSLONG; 3813072Smckusic upperdiv = ( upper - set.lwrb ) >> LG2BITSLONG; 3823072Smckusic uppermod = ( upper - set.lwrb ) & MSKBITSLONG; 383750Speter temp = mask[ lowermod ]; 384750Speter if ( lowerdiv == upperdiv ) { 385750Speter temp &= ~mask[ uppermod + 1 ]; 386750Speter } 387750Speter tempset[ lowerdiv ] |= temp; 388750Speter limit = &tempset[ upperdiv-1 ]; 389750Speter for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) { 3903072Smckusic *lp |= 0xffffffff; 391750Speter } 392750Speter if ( lowerdiv != upperdiv ) { 393750Speter tempset[ upperdiv ] |= ~mask[ uppermod + 1 ]; 394750Speter } 395750Speter } else { 39615927Sthien (void) constval( e ); 3973072Smckusic temp = con.crval - set.lwrb; 3983072Smckusic cp = (char *)tempset; 3993072Smckusic cp[temp >> LG2BITSBYTE] |= (1 << (temp & MSKBITSBYTE)); 400750Speter } 401750Speter } 4023315Speter if ( !CGENNING ) 403750Speter return; 404750Speter # ifdef PC 40515927Sthien label = (int) getlab(); 40610652Speter putprintf(" .data" , 0 ); 40710652Speter aligndot(A_SET); 40815927Sthien (void) putlab( (char *) label ); 409750Speter lp = &( tempset[0] ); 4103072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 41110652Speter while (lp < limit) { 41215927Sthien putprintf(" .long 0x%x", 1, (int) (*lp++)); 41310652Speter for (temp = 2 ; temp <= 8 && lp < limit ; temp++) { 41415927Sthien putprintf(",0x%x", 1, (int) (*lp++)); 415750Speter } 41610652Speter putprintf("", 0); 417750Speter } 41810652Speter putprintf(" .text", 0); 41915927Sthien sprintf( labelname , PREFIXFORMAT , LABELPREFIX , (char *) label ); 420*18455Sralph putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR | PCCT_STRTY , labelname ); 421750Speter # endif PC 422750Speter # ifdef OBJ 42315927Sthien (void) put(2, O_CON, (int)(((set.uprbp >> LG2BITSLONG) + 1) * 4243072Smckusic (BITSPERLONG >> LG2BITSBYTE))); 425750Speter lp = &( tempset[0] ); 4263072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 427750Speter while ( lp < limit ) { 42815927Sthien (void) put(2, O_CASE4, (int) (*lp ++)); 429750Speter } 430750Speter # endif OBJ 4313072Smckusic #else 4323072Smckusic panic("const cset"); 4333072Smckusic #endif CONSETS 434750Speter } else { 435750Speter # ifdef PC 436*18455Sralph putleaf( PCC_ICON , (int) csetp -> paircnt , 0 , PCCT_INT , (char *) 0 ); 437*18455Sralph putop( PCC_CM , PCCT_INT ); 438*18455Sralph putleaf( PCC_ICON , (int) csetp -> singcnt , 0 , PCCT_INT , (char *) 0 ); 439*18455Sralph putop( PCC_CM , PCCT_INT ); 44015927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 44115927Sthien e = el->list_node.list; 44215927Sthien if ( e->tag == T_RANG ) { 44315927Sthien (void) rvalue( e->rang.expr2 , NLNIL , RREQ ); 444*18455Sralph putop( PCC_CM , PCCT_INT ); 44515927Sthien (void) rvalue( e->rang.expr1 , NLNIL , RREQ ); 446*18455Sralph putop( PCC_CM , PCCT_INT ); 447750Speter } else { 44815927Sthien (void) rvalue( e , NLNIL , RREQ ); 449*18455Sralph putop( PCC_CM , PCCT_INT ); 450750Speter } 451750Speter } 452750Speter # endif PC 453750Speter # ifdef OBJ 45415927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 45515927Sthien e = el->list_node.list; 45615927Sthien if ( e->tag == T_RANG ) { 45715927Sthien (void) stkrval( e->rang.expr1 , NLNIL , (long) RREQ ); 45815927Sthien (void) stkrval( e->rang.expr2 , NLNIL , (long) RREQ ); 459750Speter } else { 46015927Sthien (void) stkrval( e , NLNIL , (long) RREQ ); 461750Speter } 462750Speter } 46315927Sthien (void) put(2 , O_CON24 , (int)csetp -> singcnt ); 46415927Sthien (void) put(2 , O_CON24 , (int)csetp -> paircnt ); 465750Speter # endif OBJ 466750Speter } 467750Speter } 468