1*22201Sdist /* 2*22201Sdist * Copyright (c) 1980 Regents of the University of California. 3*22201Sdist * All rights reserved. The Berkeley software License Agreement 4*22201Sdist * specifies the terms and conditions for redistribution. 5*22201Sdist */ 6781Speter 718351Smckusick #ifndef lint 8*22201Sdist static char sccsid[] = "@(#)var.c 5.1 (Berkeley) 06/05/85"; 9*22201Sdist #endif not lint 10781Speter 11781Speter #include "whoami.h" 12781Speter #include "0.h" 1310664Speter #include "objfmt.h" 14781Speter #include "align.h" 152075Smckusic #include "iorec.h" 16781Speter #ifdef PC 17781Speter # include "pc.h" 18781Speter #endif PC 1911336Speter #include "tmps.h" 2018351Smckusick #include "tree_ty.h" 21781Speter 22781Speter /* 23781Speter * Declare variables of a var part. DPOFF1 is 24781Speter * the local variable storage for all prog/proc/func 25781Speter * modules aside from the block mark. The total size 26781Speter * of all the local variables is entered into the 27781Speter * size array. 28781Speter */ 2918351Smckusick /*ARGSUSED*/ 307951Speter varbeg( lineofyvar , r ) 317951Speter int lineofyvar; 32781Speter { 337951Speter static bool var_order = FALSE; 347951Speter static bool var_seen = FALSE; 35781Speter 36837Speter /* this allows for multiple declaration 37781Speter * parts except when the "standard" 38781Speter * option has been specified. 39781Speter * If routine segment is being compiled, 40781Speter * do level one processing. 41781Speter */ 42781Speter 43781Speter #ifndef PI1 44837Speter if (!progseen) 45837Speter level1(); 467951Speter line = lineofyvar; 47837Speter if ( parts[ cbn ] & RPRT ) { 48837Speter if ( opt( 's' ) ) { 49781Speter standard(); 507951Speter error("Variable declarations should precede routine declarations"); 51837Speter } else { 527951Speter if ( !var_order ) { 537951Speter var_order = TRUE; 547951Speter warning(); 557951Speter error("Variable declarations should precede routine declarations"); 567951Speter } 57837Speter } 58781Speter } 59837Speter if ( parts[ cbn ] & VPRT ) { 60837Speter if ( opt( 's' ) ) { 61837Speter standard(); 627951Speter error("All variables should be declared in one var part"); 63837Speter } else { 647951Speter if ( !var_seen ) { 657951Speter var_seen = TRUE; 667951Speter warning(); 677951Speter error("All variables should be declared in one var part"); 687951Speter } 69837Speter } 70837Speter } 71837Speter parts[ cbn ] |= VPRT; 72781Speter #endif 73781Speter /* 74781Speter * #ifndef PI0 753229Smckusic * sizes[cbn].om_max = sizes[cbn].curtmps.om_off = -DPOFF1; 76781Speter * #endif 77781Speter */ 78781Speter forechain = NIL; 79781Speter #ifdef PI0 80781Speter send(REVVBEG); 81781Speter #endif 82781Speter } 83781Speter 84781Speter var(vline, vidl, vtype) 85781Speter #ifdef PI0 8618351Smckusick int vline; 8718351Smckusick struct tnode *vidl, *vtype; 88781Speter { 89781Speter register struct nl *np; 9018351Smckusick register struct tnode *vl; 91781Speter 92781Speter np = gtype(vtype); 93781Speter line = vline; 9418351Smckusick /* why is this here? */ 9518351Smckusick for (vl = vidl; vl != TR_NIL; vl = vl->list_node.next) { 96781Speter } 97781Speter } 98781Speter send(REVVAR, vline, vidl, vtype); 99781Speter } 100781Speter #else 101781Speter int vline; 10218351Smckusick register struct tnode *vidl; 10318351Smckusick struct tnode *vtype; 104781Speter { 105781Speter register struct nl *np; 106781Speter register struct om *op; 107781Speter long w; 108781Speter int o2; 10918351Smckusick #ifdef PC 1103836Speter struct nl *vp; 11118351Smckusick #endif 112781Speter 113781Speter np = gtype(vtype); 114781Speter line = vline; 1153949Speter w = lwidth(np); 116781Speter op = &sizes[cbn]; 11718351Smckusick for (; vidl != TR_NIL; vidl = vidl->list_node.next) { 118781Speter # ifdef OBJ 1193235Smckusic op->curtmps.om_off = 1203235Smckusic roundup((int)(op->curtmps.om_off-w), (long)align(np)); 1213235Smckusic o2 = op -> curtmps.om_off; 122781Speter # endif OBJ 123781Speter # ifdef PC 124781Speter if ( cbn == 1 ) { 125781Speter /* 126781Speter * global variables are not accessed off the fp 127781Speter * but rather by their names. 128781Speter */ 129781Speter o2 = 0; 130781Speter } else { 131781Speter /* 132781Speter * locals are aligned, too. 133781Speter */ 1343229Smckusic op->curtmps.om_off = 1353229Smckusic roundup((int)(op->curtmps.om_off - w), 1363082Smckusic (long)align(np)); 1373229Smckusic o2 = op -> curtmps.om_off; 138781Speter } 139781Speter # endif PC 14018351Smckusick # ifdef PC 14118351Smckusick vp = enter(defnl((char *) vidl->list_node.list, VAR, np, o2)); 14218351Smckusick # else 14318351Smckusick (void) enter(defnl((char *) vidl->list_node.list, VAR, np, o2)); 14418351Smckusick # endif 145781Speter if ( np -> nl_flags & NFILES ) { 146781Speter dfiles[ cbn ] = TRUE; 147781Speter } 148781Speter # ifdef PC 149781Speter if ( cbn == 1 ) { 150781Speter putprintf( " .data" , 0 ); 15110664Speter aligndot(align(np)); 152781Speter putprintf( " .comm " , 1 ); 15318351Smckusick putprintf( EXTFORMAT , 1 , (int) vidl->list_node.list ); 15418351Smckusick putprintf( ",%d" , 0 , (int) w ); 155781Speter putprintf( " .text" , 0 ); 15618351Smckusick stabgvar( vp , w , line ); 1573836Speter vp -> extra_flags |= NGLOBAL; 1583836Speter } else { 1593836Speter vp -> extra_flags |= NLOCAL; 160781Speter } 161781Speter # endif PC 162781Speter } 163781Speter # ifdef PTREE 164781Speter { 165781Speter pPointer *Vars; 166781Speter pPointer Var = VarDecl( ovidl , vtype ); 167781Speter 168781Speter pSeize( PorFHeader[ nesting ] ); 169781Speter Vars = &( pDEF( PorFHeader[ nesting ] ).PorFVars ); 170781Speter *Vars = ListAppend( *Vars , Var ); 171781Speter pRelease( PorFHeader[ nesting ] ); 172781Speter } 173781Speter # endif 174781Speter } 175781Speter #endif 176781Speter 177781Speter varend() 178781Speter { 179781Speter 180781Speter foredecl(); 181781Speter #ifndef PI0 1823229Smckusic sizes[cbn].om_max = sizes[cbn].curtmps.om_off; 183781Speter #else 184781Speter send(REVVEND); 185781Speter #endif 186781Speter } 187781Speter 188781Speter /* 189781Speter * Evening 190781Speter */ 1913082Smckusic long 1923082Smckusic leven(w) 1933082Smckusic register long w; 1943082Smckusic { 1953082Smckusic if (w < 0) 1963082Smckusic return (w & 0xfffffffe); 1973082Smckusic return ((w+1) & 0xfffffffe); 1983082Smckusic } 1993082Smckusic 20018351Smckusick #ifndef PC 2013082Smckusic int 202781Speter even(w) 203781Speter register int w; 204781Speter { 2053082Smckusic return leven((long)w); 206781Speter } 20718351Smckusick #endif 208781Speter 209781Speter /* 210781Speter * Find the width of a type in bytes. 211781Speter */ 212781Speter width(np) 213781Speter struct nl *np; 214781Speter { 215781Speter 216781Speter return (lwidth(np)); 217781Speter } 218781Speter 219781Speter long 220781Speter lwidth(np) 221781Speter struct nl *np; 222781Speter { 223781Speter register struct nl *p; 224781Speter 225781Speter p = np; 226781Speter if (p == NIL) 227781Speter return (0); 228781Speter loop: 229781Speter switch (p->class) { 23018351Smckusick default: 23118351Smckusick panic("wclass"); 232781Speter case TYPE: 233781Speter switch (nloff(p)) { 234781Speter case TNIL: 235781Speter return (2); 236781Speter case TSTR: 237781Speter case TSET: 238781Speter panic("width"); 239781Speter default: 240781Speter p = p->type; 241781Speter goto loop; 242781Speter } 243781Speter case ARRAY: 244781Speter return (aryconst(p, 0)); 245781Speter case PTR: 246781Speter return ( sizeof ( int * ) ); 247781Speter case FILET: 2482075Smckusic return ( sizeof(struct iorec) + lwidth( p -> type ) ); 24918351Smckusick case CRANGE: 25018351Smckusick p = p->type; 25118351Smckusick goto loop; 252781Speter case RANGE: 253781Speter if (p->type == nl+TDOUBLE) 254781Speter #ifdef DEBUG 255781Speter return (hp21mx ? 4 : 8); 256781Speter #else 257781Speter return (8); 258781Speter #endif 259781Speter case SCAL: 260781Speter return (bytes(p->range[0], p->range[1])); 261781Speter case SET: 262781Speter setran(p->type); 26311822Smckusick /* 26411822Smckusick * Sets are some multiple of longs 26511822Smckusick */ 2663082Smckusic return roundup((int)((set.uprbp >> 3) + 1), 26711822Smckusick (long)(sizeof(long))); 268781Speter case STR: 269781Speter case RECORD: 270781Speter return ( p->value[NL_OFFS] ); 271781Speter } 272781Speter } 273781Speter 274781Speter /* 275781Speter * round up x to a multiple of y 276781Speter * for computing offsets of aligned things. 277781Speter * y had better be positive. 278781Speter * rounding is in the direction of x. 279781Speter */ 280781Speter long 281781Speter roundup( x , y ) 2823082Smckusic int x; 283781Speter register long y; 284781Speter { 285781Speter 286781Speter if ( y == 0 ) { 2874030Smckusic return x; 288781Speter } 289781Speter if ( x >= 0 ) { 290781Speter return ( ( ( x + ( y - 1 ) ) / y ) * y ); 291781Speter } else { 292781Speter return ( ( ( x - ( y - 1 ) ) / y ) * y ); 293781Speter } 294781Speter } 295781Speter 296781Speter /* 297781Speter * alignment of an object using the c alignment scheme 298781Speter */ 299781Speter int 300781Speter align( np ) 301781Speter struct nl *np; 302781Speter { 303781Speter register struct nl *p; 30411822Smckusick long elementalign; 305781Speter 306781Speter p = np; 307781Speter if ( p == NIL ) { 308781Speter return 0; 309781Speter } 310781Speter alignit: 311781Speter switch ( p -> class ) { 31218351Smckusick default: 31318351Smckusick panic( "align" ); 314781Speter case TYPE: 315781Speter switch ( nloff( p ) ) { 316781Speter case TNIL: 317781Speter return A_POINT; 318781Speter case TSTR: 31910664Speter return A_STRUCT; 320781Speter case TSET: 321781Speter return A_SET; 322781Speter default: 323781Speter p = p -> type; 324781Speter goto alignit; 325781Speter } 326781Speter case ARRAY: 327781Speter /* 32811822Smckusick * arrays are structures, since they can get 32910664Speter * assigned form/to as structure assignments. 33011822Smckusick * preserve internal alignment if it is greater. 331781Speter */ 33211822Smckusick elementalign = align(p -> type); 33311822Smckusick return elementalign > A_STRUCT ? elementalign : A_STRUCT; 334781Speter case PTR: 335781Speter return A_POINT; 336781Speter case FILET: 337781Speter return A_FILET; 33818351Smckusick case CRANGE: 339781Speter case RANGE: 340781Speter if ( p -> type == nl+TDOUBLE ) { 341781Speter return A_DOUBLE; 342781Speter } 343781Speter /* else, fall through */ 344781Speter case SCAL: 345781Speter switch ( bytes( p -> range[0] , p -> range[1] ) ) { 346781Speter case 4: 347781Speter return A_LONG; 348781Speter case 2: 349781Speter return A_SHORT; 350781Speter case 1: 351781Speter return A_CHAR; 352781Speter default: 353781Speter panic( "align: scal" ); 354781Speter } 355781Speter case SET: 356781Speter return A_SET; 357781Speter case STR: 35810664Speter /* 35910664Speter * arrays of chars are structs 36010664Speter */ 36110664Speter return A_STRUCT; 362781Speter case RECORD: 363781Speter /* 3648681Speter * the alignment of a record is in its align_info field 3658681Speter * why don't we use this for the rest of the namelist? 366781Speter */ 3678681Speter return p -> align_info; 368781Speter } 369781Speter } 370781Speter 37110664Speter #ifdef PC 3723949Speter /* 37310664Speter * output an alignment pseudo-op. 3743949Speter */ 37510664Speter aligndot(alignment) 3763949Speter int alignment; 37710664Speter #ifdef vax 3783949Speter { 37910664Speter switch (alignment) { 38010664Speter case 1: 38110664Speter return; 38210664Speter case 2: 38310664Speter putprintf(" .align 1", 0); 38410664Speter return; 38510664Speter default: 38610664Speter case 4: 38710664Speter putprintf(" .align 2", 0); 38810664Speter return; 3893949Speter } 3903949Speter } 39110664Speter #endif vax 39210664Speter #ifdef mc68000 39310664Speter { 39410664Speter switch (alignment) { 39510664Speter case 1: 39610664Speter return; 39710664Speter default: 39810664Speter putprintf(" .even", 0); 39910664Speter return; 40010664Speter } 40110664Speter } 40210664Speter #endif mc68000 40310664Speter #endif PC 40410664Speter 405781Speter /* 406781Speter * Return the width of an element 407781Speter * of a n time subscripted np. 408781Speter */ 409781Speter long aryconst(np, n) 410781Speter struct nl *np; 411781Speter int n; 412781Speter { 413781Speter register struct nl *p; 414781Speter long s, d; 415781Speter 416781Speter if ((p = np) == NIL) 417781Speter return (NIL); 418781Speter if (p->class != ARRAY) 419781Speter panic("ary"); 42018351Smckusick /* 42118351Smckusick * If it is a conformant array, we cannot find the width from 42218351Smckusick * the type. 42318351Smckusick */ 42418351Smckusick if (p->chain->class == CRANGE) 42518351Smckusick return (NIL); 426781Speter s = lwidth(p->type); 427781Speter /* 428781Speter * Arrays of anything but characters are word aligned. 429781Speter */ 430781Speter if (s & 1) 431781Speter if (s != 1) 432781Speter s++; 433781Speter /* 434781Speter * Skip the first n subscripts 435781Speter */ 436781Speter while (n >= 0) { 437781Speter p = p->chain; 438781Speter n--; 439781Speter } 440781Speter /* 441781Speter * Sum across remaining subscripts. 442781Speter */ 443781Speter while (p != NIL) { 444781Speter if (p->class != RANGE && p->class != SCAL) 445781Speter panic("aryran"); 446781Speter d = p->range[1] - p->range[0] + 1; 447781Speter s *= d; 448781Speter p = p->chain; 449781Speter } 450781Speter return (s); 451781Speter } 452781Speter 453781Speter /* 454781Speter * Find the lower bound of a set, and also its size in bits. 455781Speter */ 456781Speter setran(q) 457781Speter struct nl *q; 458781Speter { 459781Speter register lb, ub; 460781Speter register struct nl *p; 461781Speter 462781Speter p = q; 463781Speter if (p == NIL) 46418351Smckusick return; 465781Speter lb = p->range[0]; 466781Speter ub = p->range[1]; 467781Speter if (p->class != RANGE && p->class != SCAL) 468781Speter panic("setran"); 469781Speter set.lwrb = lb; 470781Speter /* set.(upperbound prime) = number of bits - 1; */ 471781Speter set.uprbp = ub-lb; 472781Speter } 473781Speter 474781Speter /* 475781Speter * Return the number of bytes required to hold an arithmetic quantity 476781Speter */ 477781Speter bytes(lb, ub) 478781Speter long lb, ub; 479781Speter { 480781Speter 481781Speter #ifndef DEBUG 482781Speter if (lb < -32768 || ub > 32767) 483781Speter return (4); 484781Speter else if (lb < -128 || ub > 127) 485781Speter return (2); 486781Speter #else 487781Speter if (!hp21mx && (lb < -32768 || ub > 32767)) 488781Speter return (4); 489781Speter if (lb < -128 || ub > 127) 490781Speter return (2); 491781Speter #endif 492781Speter else 493781Speter return (1); 494781Speter } 495