1781Speter /* Copyright (c) 1979 Regents of the University of California */ 2781Speter 3*18351Smckusick #ifndef lint 4*18351Smckusick static char sccsid[] = "@(#)var.c 2.2 03/15/85"; 5*18351Smckusick #endif 6781Speter 7781Speter #include "whoami.h" 8781Speter #include "0.h" 910664Speter #include "objfmt.h" 10781Speter #include "align.h" 112075Smckusic #include "iorec.h" 12781Speter #ifdef PC 13781Speter # include "pc.h" 14781Speter # include "pcops.h" 15781Speter #endif PC 1611336Speter #include "tmps.h" 17*18351Smckusick #include "tree_ty.h" 18781Speter 19781Speter /* 20781Speter * Declare variables of a var part. DPOFF1 is 21781Speter * the local variable storage for all prog/proc/func 22781Speter * modules aside from the block mark. The total size 23781Speter * of all the local variables is entered into the 24781Speter * size array. 25781Speter */ 26*18351Smckusick /*ARGSUSED*/ 277951Speter varbeg( lineofyvar , r ) 287951Speter int lineofyvar; 29781Speter { 307951Speter static bool var_order = FALSE; 317951Speter static bool var_seen = FALSE; 32781Speter 33837Speter /* this allows for multiple declaration 34781Speter * parts except when the "standard" 35781Speter * option has been specified. 36781Speter * If routine segment is being compiled, 37781Speter * do level one processing. 38781Speter */ 39781Speter 40781Speter #ifndef PI1 41837Speter if (!progseen) 42837Speter level1(); 437951Speter line = lineofyvar; 44837Speter if ( parts[ cbn ] & RPRT ) { 45837Speter if ( opt( 's' ) ) { 46781Speter standard(); 477951Speter error("Variable declarations should precede routine declarations"); 48837Speter } else { 497951Speter if ( !var_order ) { 507951Speter var_order = TRUE; 517951Speter warning(); 527951Speter error("Variable declarations should precede routine declarations"); 537951Speter } 54837Speter } 55781Speter } 56837Speter if ( parts[ cbn ] & VPRT ) { 57837Speter if ( opt( 's' ) ) { 58837Speter standard(); 597951Speter error("All variables should be declared in one var part"); 60837Speter } else { 617951Speter if ( !var_seen ) { 627951Speter var_seen = TRUE; 637951Speter warning(); 647951Speter error("All variables should be declared in one var part"); 657951Speter } 66837Speter } 67837Speter } 68837Speter parts[ cbn ] |= VPRT; 69781Speter #endif 70781Speter /* 71781Speter * #ifndef PI0 723229Smckusic * sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1; 73781Speter * #endif 74781Speter */ 75781Speter forechain = NIL; 76781Speter #ifdef PI0 77781Speter send(REVVBEG); 78781Speter #endif 79781Speter } 80781Speter 81781Speter var(vline, vidl, vtype) 82781Speter #ifdef PI0 83*18351Smckusick int vline; 84*18351Smckusick struct tnode *vidl, *vtype; 85781Speter { 86781Speter register struct nl *np; 87*18351Smckusick register struct tnode *vl; 88781Speter 89781Speter np = gtype(vtype); 90781Speter line = vline; 91*18351Smckusick /* why is this here? */ 92*18351Smckusick for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) { 93781Speter } 94781Speter } 95781Speter send(REVVAR, vline, vidl, vtype); 96781Speter } 97781Speter #else 98781Speter int vline; 99*18351Smckusick register struct tnode *vidl; 100*18351Smckusick struct tnode *vtype; 101781Speter { 102781Speter register struct nl *np; 103781Speter register struct om *op; 104781Speter long w; 105781Speter int o2; 106*18351Smckusick #ifdef PC 1073836Speter struct nl *vp; 108*18351Smckusick #endif 109781Speter 110781Speter np = gtype(vtype); 111781Speter line = vline; 1123949Speter w = lwidth(np); 113781Speter op = &sizes[cbn]; 114*18351Smckusick for (; vidl != TR_NIL; vidl = vidl->list_node.next) { 115781Speter # ifdef OBJ 1163235Smckusic op->curtmps.om_off = 1173235Smckusic roundup((int)(op->curtmps.om_off-w), (long)align(np)); 1183235Smckusic o2 = op -> curtmps.om_off; 119781Speter # endif OBJ 120781Speter # ifdef PC 121781Speter if ( cbn == 1 ) { 122781Speter /* 123781Speter * global variables are not accessed off the fp 124781Speter * but rather by their names. 125781Speter */ 126781Speter o2 = 0; 127781Speter } else { 128781Speter /* 129781Speter * locals are aligned, too. 130781Speter */ 1313229Smckusic op->curtmps.om_off = 1323229Smckusic roundup((int)(op->curtmps.om_off - w), 1333082Smckusic (long)align(np)); 1343229Smckusic o2 = op -> curtmps.om_off; 135781Speter } 136781Speter # endif PC 137*18351Smckusick # ifdef PC 138*18351Smckusick vp = enter(defnl((char *) vidl->list_node.list, VAR, np, o2)); 139*18351Smckusick # else 140*18351Smckusick (void) enter(defnl((char *) vidl->list_node.list, VAR, np, o2)); 141*18351Smckusick # endif 142781Speter if ( np -> nl_flags & NFILES ) { 143781Speter dfiles[ cbn ] = TRUE; 144781Speter } 145781Speter # ifdef PC 146781Speter if ( cbn == 1 ) { 147781Speter putprintf( " .data" , 0 ); 14810664Speter aligndot(align(np)); 149781Speter putprintf( " .comm " , 1 ); 150*18351Smckusick putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list ); 151*18351Smckusick putprintf( ",%d" , 0 , (int) w ); 152781Speter putprintf( " .text" , 0 ); 153*18351Smckusick stabgvar( vp , w , line ); 1543836Speter vp -> extra_flags |= NGLOBAL; 1553836Speter } else { 1563836Speter vp -> extra_flags |= NLOCAL; 157781Speter } 158781Speter # endif PC 159781Speter } 160781Speter # ifdef PTREE 161781Speter { 162781Speter pPointer *Vars; 163781Speter pPointer Var = VarDecl( ovidl , vtype ); 164781Speter 165781Speter pSeize( PorFHeader[ nesting ] ); 166781Speter Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars ); 167781Speter *Vars = ListAppend( *Vars , Var ); 168781Speter pRelease( PorFHeader[ nesting ] ); 169781Speter } 170781Speter # endif 171781Speter } 172781Speter #endif 173781Speter 174781Speter varend() 175781Speter { 176781Speter 177781Speter foredecl(); 178781Speter #ifndef PI0 1793229Smckusic sizes[cbn].om_max = sizes[cbn].curtmps.om_off; 180781Speter #else 181781Speter send(REVVEND); 182781Speter #endif 183781Speter } 184781Speter 185781Speter /* 186781Speter * Evening 187781Speter */ 1883082Smckusic long 1893082Smckusic leven(w) 1903082Smckusic register long w; 1913082Smckusic { 1923082Smckusic if (w < 0) 1933082Smckusic return (w & 0xfffffffe); 1943082Smckusic return ((w+1) & 0xfffffffe); 1953082Smckusic } 1963082Smckusic 197*18351Smckusick #ifndef PC 1983082Smckusic int 199781Speter even(w) 200781Speter register int w; 201781Speter { 2023082Smckusic return leven((long)w); 203781Speter } 204*18351Smckusick #endif 205781Speter 206781Speter /* 207781Speter * Find the width of a type in bytes. 208781Speter */ 209781Speter width(np) 210781Speter struct nl *np; 211781Speter { 212781Speter 213781Speter return (lwidth(np)); 214781Speter } 215781Speter 216781Speter long 217781Speter lwidth(np) 218781Speter struct nl *np; 219781Speter { 220781Speter register struct nl *p; 221781Speter 222781Speter p = np; 223781Speter if (p == NIL) 224781Speter return (0); 225781Speter loop: 226781Speter switch (p->class) { 227*18351Smckusick default: 228*18351Smckusick panic("wclass"); 229781Speter case TYPE: 230781Speter switch (nloff(p)) { 231781Speter case TNIL: 232781Speter return (2); 233781Speter case TSTR: 234781Speter case TSET: 235781Speter panic("width"); 236781Speter default: 237781Speter p = p->type; 238781Speter goto loop; 239781Speter } 240781Speter case ARRAY: 241781Speter return (aryconst(p, 0)); 242781Speter case PTR: 243781Speter return ( sizeof ( int * ) ); 244781Speter case FILET: 2452075Smckusic return ( sizeof(struct iorec) + lwidth( p -> type ) ); 246*18351Smckusick case CRANGE: 247*18351Smckusick p = p->type; 248*18351Smckusick goto loop; 249781Speter case RANGE: 250781Speter if (p->type == nl+TDOUBLE) 251781Speter #ifdef DEBUG 252781Speter return (hp21mx ? 4 : 8); 253781Speter #else 254781Speter return (8); 255781Speter #endif 256781Speter case SCAL: 257781Speter return (bytes(p->range[0], p->range[1])); 258781Speter case SET: 259781Speter setran(p->type); 26011822Smckusick /* 26111822Smckusick * Sets are some multiple of longs 26211822Smckusick */ 2633082Smckusic return roundup((int)((set.uprbp >> 3) + 1), 26411822Smckusick (long)(sizeof(long))); 265781Speter case STR: 266781Speter case RECORD: 267781Speter return ( p->value[NL_OFFS] ); 268781Speter } 269781Speter } 270781Speter 271781Speter /* 272781Speter * round up x to a multiple of y 273781Speter * for computing offsets of aligned things. 274781Speter * y had better be positive. 275781Speter * rounding is in the direction of x. 276781Speter */ 277781Speter long 278781Speter roundup( x , y ) 2793082Smckusic int x; 280781Speter register long y; 281781Speter { 282781Speter 283781Speter if ( y == 0 ) { 2844030Smckusic return x; 285781Speter } 286781Speter if ( x >= 0 ) { 287781Speter return ( ( ( x + ( y - 1 ) ) / y ) * y ); 288781Speter } else { 289781Speter return ( ( ( x - ( y - 1 ) ) / y ) * y ); 290781Speter } 291781Speter } 292781Speter 293781Speter /* 294781Speter * alignment of an object using the c alignment scheme 295781Speter */ 296781Speter int 297781Speter align( np ) 298781Speter struct nl *np; 299781Speter { 300781Speter register struct nl *p; 30111822Smckusick long elementalign; 302781Speter 303781Speter p = np; 304781Speter if ( p == NIL ) { 305781Speter return 0; 306781Speter } 307781Speter alignit: 308781Speter switch ( p -> class ) { 309*18351Smckusick default: 310*18351Smckusick panic( "align" ); 311781Speter case TYPE: 312781Speter switch ( nloff( p ) ) { 313781Speter case TNIL: 314781Speter return A_POINT; 315781Speter case TSTR: 31610664Speter return A_STRUCT; 317781Speter case TSET: 318781Speter return A_SET; 319781Speter default: 320781Speter p = p -> type; 321781Speter goto alignit; 322781Speter } 323781Speter case ARRAY: 324781Speter /* 32511822Smckusick * arrays are structures, since they can get 32610664Speter * assigned form/to as structure assignments. 32711822Smckusick * preserve internal alignment if it is greater. 328781Speter */ 32911822Smckusick elementalign = align(p -> type); 33011822Smckusick return elementalign > A_STRUCT ? elementalign : A_STRUCT; 331781Speter case PTR: 332781Speter return A_POINT; 333781Speter case FILET: 334781Speter return A_FILET; 335*18351Smckusick case CRANGE: 336781Speter case RANGE: 337781Speter if ( p -> type == nl+TDOUBLE ) { 338781Speter return A_DOUBLE; 339781Speter } 340781Speter /* else, fall through */ 341781Speter case SCAL: 342781Speter switch ( bytes( p -> range[0] , p -> range[1] ) ) { 343781Speter case 4: 344781Speter return A_LONG; 345781Speter case 2: 346781Speter return A_SHORT; 347781Speter case 1: 348781Speter return A_CHAR; 349781Speter default: 350781Speter panic( "align: scal" ); 351781Speter } 352781Speter case SET: 353781Speter return A_SET; 354781Speter case STR: 35510664Speter /* 35610664Speter * arrays of chars are structs 35710664Speter */ 35810664Speter return A_STRUCT; 359781Speter case RECORD: 360781Speter /* 3618681Speter * the alignment of a record is in its align_info field 3628681Speter * why don't we use this for the rest of the namelist? 363781Speter */ 3648681Speter return p -> align_info; 365781Speter } 366781Speter } 367781Speter 36810664Speter #ifdef PC 3693949Speter /* 37010664Speter * output an alignment pseudo-op. 3713949Speter */ 37210664Speter aligndot(alignment) 3733949Speter int alignment; 37410664Speter #ifdef vax 3753949Speter { 37610664Speter switch (alignment) { 37710664Speter case 1: 37810664Speter return; 37910664Speter case 2: 38010664Speter putprintf(" .align 1", 0); 38110664Speter return; 38210664Speter default: 38310664Speter case 4: 38410664Speter putprintf(" .align 2", 0); 38510664Speter return; 3863949Speter } 3873949Speter } 38810664Speter #endif vax 38910664Speter #ifdef mc68000 39010664Speter { 39110664Speter switch (alignment) { 39210664Speter case 1: 39310664Speter return; 39410664Speter default: 39510664Speter putprintf(" .even", 0); 39610664Speter return; 39710664Speter } 39810664Speter } 39910664Speter #endif mc68000 40010664Speter #endif PC 40110664Speter 402781Speter /* 403781Speter * Return the width of an element 404781Speter * of a n time subscripted np. 405781Speter */ 406781Speter long aryconst(np, n) 407781Speter struct nl *np; 408781Speter int n; 409781Speter { 410781Speter register struct nl *p; 411781Speter long s, d; 412781Speter 413781Speter if ((p = np) == NIL) 414781Speter return (NIL); 415781Speter if (p->class != ARRAY) 416781Speter panic("ary"); 417*18351Smckusick /* 418*18351Smckusick * If it is a conformant array, we cannot find the width from 419*18351Smckusick * the type. 420*18351Smckusick */ 421*18351Smckusick if (p->chain->class == CRANGE) 422*18351Smckusick return (NIL); 423781Speter s = lwidth(p->type); 424781Speter /* 425781Speter * Arrays of anything but characters are word aligned. 426781Speter */ 427781Speter if (s & 1) 428781Speter if (s != 1) 429781Speter s++; 430781Speter /* 431781Speter * Skip the first n subscripts 432781Speter */ 433781Speter while (n >= 0) { 434781Speter p = p->chain; 435781Speter n--; 436781Speter } 437781Speter /* 438781Speter * Sum across remaining subscripts. 439781Speter */ 440781Speter while (p != NIL) { 441781Speter if (p->class != RANGE && p->class != SCAL) 442781Speter panic("aryran"); 443781Speter d = p->range[1] - p->range[0] + 1; 444781Speter s *= d; 445781Speter p = p->chain; 446781Speter } 447781Speter return (s); 448781Speter } 449781Speter 450781Speter /* 451781Speter * Find the lower bound of a set, and also its size in bits. 452781Speter */ 453781Speter setran(q) 454781Speter struct nl *q; 455781Speter { 456781Speter register lb, ub; 457781Speter register struct nl *p; 458781Speter 459781Speter p = q; 460781Speter if (p == NIL) 461*18351Smckusick return; 462781Speter lb = p->range[0]; 463781Speter ub = p->range[1]; 464781Speter if (p->class != RANGE && p->class != SCAL) 465781Speter panic("setran"); 466781Speter set.lwrb = lb; 467781Speter /* set.(upperbound prime) = number of bits - 1; */ 468781Speter set.uprbp = ub-lb; 469781Speter } 470781Speter 471781Speter /* 472781Speter * Return the number of bytes required to hold an arithmetic quantity 473781Speter */ 474781Speter bytes(lb, ub) 475781Speter long lb, ub; 476781Speter { 477781Speter 478781Speter #ifndef DEBUG 479781Speter if (lb < -32768 || ub > 32767) 480781Speter return (4); 481781Speter else if (lb < -128 || ub > 127) 482781Speter return (2); 483781Speter #else 484781Speter if (!hp21mx && (lb < -32768 || ub > 32767)) 485781Speter return (4); 486781Speter if (lb < -128 || ub > 127) 487781Speter return (2); 488781Speter #endif 489781Speter else 490781Speter return (1); 491781Speter } 492