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 } 474