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