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