1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622161Sdist */ 7750Speter 815927Sthien #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)cset.c 5.2 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11750Speter 12750Speter #include "whoami.h" 13750Speter #include "0.h" 14750Speter #include "tree.h" 15750Speter #include "opcode.h" 16750Speter #include "objfmt.h" 1715927Sthien #include "tree_ty.h" 183072Smckusic #ifdef PC 19750Speter #include "pc.h" 2018455Sralph #include <pcc.h> 2110652Speter #include "align.h" 223072Smckusic #endif PC 23750Speter 24750Speter /* 253072Smckusic * CONSETS causes compile time constant sets to be constructed here. 263072Smckusic * 273072Smckusic * COMPSETSZE defines the maximum number of longs to be used in 283072Smckusic * constant set construction 293072Smckusic */ 303072Smckusic #define CONSETS 313072Smckusic #define COMPSETSZE 10 323072Smckusic 333072Smckusic #define BITSPERBYTE 8 343072Smckusic #define BITSPERLONG 32 353072Smckusic #define LG2BITSBYTE 3 363072Smckusic #define MSKBITSBYTE 0x07 373072Smckusic #define LG2BITSLONG 5 383072Smckusic #define MSKBITSLONG 0x1f 393072Smckusic 403072Smckusic /* 41750Speter * rummage through a `constant' set (i.e. anything within [ ]'s) tree 42750Speter * and decide if this is a compile time constant set or a runtime set. 43750Speter * this information is returned in a structure passed from the caller. 44750Speter * while rummaging, this also reorders the tree so that all ranges 45750Speter * preceed all singletons. 46750Speter */ 47750Speter bool 48750Speter precset( r , settype , csetp ) 4915927Sthien struct tnode *r; 50750Speter struct nl *settype; 51750Speter struct csetstr *csetp; 52750Speter { 5315927Sthien register struct tnode *e; 54750Speter register struct nl *t; 55750Speter register struct nl *exptype; 5615927Sthien register struct tnode *el; 5715927Sthien register struct tnode *pairp; 5815927Sthien register struct tnode *singp; 5915927Sthien struct tnode *ip; 603072Smckusic int lower; 613072Smckusic int upper; 62750Speter bool setofint; 63750Speter 64750Speter csetp -> csettype = NIL; 65750Speter csetp -> paircnt = 0; 66750Speter csetp -> singcnt = 0; 67750Speter csetp -> comptime = TRUE; 68750Speter setofint = FALSE; 69750Speter if ( settype != NIL ) { 70750Speter if ( settype -> class == SET ) { 71750Speter /* 72750Speter * the easy case, we are told the type of the set. 73750Speter */ 74750Speter exptype = settype -> type; 75750Speter } else { 76750Speter /* 77750Speter * we are told the type, but it's not a set 78750Speter * supposedly possible if someone tries 79750Speter * e.g string context [1,2] = 'abc' 80750Speter */ 81750Speter error("Constant set involved in non set context"); 82750Speter return csetp -> comptime; 83750Speter } 84750Speter } else { 85750Speter /* 86750Speter * So far we have no indication 87750Speter * of what the set type should be. 88750Speter * We "look ahead" and try to infer 89750Speter * The type of the constant set 90750Speter * by evaluating one of its members. 91750Speter */ 9215927Sthien e = r->cset_node.el_list; 93750Speter if (e == NIL) { 94750Speter /* 951552Speter * tentative for [], return type of `intset' 96750Speter */ 9715927Sthien settype = lookup( (char *) intset ); 981552Speter if ( settype == NIL ) { 991552Speter panic( "empty set" ); 1001552Speter } 1011552Speter settype = settype -> type; 1021552Speter if ( settype == NIL ) { 1031552Speter return csetp -> comptime; 1041552Speter } 1051552Speter if ( isnta( settype , "t" ) ) { 1061552Speter error("Set default type \"intset\" is not a set"); 1071552Speter return csetp -> comptime; 1081552Speter } 1091552Speter csetp -> csettype = settype; 1103170Smckusic setran( settype -> type ); 1113072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1123072Smckusic csetp -> comptime = FALSE; 113750Speter return csetp -> comptime; 114750Speter } 11515927Sthien e = e->list_node.list; 116750Speter if (e == NIL) { 117750Speter return csetp -> comptime; 118750Speter } 11915927Sthien if (e->tag == T_RANG) { 12015927Sthien e = e->rang.expr1; 121750Speter } 122750Speter codeoff(); 12315927Sthien t = rvalue(e, NLNIL , RREQ ); 124750Speter codeon(); 125750Speter if (t == NIL) { 126750Speter return csetp -> comptime; 127750Speter } 128750Speter /* 129750Speter * The type of the set, settype, is 130750Speter * deemed to be a set of the base type 131750Speter * of t, which we call exptype. If, 132750Speter * however, this would involve a 133750Speter * "set of integer", we cop out 134750Speter * and use "intset"'s current scoped 135750Speter * type instead. 136750Speter */ 137750Speter if (isa(t, "r")) { 138750Speter error("Sets may not have 'real' elements"); 139750Speter return csetp -> comptime; 140750Speter } 141750Speter if (isnta(t, "bcsi")) { 142750Speter error("Set elements must be scalars, not %ss", nameof(t)); 143750Speter return csetp -> comptime; 144750Speter } 145750Speter if (isa(t, "i")) { 14615927Sthien settype = lookup((char *) intset); 147750Speter if (settype == NIL) 148750Speter panic("intset"); 149750Speter settype = settype->type; 150750Speter if (settype == NIL) 151750Speter return csetp -> comptime; 152750Speter if (isnta(settype, "t")) { 153750Speter error("Set default type \"intset\" is not a set"); 154750Speter return csetp -> comptime; 155750Speter } 156750Speter exptype = settype->type; 157750Speter /* 158750Speter * say we are doing an intset 159750Speter * but, if we get out of range errors for intset 160750Speter * we punt constructing the set at compile time. 161750Speter */ 162750Speter setofint = TRUE; 163750Speter } else { 164750Speter exptype = t->type; 165750Speter if (exptype == NIL) 166750Speter return csetp -> comptime; 167750Speter if (exptype->class != RANGE) 168750Speter exptype = exptype->type; 16915927Sthien settype = defnl((char *) 0, SET, exptype, 0); 170750Speter } 171750Speter } 172750Speter csetp -> csettype = settype; 1733072Smckusic # ifndef CONSETS 1743072Smckusic csetp -> comptime = FALSE; 1753072Smckusic # endif CONSETS 176750Speter setran( exptype ); 1773072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1783072Smckusic csetp -> comptime = FALSE; 179750Speter lower = set.lwrb; 180750Speter upper = set.lwrb + set.uprbp; 181750Speter pairp = NIL; 182750Speter singp = NIL; 183750Speter codeoff(); 18415927Sthien while ( el = r->cset_node.el_list ) { 18515927Sthien e = el->list_node.list; 186750Speter if (e == NIL) { 187750Speter /* 188750Speter * don't hang this one anywhere. 189750Speter */ 190750Speter csetp -> csettype = NIL; 19115927Sthien r->cset_node.el_list = el->list_node.next; 192750Speter continue; 193750Speter } 19415927Sthien if (e->tag == T_RANG) { 19515927Sthien if ( csetp -> comptime && constval( e->rang.expr2 ) ) { 1963072Smckusic #ifdef CONSETS 197750Speter t = con.ctype; 1983072Smckusic if ( con.crval < lower || con.crval > upper ) { 199750Speter if ( setofint ) { 200750Speter csetp -> comptime = FALSE; 201750Speter } else { 2023072Smckusic error("Range upper bound of %D out of set bounds" , ((long)con.crval) ); 203750Speter csetp -> csettype = NIL; 204750Speter } 205750Speter } 2063072Smckusic #endif CONSETS 207750Speter } else { 208750Speter csetp -> comptime = FALSE; 20915927Sthien t = rvalue(e->rang.expr2, NLNIL , RREQ ); 210750Speter if (t == NIL) { 21115927Sthien (void) rvalue(e->rang.expr1, NLNIL , RREQ ); 212750Speter goto pairhang; 213750Speter } 214750Speter } 21515927Sthien if (incompat(t, exptype, e->rang.expr2)) { 216750Speter cerror("Upper bound of element type clashed with set type in constant set"); 217750Speter } 21815927Sthien if ( csetp -> comptime && constval( e->rang.expr1 ) ) { 2193072Smckusic #ifdef CONSETS 220750Speter t = con.ctype; 2213072Smckusic if ( con.crval < lower || con.crval > upper ) { 222750Speter if ( setofint ) { 223750Speter csetp -> comptime = FALSE; 224750Speter } else { 2253072Smckusic error("Range lower bound of %D out of set bounds" , ((long)con.crval) ); 226750Speter csetp -> csettype = NIL; 227750Speter } 228750Speter } 2293072Smckusic #endif CONSETS 230750Speter } else { 231750Speter csetp -> comptime = FALSE; 23215927Sthien t = rvalue(e->rang.expr1, NLNIL , RREQ ); 233750Speter if (t == NIL) { 234750Speter goto pairhang; 235750Speter } 236750Speter } 23715927Sthien if (incompat(t, exptype, e->rang.expr1)) { 238750Speter cerror("Lower bound of element type clashed with set type in constant set"); 239750Speter } 240750Speter pairhang: 241750Speter /* 242750Speter * remove this range from the tree list and 243750Speter * hang it on the pairs list. 244750Speter */ 24515927Sthien ip = el->list_node.next; 24615927Sthien el->list_node.next = pairp; 24715927Sthien pairp = r->cset_node.el_list; 24815927Sthien r->cset_node.el_list = ip; 249750Speter csetp -> paircnt++; 250750Speter } else { 251750Speter if ( csetp -> comptime && constval( e ) ) { 2523072Smckusic #ifdef CONSETS 253750Speter t = con.ctype; 2543072Smckusic if ( con.crval < lower || con.crval > upper ) { 255750Speter if ( setofint ) { 256750Speter csetp -> comptime = FALSE; 257750Speter } else { 2583072Smckusic error("Value of %D out of set bounds" , ((long)con.crval) ); 259750Speter csetp -> csettype = NIL; 260750Speter } 261750Speter } 2623072Smckusic #endif CONSETS 263750Speter } else { 264750Speter csetp -> comptime = FALSE; 26515927Sthien t = rvalue( e, NLNIL , RREQ ); 266750Speter if (t == NIL) { 267750Speter goto singhang; 268750Speter } 269750Speter } 270750Speter if (incompat(t, exptype, e)) { 271750Speter cerror("Element type clashed with set type in constant set"); 272750Speter } 273750Speter singhang: 274750Speter /* 275750Speter * take this expression off the tree list and 276750Speter * hang it on the list of singletons. 277750Speter */ 27815927Sthien ip = el->list_node.next; 27915927Sthien el->list_node.next = singp; 28015927Sthien singp = r->cset_node.el_list; 28115927Sthien r->cset_node.el_list = ip; 282750Speter csetp -> singcnt++; 283750Speter } 284750Speter } 285750Speter codeon(); 286750Speter # ifdef PC 287750Speter if ( pairp != NIL ) { 28815927Sthien for ( el = pairp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */; 28915927Sthien el->list_node.next = singp; 29015927Sthien r->cset_node.el_list = pairp; 291750Speter } else { 29215927Sthien r->cset_node.el_list = singp; 293750Speter } 294750Speter # endif PC 295750Speter # ifdef OBJ 296750Speter if ( singp != NIL ) { 29715927Sthien for ( el = singp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */; 29815927Sthien el->list_node.next = pairp; 29915927Sthien r->cset_node.el_list = singp; 300750Speter } else { 30115927Sthien r->cset_node.el_list = pairp; 302750Speter } 303750Speter # endif OBJ 304750Speter if ( csetp -> csettype == NIL ) { 305750Speter csetp -> comptime = TRUE; 306750Speter } 307750Speter return csetp -> comptime; 308750Speter } 309750Speter 3103072Smckusic #ifdef CONSETS 311750Speter /* 312750Speter * mask[i] has the low i bits turned off. 313750Speter */ 314750Speter long mask[] = { 3153072Smckusic # ifdef DEC11 316750Speter 0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 , 317750Speter 0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 , 318750Speter 0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 , 319750Speter 0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 , 320750Speter 0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 , 321750Speter 0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 , 322750Speter 0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 , 323750Speter 0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 , 324750Speter 0x00000000 3253072Smckusic # else 3263072Smckusic 0xffffffff , 0xfeffffff , 0xfcffffff , 0xf8ffffff , 3273072Smckusic 0xf0ffffff , 0xe0ffffff , 0xc0ffffff , 0x80ffffff , 3283072Smckusic 0x00ffffff , 0x00feffff , 0x00fcffff , 0x00f8ffff , 3293072Smckusic 0x00f0ffff , 0x00e0ffff , 0x00c0ffff , 0x0080ffff , 3303072Smckusic 0x0000ffff , 0x0000feff , 0x0000fcff , 0x0000f8ff , 3313072Smckusic 0x0000f0ff , 0x0000e0ff , 0x0000c0ff , 0x000080ff , 3323072Smckusic 0x000000ff , 0x000000fe , 0x000000fc , 0x000000f8 , 3333072Smckusic 0x000000f0 , 0x000000e0 , 0x000000c0 , 0x00000080 , 3343072Smckusic 0x00000000 3353072Smckusic # endif DEC11 3363072Smckusic }; 337750Speter /* 338750Speter * given a csetstr, either 339750Speter * put out a compile time constant set and an lvalue to it. 340750Speter * or 341750Speter * put out rvalues for the singletons and the pairs 342750Speter * and counts of each. 343750Speter */ 3443072Smckusic #endif CONSETS 345750Speter postcset( r , csetp ) 34615927Sthien struct tnode *r; 347750Speter struct csetstr *csetp; 348750Speter { 34915927Sthien register struct tnode *el; 35015927Sthien register struct tnode *e; 351750Speter int lower; 352750Speter int upper; 353750Speter int lowerdiv; 354750Speter int lowermod; 355750Speter int upperdiv; 356750Speter int uppermod; 357750Speter long *lp; 358750Speter long *limit; 3593072Smckusic long tempset[ COMPSETSZE ]; 360750Speter long temp; 3613072Smckusic char *cp; 3623072Smckusic # ifdef PC 36315927Sthien int label; 3643072Smckusic char labelname[ BUFSIZ ]; 3653072Smckusic # endif PC 366750Speter 367750Speter if ( csetp -> comptime ) { 3683072Smckusic #ifdef CONSETS 369750Speter setran( ( csetp -> csettype ) -> type ); 3703072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 371750Speter for ( lp = &tempset[0] ; lp < limit ; lp++ ) { 372750Speter *lp = 0; 373750Speter } 37415927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 37515927Sthien e = el->list_node.list; 37615927Sthien if ( e->tag == T_RANG ) { 37715927Sthien (void) constval( e->rang.expr1 ); 3783072Smckusic lower = con.crval; 37915927Sthien (void) constval( e->rang.expr2 ); 3803072Smckusic upper = con.crval; 381750Speter if ( upper < lower ) { 382750Speter continue; 383750Speter } 3843072Smckusic lowerdiv = ( lower - set.lwrb ) >> LG2BITSLONG; 3853072Smckusic lowermod = ( lower - set.lwrb ) & MSKBITSLONG; 3863072Smckusic upperdiv = ( upper - set.lwrb ) >> LG2BITSLONG; 3873072Smckusic uppermod = ( upper - set.lwrb ) & MSKBITSLONG; 388750Speter temp = mask[ lowermod ]; 389750Speter if ( lowerdiv == upperdiv ) { 390750Speter temp &= ~mask[ uppermod + 1 ]; 391750Speter } 392750Speter tempset[ lowerdiv ] |= temp; 393750Speter limit = &tempset[ upperdiv-1 ]; 394750Speter for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) { 3953072Smckusic *lp |= 0xffffffff; 396750Speter } 397750Speter if ( lowerdiv != upperdiv ) { 398750Speter tempset[ upperdiv ] |= ~mask[ uppermod + 1 ]; 399750Speter } 400750Speter } else { 40115927Sthien (void) constval( e ); 4023072Smckusic temp = con.crval - set.lwrb; 4033072Smckusic cp = (char *)tempset; 4043072Smckusic cp[temp >> LG2BITSBYTE] |= (1 << (temp & MSKBITSBYTE)); 405750Speter } 406750Speter } 4073315Speter if ( !CGENNING ) 408750Speter return; 409750Speter # ifdef PC 41015927Sthien label = (int) getlab(); 41110652Speter putprintf(" .data" , 0 ); 41210652Speter aligndot(A_SET); 41315927Sthien (void) putlab( (char *) label ); 414750Speter lp = &( tempset[0] ); 4153072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 41610652Speter while (lp < limit) { 41715927Sthien putprintf(" .long 0x%x", 1, (int) (*lp++)); 41810652Speter for (temp = 2 ; temp <= 8 && lp < limit ; temp++) { 41915927Sthien putprintf(",0x%x", 1, (int) (*lp++)); 420750Speter } 42110652Speter putprintf("", 0); 422750Speter } 42310652Speter putprintf(" .text", 0); 42415927Sthien sprintf( labelname , PREFIXFORMAT , LABELPREFIX , (char *) label ); 42518455Sralph putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR | PCCT_STRTY , labelname ); 426750Speter # endif PC 427750Speter # ifdef OBJ 42815927Sthien (void) put(2, O_CON, (int)(((set.uprbp >> LG2BITSLONG) + 1) * 4293072Smckusic (BITSPERLONG >> LG2BITSBYTE))); 430750Speter lp = &( tempset[0] ); 4313072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 432750Speter while ( lp < limit ) { 43315927Sthien (void) put(2, O_CASE4, (int) (*lp ++)); 434750Speter } 435750Speter # endif OBJ 4363072Smckusic #else 4373072Smckusic panic("const cset"); 4383072Smckusic #endif CONSETS 439750Speter } else { 440750Speter # ifdef PC 44118455Sralph putleaf( PCC_ICON , (int) csetp -> paircnt , 0 , PCCT_INT , (char *) 0 ); 44218455Sralph putop( PCC_CM , PCCT_INT ); 44318455Sralph putleaf( PCC_ICON , (int) csetp -> singcnt , 0 , PCCT_INT , (char *) 0 ); 44418455Sralph putop( PCC_CM , PCCT_INT ); 44515927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 44615927Sthien e = el->list_node.list; 44715927Sthien if ( e->tag == T_RANG ) { 44815927Sthien (void) rvalue( e->rang.expr2 , NLNIL , RREQ ); 44918455Sralph putop( PCC_CM , PCCT_INT ); 45015927Sthien (void) rvalue( e->rang.expr1 , NLNIL , RREQ ); 45118455Sralph putop( PCC_CM , PCCT_INT ); 452750Speter } else { 45315927Sthien (void) rvalue( e , NLNIL , RREQ ); 45418455Sralph putop( PCC_CM , PCCT_INT ); 455750Speter } 456750Speter } 457750Speter # endif PC 458750Speter # ifdef OBJ 45915927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 46015927Sthien e = el->list_node.list; 46115927Sthien if ( e->tag == T_RANG ) { 46215927Sthien (void) stkrval( e->rang.expr1 , NLNIL , (long) RREQ ); 46315927Sthien (void) stkrval( e->rang.expr2 , NLNIL , (long) RREQ ); 464750Speter } else { 46515927Sthien (void) stkrval( e , NLNIL , (long) RREQ ); 466750Speter } 467750Speter } 46815927Sthien (void) put(2 , O_CON24 , (int)csetp -> singcnt ); 46915927Sthien (void) put(2 , O_CON24 , (int)csetp -> paircnt ); 470750Speter # endif OBJ 471750Speter } 472750Speter } 473