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*/ 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 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