1781Speter /* Copyright (c) 1979 Regents of the University of California */ 2781Speter 3*3949Speter static char sccsid[] = "@(#)var.c 1.10 07/08/81"; 4781Speter 5781Speter #include "whoami.h" 6781Speter #include "0.h" 7781Speter #include "align.h" 82075Smckusic #include "iorec.h" 9781Speter #ifdef PC 10781Speter # include "pc.h" 11781Speter # include "pcops.h" 12781Speter #endif PC 13781Speter 14781Speter /* 15781Speter * Declare variables of a var part. DPOFF1 is 16781Speter * the local variable storage for all prog/proc/func 17781Speter * modules aside from the block mark. The total size 18781Speter * of all the local variables is entered into the 19781Speter * size array. 20781Speter */ 21781Speter varbeg() 22781Speter { 23781Speter 24837Speter /* this allows for multiple declaration 25781Speter * parts except when the "standard" 26781Speter * option has been specified. 27781Speter * If routine segment is being compiled, 28781Speter * do level one processing. 29781Speter */ 30781Speter 31781Speter #ifndef PI1 32837Speter if (!progseen) 33837Speter level1(); 34837Speter if ( parts[ cbn ] & RPRT ) { 35837Speter if ( opt( 's' ) ) { 36781Speter standard(); 37837Speter } else { 38837Speter warning(); 39837Speter } 40837Speter error("Variable declarations should precede routine declarations"); 41781Speter } 42837Speter if ( parts[ cbn ] & VPRT ) { 43837Speter if ( opt( 's' ) ) { 44837Speter standard(); 45837Speter } else { 46837Speter warning(); 47837Speter } 48837Speter error("All variables should be declared in one var part"); 49837Speter } 50837Speter parts[ cbn ] |= VPRT; 51781Speter #endif 52781Speter /* 53781Speter * #ifndef PI0 543229Smckusic * sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1; 55781Speter * #endif 56781Speter */ 57781Speter forechain = NIL; 58781Speter #ifdef PI0 59781Speter send(REVVBEG); 60781Speter #endif 61781Speter } 62781Speter 63781Speter var(vline, vidl, vtype) 64781Speter #ifdef PI0 65781Speter int vline, *vidl, *vtype; 66781Speter { 67781Speter register struct nl *np; 68781Speter register int *vl; 69781Speter 70781Speter np = gtype(vtype); 71781Speter line = vline; 72781Speter for (vl = vidl; vl != NIL; vl = vl[2]) { 73781Speter } 74781Speter } 75781Speter send(REVVAR, vline, vidl, vtype); 76781Speter } 77781Speter #else 78781Speter int vline; 79781Speter register int *vidl; 80781Speter int *vtype; 81781Speter { 82781Speter register struct nl *np; 83781Speter register struct om *op; 84781Speter long w; 85781Speter int o2; 86781Speter int *ovidl = vidl; 873836Speter struct nl *vp; 88781Speter 89781Speter np = gtype(vtype); 90781Speter line = vline; 91*3949Speter w = lwidth(np); 92781Speter op = &sizes[cbn]; 93781Speter for (; vidl != NIL; vidl = vidl[2]) { 94781Speter # ifdef OBJ 953235Smckusic op->curtmps.om_off = 963235Smckusic roundup((int)(op->curtmps.om_off-w), (long)align(np)); 973235Smckusic o2 = op -> curtmps.om_off; 98781Speter # endif OBJ 99781Speter # ifdef PC 100781Speter if ( cbn == 1 ) { 101781Speter /* 102781Speter * global variables are not accessed off the fp 103781Speter * but rather by their names. 104781Speter */ 105781Speter o2 = 0; 106781Speter } else { 107781Speter /* 108781Speter * locals are aligned, too. 109781Speter */ 1103229Smckusic op->curtmps.om_off = 1113229Smckusic roundup((int)(op->curtmps.om_off - w), 1123082Smckusic (long)align(np)); 1133229Smckusic o2 = op -> curtmps.om_off; 114781Speter } 115781Speter # endif PC 1163836Speter vp = enter(defnl(vidl[1], VAR, np, o2)); 117781Speter if ( np -> nl_flags & NFILES ) { 118781Speter dfiles[ cbn ] = TRUE; 119781Speter } 120781Speter # ifdef PC 121781Speter if ( cbn == 1 ) { 122781Speter putprintf( " .data" , 0 ); 123*3949Speter putprintf( " .align %d" , 0 , dotalign(align(np))); 124781Speter putprintf( " .comm " , 1 ); 125781Speter putprintf( EXTFORMAT , 1 , vidl[1] ); 126781Speter putprintf( ",%d" , 0 , w ); 127781Speter putprintf( " .text" , 0 ); 1282165Speter stabgvar( vidl[1] , p2type( np ) , o2 , w , line ); 1293836Speter vp -> extra_flags |= NGLOBAL; 1303836Speter } else { 1313836Speter vp -> extra_flags |= NLOCAL; 132781Speter } 133781Speter # endif PC 134781Speter } 135781Speter # ifdef PTREE 136781Speter { 137781Speter pPointer *Vars; 138781Speter pPointer Var = VarDecl( ovidl , vtype ); 139781Speter 140781Speter pSeize( PorFHeader[ nesting ] ); 141781Speter Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars ); 142781Speter *Vars = ListAppend( *Vars , Var ); 143781Speter pRelease( PorFHeader[ nesting ] ); 144781Speter } 145781Speter # endif 146781Speter } 147781Speter #endif 148781Speter 149781Speter varend() 150781Speter { 151781Speter 152781Speter foredecl(); 153781Speter #ifndef PI0 1543229Smckusic sizes[cbn].om_max = sizes[cbn].curtmps.om_off; 155781Speter #else 156781Speter send(REVVEND); 157781Speter #endif 158781Speter } 159781Speter 160781Speter /* 161781Speter * Evening 162781Speter */ 1633082Smckusic long 1643082Smckusic leven(w) 1653082Smckusic register long w; 1663082Smckusic { 1673082Smckusic if (w < 0) 1683082Smckusic return (w & 0xfffffffe); 1693082Smckusic return ((w+1) & 0xfffffffe); 1703082Smckusic } 1713082Smckusic 1723082Smckusic int 173781Speter even(w) 174781Speter register int w; 175781Speter { 1763082Smckusic return leven((long)w); 177781Speter } 178781Speter 179781Speter /* 180781Speter * Find the width of a type in bytes. 181781Speter */ 182781Speter width(np) 183781Speter struct nl *np; 184781Speter { 185781Speter 186781Speter return (lwidth(np)); 187781Speter } 188781Speter 189781Speter long 190781Speter lwidth(np) 191781Speter struct nl *np; 192781Speter { 193781Speter register struct nl *p; 194781Speter long w; 195781Speter 196781Speter p = np; 197781Speter if (p == NIL) 198781Speter return (0); 199781Speter loop: 200781Speter switch (p->class) { 201781Speter case TYPE: 202781Speter switch (nloff(p)) { 203781Speter case TNIL: 204781Speter return (2); 205781Speter case TSTR: 206781Speter case TSET: 207781Speter panic("width"); 208781Speter default: 209781Speter p = p->type; 210781Speter goto loop; 211781Speter } 212781Speter case ARRAY: 213781Speter return (aryconst(p, 0)); 214781Speter case PTR: 215781Speter return ( sizeof ( int * ) ); 216781Speter case FILET: 2172075Smckusic return ( sizeof(struct iorec) + lwidth( p -> type ) ); 218781Speter case RANGE: 219781Speter if (p->type == nl+TDOUBLE) 220781Speter #ifdef DEBUG 221781Speter return (hp21mx ? 4 : 8); 222781Speter #else 223781Speter return (8); 224781Speter #endif 225781Speter case SCAL: 226781Speter return (bytes(p->range[0], p->range[1])); 227781Speter case SET: 228781Speter setran(p->type); 2293082Smckusic return roundup((int)((set.uprbp >> 3) + 1), 2303082Smckusic (long)(A_SET)); 231781Speter case STR: 232781Speter case RECORD: 233781Speter return ( p->value[NL_OFFS] ); 234781Speter default: 235781Speter panic("wclass"); 236781Speter } 237781Speter } 238781Speter 239781Speter /* 240781Speter * round up x to a multiple of y 241781Speter * for computing offsets of aligned things. 242781Speter * y had better be positive. 243781Speter * rounding is in the direction of x. 244781Speter */ 245781Speter long 246781Speter roundup( x , y ) 2473082Smckusic int x; 248781Speter register long y; 249781Speter { 250781Speter 251781Speter if ( y == 0 ) { 252781Speter return 0; 253781Speter } 254781Speter if ( x >= 0 ) { 255781Speter return ( ( ( x + ( y - 1 ) ) / y ) * y ); 256781Speter } else { 257781Speter return ( ( ( x - ( y - 1 ) ) / y ) * y ); 258781Speter } 259781Speter } 260781Speter 261781Speter /* 262781Speter * alignment of an object using the c alignment scheme 263781Speter */ 264781Speter int 265781Speter align( np ) 266781Speter struct nl *np; 267781Speter { 268781Speter register struct nl *p; 269781Speter 270781Speter p = np; 271781Speter if ( p == NIL ) { 272781Speter return 0; 273781Speter } 274781Speter alignit: 275781Speter switch ( p -> class ) { 276781Speter case TYPE: 277781Speter switch ( nloff( p ) ) { 278781Speter case TNIL: 279781Speter return A_POINT; 280781Speter case TSTR: 281781Speter return A_CHAR; 282781Speter case TSET: 283781Speter return A_SET; 284781Speter default: 285781Speter p = p -> type; 286781Speter goto alignit; 287781Speter } 288781Speter case ARRAY: 289781Speter /* 290781Speter * arrays are aligned as their component types 291781Speter */ 292781Speter p = p -> type; 293781Speter goto alignit; 294781Speter case PTR: 295781Speter return A_POINT; 296781Speter case FILET: 297781Speter return A_FILET; 298781Speter case RANGE: 299781Speter if ( p -> type == nl+TDOUBLE ) { 300781Speter return A_DOUBLE; 301781Speter } 302781Speter /* else, fall through */ 303781Speter case SCAL: 304781Speter switch ( bytes( p -> range[0] , p -> range[1] ) ) { 305781Speter case 4: 306781Speter return A_LONG; 307781Speter case 2: 308781Speter return A_SHORT; 309781Speter case 1: 310781Speter return A_CHAR; 311781Speter default: 312781Speter panic( "align: scal" ); 313781Speter } 314781Speter case SET: 315781Speter return A_SET; 316781Speter case STR: 317781Speter return A_CHAR; 318781Speter case RECORD: 319781Speter /* 320781Speter * follow chain through all fields in record, 321781Speter * taking max of alignments of types of fields. 322781Speter * short circuit out if i reach the maximum alignment. 323781Speter * this is pretty likely, as A_MAX is only 4. 324781Speter */ 325781Speter { 326781Speter register long recalign; 327781Speter register long fieldalign; 328781Speter 329781Speter recalign = A_MIN; 330781Speter p = p -> chain; 331781Speter while ( ( p != NIL ) && ( recalign < A_MAX ) ) { 332781Speter fieldalign = align( p -> type ); 333781Speter if ( fieldalign > recalign ) { 334781Speter recalign = fieldalign; 335781Speter } 336781Speter p = p -> chain; 337781Speter } 338781Speter return recalign; 339781Speter } 340781Speter default: 341781Speter panic( "align" ); 342781Speter } 343781Speter } 344781Speter 345*3949Speter /* 346*3949Speter * given an alignment, return power of two for .align pseudo-op 347*3949Speter */ 348*3949Speter dotalign( alignment ) 349*3949Speter int alignment; 350*3949Speter { 351*3949Speter 352*3949Speter switch ( alignment ) { 353*3949Speter case A_CHAR: /* 354*3949Speter * also 355*3949Speter * A_STRUCT 356*3949Speter */ 357*3949Speter return 0; 358*3949Speter case A_SHORT: 359*3949Speter return 1; 360*3949Speter case A_LONG: /* 361*3949Speter * also 362*3949Speter * A_POINT, A_INT, A_FLOAT, A_DOUBLE, 363*3949Speter * A_STACK, A_FILET, A_SET 364*3949Speter */ 365*3949Speter return 2; 366*3949Speter } 367*3949Speter } 368*3949Speter 369781Speter /* 370781Speter * Return the width of an element 371781Speter * of a n time subscripted np. 372781Speter */ 373781Speter long aryconst(np, n) 374781Speter struct nl *np; 375781Speter int n; 376781Speter { 377781Speter register struct nl *p; 378781Speter long s, d; 379781Speter 380781Speter if ((p = np) == NIL) 381781Speter return (NIL); 382781Speter if (p->class != ARRAY) 383781Speter panic("ary"); 384781Speter s = lwidth(p->type); 385781Speter /* 386781Speter * Arrays of anything but characters are word aligned. 387781Speter */ 388781Speter if (s & 1) 389781Speter if (s != 1) 390781Speter s++; 391781Speter /* 392781Speter * Skip the first n subscripts 393781Speter */ 394781Speter while (n >= 0) { 395781Speter p = p->chain; 396781Speter n--; 397781Speter } 398781Speter /* 399781Speter * Sum across remaining subscripts. 400781Speter */ 401781Speter while (p != NIL) { 402781Speter if (p->class != RANGE && p->class != SCAL) 403781Speter panic("aryran"); 404781Speter d = p->range[1] - p->range[0] + 1; 405781Speter s *= d; 406781Speter p = p->chain; 407781Speter } 408781Speter return (s); 409781Speter } 410781Speter 411781Speter /* 412781Speter * Find the lower bound of a set, and also its size in bits. 413781Speter */ 414781Speter setran(q) 415781Speter struct nl *q; 416781Speter { 417781Speter register lb, ub; 418781Speter register struct nl *p; 419781Speter 420781Speter p = q; 421781Speter if (p == NIL) 422781Speter return (NIL); 423781Speter lb = p->range[0]; 424781Speter ub = p->range[1]; 425781Speter if (p->class != RANGE && p->class != SCAL) 426781Speter panic("setran"); 427781Speter set.lwrb = lb; 428781Speter /* set.(upperbound prime) = number of bits - 1; */ 429781Speter set.uprbp = ub-lb; 430781Speter } 431781Speter 432781Speter /* 433781Speter * Return the number of bytes required to hold an arithmetic quantity 434781Speter */ 435781Speter bytes(lb, ub) 436781Speter long lb, ub; 437781Speter { 438781Speter 439781Speter #ifndef DEBUG 440781Speter if (lb < -32768 || ub > 32767) 441781Speter return (4); 442781Speter else if (lb < -128 || ub > 127) 443781Speter return (2); 444781Speter #else 445781Speter if (!hp21mx && (lb < -32768 || ub > 32767)) 446781Speter return (4); 447781Speter if (lb < -128 || ub > 127) 448781Speter return (2); 449781Speter #endif 450781Speter else 451781Speter return (1); 452781Speter } 453