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