1781Speter /* Copyright (c) 1979 Regents of the University of California */ 2781Speter 3*3229Smckusic static char sccsid[] = "@(#)var.c 1.7 03/11/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 54*3229Smckusic * 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; 87781Speter 88781Speter np = gtype(vtype); 89781Speter line = vline; 90781Speter /* 91781Speter * widths are evened out 92781Speter */ 93781Speter w = (lwidth(np) + 1) &~ 1; 94781Speter op = &sizes[cbn]; 95781Speter for (; vidl != NIL; vidl = vidl[2]) { 96781Speter # ifdef OBJ 97*3229Smckusic op->curtmp.om_off = 98*3229Smckusic roundup((int)(op->curtmp.om_off-w), (long)align(np)); 99*3229Smckusic o2 = op -> curtmp.om_off; 100781Speter # endif OBJ 101781Speter # ifdef PC 102781Speter if ( cbn == 1 ) { 103781Speter /* 104781Speter * global variables are not accessed off the fp 105781Speter * but rather by their names. 106781Speter */ 107781Speter o2 = 0; 108781Speter } else { 109781Speter /* 110781Speter * locals are aligned, too. 111781Speter */ 112*3229Smckusic op->curtmps.om_off = 113*3229Smckusic roundup((int)(op->curtmps.om_off - w), 1143082Smckusic (long)align(np)); 115*3229Smckusic o2 = op -> curtmps.om_off; 116781Speter } 117781Speter # endif PC 118781Speter enter(defnl(vidl[1], VAR, np, o2)); 119781Speter if ( np -> nl_flags & NFILES ) { 120781Speter dfiles[ cbn ] = TRUE; 121781Speter } 122781Speter # ifdef PC 123781Speter if ( cbn == 1 ) { 124781Speter putprintf( " .data" , 0 ); 125781Speter putprintf( " .comm " , 1 ); 126781Speter putprintf( EXTFORMAT , 1 , vidl[1] ); 127781Speter putprintf( ",%d" , 0 , w ); 128781Speter putprintf( " .text" , 0 ); 1292165Speter stabgvar( vidl[1] , p2type( np ) , o2 , w , line ); 130781Speter } 131781Speter # endif PC 132781Speter } 133781Speter # ifdef PTREE 134781Speter { 135781Speter pPointer *Vars; 136781Speter pPointer Var = VarDecl( ovidl , vtype ); 137781Speter 138781Speter pSeize( PorFHeader[ nesting ] ); 139781Speter Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars ); 140781Speter *Vars = ListAppend( *Vars , Var ); 141781Speter pRelease( PorFHeader[ nesting ] ); 142781Speter } 143781Speter # endif 144781Speter } 145781Speter #endif 146781Speter 147781Speter varend() 148781Speter { 149781Speter 150781Speter foredecl(); 151781Speter #ifndef PI0 152*3229Smckusic sizes[cbn].om_max = sizes[cbn].curtmps.om_off; 153781Speter #else 154781Speter send(REVVEND); 155781Speter #endif 156781Speter } 157781Speter 158781Speter /* 159781Speter * Evening 160781Speter */ 1613082Smckusic long 1623082Smckusic leven(w) 1633082Smckusic register long w; 1643082Smckusic { 1653082Smckusic if (w < 0) 1663082Smckusic return (w & 0xfffffffe); 1673082Smckusic return ((w+1) & 0xfffffffe); 1683082Smckusic } 1693082Smckusic 1703082Smckusic int 171781Speter even(w) 172781Speter register int w; 173781Speter { 1743082Smckusic return leven((long)w); 175781Speter } 176781Speter 177781Speter /* 178781Speter * Find the width of a type in bytes. 179781Speter */ 180781Speter width(np) 181781Speter struct nl *np; 182781Speter { 183781Speter 184781Speter return (lwidth(np)); 185781Speter } 186781Speter 187781Speter long 188781Speter lwidth(np) 189781Speter struct nl *np; 190781Speter { 191781Speter register struct nl *p; 192781Speter long w; 193781Speter 194781Speter p = np; 195781Speter if (p == NIL) 196781Speter return (0); 197781Speter loop: 198781Speter switch (p->class) { 199781Speter case TYPE: 200781Speter switch (nloff(p)) { 201781Speter case TNIL: 202781Speter return (2); 203781Speter case TSTR: 204781Speter case TSET: 205781Speter panic("width"); 206781Speter default: 207781Speter p = p->type; 208781Speter goto loop; 209781Speter } 210781Speter case ARRAY: 211781Speter return (aryconst(p, 0)); 212781Speter case PTR: 213781Speter return ( sizeof ( int * ) ); 214781Speter case FILET: 2152075Smckusic return ( sizeof(struct iorec) + lwidth( p -> type ) ); 216781Speter case RANGE: 217781Speter if (p->type == nl+TDOUBLE) 218781Speter #ifdef DEBUG 219781Speter return (hp21mx ? 4 : 8); 220781Speter #else 221781Speter return (8); 222781Speter #endif 223781Speter case SCAL: 224781Speter return (bytes(p->range[0], p->range[1])); 225781Speter case SET: 226781Speter setran(p->type); 2273082Smckusic return roundup((int)((set.uprbp >> 3) + 1), 2283082Smckusic (long)(A_SET)); 229781Speter case STR: 230781Speter case RECORD: 231781Speter return ( p->value[NL_OFFS] ); 232781Speter default: 233781Speter panic("wclass"); 234781Speter } 235781Speter } 236781Speter 237781Speter /* 238781Speter * round up x to a multiple of y 239781Speter * for computing offsets of aligned things. 240781Speter * y had better be positive. 241781Speter * rounding is in the direction of x. 242781Speter */ 243781Speter long 244781Speter roundup( x , y ) 2453082Smckusic int x; 246781Speter register long y; 247781Speter { 248781Speter 249781Speter if ( y == 0 ) { 250781Speter return 0; 251781Speter } 252781Speter if ( x >= 0 ) { 253781Speter return ( ( ( x + ( y - 1 ) ) / y ) * y ); 254781Speter } else { 255781Speter return ( ( ( x - ( y - 1 ) ) / y ) * y ); 256781Speter } 257781Speter } 258781Speter 259781Speter /* 260781Speter * alignment of an object using the c alignment scheme 261781Speter */ 262781Speter int 263781Speter align( np ) 264781Speter struct nl *np; 265781Speter { 266781Speter register struct nl *p; 267781Speter 268781Speter p = np; 269781Speter if ( p == NIL ) { 270781Speter return 0; 271781Speter } 272781Speter alignit: 273781Speter switch ( p -> class ) { 274781Speter case TYPE: 275781Speter switch ( nloff( p ) ) { 276781Speter case TNIL: 277781Speter return A_POINT; 278781Speter case TSTR: 279781Speter return A_CHAR; 280781Speter case TSET: 281781Speter return A_SET; 282781Speter default: 283781Speter p = p -> type; 284781Speter goto alignit; 285781Speter } 286781Speter case ARRAY: 287781Speter /* 288781Speter * arrays are aligned as their component types 289781Speter */ 290781Speter p = p -> type; 291781Speter goto alignit; 292781Speter case PTR: 293781Speter return A_POINT; 294781Speter case FILET: 295781Speter return A_FILET; 296781Speter case RANGE: 297781Speter if ( p -> type == nl+TDOUBLE ) { 298781Speter return A_DOUBLE; 299781Speter } 300781Speter /* else, fall through */ 301781Speter case SCAL: 302781Speter switch ( bytes( p -> range[0] , p -> range[1] ) ) { 303781Speter case 4: 304781Speter return A_LONG; 305781Speter case 2: 306781Speter return A_SHORT; 307781Speter case 1: 308781Speter return A_CHAR; 309781Speter default: 310781Speter panic( "align: scal" ); 311781Speter } 312781Speter case SET: 313781Speter return A_SET; 314781Speter case STR: 315781Speter return A_CHAR; 316781Speter case RECORD: 317781Speter /* 318781Speter * follow chain through all fields in record, 319781Speter * taking max of alignments of types of fields. 320781Speter * short circuit out if i reach the maximum alignment. 321781Speter * this is pretty likely, as A_MAX is only 4. 322781Speter */ 323781Speter { 324781Speter register long recalign; 325781Speter register long fieldalign; 326781Speter 327781Speter recalign = A_MIN; 328781Speter p = p -> chain; 329781Speter while ( ( p != NIL ) && ( recalign < A_MAX ) ) { 330781Speter fieldalign = align( p -> type ); 331781Speter if ( fieldalign > recalign ) { 332781Speter recalign = fieldalign; 333781Speter } 334781Speter p = p -> chain; 335781Speter } 336781Speter return recalign; 337781Speter } 338781Speter default: 339781Speter panic( "align" ); 340781Speter } 341781Speter } 342781Speter 343781Speter /* 344781Speter * Return the width of an element 345781Speter * of a n time subscripted np. 346781Speter */ 347781Speter long aryconst(np, n) 348781Speter struct nl *np; 349781Speter int n; 350781Speter { 351781Speter register struct nl *p; 352781Speter long s, d; 353781Speter 354781Speter if ((p = np) == NIL) 355781Speter return (NIL); 356781Speter if (p->class != ARRAY) 357781Speter panic("ary"); 358781Speter s = lwidth(p->type); 359781Speter /* 360781Speter * Arrays of anything but characters are word aligned. 361781Speter */ 362781Speter if (s & 1) 363781Speter if (s != 1) 364781Speter s++; 365781Speter /* 366781Speter * Skip the first n subscripts 367781Speter */ 368781Speter while (n >= 0) { 369781Speter p = p->chain; 370781Speter n--; 371781Speter } 372781Speter /* 373781Speter * Sum across remaining subscripts. 374781Speter */ 375781Speter while (p != NIL) { 376781Speter if (p->class != RANGE && p->class != SCAL) 377781Speter panic("aryran"); 378781Speter d = p->range[1] - p->range[0] + 1; 379781Speter s *= d; 380781Speter p = p->chain; 381781Speter } 382781Speter return (s); 383781Speter } 384781Speter 385781Speter /* 386781Speter * Find the lower bound of a set, and also its size in bits. 387781Speter */ 388781Speter setran(q) 389781Speter struct nl *q; 390781Speter { 391781Speter register lb, ub; 392781Speter register struct nl *p; 393781Speter 394781Speter p = q; 395781Speter if (p == NIL) 396781Speter return (NIL); 397781Speter lb = p->range[0]; 398781Speter ub = p->range[1]; 399781Speter if (p->class != RANGE && p->class != SCAL) 400781Speter panic("setran"); 401781Speter set.lwrb = lb; 402781Speter /* set.(upperbound prime) = number of bits - 1; */ 403781Speter set.uprbp = ub-lb; 404781Speter } 405781Speter 406781Speter /* 407781Speter * Return the number of bytes required to hold an arithmetic quantity 408781Speter */ 409781Speter bytes(lb, ub) 410781Speter long lb, ub; 411781Speter { 412781Speter 413781Speter #ifndef DEBUG 414781Speter if (lb < -32768 || ub > 32767) 415781Speter return (4); 416781Speter else if (lb < -128 || ub > 127) 417781Speter return (2); 418781Speter #else 419781Speter if (!hp21mx && (lb < -32768 || ub > 32767)) 420781Speter return (4); 421781Speter if (lb < -128 || ub > 127) 422781Speter return (2); 423781Speter #endif 424781Speter else 425781Speter return (1); 426781Speter } 427