xref: /csrg-svn/usr.bin/pascal/src/var.c (revision 62221)
148116Sbostic /*-
2*62221Sbostic  * Copyright (c) 1980, 1993
3*62221Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
622201Sdist  */
7781Speter 
818351Smckusick #ifndef lint
9*62221Sbostic static char sccsid[] = "@(#)var.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11781Speter 
12781Speter #include "whoami.h"
13781Speter #include "0.h"
1410664Speter #include "objfmt.h"
15781Speter #include "align.h"
162075Smckusic #include "iorec.h"
17781Speter #ifdef PC
18781Speter #   include	"pc.h"
19781Speter #endif PC
2011336Speter #include "tmps.h"
2118351Smckusick #include "tree_ty.h"
22781Speter 
23781Speter /*
24781Speter  * Declare variables of a var part.  DPOFF1 is
25781Speter  * the local variable storage for all prog/proc/func
26781Speter  * modules aside from the block mark.  The total size
27781Speter  * of all the local variables is entered into the
28781Speter  * size array.
29781Speter  */
3018351Smckusick /*ARGSUSED*/
varbeg(lineofyvar,r)317951Speter varbeg( lineofyvar , r )
327951Speter     int	lineofyvar;
33781Speter {
347951Speter     static bool	var_order = FALSE;
357951Speter     static bool	var_seen = FALSE;
36781Speter 
37837Speter /* this allows for multiple declaration
38781Speter  * parts except when the "standard"
39781Speter  * option has been specified.
40781Speter  * If routine segment is being compiled,
41781Speter  * do level one processing.
42781Speter  */
43781Speter 
44781Speter #ifndef PI1
45837Speter 	if (!progseen)
46837Speter 		level1();
477951Speter 	line = lineofyvar;
48837Speter 	if ( parts[ cbn ] & RPRT ) {
49837Speter 	    if ( opt( 's' ) ) {
50781Speter 		standard();
517951Speter 		error("Variable declarations should precede routine declarations");
52837Speter 	    } else {
537951Speter 		if ( !var_order ) {
547951Speter 		    var_order = TRUE;
557951Speter 		    warning();
567951Speter 		    error("Variable declarations should precede routine declarations");
577951Speter 		}
58837Speter 	    }
59781Speter 	}
60837Speter 	if ( parts[ cbn ] & VPRT ) {
61837Speter 	    if ( opt( 's' ) ) {
62837Speter 		standard();
637951Speter 		error("All variables should be declared in one var part");
64837Speter 	    } else {
657951Speter 		if ( !var_seen ) {
667951Speter 		    var_seen = TRUE;
677951Speter 		    warning();
687951Speter 		    error("All variables should be declared in one var part");
697951Speter 		}
70837Speter 	    }
71837Speter 	}
72837Speter 	parts[ cbn ] |= VPRT;
73781Speter #endif
74781Speter     /*
75781Speter      *  #ifndef PI0
763229Smckusic      *      sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1;
77781Speter      *  #endif
78781Speter      */
79781Speter 	forechain = NIL;
80781Speter #ifdef PI0
81781Speter 	send(REVVBEG);
82781Speter #endif
83781Speter }
84781Speter 
var(vline,vidl,vtype)85781Speter var(vline, vidl, vtype)
86781Speter #ifdef PI0
8718351Smckusick 	int vline;
8818351Smckusick 	struct tnode *vidl, *vtype;
89781Speter {
90781Speter 	register struct nl *np;
9118351Smckusick 	register struct tnode *vl;
92781Speter 
93781Speter 	np = gtype(vtype);
94781Speter 	line = vline;
9518351Smckusick 	/* why is this here? */
9618351Smckusick 	for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) {
97781Speter 		}
98781Speter 	}
99781Speter 	send(REVVAR, vline, vidl, vtype);
100781Speter }
101781Speter #else
102781Speter 	int vline;
10318351Smckusick 	register struct tnode *vidl;
10418351Smckusick 	struct tnode *vtype;
105781Speter {
106781Speter 	register struct nl *np;
107781Speter 	register struct om *op;
108781Speter 	long w;
109781Speter 	int o2;
11018351Smckusick #ifdef PC
1113836Speter 	struct nl	*vp;
11218351Smckusick #endif
113781Speter 
114781Speter 	np = gtype(vtype);
115781Speter 	line = vline;
1163949Speter 	w = lwidth(np);
117781Speter 	op = &sizes[cbn];
11818351Smckusick 	for (; vidl != TR_NIL; vidl = vidl->list_node.next) {
119781Speter #		ifdef OBJ
1203235Smckusic 		    op->curtmps.om_off =
1213235Smckusic 			roundup((int)(op->curtmps.om_off-w), (long)align(np));
1223235Smckusic 		    o2 = op -> curtmps.om_off;
123781Speter #		endif OBJ
124781Speter #		ifdef PC
125781Speter 		    if ( cbn == 1 ) {
126781Speter 				/*
127781Speter 				 * global variables are not accessed off the fp
128781Speter 				 * but rather by their names.
129781Speter 				 */
130781Speter 			    o2 = 0;
131781Speter 		    } else {
132781Speter 				/*
133781Speter 				 * locals are aligned, too.
134781Speter 				 */
1353229Smckusic 			    op->curtmps.om_off =
1363229Smckusic 				roundup((int)(op->curtmps.om_off - w),
1373082Smckusic 				(long)align(np));
1383229Smckusic 			    o2 = op -> curtmps.om_off;
139781Speter 		    }
140781Speter #		endif PC
14118351Smckusick #		ifdef PC
14218351Smckusick 		vp = enter(defnl((char *) vidl->list_node.list, VAR, np, o2));
14318351Smckusick #		else
14418351Smckusick 		(void) enter(defnl((char *) vidl->list_node.list, VAR, np, o2));
14518351Smckusick #		endif
14624053Smckusick 		if ( np != NLNIL && (np -> nl_flags & NFILES) ) {
147781Speter 		    dfiles[ cbn ] = TRUE;
148781Speter 		}
149781Speter #		ifdef PC
150781Speter 		    if ( cbn == 1 ) {
151781Speter 			putprintf( "	.data" , 0 );
15210664Speter 			aligndot(align(np));
153781Speter 			putprintf( "	.comm	" , 1 );
15418351Smckusick 			putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list );
15518351Smckusick 			putprintf( ",%d" , 0 , (int) w );
156781Speter 			putprintf( "	.text" , 0 );
15718351Smckusick 			stabgvar( vp , w , line );
1583836Speter 			vp -> extra_flags |= NGLOBAL;
1593836Speter 		    } else {
1603836Speter 			vp -> extra_flags |= NLOCAL;
161781Speter 		    }
162781Speter #		endif PC
163781Speter 	}
164781Speter #	ifdef PTREE
165781Speter 	    {
166781Speter 		pPointer	*Vars;
167781Speter 		pPointer	Var = VarDecl( ovidl , vtype );
168781Speter 
169781Speter 		pSeize( PorFHeader[ nesting ] );
170781Speter 		Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars );
171781Speter 		*Vars = ListAppend( *Vars , Var );
172781Speter 		pRelease( PorFHeader[ nesting ] );
173781Speter 	    }
174781Speter #	endif
175781Speter }
176781Speter #endif
177781Speter 
178781Speter varend()
179781Speter {
180781Speter 
181781Speter 	foredecl();
182781Speter #ifndef PI0
1833229Smckusic 	sizes[cbn].om_max = sizes[cbn].curtmps.om_off;
184781Speter #else
185781Speter 	send(REVVEND);
186781Speter #endif
187781Speter }
188781Speter 
189781Speter /*
190781Speter  * Find the width of a type in bytes.
191781Speter  */
192781Speter width(np)
193781Speter 	struct nl *np;
194781Speter {
195781Speter 
196781Speter 	return (lwidth(np));
197781Speter }
198781Speter 
199781Speter long
200781Speter lwidth(np)
201781Speter 	struct nl *np;
202781Speter {
203781Speter 	register struct nl *p;
204781Speter 
205781Speter 	p = np;
206781Speter 	if (p == NIL)
207781Speter 		return (0);
208781Speter loop:
209781Speter 	switch (p->class) {
21018351Smckusick 		default:
21118351Smckusick 			panic("wclass");
212781Speter 		case TYPE:
213781Speter 			switch (nloff(p)) {
214781Speter 				case TNIL:
215781Speter 					return (2);
216781Speter 				case TSTR:
217781Speter 				case TSET:
218781Speter 					panic("width");
219781Speter 				default:
220781Speter 					p = p->type;
221781Speter 					goto loop;
222781Speter 			}
223781Speter 		case ARRAY:
224781Speter 			return (aryconst(p, 0));
225781Speter 		case PTR:
226781Speter 			return ( sizeof ( int * ) );
227781Speter 		case FILET:
2282075Smckusic 			return ( sizeof(struct iorec) + lwidth( p -> type ) );
22918351Smckusick 		case CRANGE:
23018351Smckusick 			p = p->type;
23118351Smckusick 			goto loop;
232781Speter 		case RANGE:
233781Speter 			if (p->type == nl+TDOUBLE)
234781Speter #ifdef DEBUG
235781Speter 				return (hp21mx ? 4 : 8);
236781Speter #else
237781Speter 				return (8);
238781Speter #endif
239781Speter 		case SCAL:
240781Speter 			return (bytes(p->range[0], p->range[1]));
241781Speter 		case SET:
242781Speter 			setran(p->type);
24311822Smckusick 			/*
24411822Smckusick 			 * Sets are some multiple of longs
24511822Smckusick 			 */
2463082Smckusic 			return roundup((int)((set.uprbp >> 3) + 1),
24711822Smckusick 				(long)(sizeof(long)));
248781Speter 		case STR:
249781Speter 		case RECORD:
250781Speter 			return ( p->value[NL_OFFS] );
251781Speter 	}
252781Speter }
253781Speter 
254781Speter     /*
255781Speter      *	round up x to a multiple of y
256781Speter      *	for computing offsets of aligned things.
257781Speter      *	y had better be positive.
258781Speter      *	rounding is in the direction of x.
259781Speter      */
260781Speter long
261781Speter roundup( x , y )
2623082Smckusic     int			x;
263781Speter     register long	y;
264781Speter     {
265781Speter 
266781Speter 	if ( y == 0 ) {
2674030Smckusic 	    return x;
268781Speter 	}
269781Speter 	if ( x >= 0 ) {
270781Speter 		return ( ( ( x + ( y - 1 ) ) / y ) * y );
271781Speter 	} else {
272781Speter 		return ( ( ( x - ( y - 1 ) ) / y ) * y );
273781Speter 	}
274781Speter     }
275781Speter 
276781Speter     /*
277781Speter      *	alignment of an object using the c alignment scheme
278781Speter      */
279781Speter int
280781Speter align( np )
281781Speter     struct nl	*np;
282781Speter     {
283781Speter 	register struct nl *p;
28411822Smckusick 	long elementalign;
285781Speter 
286781Speter 	p = np;
287781Speter 	if ( p == NIL ) {
288781Speter 	    return 0;
289781Speter 	}
290781Speter alignit:
291781Speter 	switch ( p -> class ) {
29218351Smckusick 	    default:
29318351Smckusick 		    panic( "align" );
294781Speter 	    case TYPE:
295781Speter 		    switch ( nloff( p ) ) {
296781Speter 			case TNIL:
297781Speter 				return A_POINT;
298781Speter 			case TSTR:
29910664Speter 				return A_STRUCT;
300781Speter 			case TSET:
301781Speter 				return A_SET;
302781Speter 			default:
303781Speter 				p = p -> type;
304781Speter 				goto alignit;
305781Speter 		    }
306781Speter 	    case ARRAY:
307781Speter 			/*
30811822Smckusick 			 * arrays are structures, since they can get
30910664Speter 			 * assigned form/to as structure assignments.
31011822Smckusick 			 * preserve internal alignment if it is greater.
311781Speter 			 */
31211822Smckusick 		    elementalign = align(p -> type);
31311822Smckusick 		    return elementalign > A_STRUCT ? elementalign : A_STRUCT;
314781Speter 	    case PTR:
315781Speter 		    return A_POINT;
316781Speter 	    case FILET:
317781Speter 		    return A_FILET;
31818351Smckusick 	    case CRANGE:
319781Speter 	    case RANGE:
320781Speter 		    if ( p -> type == nl+TDOUBLE ) {
321781Speter 			return A_DOUBLE;
322781Speter 		    }
323781Speter 		    /* else, fall through */
324781Speter 	    case SCAL:
325781Speter 		    switch ( bytes( p -> range[0] , p -> range[1] ) ) {
326781Speter 			case 4:
327781Speter 			    return A_LONG;
328781Speter 			case 2:
329781Speter 			    return A_SHORT;
330781Speter 			case 1:
331781Speter 			    return A_CHAR;
332781Speter 			default:
333781Speter 			    panic( "align: scal" );
334781Speter 		    }
335781Speter 	    case SET:
336781Speter 		    return A_SET;
337781Speter 	    case STR:
33810664Speter 			/*
33910664Speter 			 * arrays of chars are structs
34010664Speter 			 */
34110664Speter 		    return A_STRUCT;
342781Speter 	    case RECORD:
343781Speter 			/*
3448681Speter 			 * the alignment of a record is in its align_info field
3458681Speter 			 * why don't we use this for the rest of the namelist?
346781Speter 			 */
3478681Speter 		    return p -> align_info;
348781Speter 	}
349781Speter     }
350781Speter 
35110664Speter #ifdef PC
3523949Speter     /*
35310664Speter      *	output an alignment pseudo-op.
3543949Speter      */
35510664Speter aligndot(alignment)
3563949Speter     int	alignment;
35730038Smckusick #if defined(vax) || defined(tahoe)
3583949Speter {
35910664Speter     switch (alignment) {
36010664Speter 	case 1:
36110664Speter 	    return;
36210664Speter 	case 2:
36310664Speter 	    putprintf("	.align 1", 0);
36410664Speter 	    return;
36510664Speter 	default:
36610664Speter 	case 4:
36710664Speter 	    putprintf("	.align 2", 0);
36810664Speter 	    return;
3693949Speter     }
3703949Speter }
37130038Smckusick #endif vax || tahoe
37210664Speter #ifdef mc68000
37310664Speter {
37410664Speter     switch (alignment) {
37510664Speter 	case 1:
37610664Speter 	    return;
37710664Speter 	default:
37810664Speter 	    putprintf("	.even", 0);
37910664Speter 	    return;
38010664Speter     }
38110664Speter }
38210664Speter #endif mc68000
38310664Speter #endif PC
38410664Speter 
385781Speter /*
386781Speter  * Return the width of an element
387781Speter  * of a n time subscripted np.
388781Speter  */
389781Speter long aryconst(np, n)
390781Speter 	struct nl *np;
391781Speter 	int n;
392781Speter {
393781Speter 	register struct nl *p;
394781Speter 	long s, d;
395781Speter 
396781Speter 	if ((p = np) == NIL)
397781Speter 		return (NIL);
398781Speter 	if (p->class != ARRAY)
399781Speter 		panic("ary");
40018351Smckusick 	/*
40118351Smckusick 	 * If it is a conformant array, we cannot find the width from
40218351Smckusick 	 * the type.
40318351Smckusick 	 */
40418351Smckusick 	if (p->chain->class == CRANGE)
40518351Smckusick 		return (NIL);
406781Speter 	s = lwidth(p->type);
407781Speter 	/*
408781Speter 	 * Arrays of anything but characters are word aligned.
409781Speter 	 */
410781Speter 	if (s & 1)
411781Speter 		if (s != 1)
412781Speter 			s++;
413781Speter 	/*
414781Speter 	 * Skip the first n subscripts
415781Speter 	 */
416781Speter 	while (n >= 0) {
417781Speter 		p = p->chain;
418781Speter 		n--;
419781Speter 	}
420781Speter 	/*
421781Speter 	 * Sum across remaining subscripts.
422781Speter 	 */
423781Speter 	while (p != NIL) {
424781Speter 		if (p->class != RANGE && p->class != SCAL)
425781Speter 			panic("aryran");
426781Speter 		d = p->range[1] - p->range[0] + 1;
427781Speter 		s *= d;
428781Speter 		p = p->chain;
429781Speter 	}
430781Speter 	return (s);
431781Speter }
432781Speter 
433781Speter /*
434781Speter  * Find the lower bound of a set, and also its size in bits.
435781Speter  */
436781Speter setran(q)
437781Speter 	struct nl *q;
438781Speter {
439781Speter 	register lb, ub;
440781Speter 	register struct nl *p;
441781Speter 
442781Speter 	p = q;
443781Speter 	if (p == NIL)
44418351Smckusick 		return;
445781Speter 	lb = p->range[0];
446781Speter 	ub = p->range[1];
447781Speter 	if (p->class != RANGE && p->class != SCAL)
448781Speter 		panic("setran");
449781Speter 	set.lwrb = lb;
450781Speter 	/* set.(upperbound prime) = number of bits - 1; */
451781Speter 	set.uprbp = ub-lb;
452781Speter }
453781Speter 
454781Speter /*
455781Speter  * Return the number of bytes required to hold an arithmetic quantity
456781Speter  */
457781Speter bytes(lb, ub)
458781Speter 	long lb, ub;
459781Speter {
460781Speter 
461781Speter #ifndef DEBUG
462781Speter 	if (lb < -32768 || ub > 32767)
463781Speter 		return (4);
464781Speter 	else if (lb < -128 || ub > 127)
465781Speter 		return (2);
466781Speter #else
467781Speter 	if (!hp21mx && (lb < -32768 || ub > 32767))
468781Speter 		return (4);
469781Speter 	if (lb < -128 || ub > 127)
470781Speter 		return (2);
471781Speter #endif
472781Speter 	else
473781Speter 		return (1);
474781Speter }
475