1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 622201Sdist */ 7781Speter 818351Smckusick #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)var.c 5.5 (Berkeley) 04/16/91"; 10*48116Sbostic #endif /* not lint */ 11781Speter 12781Speter #include "whoami.h" 13781Speter #include "0.h" 1410664Speter #include "objfmt.h" 15781Speter #include "align.h" 162075Smckusic #include "iorec.h" 17781Speter #ifdef PC 18781Speter # include "pc.h" 19781Speter #endif PC 2011336Speter #include "tmps.h" 2118351Smckusick #include "tree_ty.h" 22781Speter 23781Speter /* 24781Speter * Declare variables of a var part. DPOFF1 is 25781Speter * the local variable storage for all prog/proc/func 26781Speter * modules aside from the block mark. The total size 27781Speter * of all the local variables is entered into the 28781Speter * size array. 29781Speter */ 3018351Smckusick /*ARGSUSED*/ 317951Speter varbeg( lineofyvar , r ) 327951Speter int lineofyvar; 33781Speter { 347951Speter static bool var_order = FALSE; 357951Speter static bool var_seen = FALSE; 36781Speter 37837Speter /* this allows for multiple declaration 38781Speter * parts except when the "standard" 39781Speter * option has been specified. 40781Speter * If routine segment is being compiled, 41781Speter * do level one processing. 42781Speter */ 43781Speter 44781Speter #ifndef PI1 45837Speter if (!progseen) 46837Speter level1(); 477951Speter line = lineofyvar; 48837Speter if ( parts[ cbn ] & RPRT ) { 49837Speter if ( opt( 's' ) ) { 50781Speter standard(); 517951Speter error("Variable declarations should precede routine declarations"); 52837Speter } else { 537951Speter if ( !var_order ) { 547951Speter var_order = TRUE; 557951Speter warning(); 567951Speter error("Variable declarations should precede routine declarations"); 577951Speter } 58837Speter } 59781Speter } 60837Speter if ( parts[ cbn ] & VPRT ) { 61837Speter if ( opt( 's' ) ) { 62837Speter standard(); 637951Speter error("All variables should be declared in one var part"); 64837Speter } else { 657951Speter if ( !var_seen ) { 667951Speter var_seen = TRUE; 677951Speter warning(); 687951Speter error("All variables should be declared in one var part"); 697951Speter } 70837Speter } 71837Speter } 72837Speter parts[ cbn ] |= VPRT; 73781Speter #endif 74781Speter /* 75781Speter * #ifndef PI0 763229Smckusic * sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1; 77781Speter * #endif 78781Speter */ 79781Speter forechain = NIL; 80781Speter #ifdef PI0 81781Speter send(REVVBEG); 82781Speter #endif 83781Speter } 84781Speter 85781Speter var(vline, vidl, vtype) 86781Speter #ifdef PI0 8718351Smckusick int vline; 8818351Smckusick struct tnode *vidl, *vtype; 89781Speter { 90781Speter register struct nl *np; 9118351Smckusick register struct tnode *vl; 92781Speter 93781Speter np = gtype(vtype); 94781Speter line = vline; 9518351Smckusick /* why is this here? */ 9618351Smckusick for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) { 97781Speter } 98781Speter } 99781Speter send(REVVAR, vline, vidl, vtype); 100781Speter } 101781Speter #else 102781Speter int vline; 10318351Smckusick register struct tnode *vidl; 10418351Smckusick struct tnode *vtype; 105781Speter { 106781Speter register struct nl *np; 107781Speter register struct om *op; 108781Speter long w; 109781Speter int o2; 11018351Smckusick #ifdef PC 1113836Speter struct nl *vp; 11218351Smckusick #endif 113781Speter 114781Speter np = gtype(vtype); 115781Speter line = vline; 1163949Speter w = lwidth(np); 117781Speter op = &sizes[cbn]; 11818351Smckusick for (; vidl != TR_NIL; vidl = vidl->list_node.next) { 119781Speter # ifdef OBJ 1203235Smckusic op->curtmps.om_off = 1213235Smckusic roundup((int)(op->curtmps.om_off-w), (long)align(np)); 1223235Smckusic o2 = op -> curtmps.om_off; 123781Speter # endif OBJ 124781Speter # ifdef PC 125781Speter if ( cbn == 1 ) { 126781Speter /* 127781Speter * global variables are not accessed off the fp 128781Speter * but rather by their names. 129781Speter */ 130781Speter o2 = 0; 131781Speter } else { 132781Speter /* 133781Speter * locals are aligned, too. 134781Speter */ 1353229Smckusic op->curtmps.om_off = 1363229Smckusic roundup((int)(op->curtmps.om_off - w), 1373082Smckusic (long)align(np)); 1383229Smckusic o2 = op -> curtmps.om_off; 139781Speter } 140781Speter # endif PC 14118351Smckusick # ifdef PC 14218351Smckusick vp = enter(defnl((char *) vidl->list_node.list, VAR, np, o2)); 14318351Smckusick # else 14418351Smckusick (void) enter(defnl((char *) vidl->list_node.list, VAR, np, o2)); 14518351Smckusick # endif 14624053Smckusick if ( np != NLNIL && (np -> nl_flags & NFILES) ) { 147781Speter dfiles[ cbn ] = TRUE; 148781Speter } 149781Speter # ifdef PC 150781Speter if ( cbn == 1 ) { 151781Speter putprintf( " .data" , 0 ); 15210664Speter aligndot(align(np)); 153781Speter putprintf( " .comm " , 1 ); 15418351Smckusick putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list ); 15518351Smckusick putprintf( ",%d" , 0 , (int) w ); 156781Speter putprintf( " .text" , 0 ); 15718351Smckusick stabgvar( vp , w , line ); 1583836Speter vp -> extra_flags |= NGLOBAL; 1593836Speter } else { 1603836Speter vp -> extra_flags |= NLOCAL; 161781Speter } 162781Speter # endif PC 163781Speter } 164781Speter # ifdef PTREE 165781Speter { 166781Speter pPointer *Vars; 167781Speter pPointer Var = VarDecl( ovidl , vtype ); 168781Speter 169781Speter pSeize( PorFHeader[ nesting ] ); 170781Speter Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars ); 171781Speter *Vars = ListAppend( *Vars , Var ); 172781Speter pRelease( PorFHeader[ nesting ] ); 173781Speter } 174781Speter # endif 175781Speter } 176781Speter #endif 177781Speter 178781Speter varend() 179781Speter { 180781Speter 181781Speter foredecl(); 182781Speter #ifndef PI0 1833229Smckusic sizes[cbn].om_max = sizes[cbn].curtmps.om_off; 184781Speter #else 185781Speter send(REVVEND); 186781Speter #endif 187781Speter } 188781Speter 189781Speter /* 190781Speter * Find the width of a type in bytes. 191781Speter */ 192781Speter width(np) 193781Speter struct nl *np; 194781Speter { 195781Speter 196781Speter return (lwidth(np)); 197781Speter } 198781Speter 199781Speter long 200781Speter lwidth(np) 201781Speter struct nl *np; 202781Speter { 203781Speter register struct nl *p; 204781Speter 205781Speter p = np; 206781Speter if (p == NIL) 207781Speter return (0); 208781Speter loop: 209781Speter switch (p->class) { 21018351Smckusick default: 21118351Smckusick panic("wclass"); 212781Speter case TYPE: 213781Speter switch (nloff(p)) { 214781Speter case TNIL: 215781Speter return (2); 216781Speter case TSTR: 217781Speter case TSET: 218781Speter panic("width"); 219781Speter default: 220781Speter p = p->type; 221781Speter goto loop; 222781Speter } 223781Speter case ARRAY: 224781Speter return (aryconst(p, 0)); 225781Speter case PTR: 226781Speter return ( sizeof ( int * ) ); 227781Speter case FILET: 2282075Smckusic return ( sizeof(struct iorec) + lwidth( p -> type ) ); 22918351Smckusick case CRANGE: 23018351Smckusick p = p->type; 23118351Smckusick goto loop; 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); 24311822Smckusick /* 24411822Smckusick * Sets are some multiple of longs 24511822Smckusick */ 2463082Smckusic return roundup((int)((set.uprbp >> 3) + 1), 24711822Smckusick (long)(sizeof(long))); 248781Speter case STR: 249781Speter case RECORD: 250781Speter return ( p->value[NL_OFFS] ); 251781Speter } 252781Speter } 253781Speter 254781Speter /* 255781Speter * round up x to a multiple of y 256781Speter * for computing offsets of aligned things. 257781Speter * y had better be positive. 258781Speter * rounding is in the direction of x. 259781Speter */ 260781Speter long 261781Speter roundup( x , y ) 2623082Smckusic int x; 263781Speter register long y; 264781Speter { 265781Speter 266781Speter if ( y == 0 ) { 2674030Smckusic return x; 268781Speter } 269781Speter if ( x >= 0 ) { 270781Speter return ( ( ( x + ( y - 1 ) ) / y ) * y ); 271781Speter } else { 272781Speter return ( ( ( x - ( y - 1 ) ) / y ) * y ); 273781Speter } 274781Speter } 275781Speter 276781Speter /* 277781Speter * alignment of an object using the c alignment scheme 278781Speter */ 279781Speter int 280781Speter align( np ) 281781Speter struct nl *np; 282781Speter { 283781Speter register struct nl *p; 28411822Smckusick long elementalign; 285781Speter 286781Speter p = np; 287781Speter if ( p == NIL ) { 288781Speter return 0; 289781Speter } 290781Speter alignit: 291781Speter switch ( p -> class ) { 29218351Smckusick default: 29318351Smckusick panic( "align" ); 294781Speter case TYPE: 295781Speter switch ( nloff( p ) ) { 296781Speter case TNIL: 297781Speter return A_POINT; 298781Speter case TSTR: 29910664Speter return A_STRUCT; 300781Speter case TSET: 301781Speter return A_SET; 302781Speter default: 303781Speter p = p -> type; 304781Speter goto alignit; 305781Speter } 306781Speter case ARRAY: 307781Speter /* 30811822Smckusick * arrays are structures, since they can get 30910664Speter * assigned form/to as structure assignments. 31011822Smckusick * preserve internal alignment if it is greater. 311781Speter */ 31211822Smckusick elementalign = align(p -> type); 31311822Smckusick return elementalign > A_STRUCT ? elementalign : A_STRUCT; 314781Speter case PTR: 315781Speter return A_POINT; 316781Speter case FILET: 317781Speter return A_FILET; 31818351Smckusick case CRANGE: 319781Speter case RANGE: 320781Speter if ( p -> type == nl+TDOUBLE ) { 321781Speter return A_DOUBLE; 322781Speter } 323781Speter /* else, fall through */ 324781Speter case SCAL: 325781Speter switch ( bytes( p -> range[0] , p -> range[1] ) ) { 326781Speter case 4: 327781Speter return A_LONG; 328781Speter case 2: 329781Speter return A_SHORT; 330781Speter case 1: 331781Speter return A_CHAR; 332781Speter default: 333781Speter panic( "align: scal" ); 334781Speter } 335781Speter case SET: 336781Speter return A_SET; 337781Speter case STR: 33810664Speter /* 33910664Speter * arrays of chars are structs 34010664Speter */ 34110664Speter return A_STRUCT; 342781Speter case RECORD: 343781Speter /* 3448681Speter * the alignment of a record is in its align_info field 3458681Speter * why don't we use this for the rest of the namelist? 346781Speter */ 3478681Speter return p -> align_info; 348781Speter } 349781Speter } 350781Speter 35110664Speter #ifdef PC 3523949Speter /* 35310664Speter * output an alignment pseudo-op. 3543949Speter */ 35510664Speter aligndot(alignment) 3563949Speter int alignment; 35730038Smckusick #if defined(vax) || defined(tahoe) 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 } 37130038Smckusick #endif vax || tahoe 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"); 40018351Smckusick /* 40118351Smckusick * If it is a conformant array, we cannot find the width from 40218351Smckusick * the type. 40318351Smckusick */ 40418351Smckusick if (p->chain->class == CRANGE) 40518351Smckusick return (NIL); 406781Speter s = lwidth(p->type); 407781Speter /* 408781Speter * Arrays of anything but characters are word aligned. 409781Speter */ 410781Speter if (s & 1) 411781Speter if (s != 1) 412781Speter s++; 413781Speter /* 414781Speter * Skip the first n subscripts 415781Speter */ 416781Speter while (n >= 0) { 417781Speter p = p->chain; 418781Speter n--; 419781Speter } 420781Speter /* 421781Speter * Sum across remaining subscripts. 422781Speter */ 423781Speter while (p != NIL) { 424781Speter if (p->class != RANGE && p->class != SCAL) 425781Speter panic("aryran"); 426781Speter d = p->range[1] - p->range[0] + 1; 427781Speter s *= d; 428781Speter p = p->chain; 429781Speter } 430781Speter return (s); 431781Speter } 432781Speter 433781Speter /* 434781Speter * Find the lower bound of a set, and also its size in bits. 435781Speter */ 436781Speter setran(q) 437781Speter struct nl *q; 438781Speter { 439781Speter register lb, ub; 440781Speter register struct nl *p; 441781Speter 442781Speter p = q; 443781Speter if (p == NIL) 44418351Smckusick return; 445781Speter lb = p->range[0]; 446781Speter ub = p->range[1]; 447781Speter if (p->class != RANGE && p->class != SCAL) 448781Speter panic("setran"); 449781Speter set.lwrb = lb; 450781Speter /* set.(upperbound prime) = number of bits - 1; */ 451781Speter set.uprbp = ub-lb; 452781Speter } 453781Speter 454781Speter /* 455781Speter * Return the number of bytes required to hold an arithmetic quantity 456781Speter */ 457781Speter bytes(lb, ub) 458781Speter long lb, ub; 459781Speter { 460781Speter 461781Speter #ifndef DEBUG 462781Speter if (lb < -32768 || ub > 32767) 463781Speter return (4); 464781Speter else if (lb < -128 || ub > 127) 465781Speter return (2); 466781Speter #else 467781Speter if (!hp21mx && (lb < -32768 || ub > 32767)) 468781Speter return (4); 469781Speter if (lb < -128 || ub > 127) 470781Speter return (2); 471781Speter #endif 472781Speter else 473781Speter return (1); 474781Speter } 475