xref: /csrg-svn/usr.bin/pascal/src/cset.c (revision 750)
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