1*22161Sdist /* 2*22161Sdist * Copyright (c) 1980 Regents of the University of California. 3*22161Sdist * All rights reserved. The Berkeley software License Agreement 4*22161Sdist * specifies the terms and conditions for redistribution. 5*22161Sdist */ 6750Speter 715927Sthien #ifndef lint 8*22161Sdist static char sccsid[] = "@(#)cset.c 5.1 (Berkeley) 06/05/85"; 9*22161Sdist #endif not lint 10750Speter 11750Speter #include "whoami.h" 12750Speter #include "0.h" 13750Speter #include "tree.h" 14750Speter #include "opcode.h" 15750Speter #include "objfmt.h" 1615927Sthien #include "tree_ty.h" 173072Smckusic #ifdef PC 18750Speter #include "pc.h" 1918455Sralph #include <pcc.h> 2010652Speter #include "align.h" 213072Smckusic #endif PC 22750Speter 23750Speter /* 243072Smckusic * CONSETS causes compile time constant sets to be constructed here. 253072Smckusic * 263072Smckusic * COMPSETSZE defines the maximum number of longs to be used in 273072Smckusic * constant set construction 283072Smckusic */ 293072Smckusic #define CONSETS 303072Smckusic #define COMPSETSZE 10 313072Smckusic 323072Smckusic #define BITSPERBYTE 8 333072Smckusic #define BITSPERLONG 32 343072Smckusic #define LG2BITSBYTE 3 353072Smckusic #define MSKBITSBYTE 0x07 363072Smckusic #define LG2BITSLONG 5 373072Smckusic #define MSKBITSLONG 0x1f 383072Smckusic 393072Smckusic /* 40750Speter * rummage through a `constant' set (i.e. anything within [ ]'s) tree 41750Speter * and decide if this is a compile time constant set or a runtime set. 42750Speter * this information is returned in a structure passed from the caller. 43750Speter * while rummaging, this also reorders the tree so that all ranges 44750Speter * preceed all singletons. 45750Speter */ 46750Speter bool 47750Speter precset( r , settype , csetp ) 4815927Sthien struct tnode *r; 49750Speter struct nl *settype; 50750Speter struct csetstr *csetp; 51750Speter { 5215927Sthien register struct tnode *e; 53750Speter register struct nl *t; 54750Speter register struct nl *exptype; 5515927Sthien register struct tnode *el; 5615927Sthien register struct tnode *pairp; 5715927Sthien register struct tnode *singp; 5815927Sthien struct tnode *ip; 593072Smckusic int lower; 603072Smckusic int upper; 61750Speter bool setofint; 62750Speter 63750Speter csetp -> csettype = NIL; 64750Speter csetp -> paircnt = 0; 65750Speter csetp -> singcnt = 0; 66750Speter csetp -> comptime = TRUE; 67750Speter setofint = FALSE; 68750Speter if ( settype != NIL ) { 69750Speter if ( settype -> class == SET ) { 70750Speter /* 71750Speter * the easy case, we are told the type of the set. 72750Speter */ 73750Speter exptype = settype -> type; 74750Speter } else { 75750Speter /* 76750Speter * we are told the type, but it's not a set 77750Speter * supposedly possible if someone tries 78750Speter * e.g string context [1,2] = 'abc' 79750Speter */ 80750Speter error("Constant set involved in non set context"); 81750Speter return csetp -> comptime; 82750Speter } 83750Speter } else { 84750Speter /* 85750Speter * So far we have no indication 86750Speter * of what the set type should be. 87750Speter * We "look ahead" and try to infer 88750Speter * The type of the constant set 89750Speter * by evaluating one of its members. 90750Speter */ 9115927Sthien e = r->cset_node.el_list; 92750Speter if (e == NIL) { 93750Speter /* 941552Speter * tentative for [], return type of `intset' 95750Speter */ 9615927Sthien settype = lookup( (char *) intset ); 971552Speter if ( settype == NIL ) { 981552Speter panic( "empty set" ); 991552Speter } 1001552Speter settype = settype -> type; 1011552Speter if ( settype == NIL ) { 1021552Speter return csetp -> comptime; 1031552Speter } 1041552Speter if ( isnta( settype , "t" ) ) { 1051552Speter error("Set default type \"intset\" is not a set"); 1061552Speter return csetp -> comptime; 1071552Speter } 1081552Speter csetp -> csettype = settype; 1093170Smckusic setran( settype -> type ); 1103072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1113072Smckusic csetp -> comptime = FALSE; 112750Speter return csetp -> comptime; 113750Speter } 11415927Sthien e = e->list_node.list; 115750Speter if (e == NIL) { 116750Speter return csetp -> comptime; 117750Speter } 11815927Sthien if (e->tag == T_RANG) { 11915927Sthien e = e->rang.expr1; 120750Speter } 121750Speter codeoff(); 12215927Sthien t = rvalue(e, NLNIL , RREQ ); 123750Speter codeon(); 124750Speter if (t == NIL) { 125750Speter return csetp -> comptime; 126750Speter } 127750Speter /* 128750Speter * The type of the set, settype, is 129750Speter * deemed to be a set of the base type 130750Speter * of t, which we call exptype. If, 131750Speter * however, this would involve a 132750Speter * "set of integer", we cop out 133750Speter * and use "intset"'s current scoped 134750Speter * type instead. 135750Speter */ 136750Speter if (isa(t, "r")) { 137750Speter error("Sets may not have 'real' elements"); 138750Speter return csetp -> comptime; 139750Speter } 140750Speter if (isnta(t, "bcsi")) { 141750Speter error("Set elements must be scalars, not %ss", nameof(t)); 142750Speter return csetp -> comptime; 143750Speter } 144750Speter if (isa(t, "i")) { 14515927Sthien settype = lookup((char *) intset); 146750Speter if (settype == NIL) 147750Speter panic("intset"); 148750Speter settype = settype->type; 149750Speter if (settype == NIL) 150750Speter return csetp -> comptime; 151750Speter if (isnta(settype, "t")) { 152750Speter error("Set default type \"intset\" is not a set"); 153750Speter return csetp -> comptime; 154750Speter } 155750Speter exptype = settype->type; 156750Speter /* 157750Speter * say we are doing an intset 158750Speter * but, if we get out of range errors for intset 159750Speter * we punt constructing the set at compile time. 160750Speter */ 161750Speter setofint = TRUE; 162750Speter } else { 163750Speter exptype = t->type; 164750Speter if (exptype == NIL) 165750Speter return csetp -> comptime; 166750Speter if (exptype->class != RANGE) 167750Speter exptype = exptype->type; 16815927Sthien settype = defnl((char *) 0, SET, exptype, 0); 169750Speter } 170750Speter } 171750Speter csetp -> csettype = settype; 1723072Smckusic # ifndef CONSETS 1733072Smckusic csetp -> comptime = FALSE; 1743072Smckusic # endif CONSETS 175750Speter setran( exptype ); 1763072Smckusic if (((set.uprbp + 1) >> LG2BITSLONG) >= COMPSETSZE) 1773072Smckusic csetp -> comptime = FALSE; 178750Speter lower = set.lwrb; 179750Speter upper = set.lwrb + set.uprbp; 180750Speter pairp = NIL; 181750Speter singp = NIL; 182750Speter codeoff(); 18315927Sthien while ( el = r->cset_node.el_list ) { 18415927Sthien e = el->list_node.list; 185750Speter if (e == NIL) { 186750Speter /* 187750Speter * don't hang this one anywhere. 188750Speter */ 189750Speter csetp -> csettype = NIL; 19015927Sthien r->cset_node.el_list = el->list_node.next; 191750Speter continue; 192750Speter } 19315927Sthien if (e->tag == T_RANG) { 19415927Sthien if ( csetp -> comptime && constval( e->rang.expr2 ) ) { 1953072Smckusic #ifdef CONSETS 196750Speter t = con.ctype; 1973072Smckusic if ( con.crval < lower || con.crval > upper ) { 198750Speter if ( setofint ) { 199750Speter csetp -> comptime = FALSE; 200750Speter } else { 2013072Smckusic error("Range upper bound of %D out of set bounds" , ((long)con.crval) ); 202750Speter csetp -> csettype = NIL; 203750Speter } 204750Speter } 2053072Smckusic #endif CONSETS 206750Speter } else { 207750Speter csetp -> comptime = FALSE; 20815927Sthien t = rvalue(e->rang.expr2, NLNIL , RREQ ); 209750Speter if (t == NIL) { 21015927Sthien (void) rvalue(e->rang.expr1, NLNIL , RREQ ); 211750Speter goto pairhang; 212750Speter } 213750Speter } 21415927Sthien if (incompat(t, exptype, e->rang.expr2)) { 215750Speter cerror("Upper bound of element type clashed with set type in constant set"); 216750Speter } 21715927Sthien if ( csetp -> comptime && constval( e->rang.expr1 ) ) { 2183072Smckusic #ifdef CONSETS 219750Speter t = con.ctype; 2203072Smckusic if ( con.crval < lower || con.crval > upper ) { 221750Speter if ( setofint ) { 222750Speter csetp -> comptime = FALSE; 223750Speter } else { 2243072Smckusic error("Range lower bound of %D out of set bounds" , ((long)con.crval) ); 225750Speter csetp -> csettype = NIL; 226750Speter } 227750Speter } 2283072Smckusic #endif CONSETS 229750Speter } else { 230750Speter csetp -> comptime = FALSE; 23115927Sthien t = rvalue(e->rang.expr1, NLNIL , RREQ ); 232750Speter if (t == NIL) { 233750Speter goto pairhang; 234750Speter } 235750Speter } 23615927Sthien if (incompat(t, exptype, e->rang.expr1)) { 237750Speter cerror("Lower bound of element type clashed with set type in constant set"); 238750Speter } 239750Speter pairhang: 240750Speter /* 241750Speter * remove this range from the tree list and 242750Speter * hang it on the pairs list. 243750Speter */ 24415927Sthien ip = el->list_node.next; 24515927Sthien el->list_node.next = pairp; 24615927Sthien pairp = r->cset_node.el_list; 24715927Sthien r->cset_node.el_list = ip; 248750Speter csetp -> paircnt++; 249750Speter } else { 250750Speter if ( csetp -> comptime && constval( e ) ) { 2513072Smckusic #ifdef CONSETS 252750Speter t = con.ctype; 2533072Smckusic if ( con.crval < lower || con.crval > upper ) { 254750Speter if ( setofint ) { 255750Speter csetp -> comptime = FALSE; 256750Speter } else { 2573072Smckusic error("Value of %D out of set bounds" , ((long)con.crval) ); 258750Speter csetp -> csettype = NIL; 259750Speter } 260750Speter } 2613072Smckusic #endif CONSETS 262750Speter } else { 263750Speter csetp -> comptime = FALSE; 26415927Sthien t = rvalue( e, NLNIL , RREQ ); 265750Speter if (t == NIL) { 266750Speter goto singhang; 267750Speter } 268750Speter } 269750Speter if (incompat(t, exptype, e)) { 270750Speter cerror("Element type clashed with set type in constant set"); 271750Speter } 272750Speter singhang: 273750Speter /* 274750Speter * take this expression off the tree list and 275750Speter * hang it on the list of singletons. 276750Speter */ 27715927Sthien ip = el->list_node.next; 27815927Sthien el->list_node.next = singp; 27915927Sthien singp = r->cset_node.el_list; 28015927Sthien r->cset_node.el_list = ip; 281750Speter csetp -> singcnt++; 282750Speter } 283750Speter } 284750Speter codeon(); 285750Speter # ifdef PC 286750Speter if ( pairp != NIL ) { 28715927Sthien for ( el = pairp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */; 28815927Sthien el->list_node.next = singp; 28915927Sthien r->cset_node.el_list = pairp; 290750Speter } else { 29115927Sthien r->cset_node.el_list = singp; 292750Speter } 293750Speter # endif PC 294750Speter # ifdef OBJ 295750Speter if ( singp != NIL ) { 29615927Sthien for ( el = singp ; el->list_node.next != NIL ; el = el->list_node.next ) /* void */; 29715927Sthien el->list_node.next = pairp; 29815927Sthien r->cset_node.el_list = singp; 299750Speter } else { 30015927Sthien r->cset_node.el_list = pairp; 301750Speter } 302750Speter # endif OBJ 303750Speter if ( csetp -> csettype == NIL ) { 304750Speter csetp -> comptime = TRUE; 305750Speter } 306750Speter return csetp -> comptime; 307750Speter } 308750Speter 3093072Smckusic #ifdef CONSETS 310750Speter /* 311750Speter * mask[i] has the low i bits turned off. 312750Speter */ 313750Speter long mask[] = { 3143072Smckusic # ifdef DEC11 315750Speter 0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 , 316750Speter 0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 , 317750Speter 0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 , 318750Speter 0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 , 319750Speter 0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 , 320750Speter 0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 , 321750Speter 0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 , 322750Speter 0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 , 323750Speter 0x00000000 3243072Smckusic # else 3253072Smckusic 0xffffffff , 0xfeffffff , 0xfcffffff , 0xf8ffffff , 3263072Smckusic 0xf0ffffff , 0xe0ffffff , 0xc0ffffff , 0x80ffffff , 3273072Smckusic 0x00ffffff , 0x00feffff , 0x00fcffff , 0x00f8ffff , 3283072Smckusic 0x00f0ffff , 0x00e0ffff , 0x00c0ffff , 0x0080ffff , 3293072Smckusic 0x0000ffff , 0x0000feff , 0x0000fcff , 0x0000f8ff , 3303072Smckusic 0x0000f0ff , 0x0000e0ff , 0x0000c0ff , 0x000080ff , 3313072Smckusic 0x000000ff , 0x000000fe , 0x000000fc , 0x000000f8 , 3323072Smckusic 0x000000f0 , 0x000000e0 , 0x000000c0 , 0x00000080 , 3333072Smckusic 0x00000000 3343072Smckusic # endif DEC11 3353072Smckusic }; 336750Speter /* 337750Speter * given a csetstr, either 338750Speter * put out a compile time constant set and an lvalue to it. 339750Speter * or 340750Speter * put out rvalues for the singletons and the pairs 341750Speter * and counts of each. 342750Speter */ 3433072Smckusic #endif CONSETS 344750Speter postcset( r , csetp ) 34515927Sthien struct tnode *r; 346750Speter struct csetstr *csetp; 347750Speter { 34815927Sthien register struct tnode *el; 34915927Sthien register struct tnode *e; 350750Speter int lower; 351750Speter int upper; 352750Speter int lowerdiv; 353750Speter int lowermod; 354750Speter int upperdiv; 355750Speter int uppermod; 356750Speter long *lp; 357750Speter long *limit; 3583072Smckusic long tempset[ COMPSETSZE ]; 359750Speter long temp; 3603072Smckusic char *cp; 3613072Smckusic # ifdef PC 36215927Sthien int label; 3633072Smckusic char labelname[ BUFSIZ ]; 3643072Smckusic # endif PC 365750Speter 366750Speter if ( csetp -> comptime ) { 3673072Smckusic #ifdef CONSETS 368750Speter setran( ( csetp -> csettype ) -> type ); 3693072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 370750Speter for ( lp = &tempset[0] ; lp < limit ; lp++ ) { 371750Speter *lp = 0; 372750Speter } 37315927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 37415927Sthien e = el->list_node.list; 37515927Sthien if ( e->tag == T_RANG ) { 37615927Sthien (void) constval( e->rang.expr1 ); 3773072Smckusic lower = con.crval; 37815927Sthien (void) constval( e->rang.expr2 ); 3793072Smckusic upper = con.crval; 380750Speter if ( upper < lower ) { 381750Speter continue; 382750Speter } 3833072Smckusic lowerdiv = ( lower - set.lwrb ) >> LG2BITSLONG; 3843072Smckusic lowermod = ( lower - set.lwrb ) & MSKBITSLONG; 3853072Smckusic upperdiv = ( upper - set.lwrb ) >> LG2BITSLONG; 3863072Smckusic uppermod = ( upper - set.lwrb ) & MSKBITSLONG; 387750Speter temp = mask[ lowermod ]; 388750Speter if ( lowerdiv == upperdiv ) { 389750Speter temp &= ~mask[ uppermod + 1 ]; 390750Speter } 391750Speter tempset[ lowerdiv ] |= temp; 392750Speter limit = &tempset[ upperdiv-1 ]; 393750Speter for ( lp = &tempset[ lowerdiv+1 ] ; lp <= limit ; lp++ ) { 3943072Smckusic *lp |= 0xffffffff; 395750Speter } 396750Speter if ( lowerdiv != upperdiv ) { 397750Speter tempset[ upperdiv ] |= ~mask[ uppermod + 1 ]; 398750Speter } 399750Speter } else { 40015927Sthien (void) constval( e ); 4013072Smckusic temp = con.crval - set.lwrb; 4023072Smckusic cp = (char *)tempset; 4033072Smckusic cp[temp >> LG2BITSBYTE] |= (1 << (temp & MSKBITSBYTE)); 404750Speter } 405750Speter } 4063315Speter if ( !CGENNING ) 407750Speter return; 408750Speter # ifdef PC 40915927Sthien label = (int) getlab(); 41010652Speter putprintf(" .data" , 0 ); 41110652Speter aligndot(A_SET); 41215927Sthien (void) putlab( (char *) label ); 413750Speter lp = &( tempset[0] ); 4143072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 41510652Speter while (lp < limit) { 41615927Sthien putprintf(" .long 0x%x", 1, (int) (*lp++)); 41710652Speter for (temp = 2 ; temp <= 8 && lp < limit ; temp++) { 41815927Sthien putprintf(",0x%x", 1, (int) (*lp++)); 419750Speter } 42010652Speter putprintf("", 0); 421750Speter } 42210652Speter putprintf(" .text", 0); 42315927Sthien sprintf( labelname , PREFIXFORMAT , LABELPREFIX , (char *) label ); 42418455Sralph putleaf( PCC_ICON , 0 , 0 , PCCTM_PTR | PCCT_STRTY , labelname ); 425750Speter # endif PC 426750Speter # ifdef OBJ 42715927Sthien (void) put(2, O_CON, (int)(((set.uprbp >> LG2BITSLONG) + 1) * 4283072Smckusic (BITSPERLONG >> LG2BITSBYTE))); 429750Speter lp = &( tempset[0] ); 4303072Smckusic limit = &tempset[ ( set.uprbp >> LG2BITSLONG ) + 1 ]; 431750Speter while ( lp < limit ) { 43215927Sthien (void) put(2, O_CASE4, (int) (*lp ++)); 433750Speter } 434750Speter # endif OBJ 4353072Smckusic #else 4363072Smckusic panic("const cset"); 4373072Smckusic #endif CONSETS 438750Speter } else { 439750Speter # ifdef PC 44018455Sralph putleaf( PCC_ICON , (int) csetp -> paircnt , 0 , PCCT_INT , (char *) 0 ); 44118455Sralph putop( PCC_CM , PCCT_INT ); 44218455Sralph putleaf( PCC_ICON , (int) csetp -> singcnt , 0 , PCCT_INT , (char *) 0 ); 44318455Sralph putop( PCC_CM , PCCT_INT ); 44415927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 44515927Sthien e = el->list_node.list; 44615927Sthien if ( e->tag == T_RANG ) { 44715927Sthien (void) rvalue( e->rang.expr2 , NLNIL , RREQ ); 44818455Sralph putop( PCC_CM , PCCT_INT ); 44915927Sthien (void) rvalue( e->rang.expr1 , NLNIL , RREQ ); 45018455Sralph putop( PCC_CM , PCCT_INT ); 451750Speter } else { 45215927Sthien (void) rvalue( e , NLNIL , RREQ ); 45318455Sralph putop( PCC_CM , PCCT_INT ); 454750Speter } 455750Speter } 456750Speter # endif PC 457750Speter # ifdef OBJ 45815927Sthien for ( el = r->cset_node.el_list ; el != NIL ; el = el->list_node.next ) { 45915927Sthien e = el->list_node.list; 46015927Sthien if ( e->tag == T_RANG ) { 46115927Sthien (void) stkrval( e->rang.expr1 , NLNIL , (long) RREQ ); 46215927Sthien (void) stkrval( e->rang.expr2 , NLNIL , (long) RREQ ); 463750Speter } else { 46415927Sthien (void) stkrval( e , NLNIL , (long) RREQ ); 465750Speter } 466750Speter } 46715927Sthien (void) put(2 , O_CON24 , (int)csetp -> singcnt ); 46815927Sthien (void) put(2 , O_CON24 , (int)csetp -> paircnt ); 469750Speter # endif OBJ 470750Speter } 471750Speter } 472