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