xref: /csrg-svn/usr.bin/pascal/src/var.c (revision 3949)
1781Speter /* Copyright (c) 1979 Regents of the University of California */
2781Speter 
3*3949Speter static char sccsid[] = "@(#)var.c 1.10 07/08/81";
4781Speter 
5781Speter #include "whoami.h"
6781Speter #include "0.h"
7781Speter #include "align.h"
82075Smckusic #include "iorec.h"
9781Speter #ifdef PC
10781Speter #   include	"pc.h"
11781Speter #   include	"pcops.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 
24837Speter /* 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
32837Speter 	if (!progseen)
33837Speter 		level1();
34837Speter 	if ( parts[ cbn ] & RPRT ) {
35837Speter 	    if ( opt( 's' ) ) {
36781Speter 		standard();
37837Speter 	    } else {
38837Speter 		warning();
39837Speter 	    }
40837Speter 	    error("Variable declarations should precede routine declarations");
41781Speter 	}
42837Speter 	if ( parts[ cbn ] & VPRT ) {
43837Speter 	    if ( opt( 's' ) ) {
44837Speter 		standard();
45837Speter 	    } else {
46837Speter 		warning();
47837Speter 	    }
48837Speter 	    error("All variables should be declared in one var part");
49837Speter 	}
50837Speter 	parts[ cbn ] |= VPRT;
51781Speter #endif
52781Speter     /*
53781Speter      *  #ifndef PI0
543229Smckusic      *      sizes[cbn].om_max = sizes[cbn].curtmps.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;
873836Speter 	struct nl	*vp;
88781Speter 
89781Speter 	np = gtype(vtype);
90781Speter 	line = vline;
91*3949Speter 	w = lwidth(np);
92781Speter 	op = &sizes[cbn];
93781Speter 	for (; vidl != NIL; vidl = vidl[2]) {
94781Speter #		ifdef OBJ
953235Smckusic 		    op->curtmps.om_off =
963235Smckusic 			roundup((int)(op->curtmps.om_off-w), (long)align(np));
973235Smckusic 		    o2 = op -> curtmps.om_off;
98781Speter #		endif OBJ
99781Speter #		ifdef PC
100781Speter 		    if ( cbn == 1 ) {
101781Speter 				/*
102781Speter 				 * global variables are not accessed off the fp
103781Speter 				 * but rather by their names.
104781Speter 				 */
105781Speter 			    o2 = 0;
106781Speter 		    } else {
107781Speter 				/*
108781Speter 				 * locals are aligned, too.
109781Speter 				 */
1103229Smckusic 			    op->curtmps.om_off =
1113229Smckusic 				roundup((int)(op->curtmps.om_off - w),
1123082Smckusic 				(long)align(np));
1133229Smckusic 			    o2 = op -> curtmps.om_off;
114781Speter 		    }
115781Speter #		endif PC
1163836Speter 		vp = 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 );
123*3949Speter 			putprintf( "	.align	%d" , 0 , dotalign(align(np)));
124781Speter 			putprintf( "	.comm	" , 1 );
125781Speter 			putprintf( EXTFORMAT , 1 , vidl[1] );
126781Speter 			putprintf( ",%d" , 0 , w );
127781Speter 			putprintf( "	.text" , 0 );
1282165Speter 			stabgvar( vidl[1] , p2type( np ) , o2 , w , line );
1293836Speter 			vp -> extra_flags |= NGLOBAL;
1303836Speter 		    } else {
1313836Speter 			vp -> extra_flags |= NLOCAL;
132781Speter 		    }
133781Speter #		endif PC
134781Speter 	}
135781Speter #	ifdef PTREE
136781Speter 	    {
137781Speter 		pPointer	*Vars;
138781Speter 		pPointer	Var = VarDecl( ovidl , vtype );
139781Speter 
140781Speter 		pSeize( PorFHeader[ nesting ] );
141781Speter 		Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars );
142781Speter 		*Vars = ListAppend( *Vars , Var );
143781Speter 		pRelease( PorFHeader[ nesting ] );
144781Speter 	    }
145781Speter #	endif
146781Speter }
147781Speter #endif
148781Speter 
149781Speter varend()
150781Speter {
151781Speter 
152781Speter 	foredecl();
153781Speter #ifndef PI0
1543229Smckusic 	sizes[cbn].om_max = sizes[cbn].curtmps.om_off;
155781Speter #else
156781Speter 	send(REVVEND);
157781Speter #endif
158781Speter }
159781Speter 
160781Speter /*
161781Speter  * Evening
162781Speter  */
1633082Smckusic long
1643082Smckusic leven(w)
1653082Smckusic 	register long w;
1663082Smckusic {
1673082Smckusic 	if (w < 0)
1683082Smckusic 		return (w & 0xfffffffe);
1693082Smckusic 	return ((w+1) & 0xfffffffe);
1703082Smckusic }
1713082Smckusic 
1723082Smckusic int
173781Speter even(w)
174781Speter 	register int w;
175781Speter {
1763082Smckusic 	return leven((long)w);
177781Speter }
178781Speter 
179781Speter /*
180781Speter  * Find the width of a type in bytes.
181781Speter  */
182781Speter width(np)
183781Speter 	struct nl *np;
184781Speter {
185781Speter 
186781Speter 	return (lwidth(np));
187781Speter }
188781Speter 
189781Speter long
190781Speter lwidth(np)
191781Speter 	struct nl *np;
192781Speter {
193781Speter 	register struct nl *p;
194781Speter 	long w;
195781Speter 
196781Speter 	p = np;
197781Speter 	if (p == NIL)
198781Speter 		return (0);
199781Speter loop:
200781Speter 	switch (p->class) {
201781Speter 		case TYPE:
202781Speter 			switch (nloff(p)) {
203781Speter 				case TNIL:
204781Speter 					return (2);
205781Speter 				case TSTR:
206781Speter 				case TSET:
207781Speter 					panic("width");
208781Speter 				default:
209781Speter 					p = p->type;
210781Speter 					goto loop;
211781Speter 			}
212781Speter 		case ARRAY:
213781Speter 			return (aryconst(p, 0));
214781Speter 		case PTR:
215781Speter 			return ( sizeof ( int * ) );
216781Speter 		case FILET:
2172075Smckusic 			return ( sizeof(struct iorec) + lwidth( p -> type ) );
218781Speter 		case RANGE:
219781Speter 			if (p->type == nl+TDOUBLE)
220781Speter #ifdef DEBUG
221781Speter 				return (hp21mx ? 4 : 8);
222781Speter #else
223781Speter 				return (8);
224781Speter #endif
225781Speter 		case SCAL:
226781Speter 			return (bytes(p->range[0], p->range[1]));
227781Speter 		case SET:
228781Speter 			setran(p->type);
2293082Smckusic 			return roundup((int)((set.uprbp >> 3) + 1),
2303082Smckusic 				(long)(A_SET));
231781Speter 		case STR:
232781Speter 		case RECORD:
233781Speter 			return ( p->value[NL_OFFS] );
234781Speter 		default:
235781Speter 			panic("wclass");
236781Speter 	}
237781Speter }
238781Speter 
239781Speter     /*
240781Speter      *	round up x to a multiple of y
241781Speter      *	for computing offsets of aligned things.
242781Speter      *	y had better be positive.
243781Speter      *	rounding is in the direction of x.
244781Speter      */
245781Speter long
246781Speter roundup( x , y )
2473082Smckusic     int			x;
248781Speter     register long	y;
249781Speter     {
250781Speter 
251781Speter 	if ( y == 0 ) {
252781Speter 	    return 0;
253781Speter 	}
254781Speter 	if ( x >= 0 ) {
255781Speter 		return ( ( ( x + ( y - 1 ) ) / y ) * y );
256781Speter 	} else {
257781Speter 		return ( ( ( x - ( y - 1 ) ) / y ) * y );
258781Speter 	}
259781Speter     }
260781Speter 
261781Speter     /*
262781Speter      *	alignment of an object using the c alignment scheme
263781Speter      */
264781Speter int
265781Speter align( np )
266781Speter     struct nl	*np;
267781Speter     {
268781Speter 	register struct nl *p;
269781Speter 
270781Speter 	p = np;
271781Speter 	if ( p == NIL ) {
272781Speter 	    return 0;
273781Speter 	}
274781Speter alignit:
275781Speter 	switch ( p -> class ) {
276781Speter 	    case TYPE:
277781Speter 		    switch ( nloff( p ) ) {
278781Speter 			case TNIL:
279781Speter 				return A_POINT;
280781Speter 			case TSTR:
281781Speter 				return A_CHAR;
282781Speter 			case TSET:
283781Speter 				return A_SET;
284781Speter 			default:
285781Speter 				p = p -> type;
286781Speter 				goto alignit;
287781Speter 		    }
288781Speter 	    case ARRAY:
289781Speter 			/*
290781Speter 			 * arrays are aligned as their component types
291781Speter 			 */
292781Speter 		    p = p -> type;
293781Speter 		    goto alignit;
294781Speter 	    case PTR:
295781Speter 		    return A_POINT;
296781Speter 	    case FILET:
297781Speter 		    return A_FILET;
298781Speter 	    case RANGE:
299781Speter 		    if ( p -> type == nl+TDOUBLE ) {
300781Speter 			return A_DOUBLE;
301781Speter 		    }
302781Speter 		    /* else, fall through */
303781Speter 	    case SCAL:
304781Speter 		    switch ( bytes( p -> range[0] , p -> range[1] ) ) {
305781Speter 			case 4:
306781Speter 			    return A_LONG;
307781Speter 			case 2:
308781Speter 			    return A_SHORT;
309781Speter 			case 1:
310781Speter 			    return A_CHAR;
311781Speter 			default:
312781Speter 			    panic( "align: scal" );
313781Speter 		    }
314781Speter 	    case SET:
315781Speter 		    return A_SET;
316781Speter 	    case STR:
317781Speter 		    return A_CHAR;
318781Speter 	    case RECORD:
319781Speter 			/*
320781Speter 			 * follow chain through all fields in record,
321781Speter 			 * taking max of alignments of types of fields.
322781Speter 			 * short circuit out if i reach the maximum alignment.
323781Speter 			 * this is pretty likely, as A_MAX is only 4.
324781Speter 			 */
325781Speter 		    {
326781Speter 			register long recalign;
327781Speter 			register long fieldalign;
328781Speter 
329781Speter 			recalign = A_MIN;
330781Speter 			p = p -> chain;
331781Speter 			while ( ( p != NIL ) && ( recalign < A_MAX ) ) {
332781Speter 			    fieldalign = align( p -> type );
333781Speter 			    if ( fieldalign > recalign ) {
334781Speter 				recalign = fieldalign;
335781Speter 			    }
336781Speter 			    p = p -> chain;
337781Speter 			}
338781Speter 			return recalign;
339781Speter 		    }
340781Speter 	    default:
341781Speter 		    panic( "align" );
342781Speter 	}
343781Speter     }
344781Speter 
345*3949Speter     /*
346*3949Speter      *	given an alignment, return power of two for .align pseudo-op
347*3949Speter      */
348*3949Speter dotalign( alignment )
349*3949Speter     int	alignment;
350*3949Speter {
351*3949Speter 
352*3949Speter     switch ( alignment ) {
353*3949Speter 	case A_CHAR:		/*
354*3949Speter 				 * also
355*3949Speter 				 *	A_STRUCT
356*3949Speter 				 */
357*3949Speter 		return 0;
358*3949Speter 	case A_SHORT:
359*3949Speter 		return 1;
360*3949Speter 	case A_LONG:		/*
361*3949Speter 				 * also
362*3949Speter 				 *	A_POINT, A_INT, A_FLOAT, A_DOUBLE,
363*3949Speter 				 *	A_STACK, A_FILET, A_SET
364*3949Speter 				 */
365*3949Speter 		return 2;
366*3949Speter     }
367*3949Speter }
368*3949Speter 
369781Speter /*
370781Speter  * Return the width of an element
371781Speter  * of a n time subscripted np.
372781Speter  */
373781Speter long aryconst(np, n)
374781Speter 	struct nl *np;
375781Speter 	int n;
376781Speter {
377781Speter 	register struct nl *p;
378781Speter 	long s, d;
379781Speter 
380781Speter 	if ((p = np) == NIL)
381781Speter 		return (NIL);
382781Speter 	if (p->class != ARRAY)
383781Speter 		panic("ary");
384781Speter 	s = lwidth(p->type);
385781Speter 	/*
386781Speter 	 * Arrays of anything but characters are word aligned.
387781Speter 	 */
388781Speter 	if (s & 1)
389781Speter 		if (s != 1)
390781Speter 			s++;
391781Speter 	/*
392781Speter 	 * Skip the first n subscripts
393781Speter 	 */
394781Speter 	while (n >= 0) {
395781Speter 		p = p->chain;
396781Speter 		n--;
397781Speter 	}
398781Speter 	/*
399781Speter 	 * Sum across remaining subscripts.
400781Speter 	 */
401781Speter 	while (p != NIL) {
402781Speter 		if (p->class != RANGE && p->class != SCAL)
403781Speter 			panic("aryran");
404781Speter 		d = p->range[1] - p->range[0] + 1;
405781Speter 		s *= d;
406781Speter 		p = p->chain;
407781Speter 	}
408781Speter 	return (s);
409781Speter }
410781Speter 
411781Speter /*
412781Speter  * Find the lower bound of a set, and also its size in bits.
413781Speter  */
414781Speter setran(q)
415781Speter 	struct nl *q;
416781Speter {
417781Speter 	register lb, ub;
418781Speter 	register struct nl *p;
419781Speter 
420781Speter 	p = q;
421781Speter 	if (p == NIL)
422781Speter 		return (NIL);
423781Speter 	lb = p->range[0];
424781Speter 	ub = p->range[1];
425781Speter 	if (p->class != RANGE && p->class != SCAL)
426781Speter 		panic("setran");
427781Speter 	set.lwrb = lb;
428781Speter 	/* set.(upperbound prime) = number of bits - 1; */
429781Speter 	set.uprbp = ub-lb;
430781Speter }
431781Speter 
432781Speter /*
433781Speter  * Return the number of bytes required to hold an arithmetic quantity
434781Speter  */
435781Speter bytes(lb, ub)
436781Speter 	long lb, ub;
437781Speter {
438781Speter 
439781Speter #ifndef DEBUG
440781Speter 	if (lb < -32768 || ub > 32767)
441781Speter 		return (4);
442781Speter 	else if (lb < -128 || ub > 127)
443781Speter 		return (2);
444781Speter #else
445781Speter 	if (!hp21mx && (lb < -32768 || ub > 32767))
446781Speter 		return (4);
447781Speter 	if (lb < -128 || ub > 127)
448781Speter 		return (2);
449781Speter #endif
450781Speter 	else
451781Speter 		return (1);
452781Speter }
453