1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)var.c 8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11
12 #include "whoami.h"
13 #include "0.h"
14 #include "objfmt.h"
15 #include "align.h"
16 #include "iorec.h"
17 #ifdef PC
18 # include "pc.h"
19 #endif PC
20 #include "tmps.h"
21 #include "tree_ty.h"
22
23 /*
24 * Declare variables of a var part. DPOFF1 is
25 * the local variable storage for all prog/proc/func
26 * modules aside from the block mark. The total size
27 * of all the local variables is entered into the
28 * size array.
29 */
30 /*ARGSUSED*/
varbeg(lineofyvar,r)31 varbeg( lineofyvar , r )
32 int lineofyvar;
33 {
34 static bool var_order = FALSE;
35 static bool var_seen = FALSE;
36
37 /* this allows for multiple declaration
38 * parts except when the "standard"
39 * option has been specified.
40 * If routine segment is being compiled,
41 * do level one processing.
42 */
43
44 #ifndef PI1
45 if (!progseen)
46 level1();
47 line = lineofyvar;
48 if ( parts[ cbn ] & RPRT ) {
49 if ( opt( 's' ) ) {
50 standard();
51 error("Variable declarations should precede routine declarations");
52 } else {
53 if ( !var_order ) {
54 var_order = TRUE;
55 warning();
56 error("Variable declarations should precede routine declarations");
57 }
58 }
59 }
60 if ( parts[ cbn ] & VPRT ) {
61 if ( opt( 's' ) ) {
62 standard();
63 error("All variables should be declared in one var part");
64 } else {
65 if ( !var_seen ) {
66 var_seen = TRUE;
67 warning();
68 error("All variables should be declared in one var part");
69 }
70 }
71 }
72 parts[ cbn ] |= VPRT;
73 #endif
74 /*
75 * #ifndef PI0
76 * sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1;
77 * #endif
78 */
79 forechain = NIL;
80 #ifdef PI0
81 send(REVVBEG);
82 #endif
83 }
84
var(vline,vidl,vtype)85 var(vline, vidl, vtype)
86 #ifdef PI0
87 int vline;
88 struct tnode *vidl, *vtype;
89 {
90 register struct nl *np;
91 register struct tnode *vl;
92
93 np = gtype(vtype);
94 line = vline;
95 /* why is this here? */
96 for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) {
97 }
98 }
99 send(REVVAR, vline, vidl, vtype);
100 }
101 #else
102 int vline;
103 register struct tnode *vidl;
104 struct tnode *vtype;
105 {
106 register struct nl *np;
107 register struct om *op;
108 long w;
109 int o2;
110 #ifdef PC
111 struct nl *vp;
112 #endif
113
114 np = gtype(vtype);
115 line = vline;
116 w = lwidth(np);
117 op = &sizes[cbn];
118 for (; vidl != TR_NIL; vidl = vidl->list_node.next) {
119 # ifdef OBJ
120 op->curtmps.om_off =
121 roundup((int)(op->curtmps.om_off-w), (long)align(np));
122 o2 = op -> curtmps.om_off;
123 # endif OBJ
124 # ifdef PC
125 if ( cbn == 1 ) {
126 /*
127 * global variables are not accessed off the fp
128 * but rather by their names.
129 */
130 o2 = 0;
131 } else {
132 /*
133 * locals are aligned, too.
134 */
135 op->curtmps.om_off =
136 roundup((int)(op->curtmps.om_off - w),
137 (long)align(np));
138 o2 = op -> curtmps.om_off;
139 }
140 # endif PC
141 # ifdef PC
142 vp = enter(defnl((char *) vidl->list_node.list, VAR, np, o2));
143 # else
144 (void) enter(defnl((char *) vidl->list_node.list, VAR, np, o2));
145 # endif
146 if ( np != NLNIL && (np -> nl_flags & NFILES) ) {
147 dfiles[ cbn ] = TRUE;
148 }
149 # ifdef PC
150 if ( cbn == 1 ) {
151 putprintf( " .data" , 0 );
152 aligndot(align(np));
153 putprintf( " .comm " , 1 );
154 putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list );
155 putprintf( ",%d" , 0 , (int) w );
156 putprintf( " .text" , 0 );
157 stabgvar( vp , w , line );
158 vp -> extra_flags |= NGLOBAL;
159 } else {
160 vp -> extra_flags |= NLOCAL;
161 }
162 # endif PC
163 }
164 # ifdef PTREE
165 {
166 pPointer *Vars;
167 pPointer Var = VarDecl( ovidl , vtype );
168
169 pSeize( PorFHeader[ nesting ] );
170 Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars );
171 *Vars = ListAppend( *Vars , Var );
172 pRelease( PorFHeader[ nesting ] );
173 }
174 # endif
175 }
176 #endif
177
178 varend()
179 {
180
181 foredecl();
182 #ifndef PI0
183 sizes[cbn].om_max = sizes[cbn].curtmps.om_off;
184 #else
185 send(REVVEND);
186 #endif
187 }
188
189 /*
190 * Find the width of a type in bytes.
191 */
192 width(np)
193 struct nl *np;
194 {
195
196 return (lwidth(np));
197 }
198
199 long
200 lwidth(np)
201 struct nl *np;
202 {
203 register struct nl *p;
204
205 p = np;
206 if (p == NIL)
207 return (0);
208 loop:
209 switch (p->class) {
210 default:
211 panic("wclass");
212 case TYPE:
213 switch (nloff(p)) {
214 case TNIL:
215 return (2);
216 case TSTR:
217 case TSET:
218 panic("width");
219 default:
220 p = p->type;
221 goto loop;
222 }
223 case ARRAY:
224 return (aryconst(p, 0));
225 case PTR:
226 return ( sizeof ( int * ) );
227 case FILET:
228 return ( sizeof(struct iorec) + lwidth( p -> type ) );
229 case CRANGE:
230 p = p->type;
231 goto loop;
232 case RANGE:
233 if (p->type == nl+TDOUBLE)
234 #ifdef DEBUG
235 return (hp21mx ? 4 : 8);
236 #else
237 return (8);
238 #endif
239 case SCAL:
240 return (bytes(p->range[0], p->range[1]));
241 case SET:
242 setran(p->type);
243 /*
244 * Sets are some multiple of longs
245 */
246 return roundup((int)((set.uprbp >> 3) + 1),
247 (long)(sizeof(long)));
248 case STR:
249 case RECORD:
250 return ( p->value[NL_OFFS] );
251 }
252 }
253
254 /*
255 * round up x to a multiple of y
256 * for computing offsets of aligned things.
257 * y had better be positive.
258 * rounding is in the direction of x.
259 */
260 long
261 roundup( x , y )
262 int x;
263 register long y;
264 {
265
266 if ( y == 0 ) {
267 return x;
268 }
269 if ( x >= 0 ) {
270 return ( ( ( x + ( y - 1 ) ) / y ) * y );
271 } else {
272 return ( ( ( x - ( y - 1 ) ) / y ) * y );
273 }
274 }
275
276 /*
277 * alignment of an object using the c alignment scheme
278 */
279 int
280 align( np )
281 struct nl *np;
282 {
283 register struct nl *p;
284 long elementalign;
285
286 p = np;
287 if ( p == NIL ) {
288 return 0;
289 }
290 alignit:
291 switch ( p -> class ) {
292 default:
293 panic( "align" );
294 case TYPE:
295 switch ( nloff( p ) ) {
296 case TNIL:
297 return A_POINT;
298 case TSTR:
299 return A_STRUCT;
300 case TSET:
301 return A_SET;
302 default:
303 p = p -> type;
304 goto alignit;
305 }
306 case ARRAY:
307 /*
308 * arrays are structures, since they can get
309 * assigned form/to as structure assignments.
310 * preserve internal alignment if it is greater.
311 */
312 elementalign = align(p -> type);
313 return elementalign > A_STRUCT ? elementalign : A_STRUCT;
314 case PTR:
315 return A_POINT;
316 case FILET:
317 return A_FILET;
318 case CRANGE:
319 case RANGE:
320 if ( p -> type == nl+TDOUBLE ) {
321 return A_DOUBLE;
322 }
323 /* else, fall through */
324 case SCAL:
325 switch ( bytes( p -> range[0] , p -> range[1] ) ) {
326 case 4:
327 return A_LONG;
328 case 2:
329 return A_SHORT;
330 case 1:
331 return A_CHAR;
332 default:
333 panic( "align: scal" );
334 }
335 case SET:
336 return A_SET;
337 case STR:
338 /*
339 * arrays of chars are structs
340 */
341 return A_STRUCT;
342 case RECORD:
343 /*
344 * the alignment of a record is in its align_info field
345 * why don't we use this for the rest of the namelist?
346 */
347 return p -> align_info;
348 }
349 }
350
351 #ifdef PC
352 /*
353 * output an alignment pseudo-op.
354 */
355 aligndot(alignment)
356 int alignment;
357 #if defined(vax) || defined(tahoe)
358 {
359 switch (alignment) {
360 case 1:
361 return;
362 case 2:
363 putprintf(" .align 1", 0);
364 return;
365 default:
366 case 4:
367 putprintf(" .align 2", 0);
368 return;
369 }
370 }
371 #endif vax || tahoe
372 #ifdef mc68000
373 {
374 switch (alignment) {
375 case 1:
376 return;
377 default:
378 putprintf(" .even", 0);
379 return;
380 }
381 }
382 #endif mc68000
383 #endif PC
384
385 /*
386 * Return the width of an element
387 * of a n time subscripted np.
388 */
389 long aryconst(np, n)
390 struct nl *np;
391 int n;
392 {
393 register struct nl *p;
394 long s, d;
395
396 if ((p = np) == NIL)
397 return (NIL);
398 if (p->class != ARRAY)
399 panic("ary");
400 /*
401 * If it is a conformant array, we cannot find the width from
402 * the type.
403 */
404 if (p->chain->class == CRANGE)
405 return (NIL);
406 s = lwidth(p->type);
407 /*
408 * Arrays of anything but characters are word aligned.
409 */
410 if (s & 1)
411 if (s != 1)
412 s++;
413 /*
414 * Skip the first n subscripts
415 */
416 while (n >= 0) {
417 p = p->chain;
418 n--;
419 }
420 /*
421 * Sum across remaining subscripts.
422 */
423 while (p != NIL) {
424 if (p->class != RANGE && p->class != SCAL)
425 panic("aryran");
426 d = p->range[1] - p->range[0] + 1;
427 s *= d;
428 p = p->chain;
429 }
430 return (s);
431 }
432
433 /*
434 * Find the lower bound of a set, and also its size in bits.
435 */
436 setran(q)
437 struct nl *q;
438 {
439 register lb, ub;
440 register struct nl *p;
441
442 p = q;
443 if (p == NIL)
444 return;
445 lb = p->range[0];
446 ub = p->range[1];
447 if (p->class != RANGE && p->class != SCAL)
448 panic("setran");
449 set.lwrb = lb;
450 /* set.(upperbound prime) = number of bits - 1; */
451 set.uprbp = ub-lb;
452 }
453
454 /*
455 * Return the number of bytes required to hold an arithmetic quantity
456 */
457 bytes(lb, ub)
458 long lb, ub;
459 {
460
461 #ifndef DEBUG
462 if (lb < -32768 || ub > 32767)
463 return (4);
464 else if (lb < -128 || ub > 127)
465 return (2);
466 #else
467 if (!hp21mx && (lb < -32768 || ub > 32767))
468 return (4);
469 if (lb < -128 || ub > 127)
470 return (2);
471 #endif
472 else
473 return (1);
474 }
475