1*781Speter /* Copyright (c) 1979 Regents of the University of California */ 2*781Speter 3*781Speter static char sccsid[] = "@(#)var.c 1.1 08/27/80"; 4*781Speter 5*781Speter #include "whoami.h" 6*781Speter #include "0.h" 7*781Speter #include "align.h" 8*781Speter #ifdef PC 9*781Speter # include "pc.h" 10*781Speter # include "pcops.h" 11*781Speter # include "iorec.h" 12*781Speter #endif PC 13*781Speter 14*781Speter /* 15*781Speter * Declare variables of a var part. DPOFF1 is 16*781Speter * the local variable storage for all prog/proc/func 17*781Speter * modules aside from the block mark. The total size 18*781Speter * of all the local variables is entered into the 19*781Speter * size array. 20*781Speter */ 21*781Speter varbeg() 22*781Speter { 23*781Speter 24*781Speter /* PC allows for multiple declaration 25*781Speter * parts except when the "standard" 26*781Speter * option has been specified. 27*781Speter * If routine segment is being compiled, 28*781Speter * do level one processing. 29*781Speter */ 30*781Speter 31*781Speter #ifndef PI1 32*781Speter if (!progseen) 33*781Speter level1(); 34*781Speter #ifdef PC 35*781Speter if (opt('s')) { 36*781Speter if (parts & VPRT){ 37*781Speter standard(); 38*781Speter error("All variables must be declared in one var part"); 39*781Speter } 40*781Speter } 41*781Speter #else 42*781Speter if (parts & VPRT) 43*781Speter error("All variables must be declared in one var part"); 44*781Speter #endif PC 45*781Speter 46*781Speter parts |= VPRT; 47*781Speter #endif 48*781Speter /* 49*781Speter * #ifndef PI0 50*781Speter * sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 51*781Speter * #endif 52*781Speter */ 53*781Speter forechain = NIL; 54*781Speter #ifdef PI0 55*781Speter send(REVVBEG); 56*781Speter #endif 57*781Speter } 58*781Speter 59*781Speter var(vline, vidl, vtype) 60*781Speter #ifdef PI0 61*781Speter int vline, *vidl, *vtype; 62*781Speter { 63*781Speter register struct nl *np; 64*781Speter register int *vl; 65*781Speter 66*781Speter np = gtype(vtype); 67*781Speter line = vline; 68*781Speter for (vl = vidl; vl != NIL; vl = vl[2]) { 69*781Speter } 70*781Speter } 71*781Speter send(REVVAR, vline, vidl, vtype); 72*781Speter } 73*781Speter #else 74*781Speter int vline; 75*781Speter register int *vidl; 76*781Speter int *vtype; 77*781Speter { 78*781Speter register struct nl *np; 79*781Speter register struct om *op; 80*781Speter long w; 81*781Speter int o2; 82*781Speter int *ovidl = vidl; 83*781Speter 84*781Speter np = gtype(vtype); 85*781Speter line = vline; 86*781Speter /* 87*781Speter * widths are evened out 88*781Speter */ 89*781Speter w = (lwidth(np) + 1) &~ 1; 90*781Speter op = &sizes[cbn]; 91*781Speter for (; vidl != NIL; vidl = vidl[2]) { 92*781Speter # ifdef OBJ 93*781Speter op -> om_off = roundup( op -> om_off - w , align( np ) ); 94*781Speter o2 = op -> om_off; 95*781Speter # endif OBJ 96*781Speter # ifdef PC 97*781Speter if ( cbn == 1 ) { 98*781Speter /* 99*781Speter * global variables are not accessed off the fp 100*781Speter * but rather by their names. 101*781Speter */ 102*781Speter o2 = 0; 103*781Speter } else { 104*781Speter /* 105*781Speter * locals are aligned, too. 106*781Speter */ 107*781Speter op -> om_off = roundup( op -> om_off - w 108*781Speter , align( np ) ); 109*781Speter o2 = op -> om_off; 110*781Speter } 111*781Speter # endif PC 112*781Speter enter(defnl(vidl[1], VAR, np, o2)); 113*781Speter if ( np -> nl_flags & NFILES ) { 114*781Speter dfiles[ cbn ] = TRUE; 115*781Speter } 116*781Speter # ifdef PC 117*781Speter if ( cbn == 1 ) { 118*781Speter putprintf( " .data" , 0 ); 119*781Speter putprintf( " .comm " , 1 ); 120*781Speter putprintf( EXTFORMAT , 1 , vidl[1] ); 121*781Speter putprintf( ",%d" , 0 , w ); 122*781Speter putprintf( " .text" , 0 ); 123*781Speter } 124*781Speter stabvar( vidl[1] , p2type( np ) , cbn , o2 , w ); 125*781Speter # endif PC 126*781Speter } 127*781Speter # ifdef PTREE 128*781Speter { 129*781Speter pPointer *Vars; 130*781Speter pPointer Var = VarDecl( ovidl , vtype ); 131*781Speter 132*781Speter pSeize( PorFHeader[ nesting ] ); 133*781Speter Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars ); 134*781Speter *Vars = ListAppend( *Vars , Var ); 135*781Speter pRelease( PorFHeader[ nesting ] ); 136*781Speter } 137*781Speter # endif 138*781Speter } 139*781Speter #endif 140*781Speter 141*781Speter varend() 142*781Speter { 143*781Speter 144*781Speter foredecl(); 145*781Speter #ifndef PI0 146*781Speter sizes[cbn].om_max = sizes[cbn].om_off; 147*781Speter #else 148*781Speter send(REVVEND); 149*781Speter #endif 150*781Speter } 151*781Speter 152*781Speter /* 153*781Speter * Evening 154*781Speter */ 155*781Speter even(w) 156*781Speter register int w; 157*781Speter { 158*781Speter if (w < 0) 159*781Speter return (w & ~1); 160*781Speter return ((w+1) & ~1); 161*781Speter } 162*781Speter 163*781Speter /* 164*781Speter * Find the width of a type in bytes. 165*781Speter */ 166*781Speter width(np) 167*781Speter struct nl *np; 168*781Speter { 169*781Speter 170*781Speter return (lwidth(np)); 171*781Speter } 172*781Speter 173*781Speter long 174*781Speter lwidth(np) 175*781Speter struct nl *np; 176*781Speter { 177*781Speter register struct nl *p; 178*781Speter long w; 179*781Speter 180*781Speter p = np; 181*781Speter if (p == NIL) 182*781Speter return (0); 183*781Speter loop: 184*781Speter switch (p->class) { 185*781Speter case TYPE: 186*781Speter switch (nloff(p)) { 187*781Speter case TNIL: 188*781Speter return (2); 189*781Speter case TSTR: 190*781Speter case TSET: 191*781Speter panic("width"); 192*781Speter default: 193*781Speter p = p->type; 194*781Speter goto loop; 195*781Speter } 196*781Speter case ARRAY: 197*781Speter return (aryconst(p, 0)); 198*781Speter case PTR: 199*781Speter return ( sizeof ( int * ) ); 200*781Speter case FILET: 201*781Speter # ifdef OBJ 202*781Speter return ( sizeof ( int * ) ); 203*781Speter # endif OBJ 204*781Speter # ifdef PC 205*781Speter return ( sizeof(struct iorec) 206*781Speter + lwidth( p -> type ) ); 207*781Speter # endif PC 208*781Speter case RANGE: 209*781Speter if (p->type == nl+TDOUBLE) 210*781Speter #ifdef DEBUG 211*781Speter return (hp21mx ? 4 : 8); 212*781Speter #else 213*781Speter return (8); 214*781Speter #endif 215*781Speter case SCAL: 216*781Speter return (bytes(p->range[0], p->range[1])); 217*781Speter case SET: 218*781Speter setran(p->type); 219*781Speter return roundup( ( set.uprbp >> 3 ) + 1 , A_SET ); 220*781Speter case STR: 221*781Speter case RECORD: 222*781Speter return ( p->value[NL_OFFS] ); 223*781Speter default: 224*781Speter panic("wclass"); 225*781Speter } 226*781Speter } 227*781Speter 228*781Speter /* 229*781Speter * round up x to a multiple of y 230*781Speter * for computing offsets of aligned things. 231*781Speter * y had better be positive. 232*781Speter * rounding is in the direction of x. 233*781Speter */ 234*781Speter long 235*781Speter roundup( x , y ) 236*781Speter long x; 237*781Speter register long y; 238*781Speter { 239*781Speter 240*781Speter if ( y == 0 ) { 241*781Speter return 0; 242*781Speter } 243*781Speter if ( x >= 0 ) { 244*781Speter return ( ( ( x + ( y - 1 ) ) / y ) * y ); 245*781Speter } else { 246*781Speter return ( ( ( x - ( y - 1 ) ) / y ) * y ); 247*781Speter } 248*781Speter } 249*781Speter 250*781Speter /* 251*781Speter * alignment of an object using the c alignment scheme 252*781Speter */ 253*781Speter int 254*781Speter align( np ) 255*781Speter struct nl *np; 256*781Speter { 257*781Speter register struct nl *p; 258*781Speter 259*781Speter p = np; 260*781Speter if ( p == NIL ) { 261*781Speter return 0; 262*781Speter } 263*781Speter alignit: 264*781Speter switch ( p -> class ) { 265*781Speter case TYPE: 266*781Speter switch ( nloff( p ) ) { 267*781Speter case TNIL: 268*781Speter return A_POINT; 269*781Speter case TSTR: 270*781Speter return A_CHAR; 271*781Speter case TSET: 272*781Speter return A_SET; 273*781Speter default: 274*781Speter p = p -> type; 275*781Speter goto alignit; 276*781Speter } 277*781Speter case ARRAY: 278*781Speter /* 279*781Speter * arrays are aligned as their component types 280*781Speter */ 281*781Speter p = p -> type; 282*781Speter goto alignit; 283*781Speter case PTR: 284*781Speter return A_POINT; 285*781Speter case FILET: 286*781Speter return A_FILET; 287*781Speter case RANGE: 288*781Speter if ( p -> type == nl+TDOUBLE ) { 289*781Speter return A_DOUBLE; 290*781Speter } 291*781Speter /* else, fall through */ 292*781Speter case SCAL: 293*781Speter switch ( bytes( p -> range[0] , p -> range[1] ) ) { 294*781Speter case 4: 295*781Speter return A_LONG; 296*781Speter case 2: 297*781Speter return A_SHORT; 298*781Speter case 1: 299*781Speter return A_CHAR; 300*781Speter default: 301*781Speter panic( "align: scal" ); 302*781Speter } 303*781Speter case SET: 304*781Speter return A_SET; 305*781Speter case STR: 306*781Speter return A_CHAR; 307*781Speter case RECORD: 308*781Speter /* 309*781Speter * follow chain through all fields in record, 310*781Speter * taking max of alignments of types of fields. 311*781Speter * short circuit out if i reach the maximum alignment. 312*781Speter * this is pretty likely, as A_MAX is only 4. 313*781Speter */ 314*781Speter { 315*781Speter register long recalign; 316*781Speter register long fieldalign; 317*781Speter 318*781Speter recalign = A_MIN; 319*781Speter p = p -> chain; 320*781Speter while ( ( p != NIL ) && ( recalign < A_MAX ) ) { 321*781Speter fieldalign = align( p -> type ); 322*781Speter if ( fieldalign > recalign ) { 323*781Speter recalign = fieldalign; 324*781Speter } 325*781Speter p = p -> chain; 326*781Speter } 327*781Speter return recalign; 328*781Speter } 329*781Speter default: 330*781Speter panic( "align" ); 331*781Speter } 332*781Speter } 333*781Speter 334*781Speter /* 335*781Speter * Return the width of an element 336*781Speter * of a n time subscripted np. 337*781Speter */ 338*781Speter long aryconst(np, n) 339*781Speter struct nl *np; 340*781Speter int n; 341*781Speter { 342*781Speter register struct nl *p; 343*781Speter long s, d; 344*781Speter 345*781Speter if ((p = np) == NIL) 346*781Speter return (NIL); 347*781Speter if (p->class != ARRAY) 348*781Speter panic("ary"); 349*781Speter s = lwidth(p->type); 350*781Speter /* 351*781Speter * Arrays of anything but characters are word aligned. 352*781Speter */ 353*781Speter if (s & 1) 354*781Speter if (s != 1) 355*781Speter s++; 356*781Speter /* 357*781Speter * Skip the first n subscripts 358*781Speter */ 359*781Speter while (n >= 0) { 360*781Speter p = p->chain; 361*781Speter n--; 362*781Speter } 363*781Speter /* 364*781Speter * Sum across remaining subscripts. 365*781Speter */ 366*781Speter while (p != NIL) { 367*781Speter if (p->class != RANGE && p->class != SCAL) 368*781Speter panic("aryran"); 369*781Speter d = p->range[1] - p->range[0] + 1; 370*781Speter s *= d; 371*781Speter p = p->chain; 372*781Speter } 373*781Speter return (s); 374*781Speter } 375*781Speter 376*781Speter /* 377*781Speter * Find the lower bound of a set, and also its size in bits. 378*781Speter */ 379*781Speter setran(q) 380*781Speter struct nl *q; 381*781Speter { 382*781Speter register lb, ub; 383*781Speter register struct nl *p; 384*781Speter 385*781Speter p = q; 386*781Speter if (p == NIL) 387*781Speter return (NIL); 388*781Speter lb = p->range[0]; 389*781Speter ub = p->range[1]; 390*781Speter if (p->class != RANGE && p->class != SCAL) 391*781Speter panic("setran"); 392*781Speter set.lwrb = lb; 393*781Speter /* set.(upperbound prime) = number of bits - 1; */ 394*781Speter set.uprbp = ub-lb; 395*781Speter } 396*781Speter 397*781Speter /* 398*781Speter * Return the number of bytes required to hold an arithmetic quantity 399*781Speter */ 400*781Speter bytes(lb, ub) 401*781Speter long lb, ub; 402*781Speter { 403*781Speter 404*781Speter #ifndef DEBUG 405*781Speter if (lb < -32768 || ub > 32767) 406*781Speter return (4); 407*781Speter else if (lb < -128 || ub > 127) 408*781Speter return (2); 409*781Speter #else 410*781Speter if (!hp21mx && (lb < -32768 || ub > 32767)) 411*781Speter return (4); 412*781Speter if (lb < -128 || ub > 127) 413*781Speter return (2); 414*781Speter #endif 415*781Speter else 416*781Speter return (1); 417*781Speter } 418