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