1781Speter /* Copyright (c) 1979 Regents of the University of California */ 2781Speter 3*837Speter static char sccsid[] = "@(#)var.c 1.3 09/02/80"; 4781Speter 5781Speter #include "whoami.h" 6781Speter #include "0.h" 7781Speter #include "align.h" 8781Speter #ifdef PC 9781Speter # include "pc.h" 10781Speter # include "pcops.h" 11781Speter # include "iorec.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 24*837Speter /* 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 32*837Speter if (!progseen) 33*837Speter level1(); 34*837Speter if ( parts[ cbn ] & RPRT ) { 35*837Speter if ( opt( 's' ) ) { 36781Speter standard(); 37*837Speter } else { 38*837Speter warning(); 39*837Speter } 40*837Speter error("Variable declarations should precede routine declarations"); 41781Speter } 42*837Speter if ( parts[ cbn ] & VPRT ) { 43*837Speter if ( opt( 's' ) ) { 44*837Speter standard(); 45*837Speter } else { 46*837Speter warning(); 47*837Speter } 48*837Speter error("All variables should be declared in one var part"); 49*837Speter } 50*837Speter 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 ); 127781Speter } 128827Speter stabvar( vidl[1] , p2type( np ) , cbn , o2 , w , line ); 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: 205781Speter # ifdef OBJ 206781Speter return ( sizeof ( int * ) ); 207781Speter # endif OBJ 208781Speter # ifdef PC 209781Speter return ( sizeof(struct iorec) 210781Speter + lwidth( p -> type ) ); 211781Speter # endif PC 212781Speter case RANGE: 213781Speter if (p->type == nl+TDOUBLE) 214781Speter #ifdef DEBUG 215781Speter return (hp21mx ? 4 : 8); 216781Speter #else 217781Speter return (8); 218781Speter #endif 219781Speter case SCAL: 220781Speter return (bytes(p->range[0], p->range[1])); 221781Speter case SET: 222781Speter setran(p->type); 223781Speter return roundup( ( set.uprbp >> 3 ) + 1 , A_SET ); 224781Speter case STR: 225781Speter case RECORD: 226781Speter return ( p->value[NL_OFFS] ); 227781Speter default: 228781Speter panic("wclass"); 229781Speter } 230781Speter } 231781Speter 232781Speter /* 233781Speter * round up x to a multiple of y 234781Speter * for computing offsets of aligned things. 235781Speter * y had better be positive. 236781Speter * rounding is in the direction of x. 237781Speter */ 238781Speter long 239781Speter roundup( x , y ) 240781Speter long x; 241781Speter register long y; 242781Speter { 243781Speter 244781Speter if ( y == 0 ) { 245781Speter return 0; 246781Speter } 247781Speter if ( x >= 0 ) { 248781Speter return ( ( ( x + ( y - 1 ) ) / y ) * y ); 249781Speter } else { 250781Speter return ( ( ( x - ( y - 1 ) ) / y ) * y ); 251781Speter } 252781Speter } 253781Speter 254781Speter /* 255781Speter * alignment of an object using the c alignment scheme 256781Speter */ 257781Speter int 258781Speter align( np ) 259781Speter struct nl *np; 260781Speter { 261781Speter register struct nl *p; 262781Speter 263781Speter p = np; 264781Speter if ( p == NIL ) { 265781Speter return 0; 266781Speter } 267781Speter alignit: 268781Speter switch ( p -> class ) { 269781Speter case TYPE: 270781Speter switch ( nloff( p ) ) { 271781Speter case TNIL: 272781Speter return A_POINT; 273781Speter case TSTR: 274781Speter return A_CHAR; 275781Speter case TSET: 276781Speter return A_SET; 277781Speter default: 278781Speter p = p -> type; 279781Speter goto alignit; 280781Speter } 281781Speter case ARRAY: 282781Speter /* 283781Speter * arrays are aligned as their component types 284781Speter */ 285781Speter p = p -> type; 286781Speter goto alignit; 287781Speter case PTR: 288781Speter return A_POINT; 289781Speter case FILET: 290781Speter return A_FILET; 291781Speter case RANGE: 292781Speter if ( p -> type == nl+TDOUBLE ) { 293781Speter return A_DOUBLE; 294781Speter } 295781Speter /* else, fall through */ 296781Speter case SCAL: 297781Speter switch ( bytes( p -> range[0] , p -> range[1] ) ) { 298781Speter case 4: 299781Speter return A_LONG; 300781Speter case 2: 301781Speter return A_SHORT; 302781Speter case 1: 303781Speter return A_CHAR; 304781Speter default: 305781Speter panic( "align: scal" ); 306781Speter } 307781Speter case SET: 308781Speter return A_SET; 309781Speter case STR: 310781Speter return A_CHAR; 311781Speter case RECORD: 312781Speter /* 313781Speter * follow chain through all fields in record, 314781Speter * taking max of alignments of types of fields. 315781Speter * short circuit out if i reach the maximum alignment. 316781Speter * this is pretty likely, as A_MAX is only 4. 317781Speter */ 318781Speter { 319781Speter register long recalign; 320781Speter register long fieldalign; 321781Speter 322781Speter recalign = A_MIN; 323781Speter p = p -> chain; 324781Speter while ( ( p != NIL ) && ( recalign < A_MAX ) ) { 325781Speter fieldalign = align( p -> type ); 326781Speter if ( fieldalign > recalign ) { 327781Speter recalign = fieldalign; 328781Speter } 329781Speter p = p -> chain; 330781Speter } 331781Speter return recalign; 332781Speter } 333781Speter default: 334781Speter panic( "align" ); 335781Speter } 336781Speter } 337781Speter 338781Speter /* 339781Speter * Return the width of an element 340781Speter * of a n time subscripted np. 341781Speter */ 342781Speter long aryconst(np, n) 343781Speter struct nl *np; 344781Speter int n; 345781Speter { 346781Speter register struct nl *p; 347781Speter long s, d; 348781Speter 349781Speter if ((p = np) == NIL) 350781Speter return (NIL); 351781Speter if (p->class != ARRAY) 352781Speter panic("ary"); 353781Speter s = lwidth(p->type); 354781Speter /* 355781Speter * Arrays of anything but characters are word aligned. 356781Speter */ 357781Speter if (s & 1) 358781Speter if (s != 1) 359781Speter s++; 360781Speter /* 361781Speter * Skip the first n subscripts 362781Speter */ 363781Speter while (n >= 0) { 364781Speter p = p->chain; 365781Speter n--; 366781Speter } 367781Speter /* 368781Speter * Sum across remaining subscripts. 369781Speter */ 370781Speter while (p != NIL) { 371781Speter if (p->class != RANGE && p->class != SCAL) 372781Speter panic("aryran"); 373781Speter d = p->range[1] - p->range[0] + 1; 374781Speter s *= d; 375781Speter p = p->chain; 376781Speter } 377781Speter return (s); 378781Speter } 379781Speter 380781Speter /* 381781Speter * Find the lower bound of a set, and also its size in bits. 382781Speter */ 383781Speter setran(q) 384781Speter struct nl *q; 385781Speter { 386781Speter register lb, ub; 387781Speter register struct nl *p; 388781Speter 389781Speter p = q; 390781Speter if (p == NIL) 391781Speter return (NIL); 392781Speter lb = p->range[0]; 393781Speter ub = p->range[1]; 394781Speter if (p->class != RANGE && p->class != SCAL) 395781Speter panic("setran"); 396781Speter set.lwrb = lb; 397781Speter /* set.(upperbound prime) = number of bits - 1; */ 398781Speter set.uprbp = ub-lb; 399781Speter } 400781Speter 401781Speter /* 402781Speter * Return the number of bytes required to hold an arithmetic quantity 403781Speter */ 404781Speter bytes(lb, ub) 405781Speter long lb, ub; 406781Speter { 407781Speter 408781Speter #ifndef DEBUG 409781Speter if (lb < -32768 || ub > 32767) 410781Speter return (4); 411781Speter else if (lb < -128 || ub > 127) 412781Speter return (2); 413781Speter #else 414781Speter if (!hp21mx && (lb < -32768 || ub > 32767)) 415781Speter return (4); 416781Speter if (lb < -128 || ub > 127) 417781Speter return (2); 418781Speter #endif 419781Speter else 420781Speter return (1); 421781Speter } 422