xref: /csrg-svn/usr.bin/pascal/src/var.c (revision 18351)
1781Speter /* Copyright (c) 1979 Regents of the University of California */
2781Speter 
3*18351Smckusick #ifndef lint
4*18351Smckusick static char sccsid[] = "@(#)var.c 2.2 03/15/85";
5*18351Smckusick #endif
6781Speter 
7781Speter #include "whoami.h"
8781Speter #include "0.h"
910664Speter #include "objfmt.h"
10781Speter #include "align.h"
112075Smckusic #include "iorec.h"
12781Speter #ifdef PC
13781Speter #   include	"pc.h"
14781Speter #   include	"pcops.h"
15781Speter #endif PC
1611336Speter #include "tmps.h"
17*18351Smckusick #include "tree_ty.h"
18781Speter 
19781Speter /*
20781Speter  * Declare variables of a var part.  DPOFF1 is
21781Speter  * the local variable storage for all prog/proc/func
22781Speter  * modules aside from the block mark.  The total size
23781Speter  * of all the local variables is entered into the
24781Speter  * size array.
25781Speter  */
26*18351Smckusick /*ARGSUSED*/
277951Speter varbeg( lineofyvar , r )
287951Speter     int	lineofyvar;
29781Speter {
307951Speter     static bool	var_order = FALSE;
317951Speter     static bool	var_seen = FALSE;
32781Speter 
33837Speter /* this allows for multiple declaration
34781Speter  * parts except when the "standard"
35781Speter  * option has been specified.
36781Speter  * If routine segment is being compiled,
37781Speter  * do level one processing.
38781Speter  */
39781Speter 
40781Speter #ifndef PI1
41837Speter 	if (!progseen)
42837Speter 		level1();
437951Speter 	line = lineofyvar;
44837Speter 	if ( parts[ cbn ] & RPRT ) {
45837Speter 	    if ( opt( 's' ) ) {
46781Speter 		standard();
477951Speter 		error("Variable declarations should precede routine declarations");
48837Speter 	    } else {
497951Speter 		if ( !var_order ) {
507951Speter 		    var_order = TRUE;
517951Speter 		    warning();
527951Speter 		    error("Variable declarations should precede routine declarations");
537951Speter 		}
54837Speter 	    }
55781Speter 	}
56837Speter 	if ( parts[ cbn ] & VPRT ) {
57837Speter 	    if ( opt( 's' ) ) {
58837Speter 		standard();
597951Speter 		error("All variables should be declared in one var part");
60837Speter 	    } else {
617951Speter 		if ( !var_seen ) {
627951Speter 		    var_seen = TRUE;
637951Speter 		    warning();
647951Speter 		    error("All variables should be declared in one var part");
657951Speter 		}
66837Speter 	    }
67837Speter 	}
68837Speter 	parts[ cbn ] |= VPRT;
69781Speter #endif
70781Speter     /*
71781Speter      *  #ifndef PI0
723229Smckusic      *      sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1;
73781Speter      *  #endif
74781Speter      */
75781Speter 	forechain = NIL;
76781Speter #ifdef PI0
77781Speter 	send(REVVBEG);
78781Speter #endif
79781Speter }
80781Speter 
81781Speter var(vline, vidl, vtype)
82781Speter #ifdef PI0
83*18351Smckusick 	int vline;
84*18351Smckusick 	struct tnode *vidl, *vtype;
85781Speter {
86781Speter 	register struct nl *np;
87*18351Smckusick 	register struct tnode *vl;
88781Speter 
89781Speter 	np = gtype(vtype);
90781Speter 	line = vline;
91*18351Smckusick 	/* why is this here? */
92*18351Smckusick 	for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) {
93781Speter 		}
94781Speter 	}
95781Speter 	send(REVVAR, vline, vidl, vtype);
96781Speter }
97781Speter #else
98781Speter 	int vline;
99*18351Smckusick 	register struct tnode *vidl;
100*18351Smckusick 	struct tnode *vtype;
101781Speter {
102781Speter 	register struct nl *np;
103781Speter 	register struct om *op;
104781Speter 	long w;
105781Speter 	int o2;
106*18351Smckusick #ifdef PC
1073836Speter 	struct nl	*vp;
108*18351Smckusick #endif
109781Speter 
110781Speter 	np = gtype(vtype);
111781Speter 	line = vline;
1123949Speter 	w = lwidth(np);
113781Speter 	op = &sizes[cbn];
114*18351Smckusick 	for (; vidl != TR_NIL; vidl = vidl->list_node.next) {
115781Speter #		ifdef OBJ
1163235Smckusic 		    op->curtmps.om_off =
1173235Smckusic 			roundup((int)(op->curtmps.om_off-w), (long)align(np));
1183235Smckusic 		    o2 = op -> curtmps.om_off;
119781Speter #		endif OBJ
120781Speter #		ifdef PC
121781Speter 		    if ( cbn == 1 ) {
122781Speter 				/*
123781Speter 				 * global variables are not accessed off the fp
124781Speter 				 * but rather by their names.
125781Speter 				 */
126781Speter 			    o2 = 0;
127781Speter 		    } else {
128781Speter 				/*
129781Speter 				 * locals are aligned, too.
130781Speter 				 */
1313229Smckusic 			    op->curtmps.om_off =
1323229Smckusic 				roundup((int)(op->curtmps.om_off - w),
1333082Smckusic 				(long)align(np));
1343229Smckusic 			    o2 = op -> curtmps.om_off;
135781Speter 		    }
136781Speter #		endif PC
137*18351Smckusick #		ifdef PC
138*18351Smckusick 		vp = enter(defnl((char *) vidl->list_node.list, VAR, np, o2));
139*18351Smckusick #		else
140*18351Smckusick 		(void) enter(defnl((char *) vidl->list_node.list, VAR, np, o2));
141*18351Smckusick #		endif
142781Speter 		if ( np -> nl_flags & NFILES ) {
143781Speter 		    dfiles[ cbn ] = TRUE;
144781Speter 		}
145781Speter #		ifdef PC
146781Speter 		    if ( cbn == 1 ) {
147781Speter 			putprintf( "	.data" , 0 );
14810664Speter 			aligndot(align(np));
149781Speter 			putprintf( "	.comm	" , 1 );
150*18351Smckusick 			putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list );
151*18351Smckusick 			putprintf( ",%d" , 0 , (int) w );
152781Speter 			putprintf( "	.text" , 0 );
153*18351Smckusick 			stabgvar( vp , w , line );
1543836Speter 			vp -> extra_flags |= NGLOBAL;
1553836Speter 		    } else {
1563836Speter 			vp -> extra_flags |= NLOCAL;
157781Speter 		    }
158781Speter #		endif PC
159781Speter 	}
160781Speter #	ifdef PTREE
161781Speter 	    {
162781Speter 		pPointer	*Vars;
163781Speter 		pPointer	Var = VarDecl( ovidl , vtype );
164781Speter 
165781Speter 		pSeize( PorFHeader[ nesting ] );
166781Speter 		Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars );
167781Speter 		*Vars = ListAppend( *Vars , Var );
168781Speter 		pRelease( PorFHeader[ nesting ] );
169781Speter 	    }
170781Speter #	endif
171781Speter }
172781Speter #endif
173781Speter 
174781Speter varend()
175781Speter {
176781Speter 
177781Speter 	foredecl();
178781Speter #ifndef PI0
1793229Smckusic 	sizes[cbn].om_max = sizes[cbn].curtmps.om_off;
180781Speter #else
181781Speter 	send(REVVEND);
182781Speter #endif
183781Speter }
184781Speter 
185781Speter /*
186781Speter  * Evening
187781Speter  */
1883082Smckusic long
1893082Smckusic leven(w)
1903082Smckusic 	register long w;
1913082Smckusic {
1923082Smckusic 	if (w < 0)
1933082Smckusic 		return (w & 0xfffffffe);
1943082Smckusic 	return ((w+1) & 0xfffffffe);
1953082Smckusic }
1963082Smckusic 
197*18351Smckusick #ifndef PC
1983082Smckusic int
199781Speter even(w)
200781Speter 	register int w;
201781Speter {
2023082Smckusic 	return leven((long)w);
203781Speter }
204*18351Smckusick #endif
205781Speter 
206781Speter /*
207781Speter  * Find the width of a type in bytes.
208781Speter  */
209781Speter width(np)
210781Speter 	struct nl *np;
211781Speter {
212781Speter 
213781Speter 	return (lwidth(np));
214781Speter }
215781Speter 
216781Speter long
217781Speter lwidth(np)
218781Speter 	struct nl *np;
219781Speter {
220781Speter 	register struct nl *p;
221781Speter 
222781Speter 	p = np;
223781Speter 	if (p == NIL)
224781Speter 		return (0);
225781Speter loop:
226781Speter 	switch (p->class) {
227*18351Smckusick 		default:
228*18351Smckusick 			panic("wclass");
229781Speter 		case TYPE:
230781Speter 			switch (nloff(p)) {
231781Speter 				case TNIL:
232781Speter 					return (2);
233781Speter 				case TSTR:
234781Speter 				case TSET:
235781Speter 					panic("width");
236781Speter 				default:
237781Speter 					p = p->type;
238781Speter 					goto loop;
239781Speter 			}
240781Speter 		case ARRAY:
241781Speter 			return (aryconst(p, 0));
242781Speter 		case PTR:
243781Speter 			return ( sizeof ( int * ) );
244781Speter 		case FILET:
2452075Smckusic 			return ( sizeof(struct iorec) + lwidth( p -> type ) );
246*18351Smckusick 		case CRANGE:
247*18351Smckusick 			p = p->type;
248*18351Smckusick 			goto loop;
249781Speter 		case RANGE:
250781Speter 			if (p->type == nl+TDOUBLE)
251781Speter #ifdef DEBUG
252781Speter 				return (hp21mx ? 4 : 8);
253781Speter #else
254781Speter 				return (8);
255781Speter #endif
256781Speter 		case SCAL:
257781Speter 			return (bytes(p->range[0], p->range[1]));
258781Speter 		case SET:
259781Speter 			setran(p->type);
26011822Smckusick 			/*
26111822Smckusick 			 * Sets are some multiple of longs
26211822Smckusick 			 */
2633082Smckusic 			return roundup((int)((set.uprbp >> 3) + 1),
26411822Smckusick 				(long)(sizeof(long)));
265781Speter 		case STR:
266781Speter 		case RECORD:
267781Speter 			return ( p->value[NL_OFFS] );
268781Speter 	}
269781Speter }
270781Speter 
271781Speter     /*
272781Speter      *	round up x to a multiple of y
273781Speter      *	for computing offsets of aligned things.
274781Speter      *	y had better be positive.
275781Speter      *	rounding is in the direction of x.
276781Speter      */
277781Speter long
278781Speter roundup( x , y )
2793082Smckusic     int			x;
280781Speter     register long	y;
281781Speter     {
282781Speter 
283781Speter 	if ( y == 0 ) {
2844030Smckusic 	    return x;
285781Speter 	}
286781Speter 	if ( x >= 0 ) {
287781Speter 		return ( ( ( x + ( y - 1 ) ) / y ) * y );
288781Speter 	} else {
289781Speter 		return ( ( ( x - ( y - 1 ) ) / y ) * y );
290781Speter 	}
291781Speter     }
292781Speter 
293781Speter     /*
294781Speter      *	alignment of an object using the c alignment scheme
295781Speter      */
296781Speter int
297781Speter align( np )
298781Speter     struct nl	*np;
299781Speter     {
300781Speter 	register struct nl *p;
30111822Smckusick 	long elementalign;
302781Speter 
303781Speter 	p = np;
304781Speter 	if ( p == NIL ) {
305781Speter 	    return 0;
306781Speter 	}
307781Speter alignit:
308781Speter 	switch ( p -> class ) {
309*18351Smckusick 	    default:
310*18351Smckusick 		    panic( "align" );
311781Speter 	    case TYPE:
312781Speter 		    switch ( nloff( p ) ) {
313781Speter 			case TNIL:
314781Speter 				return A_POINT;
315781Speter 			case TSTR:
31610664Speter 				return A_STRUCT;
317781Speter 			case TSET:
318781Speter 				return A_SET;
319781Speter 			default:
320781Speter 				p = p -> type;
321781Speter 				goto alignit;
322781Speter 		    }
323781Speter 	    case ARRAY:
324781Speter 			/*
32511822Smckusick 			 * arrays are structures, since they can get
32610664Speter 			 * assigned form/to as structure assignments.
32711822Smckusick 			 * preserve internal alignment if it is greater.
328781Speter 			 */
32911822Smckusick 		    elementalign = align(p -> type);
33011822Smckusick 		    return elementalign > A_STRUCT ? elementalign : A_STRUCT;
331781Speter 	    case PTR:
332781Speter 		    return A_POINT;
333781Speter 	    case FILET:
334781Speter 		    return A_FILET;
335*18351Smckusick 	    case CRANGE:
336781Speter 	    case RANGE:
337781Speter 		    if ( p -> type == nl+TDOUBLE ) {
338781Speter 			return A_DOUBLE;
339781Speter 		    }
340781Speter 		    /* else, fall through */
341781Speter 	    case SCAL:
342781Speter 		    switch ( bytes( p -> range[0] , p -> range[1] ) ) {
343781Speter 			case 4:
344781Speter 			    return A_LONG;
345781Speter 			case 2:
346781Speter 			    return A_SHORT;
347781Speter 			case 1:
348781Speter 			    return A_CHAR;
349781Speter 			default:
350781Speter 			    panic( "align: scal" );
351781Speter 		    }
352781Speter 	    case SET:
353781Speter 		    return A_SET;
354781Speter 	    case STR:
35510664Speter 			/*
35610664Speter 			 * arrays of chars are structs
35710664Speter 			 */
35810664Speter 		    return A_STRUCT;
359781Speter 	    case RECORD:
360781Speter 			/*
3618681Speter 			 * the alignment of a record is in its align_info field
3628681Speter 			 * why don't we use this for the rest of the namelist?
363781Speter 			 */
3648681Speter 		    return p -> align_info;
365781Speter 	}
366781Speter     }
367781Speter 
36810664Speter #ifdef PC
3693949Speter     /*
37010664Speter      *	output an alignment pseudo-op.
3713949Speter      */
37210664Speter aligndot(alignment)
3733949Speter     int	alignment;
37410664Speter #ifdef vax
3753949Speter {
37610664Speter     switch (alignment) {
37710664Speter 	case 1:
37810664Speter 	    return;
37910664Speter 	case 2:
38010664Speter 	    putprintf("	.align 1", 0);
38110664Speter 	    return;
38210664Speter 	default:
38310664Speter 	case 4:
38410664Speter 	    putprintf("	.align 2", 0);
38510664Speter 	    return;
3863949Speter     }
3873949Speter }
38810664Speter #endif vax
38910664Speter #ifdef mc68000
39010664Speter {
39110664Speter     switch (alignment) {
39210664Speter 	case 1:
39310664Speter 	    return;
39410664Speter 	default:
39510664Speter 	    putprintf("	.even", 0);
39610664Speter 	    return;
39710664Speter     }
39810664Speter }
39910664Speter #endif mc68000
40010664Speter #endif PC
40110664Speter 
402781Speter /*
403781Speter  * Return the width of an element
404781Speter  * of a n time subscripted np.
405781Speter  */
406781Speter long aryconst(np, n)
407781Speter 	struct nl *np;
408781Speter 	int n;
409781Speter {
410781Speter 	register struct nl *p;
411781Speter 	long s, d;
412781Speter 
413781Speter 	if ((p = np) == NIL)
414781Speter 		return (NIL);
415781Speter 	if (p->class != ARRAY)
416781Speter 		panic("ary");
417*18351Smckusick 	/*
418*18351Smckusick 	 * If it is a conformant array, we cannot find the width from
419*18351Smckusick 	 * the type.
420*18351Smckusick 	 */
421*18351Smckusick 	if (p->chain->class == CRANGE)
422*18351Smckusick 		return (NIL);
423781Speter 	s = lwidth(p->type);
424781Speter 	/*
425781Speter 	 * Arrays of anything but characters are word aligned.
426781Speter 	 */
427781Speter 	if (s & 1)
428781Speter 		if (s != 1)
429781Speter 			s++;
430781Speter 	/*
431781Speter 	 * Skip the first n subscripts
432781Speter 	 */
433781Speter 	while (n >= 0) {
434781Speter 		p = p->chain;
435781Speter 		n--;
436781Speter 	}
437781Speter 	/*
438781Speter 	 * Sum across remaining subscripts.
439781Speter 	 */
440781Speter 	while (p != NIL) {
441781Speter 		if (p->class != RANGE && p->class != SCAL)
442781Speter 			panic("aryran");
443781Speter 		d = p->range[1] - p->range[0] + 1;
444781Speter 		s *= d;
445781Speter 		p = p->chain;
446781Speter 	}
447781Speter 	return (s);
448781Speter }
449781Speter 
450781Speter /*
451781Speter  * Find the lower bound of a set, and also its size in bits.
452781Speter  */
453781Speter setran(q)
454781Speter 	struct nl *q;
455781Speter {
456781Speter 	register lb, ub;
457781Speter 	register struct nl *p;
458781Speter 
459781Speter 	p = q;
460781Speter 	if (p == NIL)
461*18351Smckusick 		return;
462781Speter 	lb = p->range[0];
463781Speter 	ub = p->range[1];
464781Speter 	if (p->class != RANGE && p->class != SCAL)
465781Speter 		panic("setran");
466781Speter 	set.lwrb = lb;
467781Speter 	/* set.(upperbound prime) = number of bits - 1; */
468781Speter 	set.uprbp = ub-lb;
469781Speter }
470781Speter 
471781Speter /*
472781Speter  * Return the number of bytes required to hold an arithmetic quantity
473781Speter  */
474781Speter bytes(lb, ub)
475781Speter 	long lb, ub;
476781Speter {
477781Speter 
478781Speter #ifndef DEBUG
479781Speter 	if (lb < -32768 || ub > 32767)
480781Speter 		return (4);
481781Speter 	else if (lb < -128 || ub > 127)
482781Speter 		return (2);
483781Speter #else
484781Speter 	if (!hp21mx && (lb < -32768 || ub > 32767))
485781Speter 		return (4);
486781Speter 	if (lb < -128 || ub > 127)
487781Speter 		return (2);
488781Speter #endif
489781Speter 	else
490781Speter 		return (1);
491781Speter }
492