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