BSD 4 release
[unix-history] / usr / src / cmd / pi / cset.c
CommitLineData
ff5e2876
PK
1/* Copyright (c) 1979 Regents of the University of California */
2
31cef89c 3static char sccsid[] = "@(#)cset.c 1.2 10/19/80";
ff5e2876
PK
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 */
20bool
21precset( 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 /*
70de7f21 69 * tentative for [], return type of `intset'
ff5e2876 70 */
70de7f21
PK
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;
ff5e2876
PK
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 }
203pairhang:
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 }
234singhang:
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 */
275long 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 */
293postcset( 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 ) {
ff5e2876
PK
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}