Commit | Line | Data |
---|---|---|
0fc6e47b KB |
1 | /*- |
2 | * Copyright (c) 1980 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
252367af | 6 | */ |
c7f21b42 | 7 | |
72fbef68 | 8 | #ifndef lint |
0fc6e47b KB |
9 | static char sccsid[] = "@(#)var.c 5.5 (Berkeley) %G%"; |
10 | #endif /* not lint */ | |
c7f21b42 PK |
11 | |
12 | #include "whoami.h" | |
13 | #include "0.h" | |
82ebacca | 14 | #include "objfmt.h" |
c7f21b42 | 15 | #include "align.h" |
4c1835f7 | 16 | #include "iorec.h" |
c7f21b42 PK |
17 | #ifdef PC |
18 | # include "pc.h" | |
c7f21b42 | 19 | #endif PC |
f763caa4 | 20 | #include "tmps.h" |
72fbef68 | 21 | #include "tree_ty.h" |
c7f21b42 PK |
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 | */ | |
72fbef68 | 30 | /*ARGSUSED*/ |
7204688c PK |
31 | varbeg( lineofyvar , r ) |
32 | int lineofyvar; | |
c7f21b42 | 33 | { |
7204688c PK |
34 | static bool var_order = FALSE; |
35 | static bool var_seen = FALSE; | |
c7f21b42 | 36 | |
af97bcfa | 37 | /* this allows for multiple declaration |
c7f21b42 PK |
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 | |
af97bcfa PK |
45 | if (!progseen) |
46 | level1(); | |
7204688c | 47 | line = lineofyvar; |
af97bcfa PK |
48 | if ( parts[ cbn ] & RPRT ) { |
49 | if ( opt( 's' ) ) { | |
c7f21b42 | 50 | standard(); |
7204688c | 51 | error("Variable declarations should precede routine declarations"); |
af97bcfa | 52 | } else { |
7204688c PK |
53 | if ( !var_order ) { |
54 | var_order = TRUE; | |
55 | warning(); | |
56 | error("Variable declarations should precede routine declarations"); | |
57 | } | |
af97bcfa | 58 | } |
c7f21b42 | 59 | } |
af97bcfa PK |
60 | if ( parts[ cbn ] & VPRT ) { |
61 | if ( opt( 's' ) ) { | |
62 | standard(); | |
7204688c | 63 | error("All variables should be declared in one var part"); |
af97bcfa | 64 | } else { |
7204688c PK |
65 | if ( !var_seen ) { |
66 | var_seen = TRUE; | |
67 | warning(); | |
68 | error("All variables should be declared in one var part"); | |
69 | } | |
af97bcfa | 70 | } |
af97bcfa PK |
71 | } |
72 | parts[ cbn ] |= VPRT; | |
c7f21b42 PK |
73 | #endif |
74 | /* | |
75 | * #ifndef PI0 | |
ddb1d555 | 76 | * sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1; |
c7f21b42 PK |
77 | * #endif |
78 | */ | |
79 | forechain = NIL; | |
80 | #ifdef PI0 | |
81 | send(REVVBEG); | |
82 | #endif | |
83 | } | |
84 | ||
85 | var(vline, vidl, vtype) | |
86 | #ifdef PI0 | |
72fbef68 RT |
87 | int vline; |
88 | struct tnode *vidl, *vtype; | |
c7f21b42 PK |
89 | { |
90 | register struct nl *np; | |
72fbef68 | 91 | register struct tnode *vl; |
c7f21b42 PK |
92 | |
93 | np = gtype(vtype); | |
94 | line = vline; | |
72fbef68 RT |
95 | /* why is this here? */ |
96 | for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) { | |
c7f21b42 PK |
97 | } |
98 | } | |
99 | send(REVVAR, vline, vidl, vtype); | |
100 | } | |
101 | #else | |
102 | int vline; | |
72fbef68 RT |
103 | register struct tnode *vidl; |
104 | struct tnode *vtype; | |
c7f21b42 PK |
105 | { |
106 | register struct nl *np; | |
107 | register struct om *op; | |
108 | long w; | |
109 | int o2; | |
72fbef68 | 110 | #ifdef PC |
1f43951f | 111 | struct nl *vp; |
72fbef68 | 112 | #endif |
c7f21b42 PK |
113 | |
114 | np = gtype(vtype); | |
115 | line = vline; | |
4a4b0cfc | 116 | w = lwidth(np); |
c7f21b42 | 117 | op = &sizes[cbn]; |
72fbef68 | 118 | for (; vidl != TR_NIL; vidl = vidl->list_node.next) { |
c7f21b42 | 119 | # ifdef OBJ |
f8d06e69 KM |
120 | op->curtmps.om_off = |
121 | roundup((int)(op->curtmps.om_off-w), (long)align(np)); | |
122 | o2 = op -> curtmps.om_off; | |
c7f21b42 PK |
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 | */ | |
ddb1d555 KM |
135 | op->curtmps.om_off = |
136 | roundup((int)(op->curtmps.om_off - w), | |
6cbd3a07 | 137 | (long)align(np)); |
ddb1d555 | 138 | o2 = op -> curtmps.om_off; |
c7f21b42 PK |
139 | } |
140 | # endif PC | |
72fbef68 RT |
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 | |
cb5423b7 | 146 | if ( np != NLNIL && (np -> nl_flags & NFILES) ) { |
c7f21b42 PK |
147 | dfiles[ cbn ] = TRUE; |
148 | } | |
149 | # ifdef PC | |
150 | if ( cbn == 1 ) { | |
151 | putprintf( " .data" , 0 ); | |
82ebacca | 152 | aligndot(align(np)); |
c7f21b42 | 153 | putprintf( " .comm " , 1 ); |
72fbef68 RT |
154 | putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list ); |
155 | putprintf( ",%d" , 0 , (int) w ); | |
c7f21b42 | 156 | putprintf( " .text" , 0 ); |
8c8b6ab8 | 157 | stabgvar( vp , w , line ); |
1f43951f PK |
158 | vp -> extra_flags |= NGLOBAL; |
159 | } else { | |
160 | vp -> extra_flags |= NLOCAL; | |
c7f21b42 | 161 | } |
c7f21b42 PK |
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 | |
ddb1d555 | 183 | sizes[cbn].om_max = sizes[cbn].curtmps.om_off; |
c7f21b42 PK |
184 | #else |
185 | send(REVVEND); | |
186 | #endif | |
187 | } | |
188 | ||
c7f21b42 PK |
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; | |
c7f21b42 PK |
204 | |
205 | p = np; | |
206 | if (p == NIL) | |
207 | return (0); | |
208 | loop: | |
209 | switch (p->class) { | |
72fbef68 RT |
210 | default: |
211 | panic("wclass"); | |
c7f21b42 PK |
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: | |
4c1835f7 | 228 | return ( sizeof(struct iorec) + lwidth( p -> type ) ); |
9965cdc3 KM |
229 | case CRANGE: |
230 | p = p->type; | |
231 | goto loop; | |
c7f21b42 PK |
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); | |
e7a4b007 KM |
243 | /* |
244 | * Sets are some multiple of longs | |
245 | */ | |
6cbd3a07 | 246 | return roundup((int)((set.uprbp >> 3) + 1), |
e7a4b007 | 247 | (long)(sizeof(long))); |
c7f21b42 PK |
248 | case STR: |
249 | case RECORD: | |
250 | return ( p->value[NL_OFFS] ); | |
c7f21b42 PK |
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 ) | |
6cbd3a07 | 262 | int x; |
c7f21b42 PK |
263 | register long y; |
264 | { | |
265 | ||
266 | if ( y == 0 ) { | |
9a322285 | 267 | return x; |
c7f21b42 PK |
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; | |
e7a4b007 | 284 | long elementalign; |
c7f21b42 PK |
285 | |
286 | p = np; | |
287 | if ( p == NIL ) { | |
288 | return 0; | |
289 | } | |
290 | alignit: | |
291 | switch ( p -> class ) { | |
72fbef68 RT |
292 | default: |
293 | panic( "align" ); | |
c7f21b42 PK |
294 | case TYPE: |
295 | switch ( nloff( p ) ) { | |
296 | case TNIL: | |
297 | return A_POINT; | |
298 | case TSTR: | |
82ebacca | 299 | return A_STRUCT; |
c7f21b42 PK |
300 | case TSET: |
301 | return A_SET; | |
302 | default: | |
303 | p = p -> type; | |
304 | goto alignit; | |
305 | } | |
306 | case ARRAY: | |
307 | /* | |
e7a4b007 | 308 | * arrays are structures, since they can get |
82ebacca | 309 | * assigned form/to as structure assignments. |
e7a4b007 | 310 | * preserve internal alignment if it is greater. |
c7f21b42 | 311 | */ |
e7a4b007 KM |
312 | elementalign = align(p -> type); |
313 | return elementalign > A_STRUCT ? elementalign : A_STRUCT; | |
c7f21b42 PK |
314 | case PTR: |
315 | return A_POINT; | |
316 | case FILET: | |
317 | return A_FILET; | |
9965cdc3 | 318 | case CRANGE: |
c7f21b42 PK |
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: | |
82ebacca PK |
338 | /* |
339 | * arrays of chars are structs | |
340 | */ | |
341 | return A_STRUCT; | |
c7f21b42 PK |
342 | case RECORD: |
343 | /* | |
d25ca1ea PK |
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? | |
c7f21b42 | 346 | */ |
d25ca1ea | 347 | return p -> align_info; |
c7f21b42 PK |
348 | } |
349 | } | |
350 | ||
82ebacca | 351 | #ifdef PC |
4a4b0cfc | 352 | /* |
82ebacca | 353 | * output an alignment pseudo-op. |
4a4b0cfc | 354 | */ |
82ebacca | 355 | aligndot(alignment) |
4a4b0cfc | 356 | int alignment; |
d374dfc8 | 357 | #if defined(vax) || defined(tahoe) |
4a4b0cfc | 358 | { |
82ebacca PK |
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; | |
4a4b0cfc PK |
369 | } |
370 | } | |
d374dfc8 | 371 | #endif vax || tahoe |
82ebacca PK |
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 | ||
c7f21b42 PK |
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"); | |
9965cdc3 KM |
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); | |
c7f21b42 PK |
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) | |
72fbef68 | 444 | return; |
c7f21b42 PK |
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 | } |