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