xref: /csrg-svn/usr.bin/pascal/src/var.c (revision 837)
1781Speter /* Copyright (c) 1979 Regents of the University of California */
2781Speter 
3*837Speter static	char sccsid[] = "@(#)var.c 1.3 09/02/80";
4781Speter 
5781Speter #include "whoami.h"
6781Speter #include "0.h"
7781Speter #include "align.h"
8781Speter #ifdef PC
9781Speter #   include	"pc.h"
10781Speter #   include	"pcops.h"
11781Speter #   include	"iorec.h"
12781Speter #endif PC
13781Speter 
14781Speter /*
15781Speter  * Declare variables of a var part.  DPOFF1 is
16781Speter  * the local variable storage for all prog/proc/func
17781Speter  * modules aside from the block mark.  The total size
18781Speter  * of all the local variables is entered into the
19781Speter  * size array.
20781Speter  */
21781Speter varbeg()
22781Speter {
23781Speter 
24*837Speter /* this allows for multiple declaration
25781Speter  * parts except when the "standard"
26781Speter  * option has been specified.
27781Speter  * If routine segment is being compiled,
28781Speter  * do level one processing.
29781Speter  */
30781Speter 
31781Speter #ifndef PI1
32*837Speter 	if (!progseen)
33*837Speter 		level1();
34*837Speter 	if ( parts[ cbn ] & RPRT ) {
35*837Speter 	    if ( opt( 's' ) ) {
36781Speter 		standard();
37*837Speter 	    } else {
38*837Speter 		warning();
39*837Speter 	    }
40*837Speter 	    error("Variable declarations should precede routine declarations");
41781Speter 	}
42*837Speter 	if ( parts[ cbn ] & VPRT ) {
43*837Speter 	    if ( opt( 's' ) ) {
44*837Speter 		standard();
45*837Speter 	    } else {
46*837Speter 		warning();
47*837Speter 	    }
48*837Speter 	    error("All variables should be declared in one var part");
49*837Speter 	}
50*837Speter 	parts[ cbn ] |= VPRT;
51781Speter #endif
52781Speter     /*
53781Speter      *  #ifndef PI0
54781Speter      *      sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1;
55781Speter      *  #endif
56781Speter      */
57781Speter 	forechain = NIL;
58781Speter #ifdef PI0
59781Speter 	send(REVVBEG);
60781Speter #endif
61781Speter }
62781Speter 
63781Speter var(vline, vidl, vtype)
64781Speter #ifdef PI0
65781Speter 	int vline, *vidl, *vtype;
66781Speter {
67781Speter 	register struct nl *np;
68781Speter 	register int *vl;
69781Speter 
70781Speter 	np = gtype(vtype);
71781Speter 	line = vline;
72781Speter 	for (vl = vidl; vl != NIL; vl = vl[2]) {
73781Speter 		}
74781Speter 	}
75781Speter 	send(REVVAR, vline, vidl, vtype);
76781Speter }
77781Speter #else
78781Speter 	int vline;
79781Speter 	register int *vidl;
80781Speter 	int *vtype;
81781Speter {
82781Speter 	register struct nl *np;
83781Speter 	register struct om *op;
84781Speter 	long w;
85781Speter 	int o2;
86781Speter 	int *ovidl = vidl;
87781Speter 
88781Speter 	np = gtype(vtype);
89781Speter 	line = vline;
90781Speter 	    /*
91781Speter 	     * widths are evened out
92781Speter 	     */
93781Speter 	w = (lwidth(np) + 1) &~ 1;
94781Speter 	op = &sizes[cbn];
95781Speter 	for (; vidl != NIL; vidl = vidl[2]) {
96781Speter #		ifdef OBJ
97781Speter 		    op -> om_off = roundup( op -> om_off - w , align( np ) );
98781Speter 		    o2 = op -> om_off;
99781Speter #		endif OBJ
100781Speter #		ifdef PC
101781Speter 		    if ( cbn == 1 ) {
102781Speter 				/*
103781Speter 				 * global variables are not accessed off the fp
104781Speter 				 * but rather by their names.
105781Speter 				 */
106781Speter 			    o2 = 0;
107781Speter 		    } else {
108781Speter 				/*
109781Speter 				 * locals are aligned, too.
110781Speter 				 */
111781Speter 			    op -> om_off = roundup( op -> om_off - w
112781Speter 							, align( np ) );
113781Speter 			    o2 = op -> om_off;
114781Speter 		    }
115781Speter #		endif PC
116781Speter 		enter(defnl(vidl[1], VAR, np, o2));
117781Speter 		if ( np -> nl_flags & NFILES ) {
118781Speter 		    dfiles[ cbn ] = TRUE;
119781Speter 		}
120781Speter #		ifdef PC
121781Speter 		    if ( cbn == 1 ) {
122781Speter 			putprintf( "	.data" , 0 );
123781Speter 			putprintf( "	.comm	" , 1 );
124781Speter 			putprintf( EXTFORMAT , 1 , vidl[1] );
125781Speter 			putprintf( ",%d" , 0 , w );
126781Speter 			putprintf( "	.text" , 0 );
127781Speter 		    }
128827Speter 		    stabvar( vidl[1] , p2type( np ) , cbn , o2 , w , line );
129781Speter #		endif PC
130781Speter 	}
131781Speter #	ifdef PTREE
132781Speter 	    {
133781Speter 		pPointer	*Vars;
134781Speter 		pPointer	Var = VarDecl( ovidl , vtype );
135781Speter 
136781Speter 		pSeize( PorFHeader[ nesting ] );
137781Speter 		Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars );
138781Speter 		*Vars = ListAppend( *Vars , Var );
139781Speter 		pRelease( PorFHeader[ nesting ] );
140781Speter 	    }
141781Speter #	endif
142781Speter }
143781Speter #endif
144781Speter 
145781Speter varend()
146781Speter {
147781Speter 
148781Speter 	foredecl();
149781Speter #ifndef PI0
150781Speter 	sizes[cbn].om_max = sizes[cbn].om_off;
151781Speter #else
152781Speter 	send(REVVEND);
153781Speter #endif
154781Speter }
155781Speter 
156781Speter /*
157781Speter  * Evening
158781Speter  */
159781Speter even(w)
160781Speter 	register int w;
161781Speter {
162781Speter 	if (w < 0)
163781Speter 		return (w & ~1);
164781Speter 	return ((w+1) & ~1);
165781Speter }
166781Speter 
167781Speter /*
168781Speter  * Find the width of a type in bytes.
169781Speter  */
170781Speter width(np)
171781Speter 	struct nl *np;
172781Speter {
173781Speter 
174781Speter 	return (lwidth(np));
175781Speter }
176781Speter 
177781Speter long
178781Speter lwidth(np)
179781Speter 	struct nl *np;
180781Speter {
181781Speter 	register struct nl *p;
182781Speter 	long w;
183781Speter 
184781Speter 	p = np;
185781Speter 	if (p == NIL)
186781Speter 		return (0);
187781Speter loop:
188781Speter 	switch (p->class) {
189781Speter 		case TYPE:
190781Speter 			switch (nloff(p)) {
191781Speter 				case TNIL:
192781Speter 					return (2);
193781Speter 				case TSTR:
194781Speter 				case TSET:
195781Speter 					panic("width");
196781Speter 				default:
197781Speter 					p = p->type;
198781Speter 					goto loop;
199781Speter 			}
200781Speter 		case ARRAY:
201781Speter 			return (aryconst(p, 0));
202781Speter 		case PTR:
203781Speter 			return ( sizeof ( int * ) );
204781Speter 		case FILET:
205781Speter #			ifdef OBJ
206781Speter 			    return ( sizeof ( int * ) );
207781Speter #			endif OBJ
208781Speter #			ifdef PC
209781Speter 			    return ( sizeof(struct iorec)
210781Speter 				    + lwidth( p -> type ) );
211781Speter #			endif PC
212781Speter 		case RANGE:
213781Speter 			if (p->type == nl+TDOUBLE)
214781Speter #ifdef DEBUG
215781Speter 				return (hp21mx ? 4 : 8);
216781Speter #else
217781Speter 				return (8);
218781Speter #endif
219781Speter 		case SCAL:
220781Speter 			return (bytes(p->range[0], p->range[1]));
221781Speter 		case SET:
222781Speter 			setran(p->type);
223781Speter 			return roundup( ( set.uprbp >> 3 ) + 1 , A_SET );
224781Speter 		case STR:
225781Speter 		case RECORD:
226781Speter 			return ( p->value[NL_OFFS] );
227781Speter 		default:
228781Speter 			panic("wclass");
229781Speter 	}
230781Speter }
231781Speter 
232781Speter     /*
233781Speter      *	round up x to a multiple of y
234781Speter      *	for computing offsets of aligned things.
235781Speter      *	y had better be positive.
236781Speter      *	rounding is in the direction of x.
237781Speter      */
238781Speter long
239781Speter roundup( x , y )
240781Speter     long		x;
241781Speter     register long	y;
242781Speter     {
243781Speter 
244781Speter 	if ( y == 0 ) {
245781Speter 	    return 0;
246781Speter 	}
247781Speter 	if ( x >= 0 ) {
248781Speter 		return ( ( ( x + ( y - 1 ) ) / y ) * y );
249781Speter 	} else {
250781Speter 		return ( ( ( x - ( y - 1 ) ) / y ) * y );
251781Speter 	}
252781Speter     }
253781Speter 
254781Speter     /*
255781Speter      *	alignment of an object using the c alignment scheme
256781Speter      */
257781Speter int
258781Speter align( np )
259781Speter     struct nl	*np;
260781Speter     {
261781Speter 	register struct nl *p;
262781Speter 
263781Speter 	p = np;
264781Speter 	if ( p == NIL ) {
265781Speter 	    return 0;
266781Speter 	}
267781Speter alignit:
268781Speter 	switch ( p -> class ) {
269781Speter 	    case TYPE:
270781Speter 		    switch ( nloff( p ) ) {
271781Speter 			case TNIL:
272781Speter 				return A_POINT;
273781Speter 			case TSTR:
274781Speter 				return A_CHAR;
275781Speter 			case TSET:
276781Speter 				return A_SET;
277781Speter 			default:
278781Speter 				p = p -> type;
279781Speter 				goto alignit;
280781Speter 		    }
281781Speter 	    case ARRAY:
282781Speter 			/*
283781Speter 			 * arrays are aligned as their component types
284781Speter 			 */
285781Speter 		    p = p -> type;
286781Speter 		    goto alignit;
287781Speter 	    case PTR:
288781Speter 		    return A_POINT;
289781Speter 	    case FILET:
290781Speter 		    return A_FILET;
291781Speter 	    case RANGE:
292781Speter 		    if ( p -> type == nl+TDOUBLE ) {
293781Speter 			return A_DOUBLE;
294781Speter 		    }
295781Speter 		    /* else, fall through */
296781Speter 	    case SCAL:
297781Speter 		    switch ( bytes( p -> range[0] , p -> range[1] ) ) {
298781Speter 			case 4:
299781Speter 			    return A_LONG;
300781Speter 			case 2:
301781Speter 			    return A_SHORT;
302781Speter 			case 1:
303781Speter 			    return A_CHAR;
304781Speter 			default:
305781Speter 			    panic( "align: scal" );
306781Speter 		    }
307781Speter 	    case SET:
308781Speter 		    return A_SET;
309781Speter 	    case STR:
310781Speter 		    return A_CHAR;
311781Speter 	    case RECORD:
312781Speter 			/*
313781Speter 			 * follow chain through all fields in record,
314781Speter 			 * taking max of alignments of types of fields.
315781Speter 			 * short circuit out if i reach the maximum alignment.
316781Speter 			 * this is pretty likely, as A_MAX is only 4.
317781Speter 			 */
318781Speter 		    {
319781Speter 			register long recalign;
320781Speter 			register long fieldalign;
321781Speter 
322781Speter 			recalign = A_MIN;
323781Speter 			p = p -> chain;
324781Speter 			while ( ( p != NIL ) && ( recalign < A_MAX ) ) {
325781Speter 			    fieldalign = align( p -> type );
326781Speter 			    if ( fieldalign > recalign ) {
327781Speter 				recalign = fieldalign;
328781Speter 			    }
329781Speter 			    p = p -> chain;
330781Speter 			}
331781Speter 			return recalign;
332781Speter 		    }
333781Speter 	    default:
334781Speter 		    panic( "align" );
335781Speter 	}
336781Speter     }
337781Speter 
338781Speter /*
339781Speter  * Return the width of an element
340781Speter  * of a n time subscripted np.
341781Speter  */
342781Speter long aryconst(np, n)
343781Speter 	struct nl *np;
344781Speter 	int n;
345781Speter {
346781Speter 	register struct nl *p;
347781Speter 	long s, d;
348781Speter 
349781Speter 	if ((p = np) == NIL)
350781Speter 		return (NIL);
351781Speter 	if (p->class != ARRAY)
352781Speter 		panic("ary");
353781Speter 	s = lwidth(p->type);
354781Speter 	/*
355781Speter 	 * Arrays of anything but characters are word aligned.
356781Speter 	 */
357781Speter 	if (s & 1)
358781Speter 		if (s != 1)
359781Speter 			s++;
360781Speter 	/*
361781Speter 	 * Skip the first n subscripts
362781Speter 	 */
363781Speter 	while (n >= 0) {
364781Speter 		p = p->chain;
365781Speter 		n--;
366781Speter 	}
367781Speter 	/*
368781Speter 	 * Sum across remaining subscripts.
369781Speter 	 */
370781Speter 	while (p != NIL) {
371781Speter 		if (p->class != RANGE && p->class != SCAL)
372781Speter 			panic("aryran");
373781Speter 		d = p->range[1] - p->range[0] + 1;
374781Speter 		s *= d;
375781Speter 		p = p->chain;
376781Speter 	}
377781Speter 	return (s);
378781Speter }
379781Speter 
380781Speter /*
381781Speter  * Find the lower bound of a set, and also its size in bits.
382781Speter  */
383781Speter setran(q)
384781Speter 	struct nl *q;
385781Speter {
386781Speter 	register lb, ub;
387781Speter 	register struct nl *p;
388781Speter 
389781Speter 	p = q;
390781Speter 	if (p == NIL)
391781Speter 		return (NIL);
392781Speter 	lb = p->range[0];
393781Speter 	ub = p->range[1];
394781Speter 	if (p->class != RANGE && p->class != SCAL)
395781Speter 		panic("setran");
396781Speter 	set.lwrb = lb;
397781Speter 	/* set.(upperbound prime) = number of bits - 1; */
398781Speter 	set.uprbp = ub-lb;
399781Speter }
400781Speter 
401781Speter /*
402781Speter  * Return the number of bytes required to hold an arithmetic quantity
403781Speter  */
404781Speter bytes(lb, ub)
405781Speter 	long lb, ub;
406781Speter {
407781Speter 
408781Speter #ifndef DEBUG
409781Speter 	if (lb < -32768 || ub > 32767)
410781Speter 		return (4);
411781Speter 	else if (lb < -128 || ub > 127)
412781Speter 		return (2);
413781Speter #else
414781Speter 	if (!hp21mx && (lb < -32768 || ub > 32767))
415781Speter 		return (4);
416781Speter 	if (lb < -128 || ub > 127)
417781Speter 		return (2);
418781Speter #endif
419781Speter 	else
420781Speter 		return (1);
421781Speter }
422