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