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