1781Speter /* Copyright (c) 1979 Regents of the University of California */ 2781Speter 3*11336Speter static char sccsid[] = "@(#)var.c 1.15 02/28/83"; 4781Speter 5781Speter #include "whoami.h" 6781Speter #include "0.h" 710664Speter #include "objfmt.h" 8781Speter #include "align.h" 92075Smckusic #include "iorec.h" 10781Speter #ifdef PC 11781Speter # include "pc.h" 12781Speter # include "pcops.h" 13781Speter #endif PC 14*11336Speter #include "tmps.h" 15781Speter 16781Speter /* 17781Speter * Declare variables of a var part. DPOFF1 is 18781Speter * the local variable storage for all prog/proc/func 19781Speter * modules aside from the block mark. The total size 20781Speter * of all the local variables is entered into the 21781Speter * size array. 22781Speter */ 237951Speter varbeg( lineofyvar , r ) 247951Speter int lineofyvar; 25781Speter { 267951Speter static bool var_order = FALSE; 277951Speter static bool var_seen = FALSE; 28781Speter 29837Speter /* this allows for multiple declaration 30781Speter * parts except when the "standard" 31781Speter * option has been specified. 32781Speter * If routine segment is being compiled, 33781Speter * do level one processing. 34781Speter */ 35781Speter 36781Speter #ifndef PI1 37837Speter if (!progseen) 38837Speter level1(); 397951Speter line = lineofyvar; 40837Speter if ( parts[ cbn ] & RPRT ) { 41837Speter if ( opt( 's' ) ) { 42781Speter standard(); 437951Speter error("Variable declarations should precede routine declarations"); 44837Speter } else { 457951Speter if ( !var_order ) { 467951Speter var_order = TRUE; 477951Speter warning(); 487951Speter error("Variable declarations should precede routine declarations"); 497951Speter } 50837Speter } 51781Speter } 52837Speter if ( parts[ cbn ] & VPRT ) { 53837Speter if ( opt( 's' ) ) { 54837Speter standard(); 557951Speter error("All variables should be declared in one var part"); 56837Speter } else { 577951Speter if ( !var_seen ) { 587951Speter var_seen = TRUE; 597951Speter warning(); 607951Speter error("All variables should be declared in one var part"); 617951Speter } 62837Speter } 63837Speter } 64837Speter parts[ cbn ] |= VPRT; 65781Speter #endif 66781Speter /* 67781Speter * #ifndef PI0 683229Smckusic * sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1; 69781Speter * #endif 70781Speter */ 71781Speter forechain = NIL; 72781Speter #ifdef PI0 73781Speter send(REVVBEG); 74781Speter #endif 75781Speter } 76781Speter 77781Speter var(vline, vidl, vtype) 78781Speter #ifdef PI0 79781Speter int vline, *vidl, *vtype; 80781Speter { 81781Speter register struct nl *np; 82781Speter register int *vl; 83781Speter 84781Speter np = gtype(vtype); 85781Speter line = vline; 86781Speter for (vl = vidl; vl != NIL; vl = vl[2]) { 87781Speter } 88781Speter } 89781Speter send(REVVAR, vline, vidl, vtype); 90781Speter } 91781Speter #else 92781Speter int vline; 93781Speter register int *vidl; 94781Speter int *vtype; 95781Speter { 96781Speter register struct nl *np; 97781Speter register struct om *op; 98781Speter long w; 99781Speter int o2; 100781Speter int *ovidl = vidl; 1013836Speter struct nl *vp; 102781Speter 103781Speter np = gtype(vtype); 104781Speter line = vline; 1053949Speter w = lwidth(np); 106781Speter op = &sizes[cbn]; 107781Speter for (; vidl != NIL; vidl = vidl[2]) { 108781Speter # ifdef OBJ 1093235Smckusic op->curtmps.om_off = 1103235Smckusic roundup((int)(op->curtmps.om_off-w), (long)align(np)); 1113235Smckusic o2 = op -> curtmps.om_off; 112781Speter # endif OBJ 113781Speter # ifdef PC 114781Speter if ( cbn == 1 ) { 115781Speter /* 116781Speter * global variables are not accessed off the fp 117781Speter * but rather by their names. 118781Speter */ 119781Speter o2 = 0; 120781Speter } else { 121781Speter /* 122781Speter * locals are aligned, too. 123781Speter */ 1243229Smckusic op->curtmps.om_off = 1253229Smckusic roundup((int)(op->curtmps.om_off - w), 1263082Smckusic (long)align(np)); 1273229Smckusic o2 = op -> curtmps.om_off; 128781Speter } 129781Speter # endif PC 1303836Speter vp = enter(defnl(vidl[1], VAR, np, o2)); 131781Speter if ( np -> nl_flags & NFILES ) { 132781Speter dfiles[ cbn ] = TRUE; 133781Speter } 134781Speter # ifdef PC 135781Speter if ( cbn == 1 ) { 136781Speter putprintf( " .data" , 0 ); 13710664Speter aligndot(align(np)); 138781Speter putprintf( " .comm " , 1 ); 139781Speter putprintf( EXTFORMAT , 1 , vidl[1] ); 140781Speter putprintf( ",%d" , 0 , w ); 141781Speter putprintf( " .text" , 0 ); 1422165Speter stabgvar( vidl[1] , p2type( np ) , o2 , w , line ); 1433836Speter vp -> extra_flags |= NGLOBAL; 1443836Speter } else { 1453836Speter vp -> extra_flags |= NLOCAL; 146781Speter } 147781Speter # endif PC 148781Speter } 149781Speter # ifdef PTREE 150781Speter { 151781Speter pPointer *Vars; 152781Speter pPointer Var = VarDecl( ovidl , vtype ); 153781Speter 154781Speter pSeize( PorFHeader[ nesting ] ); 155781Speter Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars ); 156781Speter *Vars = ListAppend( *Vars , Var ); 157781Speter pRelease( PorFHeader[ nesting ] ); 158781Speter } 159781Speter # endif 160781Speter } 161781Speter #endif 162781Speter 163781Speter varend() 164781Speter { 165781Speter 166781Speter foredecl(); 167781Speter #ifndef PI0 1683229Smckusic sizes[cbn].om_max = sizes[cbn].curtmps.om_off; 169781Speter #else 170781Speter send(REVVEND); 171781Speter #endif 172781Speter } 173781Speter 174781Speter /* 175781Speter * Evening 176781Speter */ 1773082Smckusic long 1783082Smckusic leven(w) 1793082Smckusic register long w; 1803082Smckusic { 1813082Smckusic if (w < 0) 1823082Smckusic return (w & 0xfffffffe); 1833082Smckusic return ((w+1) & 0xfffffffe); 1843082Smckusic } 1853082Smckusic 1863082Smckusic int 187781Speter even(w) 188781Speter register int w; 189781Speter { 1903082Smckusic return leven((long)w); 191781Speter } 192781Speter 193781Speter /* 194781Speter * Find the width of a type in bytes. 195781Speter */ 196781Speter width(np) 197781Speter struct nl *np; 198781Speter { 199781Speter 200781Speter return (lwidth(np)); 201781Speter } 202781Speter 203781Speter long 204781Speter lwidth(np) 205781Speter struct nl *np; 206781Speter { 207781Speter register struct nl *p; 208781Speter long w; 209781Speter 210781Speter p = np; 211781Speter if (p == NIL) 212781Speter return (0); 213781Speter loop: 214781Speter switch (p->class) { 215781Speter case TYPE: 216781Speter switch (nloff(p)) { 217781Speter case TNIL: 218781Speter return (2); 219781Speter case TSTR: 220781Speter case TSET: 221781Speter panic("width"); 222781Speter default: 223781Speter p = p->type; 224781Speter goto loop; 225781Speter } 226781Speter case ARRAY: 227781Speter return (aryconst(p, 0)); 228781Speter case PTR: 229781Speter return ( sizeof ( int * ) ); 230781Speter case FILET: 2312075Smckusic return ( sizeof(struct iorec) + lwidth( p -> type ) ); 232781Speter case RANGE: 233781Speter if (p->type == nl+TDOUBLE) 234781Speter #ifdef DEBUG 235781Speter return (hp21mx ? 4 : 8); 236781Speter #else 237781Speter return (8); 238781Speter #endif 239781Speter case SCAL: 240781Speter return (bytes(p->range[0], p->range[1])); 241781Speter case SET: 242781Speter setran(p->type); 2433082Smckusic return roundup((int)((set.uprbp >> 3) + 1), 2443082Smckusic (long)(A_SET)); 245781Speter case STR: 246781Speter case RECORD: 247781Speter return ( p->value[NL_OFFS] ); 248781Speter default: 249781Speter panic("wclass"); 250781Speter } 251781Speter } 252781Speter 253781Speter /* 254781Speter * round up x to a multiple of y 255781Speter * for computing offsets of aligned things. 256781Speter * y had better be positive. 257781Speter * rounding is in the direction of x. 258781Speter */ 259781Speter long 260781Speter roundup( x , y ) 2613082Smckusic int x; 262781Speter register long y; 263781Speter { 264781Speter 265781Speter if ( y == 0 ) { 2664030Smckusic return x; 267781Speter } 268781Speter if ( x >= 0 ) { 269781Speter return ( ( ( x + ( y - 1 ) ) / y ) * y ); 270781Speter } else { 271781Speter return ( ( ( x - ( y - 1 ) ) / y ) * y ); 272781Speter } 273781Speter } 274781Speter 275781Speter /* 276781Speter * alignment of an object using the c alignment scheme 277781Speter */ 278781Speter int 279781Speter align( np ) 280781Speter struct nl *np; 281781Speter { 282781Speter register struct nl *p; 283781Speter 284781Speter p = np; 285781Speter if ( p == NIL ) { 286781Speter return 0; 287781Speter } 288781Speter alignit: 289781Speter switch ( p -> class ) { 290781Speter case TYPE: 291781Speter switch ( nloff( p ) ) { 292781Speter case TNIL: 293781Speter return A_POINT; 294781Speter case TSTR: 29510664Speter return A_STRUCT; 296781Speter case TSET: 297781Speter return A_SET; 298781Speter default: 299781Speter p = p -> type; 300781Speter goto alignit; 301781Speter } 302781Speter case ARRAY: 303781Speter /* 30410664Speter * strings are structures, since they can get 30510664Speter * assigned form/to as structure assignments. 30610664Speter * other arrays are aligned as their component types 307781Speter */ 30810664Speter if ( p -> type == nl+T1CHAR ) { 30910664Speter return A_STRUCT; 31010664Speter } 311781Speter p = p -> type; 312781Speter goto alignit; 313781Speter case PTR: 314781Speter return A_POINT; 315781Speter case FILET: 316781Speter return A_FILET; 317781Speter case RANGE: 318781Speter if ( p -> type == nl+TDOUBLE ) { 319781Speter return A_DOUBLE; 320781Speter } 321781Speter /* else, fall through */ 322781Speter case SCAL: 323781Speter switch ( bytes( p -> range[0] , p -> range[1] ) ) { 324781Speter case 4: 325781Speter return A_LONG; 326781Speter case 2: 327781Speter return A_SHORT; 328781Speter case 1: 329781Speter return A_CHAR; 330781Speter default: 331781Speter panic( "align: scal" ); 332781Speter } 333781Speter case SET: 334781Speter return A_SET; 335781Speter case STR: 33610664Speter /* 33710664Speter * arrays of chars are structs 33810664Speter */ 33910664Speter return A_STRUCT; 340781Speter case RECORD: 341781Speter /* 3428681Speter * the alignment of a record is in its align_info field 3438681Speter * why don't we use this for the rest of the namelist? 344781Speter */ 3458681Speter return p -> align_info; 346781Speter default: 347781Speter panic( "align" ); 348781Speter } 349781Speter } 350781Speter 35110664Speter #ifdef PC 3523949Speter /* 35310664Speter * output an alignment pseudo-op. 3543949Speter */ 35510664Speter aligndot(alignment) 3563949Speter int alignment; 35710664Speter #ifdef vax 3583949Speter { 35910664Speter switch (alignment) { 36010664Speter case 1: 36110664Speter return; 36210664Speter case 2: 36310664Speter putprintf(" .align 1", 0); 36410664Speter return; 36510664Speter default: 36610664Speter case 4: 36710664Speter putprintf(" .align 2", 0); 36810664Speter return; 3693949Speter } 3703949Speter } 37110664Speter #endif vax 37210664Speter #ifdef mc68000 37310664Speter { 37410664Speter switch (alignment) { 37510664Speter case 1: 37610664Speter return; 37710664Speter default: 37810664Speter putprintf(" .even", 0); 37910664Speter return; 38010664Speter } 38110664Speter } 38210664Speter #endif mc68000 38310664Speter #endif PC 38410664Speter 385781Speter /* 386781Speter * Return the width of an element 387781Speter * of a n time subscripted np. 388781Speter */ 389781Speter long aryconst(np, n) 390781Speter struct nl *np; 391781Speter int n; 392781Speter { 393781Speter register struct nl *p; 394781Speter long s, d; 395781Speter 396781Speter if ((p = np) == NIL) 397781Speter return (NIL); 398781Speter if (p->class != ARRAY) 399781Speter panic("ary"); 400781Speter s = lwidth(p->type); 401781Speter /* 402781Speter * Arrays of anything but characters are word aligned. 403781Speter */ 404781Speter if (s & 1) 405781Speter if (s != 1) 406781Speter s++; 407781Speter /* 408781Speter * Skip the first n subscripts 409781Speter */ 410781Speter while (n >= 0) { 411781Speter p = p->chain; 412781Speter n--; 413781Speter } 414781Speter /* 415781Speter * Sum across remaining subscripts. 416781Speter */ 417781Speter while (p != NIL) { 418781Speter if (p->class != RANGE && p->class != SCAL) 419781Speter panic("aryran"); 420781Speter d = p->range[1] - p->range[0] + 1; 421781Speter s *= d; 422781Speter p = p->chain; 423781Speter } 424781Speter return (s); 425781Speter } 426781Speter 427781Speter /* 428781Speter * Find the lower bound of a set, and also its size in bits. 429781Speter */ 430781Speter setran(q) 431781Speter struct nl *q; 432781Speter { 433781Speter register lb, ub; 434781Speter register struct nl *p; 435781Speter 436781Speter p = q; 437781Speter if (p == NIL) 438781Speter return (NIL); 439781Speter lb = p->range[0]; 440781Speter ub = p->range[1]; 441781Speter if (p->class != RANGE && p->class != SCAL) 442781Speter panic("setran"); 443781Speter set.lwrb = lb; 444781Speter /* set.(upperbound prime) = number of bits - 1; */ 445781Speter set.uprbp = ub-lb; 446781Speter } 447781Speter 448781Speter /* 449781Speter * Return the number of bytes required to hold an arithmetic quantity 450781Speter */ 451781Speter bytes(lb, ub) 452781Speter long lb, ub; 453781Speter { 454781Speter 455781Speter #ifndef DEBUG 456781Speter if (lb < -32768 || ub > 32767) 457781Speter return (4); 458781Speter else if (lb < -128 || ub > 127) 459781Speter return (2); 460781Speter #else 461781Speter if (!hp21mx && (lb < -32768 || ub > 32767)) 462781Speter return (4); 463781Speter if (lb < -128 || ub > 127) 464781Speter return (2); 465781Speter #endif 466781Speter else 467781Speter return (1); 468781Speter } 469