19657Slinton /* Copyright (c) 1982 Regents of the University of California */ 29657Slinton 3*12547Scsvaf static char sccsid[] = "@(#)symbols.c 1.8 05/18/83"; 49657Slinton 59657Slinton /* 69657Slinton * Symbol management. 79657Slinton */ 89657Slinton 99657Slinton #include "defs.h" 109657Slinton #include "symbols.h" 119657Slinton #include "languages.h" 129657Slinton #include "printsym.h" 139657Slinton #include "tree.h" 149657Slinton #include "operators.h" 159657Slinton #include "eval.h" 169657Slinton #include "mappings.h" 179657Slinton #include "events.h" 189657Slinton #include "process.h" 199657Slinton #include "runtime.h" 209657Slinton #include "machine.h" 219657Slinton #include "names.h" 229657Slinton 239657Slinton #ifndef public 249657Slinton typedef struct Symbol *Symbol; 259657Slinton 269657Slinton #include "machine.h" 279657Slinton #include "names.h" 289657Slinton #include "languages.h" 299657Slinton 309657Slinton /* 319657Slinton * Symbol classes 329657Slinton */ 339657Slinton 349657Slinton typedef enum { 359657Slinton BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD, 36*12547Scsvaf PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 379657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 38*12547Scsvaf FPROC, FFUNC, MODULE, TAG, COMMON, TYPEREF 399657Slinton } Symclass; 409657Slinton 41*12547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 42*12547Scsvaf 439657Slinton struct Symbol { 449657Slinton Name name; 459657Slinton Language language; 469657Slinton Symclass class : 8; 479657Slinton Integer level : 8; 489657Slinton Symbol type; 499657Slinton Symbol chain; 509657Slinton union { 519657Slinton int offset; /* variable address */ 529657Slinton long iconval; /* integer constant value */ 539657Slinton double fconval; /* floating constant value */ 549657Slinton struct { /* field offset and size (both in bits) */ 559657Slinton int offset; 569657Slinton int length; 579657Slinton } field; 58*12547Scsvaf struct { /* common offset and chain; used to relocate */ 59*12547Scsvaf int offset; /* vars in global BSS */ 60*12547Scsvaf Symbol chain; 61*12547Scsvaf } common; 629657Slinton struct { /* range bounds */ 63*12547Scsvaf Rangetype lowertype : 16; 64*12547Scsvaf Rangetype uppertype : 16; 659657Slinton long lower; 669657Slinton long upper; 679657Slinton } rangev; 6811865Slinton struct { 6911865Slinton int offset : 16; /* offset for of function value */ 7011865Slinton Boolean src : 16; /* true if there is source line info */ 7111865Slinton Address beginaddr; /* address of function code */ 729657Slinton } funcv; 739657Slinton struct { /* variant record info */ 749657Slinton int size; 759657Slinton Symbol vtorec; 769657Slinton Symbol vtag; 779657Slinton } varnt; 789657Slinton } symvalue; 799657Slinton Symbol block; /* symbol containing this symbol */ 809657Slinton Symbol next_sym; /* hash chain */ 819657Slinton }; 829657Slinton 839657Slinton /* 849657Slinton * Basic types. 859657Slinton */ 869657Slinton 879657Slinton Symbol t_boolean; 889657Slinton Symbol t_char; 899657Slinton Symbol t_int; 909657Slinton Symbol t_real; 919657Slinton Symbol t_nil; 929657Slinton 939657Slinton Symbol program; 949657Slinton Symbol curfunc; 959657Slinton 969657Slinton #define symname(s) ident(s->name) 979657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 989657Slinton #define isblock(s) (Boolean) ( \ 999657Slinton s->class == FUNC or s->class == PROC or \ 1009657Slinton s->class == MODULE or s->class == PROG \ 1019657Slinton ) 1029657Slinton 10311865Slinton #define nosource(f) (not (f)->symvalue.funcv.src) 10411865Slinton 1059657Slinton #include "tree.h" 1069657Slinton 1079657Slinton /* 1089657Slinton * Some macros to make finding a symbol with certain attributes. 1099657Slinton */ 1109657Slinton 1119657Slinton #define find(s, withname) \ 1129657Slinton { \ 1139657Slinton s = lookup(withname); \ 1149657Slinton while (s != nil and not (s->name == (withname) and 1159657Slinton 1169657Slinton #define where /* qualification */ 1179657Slinton 1189657Slinton #define endfind(s) )) { \ 1199657Slinton s = s->next_sym; \ 1209657Slinton } \ 1219657Slinton } 1229657Slinton 1239657Slinton #endif 1249657Slinton 1259657Slinton /* 1269657Slinton * Symbol table structure currently does not support deletions. 1279657Slinton */ 1289657Slinton 1299657Slinton #define HASHTABLESIZE 2003 1309657Slinton 1319657Slinton private Symbol hashtab[HASHTABLESIZE]; 1329657Slinton 1339657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 1349657Slinton 1359657Slinton /* 1369657Slinton * Allocate a new symbol. 1379657Slinton */ 1389657Slinton 13911171Slinton #define SYMBLOCKSIZE 100 1409657Slinton 1419657Slinton typedef struct Sympool { 1429657Slinton struct Symbol sym[SYMBLOCKSIZE]; 1439657Slinton struct Sympool *prevpool; 1449657Slinton } *Sympool; 1459657Slinton 1469657Slinton private Sympool sympool = nil; 1479657Slinton private Integer nleft = 0; 1489657Slinton 1499657Slinton public Symbol symbol_alloc() 1509657Slinton { 1519657Slinton register Sympool newpool; 1529657Slinton 1539657Slinton if (nleft <= 0) { 1549657Slinton newpool = new(Sympool); 15511171Slinton bzero(newpool, sizeof(newpool)); 1569657Slinton newpool->prevpool = sympool; 1579657Slinton sympool = newpool; 1589657Slinton nleft = SYMBLOCKSIZE; 1599657Slinton } 1609657Slinton --nleft; 1619657Slinton return &(sympool->sym[nleft]); 1629657Slinton } 1639657Slinton 164*12547Scsvaf 165*12547Scsvaf public symbol_dump(func) 166*12547Scsvaf Symbol func; 167*12547Scsvaf { 168*12547Scsvaf register Symbol s; 169*12547Scsvaf register Integer i; 170*12547Scsvaf 171*12547Scsvaf printf(" symbols in %s \n",symname(func)); 172*12547Scsvaf for(i=0; i< HASHTABLESIZE; i++) 173*12547Scsvaf for(s=hashtab[i]; s != nil; s=s->next_sym) { 174*12547Scsvaf if (s->block == func) psym(s); 175*12547Scsvaf } 176*12547Scsvaf } 177*12547Scsvaf 1789657Slinton /* 1799657Slinton * Free all the symbols currently allocated. 1809657Slinton */ 1819657Slinton public symbol_free() 1829657Slinton { 1839657Slinton Sympool s, t; 1849657Slinton register Integer i; 1859657Slinton 1869657Slinton s = sympool; 1879657Slinton while (s != nil) { 1889657Slinton t = s->prevpool; 1899657Slinton dispose(s); 1909657Slinton s = t; 1919657Slinton } 1929657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 1939657Slinton hashtab[i] = nil; 1949657Slinton } 1959657Slinton sympool = nil; 1969657Slinton nleft = 0; 1979657Slinton } 1989657Slinton 1999657Slinton /* 2009657Slinton * Create a new symbol with the given attributes. 2019657Slinton */ 2029657Slinton 2039657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 2049657Slinton Name name; 2059657Slinton Integer blevel; 2069657Slinton Symclass class; 2079657Slinton Symbol type; 2089657Slinton Symbol chain; 2099657Slinton { 2109657Slinton register Symbol s; 2119657Slinton 2129657Slinton s = symbol_alloc(); 2139657Slinton s->name = name; 2149657Slinton s->level = blevel; 2159657Slinton s->class = class; 2169657Slinton s->type = type; 2179657Slinton s->chain = chain; 2189657Slinton return s; 2199657Slinton } 2209657Slinton 2219657Slinton /* 2229657Slinton * Insert a symbol into the hash table. 2239657Slinton */ 2249657Slinton 2259657Slinton public Symbol insert(name) 2269657Slinton Name name; 2279657Slinton { 2289657Slinton register Symbol s; 2299657Slinton register unsigned int h; 2309657Slinton 2319657Slinton h = hash(name); 2329657Slinton s = symbol_alloc(); 2339657Slinton s->name = name; 2349657Slinton s->next_sym = hashtab[h]; 2359657Slinton hashtab[h] = s; 2369657Slinton return s; 2379657Slinton } 2389657Slinton 2399657Slinton /* 2409657Slinton * Symbol lookup. 2419657Slinton */ 2429657Slinton 2439657Slinton public Symbol lookup(name) 2449657Slinton Name name; 2459657Slinton { 2469657Slinton register Symbol s; 2479657Slinton register unsigned int h; 2489657Slinton 2499657Slinton h = hash(name); 2509657Slinton s = hashtab[h]; 2519657Slinton while (s != nil and s->name != name) { 2529657Slinton s = s->next_sym; 2539657Slinton } 2549657Slinton return s; 2559657Slinton } 2569657Slinton 2579657Slinton /* 2589657Slinton * Dump out all the variables associated with the given 2599657Slinton * procedure, function, or program at the given recursive level. 2609657Slinton * 2619657Slinton * This is quite inefficient. We traverse the entire symbol table 2629657Slinton * each time we're called. The assumption is that this routine 2639657Slinton * won't be called frequently enough to merit improved performance. 2649657Slinton */ 2659657Slinton 2669657Slinton public dumpvars(f, frame) 2679657Slinton Symbol f; 2689657Slinton Frame frame; 2699657Slinton { 2709657Slinton register Integer i; 2719657Slinton register Symbol s; 2729657Slinton 2739657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 2749657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 2759657Slinton if (container(s) == f) { 2769657Slinton if (should_print(s)) { 2779657Slinton printv(s, frame); 2789657Slinton putchar('\n'); 2799657Slinton } else if (s->class == MODULE) { 2809657Slinton dumpvars(s, frame); 2819657Slinton } 2829657Slinton } 2839657Slinton } 2849657Slinton } 2859657Slinton } 2869657Slinton 2879657Slinton /* 2889657Slinton * Create a builtin type. 2899657Slinton * Builtin types are circular in that btype->type->type = btype. 2909657Slinton */ 2919657Slinton 2929657Slinton public Symbol maketype(name, lower, upper) 2939657Slinton String name; 2949657Slinton long lower; 2959657Slinton long upper; 2969657Slinton { 2979657Slinton register Symbol s; 2989657Slinton 2999657Slinton s = newSymbol(identname(name, true), 0, TYPE, nil, nil); 3009657Slinton s->language = findlanguage(".c"); 3019657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 3029657Slinton s->type->symvalue.rangev.lower = lower; 3039657Slinton s->type->symvalue.rangev.upper = upper; 3049657Slinton return s; 3059657Slinton } 3069657Slinton 3079657Slinton /* 3089657Slinton * These functions are now compiled inline. 3099657Slinton * 3109657Slinton * public String symname(s) 3119657Slinton Symbol s; 3129657Slinton { 3139657Slinton checkref(s); 3149657Slinton return ident(s->name); 3159657Slinton } 3169657Slinton 3179657Slinton * 3189657Slinton * public Address codeloc(f) 3199657Slinton Symbol f; 3209657Slinton { 3219657Slinton checkref(f); 3229657Slinton if (not isblock(f)) { 3239657Slinton panic("codeloc: \"%s\" is not a block", ident(f->name)); 3249657Slinton } 3259657Slinton return f->symvalue.funcv.beginaddr; 3269657Slinton } 3279657Slinton * 3289657Slinton */ 3299657Slinton 3309657Slinton /* 3319657Slinton * Reduce type to avoid worrying about type names. 3329657Slinton */ 3339657Slinton 3349657Slinton public Symbol rtype(type) 3359657Slinton Symbol type; 3369657Slinton { 3379657Slinton register Symbol t; 3389657Slinton 3399657Slinton t = type; 3409657Slinton if (t != nil) { 341*12547Scsvaf if (t->class == VAR or t->class == FIELD or t->class == REF ) { 3429657Slinton t = t->type; 3439657Slinton } 3449657Slinton while (t->class == TYPE or t->class == TAG) { 3459657Slinton t = t->type; 3469657Slinton } 3479657Slinton } 3489657Slinton return t; 3499657Slinton } 3509657Slinton 3519657Slinton public Integer level(s) 3529657Slinton Symbol s; 3539657Slinton { 3549657Slinton checkref(s); 3559657Slinton return s->level; 3569657Slinton } 3579657Slinton 3589657Slinton public Symbol container(s) 3599657Slinton Symbol s; 3609657Slinton { 3619657Slinton checkref(s); 3629657Slinton return s->block; 3639657Slinton } 3649657Slinton 3659657Slinton /* 3669657Slinton * Return the object address of the given symbol. 3679657Slinton * 3689657Slinton * There are the following possibilities: 3699657Slinton * 3709657Slinton * globals - just take offset 3719657Slinton * locals - take offset from locals base 3729657Slinton * arguments - take offset from argument base 3739657Slinton * register - offset is register number 3749657Slinton */ 3759657Slinton 3769657Slinton #define isglobal(s) (s->level == 1 or s->level == 2) 3779657Slinton #define islocaloff(s) (s->level >= 3 and s->symvalue.offset < 0) 3789657Slinton #define isparamoff(s) (s->level >= 3 and s->symvalue.offset >= 0) 3799657Slinton #define isreg(s) (s->level < 0) 3809657Slinton 3819657Slinton public Address address(s, frame) 3829657Slinton Symbol s; 3839657Slinton Frame frame; 3849657Slinton { 3859657Slinton register Frame frp; 3869657Slinton register Address addr; 3879657Slinton register Symbol cur; 3889657Slinton 3899657Slinton checkref(s); 3909657Slinton if (not isactive(s->block)) { 3919657Slinton error("\"%s\" is not currently defined", symname(s)); 3929657Slinton } else if (isglobal(s)) { 3939657Slinton addr = s->symvalue.offset; 3949657Slinton } else { 3959657Slinton frp = frame; 3969657Slinton if (frp == nil) { 3979657Slinton cur = s->block; 3989657Slinton while (cur != nil and cur->class == MODULE) { 3999657Slinton cur = cur->block; 4009657Slinton } 4019657Slinton if (cur == nil) { 4029657Slinton cur = whatblock(pc); 4039657Slinton } 4049657Slinton frp = findframe(cur); 4059657Slinton if (frp == nil) { 4069657Slinton panic("unexpected nil frame for \"%s\"", symname(s)); 4079657Slinton } 4089657Slinton } 4099657Slinton if (islocaloff(s)) { 4109657Slinton addr = locals_base(frp) + s->symvalue.offset; 4119657Slinton } else if (isparamoff(s)) { 4129657Slinton addr = args_base(frp) + s->symvalue.offset; 4139657Slinton } else if (isreg(s)) { 4149657Slinton addr = savereg(s->symvalue.offset, frp); 4159657Slinton } else { 4169657Slinton panic("address: bad symbol \"%s\"", symname(s)); 4179657Slinton } 4189657Slinton } 4199657Slinton return addr; 4209657Slinton } 4219657Slinton 4229657Slinton /* 4239657Slinton * Define a symbol used to access register values. 4249657Slinton */ 4259657Slinton 4269657Slinton public defregname(n, r) 4279657Slinton Name n; 4289657Slinton Integer r; 4299657Slinton { 4309657Slinton register Symbol s, t; 4319657Slinton 4329657Slinton s = insert(n); 4339657Slinton t = newSymbol(nil, 0, PTR, t_int, nil); 4349657Slinton t->language = findlanguage(".s"); 4359657Slinton s->language = t->language; 4369657Slinton s->class = VAR; 4379657Slinton s->level = -3; 4389657Slinton s->type = t; 4399657Slinton s->block = program; 4409657Slinton s->symvalue.offset = r; 4419657Slinton } 4429657Slinton 4439657Slinton /* 4449657Slinton * Resolve an "abstract" type reference. 4459657Slinton * 4469657Slinton * It is possible in C to define a pointer to a type, but never define 4479657Slinton * the type in a particular source file. Here we try to resolve 4489657Slinton * the type definition. This is problematic, it is possible to 4499657Slinton * have multiple, different definitions for the same name type. 4509657Slinton */ 4519657Slinton 4529657Slinton public findtype(s) 4539657Slinton Symbol s; 4549657Slinton { 4559657Slinton register Symbol t, u, prev; 4569657Slinton 4579657Slinton u = s; 4589657Slinton prev = nil; 4599657Slinton while (u != nil and u->class != BADUSE) { 4609657Slinton if (u->name != nil) { 4619657Slinton prev = u; 4629657Slinton } 4639657Slinton u = u->type; 4649657Slinton } 4659657Slinton if (prev == nil) { 4669657Slinton error("couldn't find link to type reference"); 4679657Slinton } 4689657Slinton find(t, prev->name) where 4699657Slinton t->type != nil and t->class == prev->class and 4709657Slinton t->type->class != BADUSE and t->block->class == MODULE 4719657Slinton endfind(t); 4729657Slinton if (t == nil) { 4739657Slinton error("couldn't resolve reference"); 4749657Slinton } else { 4759657Slinton prev->type = t->type; 4769657Slinton } 4779657Slinton } 4789657Slinton 4799657Slinton /* 4809657Slinton * Find the size in bytes of the given type. 4819657Slinton * 4829657Slinton * This is probably the WRONG thing to do. The size should be kept 4839657Slinton * as an attribute in the symbol information as is done for structures 4849657Slinton * and fields. I haven't gotten around to cleaning this up yet. 4859657Slinton */ 4869657Slinton 487*12547Scsvaf #define MAXUCHAR 255 488*12547Scsvaf #define MAXUSHORT 65535L 4899657Slinton #define MINCHAR -128 4909657Slinton #define MAXCHAR 127 4919657Slinton #define MINSHORT -32768 4929657Slinton #define MAXSHORT 32767 4939657Slinton 4949657Slinton public Integer size(sym) 4959657Slinton Symbol sym; 4969657Slinton { 4979657Slinton register Symbol s, t; 4989657Slinton register int nel, elsize; 4999657Slinton long lower, upper; 5009657Slinton int r; 5019657Slinton 5029657Slinton t = sym; 5039657Slinton checkref(t); 5049657Slinton switch (t->class) { 5059657Slinton case RANGE: 5069657Slinton lower = t->symvalue.rangev.lower; 5079657Slinton upper = t->symvalue.rangev.upper; 5089657Slinton if (upper == 0 and lower > 0) { /* real */ 5099657Slinton r = lower; 51012045Slinton } else if ( 511*12547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or 512*12547Scsvaf (lower >= 0 and upper <= MAXUCHAR) 513*12547Scsvaf ) { 5149657Slinton r = sizeof(char); 515*12547Scsvaf } else if ( 516*12547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or 517*12547Scsvaf (lower >= 0 and upper <= MAXUSHORT) 518*12547Scsvaf ) { 5199657Slinton r = sizeof(short); 5209657Slinton } else { 5219657Slinton r = sizeof(long); 5229657Slinton } 5239657Slinton break; 5249657Slinton 5259657Slinton case ARRAY: 5269657Slinton elsize = size(t->type); 5279657Slinton nel = 1; 5289657Slinton for (t = t->chain; t != nil; t = t->chain) { 529*12547Scsvaf 530*12547Scsvaf if(t->symvalue.rangev.lowertype == R_ARG 531*12547Scsvaf or t->symvalue.rangev.lowertype == R_TEMP ) { 532*12547Scsvaf if( ! getbound(t, t->symvalue.rangev.lower, 533*12547Scsvaf t->symvalue.rangev.lowertype, &lower)) 534*12547Scsvaf error(" dynamic bounds not currently available "); 535*12547Scsvaf } 536*12547Scsvaf else lower = t->symvalue.rangev.lower; 537*12547Scsvaf 538*12547Scsvaf if(t->symvalue.rangev.uppertype == R_ARG 539*12547Scsvaf or t->symvalue.rangev.uppertype == R_TEMP ) { 540*12547Scsvaf if( ! getbound(t, t->symvalue.rangev.upper, 541*12547Scsvaf t->symvalue.rangev.uppertype, &upper)) 542*12547Scsvaf error(" dynamic bounds not currently available "); 543*12547Scsvaf } 544*12547Scsvaf else upper = t->symvalue.rangev.upper; 5459657Slinton nel *= (upper-lower+1); 5469657Slinton } 5479657Slinton r = nel*elsize; 5489657Slinton break; 5499657Slinton 550*12547Scsvaf case REF: 5519657Slinton case VAR: 5529657Slinton case FVAR: 5539657Slinton r = size(t->type); 55412127Slinton /* 55512127Slinton * 55612045Slinton if (r < sizeof(Word) and isparam(t)) { 5579657Slinton r = sizeof(Word); 5589657Slinton } 559*12547Scsvaf */ 5609657Slinton break; 5619657Slinton 5629657Slinton case CONST: 5639657Slinton r = size(t->type); 5649657Slinton break; 5659657Slinton 5669657Slinton case TYPE: 5679657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 5689657Slinton findtype(t); 5699657Slinton } 5709657Slinton r = size(t->type); 5719657Slinton break; 5729657Slinton 5739657Slinton case TAG: 5749657Slinton r = size(t->type); 5759657Slinton break; 5769657Slinton 5779657Slinton case FIELD: 5789657Slinton r = (t->symvalue.field.length + 7) div 8; 5799657Slinton break; 5809657Slinton 5819657Slinton case RECORD: 5829657Slinton case VARNT: 5839657Slinton r = t->symvalue.offset; 5849657Slinton if (r == 0 and t->chain != nil) { 5859657Slinton panic("missing size information for record"); 5869657Slinton } 5879657Slinton break; 5889657Slinton 5899657Slinton case PTR: 5909657Slinton case FILET: 5919657Slinton r = sizeof(Word); 5929657Slinton break; 5939657Slinton 5949657Slinton case SCAL: 5959657Slinton if (t->symvalue.iconval > 255) { 5969657Slinton r = sizeof(short); 5979657Slinton } else { 5989657Slinton r = sizeof(char); 5999657Slinton } 6009657Slinton break; 6019657Slinton 6029657Slinton case FPROC: 6039657Slinton case FFUNC: 6049657Slinton r = sizeof(Word); 6059657Slinton break; 6069657Slinton 6079657Slinton case PROC: 6089657Slinton case FUNC: 6099657Slinton case MODULE: 6109657Slinton case PROG: 6119657Slinton r = sizeof(Symbol); 6129657Slinton break; 6139657Slinton 6149657Slinton default: 6159657Slinton if (ord(t->class) > ord(TYPEREF)) { 6169657Slinton panic("size: bad class (%d)", ord(t->class)); 6179657Slinton } else { 6189657Slinton error("improper operation on a %s", classname(t)); 6199657Slinton } 6209657Slinton /* NOTREACHED */ 6219657Slinton } 6229657Slinton return r; 6239657Slinton } 6249657Slinton 6259657Slinton /* 6269657Slinton * Test if a symbol is a parameter. This is true if there 6279657Slinton * is a cycle from s->block to s via chain pointers. 6289657Slinton */ 6299657Slinton 6309657Slinton public Boolean isparam(s) 6319657Slinton Symbol s; 6329657Slinton { 6339657Slinton register Symbol t; 6349657Slinton 6359657Slinton t = s->block; 6369657Slinton while (t != nil and t != s) { 6379657Slinton t = t->chain; 6389657Slinton } 6399657Slinton return (Boolean) (t != nil); 6409657Slinton } 6419657Slinton 6429657Slinton /* 6439657Slinton * Test if a symbol is a var parameter, i.e. has class REF. 6449657Slinton */ 6459657Slinton 6469657Slinton public Boolean isvarparam(s) 6479657Slinton Symbol s; 6489657Slinton { 6499657Slinton return (Boolean) (s->class == REF); 6509657Slinton } 6519657Slinton 6529657Slinton /* 6539657Slinton * Test if a symbol is a variable (actually any addressible quantity 6549657Slinton * with do). 6559657Slinton */ 6569657Slinton 6579657Slinton public Boolean isvariable(s) 6589657Slinton register Symbol s; 6599657Slinton { 6609657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 6619657Slinton } 6629657Slinton 6639657Slinton /* 6649657Slinton * Test if a symbol is a block, e.g. function, procedure, or the 6659657Slinton * main program. 6669657Slinton * 6679657Slinton * This function is now expanded inline for efficiency. 6689657Slinton * 6699657Slinton * public Boolean isblock(s) 6709657Slinton register Symbol s; 6719657Slinton { 6729657Slinton return (Boolean) ( 6739657Slinton s->class == FUNC or s->class == PROC or 6749657Slinton s->class == MODULE or s->class == PROG 6759657Slinton ); 6769657Slinton } 6779657Slinton * 6789657Slinton */ 6799657Slinton 6809657Slinton /* 6819657Slinton * Test if a symbol is a module. 6829657Slinton */ 6839657Slinton 6849657Slinton public Boolean ismodule(s) 6859657Slinton register Symbol s; 6869657Slinton { 6879657Slinton return (Boolean) (s->class == MODULE); 6889657Slinton } 6899657Slinton 6909657Slinton /* 6919657Slinton * Test if a symbol is builtin, that is, a predefined type or 6929657Slinton * reserved word. 6939657Slinton */ 6949657Slinton 6959657Slinton public Boolean isbuiltin(s) 6969657Slinton register Symbol s; 6979657Slinton { 6989657Slinton return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); 6999657Slinton } 7009657Slinton 7019657Slinton /* 7029657Slinton * Test if two types match. 7039657Slinton * Equivalent names implies a match in any language. 7049657Slinton * 7059657Slinton * Special symbols must be handled with care. 7069657Slinton */ 7079657Slinton 7089657Slinton public Boolean compatible(t1, t2) 7099657Slinton register Symbol t1, t2; 7109657Slinton { 7119657Slinton Boolean b; 7129657Slinton 7139657Slinton if (t1 == t2) { 7149657Slinton b = true; 7159657Slinton } else if (t1 == nil or t2 == nil) { 7169657Slinton b = false; 7179657Slinton } else if (t1 == procsym) { 7189657Slinton b = isblock(t2); 7199657Slinton } else if (t2 == procsym) { 7209657Slinton b = isblock(t1); 7219657Slinton } else if (t1->language == nil) { 7229657Slinton b = (Boolean) (t2->language == nil or 7239657Slinton (*language_op(t2->language, L_TYPEMATCH))(t1, t2)); 724*12547Scsvaf } else if (t2->language == nil) { 725*12547Scsvaf b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 726*12547Scsvaf } else if ( isbuiltin(t1) or isbuiltin(t1->type) ) { 727*12547Scsvaf b = (Boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 7289657Slinton } else { 7299657Slinton b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 7309657Slinton } 7319657Slinton return b; 7329657Slinton } 7339657Slinton 7349657Slinton /* 7359657Slinton * Check for a type of the given name. 7369657Slinton */ 7379657Slinton 7389657Slinton public Boolean istypename(type, name) 7399657Slinton Symbol type; 7409657Slinton String name; 7419657Slinton { 7429657Slinton Symbol t; 7439657Slinton Boolean b; 7449657Slinton 7459657Slinton t = type; 7469657Slinton checkref(t); 7479657Slinton b = (Boolean) ( 7489657Slinton t->class == TYPE and t->name == identname(name, true) 7499657Slinton ); 7509657Slinton return b; 7519657Slinton } 7529657Slinton 7539657Slinton /* 7549657Slinton * Test if the name of a symbol is uniquely defined or not. 7559657Slinton */ 7569657Slinton 7579657Slinton public Boolean isambiguous(s) 7589657Slinton register Symbol s; 7599657Slinton { 7609657Slinton register Symbol t; 7619657Slinton 7629657Slinton find(t, s->name) where t != s endfind(t); 7639657Slinton return (Boolean) (t != nil); 7649657Slinton } 7659657Slinton 7669657Slinton typedef char *Arglist; 7679657Slinton 7689657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 7699657Slinton 7709657Slinton private Symbol mkstring(); 7719657Slinton private Symbol namenode(); 7729657Slinton 7739657Slinton /* 7749657Slinton * Determine the type of a parse tree. 7759657Slinton * Also make some symbol-dependent changes to the tree such as 7769657Slinton * changing removing RVAL nodes for constant symbols. 7779657Slinton */ 7789657Slinton 7799657Slinton public assigntypes(p) 7809657Slinton register Node p; 7819657Slinton { 7829657Slinton register Node p1; 7839657Slinton register Symbol s; 7849657Slinton 7859657Slinton switch (p->op) { 7869657Slinton case O_SYM: 7879657Slinton p->nodetype = namenode(p); 7889657Slinton break; 7899657Slinton 7909657Slinton case O_LCON: 7919657Slinton p->nodetype = t_int; 7929657Slinton break; 7939657Slinton 7949657Slinton case O_FCON: 7959657Slinton p->nodetype = t_real; 7969657Slinton break; 7979657Slinton 7989657Slinton case O_SCON: 7999657Slinton p->value.scon = strdup(p->value.scon); 8009657Slinton s = mkstring(p->value.scon); 8019657Slinton if (s == t_char) { 8029657Slinton p->op = O_LCON; 8039657Slinton p->value.lcon = p->value.scon[0]; 8049657Slinton } 8059657Slinton p->nodetype = s; 8069657Slinton break; 8079657Slinton 8089657Slinton case O_INDIR: 8099657Slinton p1 = p->value.arg[0]; 8109657Slinton chkclass(p1, PTR); 8119657Slinton p->nodetype = rtype(p1->nodetype)->type; 8129657Slinton break; 8139657Slinton 8149657Slinton case O_DOT: 8159657Slinton p->nodetype = p->value.arg[1]->value.sym; 8169657Slinton break; 8179657Slinton 8189657Slinton case O_RVAL: 8199657Slinton p1 = p->value.arg[0]; 8209657Slinton p->nodetype = p1->nodetype; 8219657Slinton if (p1->op == O_SYM) { 8229657Slinton if (p1->nodetype->class == FUNC) { 8239657Slinton p->op = O_CALL; 8249657Slinton p->value.arg[1] = nil; 8259657Slinton } else if (p1->value.sym->class == CONST) { 8269657Slinton if (compatible(p1->value.sym->type, t_real)) { 8279657Slinton p->op = O_FCON; 8289657Slinton p->value.fcon = p1->value.sym->symvalue.fconval; 8299657Slinton p->nodetype = t_real; 8309657Slinton dispose(p1); 8319657Slinton } else { 8329657Slinton p->op = O_LCON; 8339657Slinton p->value.lcon = p1->value.sym->symvalue.iconval; 8349657Slinton p->nodetype = p1->value.sym->type; 8359657Slinton dispose(p1); 8369657Slinton } 8379657Slinton } else if (isreg(p1->value.sym)) { 8389657Slinton p->op = O_SYM; 8399657Slinton p->value.sym = p1->value.sym; 8409657Slinton dispose(p1); 8419657Slinton } 8429657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 8439657Slinton s = p1->value.arg[0]->value.sym; 8449657Slinton if (isreg(s)) { 8459657Slinton p1->op = O_SYM; 8469657Slinton dispose(p1->value.arg[0]); 8479657Slinton p1->value.sym = s; 8489657Slinton p1->nodetype = s; 8499657Slinton } 8509657Slinton } 8519657Slinton break; 8529657Slinton 8539657Slinton /* 8549657Slinton * Perform a cast if the call is of the form "type(expr)". 8559657Slinton */ 8569657Slinton case O_CALL: 8579657Slinton p1 = p->value.arg[0]; 85811171Slinton p->nodetype = rtype(p1->nodetype)->type; 8599657Slinton break; 8609657Slinton 86111171Slinton case O_TYPERENAME: 86211171Slinton p->nodetype = p->value.arg[1]->nodetype; 86311171Slinton break; 86411171Slinton 8659657Slinton case O_ITOF: 8669657Slinton p->nodetype = t_real; 8679657Slinton break; 8689657Slinton 8699657Slinton case O_NEG: 8709657Slinton s = p->value.arg[0]->nodetype; 8719657Slinton if (not compatible(s, t_int)) { 8729657Slinton if (not compatible(s, t_real)) { 8739657Slinton beginerrmsg(); 8749657Slinton prtree(stderr, p->value.arg[0]); 8759657Slinton fprintf(stderr, "is improper type"); 8769657Slinton enderrmsg(); 8779657Slinton } else { 8789657Slinton p->op = O_NEGF; 8799657Slinton } 8809657Slinton } 8819657Slinton p->nodetype = s; 8829657Slinton break; 8839657Slinton 8849657Slinton case O_ADD: 8859657Slinton case O_SUB: 8869657Slinton case O_MUL: 8879657Slinton case O_LT: 8889657Slinton case O_LE: 8899657Slinton case O_GT: 8909657Slinton case O_GE: 8919657Slinton case O_EQ: 8929657Slinton case O_NE: 8939657Slinton { 8949657Slinton Boolean t1real, t2real; 8959657Slinton Symbol t1, t2; 8969657Slinton 8979657Slinton t1 = rtype(p->value.arg[0]->nodetype); 8989657Slinton t2 = rtype(p->value.arg[1]->nodetype); 8999657Slinton t1real = compatible(t1, t_real); 9009657Slinton t2real = compatible(t2, t_real); 9019657Slinton if (t1real or t2real) { 9029657Slinton p->op = (Operator) (ord(p->op) + 1); 9039657Slinton if (not t1real) { 9049657Slinton p->value.arg[0] = build(O_ITOF, p->value.arg[0]); 9059657Slinton } else if (not t2real) { 9069657Slinton p->value.arg[1] = build(O_ITOF, p->value.arg[1]); 9079657Slinton } 9089657Slinton } else { 9099657Slinton if (t1real) { 9109657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 9119657Slinton } 9129657Slinton if (t2real) { 9139657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 9149657Slinton } 9159657Slinton } 9169657Slinton if (ord(p->op) >= ord(O_LT)) { 9179657Slinton p->nodetype = t_boolean; 9189657Slinton } else { 9199657Slinton if (t1real or t2real) { 9209657Slinton p->nodetype = t_real; 9219657Slinton } else { 9229657Slinton p->nodetype = t_int; 9239657Slinton } 9249657Slinton } 9259657Slinton break; 9269657Slinton } 9279657Slinton 9289657Slinton case O_DIVF: 9299657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 9309657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 9319657Slinton p->nodetype = t_real; 9329657Slinton break; 9339657Slinton 9349657Slinton case O_DIV: 9359657Slinton case O_MOD: 9369657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 9379657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 9389657Slinton p->nodetype = t_int; 9399657Slinton break; 9409657Slinton 9419657Slinton case O_AND: 9429657Slinton case O_OR: 9439657Slinton chkboolean(p->value.arg[0]); 9449657Slinton chkboolean(p->value.arg[1]); 9459657Slinton p->nodetype = t_boolean; 9469657Slinton break; 9479657Slinton 9489657Slinton case O_QLINE: 9499657Slinton p->nodetype = t_int; 9509657Slinton break; 9519657Slinton 9529657Slinton default: 9539657Slinton p->nodetype = nil; 9549657Slinton break; 9559657Slinton } 9569657Slinton } 9579657Slinton 9589657Slinton /* 9599657Slinton * Create a node for a name. The symbol for the name has already 9609657Slinton * been chosen, either implicitly with "which" or explicitly from 9619657Slinton * the dot routine. 9629657Slinton */ 9639657Slinton 9649657Slinton private Symbol namenode(p) 9659657Slinton Node p; 9669657Slinton { 9679657Slinton register Symbol r, s; 9689657Slinton register Node np; 9699657Slinton 9709657Slinton s = p->value.sym; 9719657Slinton if (s->class == REF) { 9729657Slinton np = new(Node); 9739657Slinton np->op = p->op; 9749657Slinton np->nodetype = s; 9759657Slinton np->value.sym = s; 9769657Slinton p->op = O_INDIR; 9779657Slinton p->value.arg[0] = np; 9789657Slinton } 9799657Slinton /* 9809657Slinton * Old way 9819657Slinton * 9829657Slinton if (s->class == CONST or s->class == VAR or s->class == FVAR) { 9839657Slinton r = s->type; 9849657Slinton } else { 9859657Slinton r = s; 9869657Slinton } 9879657Slinton * 9889657Slinton */ 9899657Slinton return s; 9909657Slinton } 9919657Slinton 9929657Slinton /* 9939657Slinton * Convert a tree to a type via a conversion operator; 9949657Slinton * if this isn't possible generate an error. 9959657Slinton * 9969657Slinton * Note the tree is call by address, hence the #define below. 9979657Slinton */ 9989657Slinton 9999657Slinton private convert(tp, typeto, op) 10009657Slinton Node *tp; 10019657Slinton Symbol typeto; 10029657Slinton Operator op; 10039657Slinton { 10049657Slinton #define tree (*tp) 10059657Slinton 10069657Slinton Symbol s; 10079657Slinton 10089657Slinton s = rtype(tree->nodetype); 10099657Slinton typeto = rtype(typeto); 10109657Slinton if (compatible(typeto, t_real) and compatible(s, t_int)) { 10119657Slinton tree = build(op, tree); 10129657Slinton } else if (not compatible(s, typeto)) { 10139657Slinton beginerrmsg(); 10149657Slinton prtree(stderr, s); 10159657Slinton fprintf(stderr, " is improper type"); 10169657Slinton enderrmsg(); 10179657Slinton } else if (op != O_NOP and s != typeto) { 10189657Slinton tree = build(op, tree); 10199657Slinton } 10209657Slinton 10219657Slinton #undef tree 10229657Slinton } 10239657Slinton 10249657Slinton /* 10259657Slinton * Construct a node for the dot operator. 10269657Slinton * 10279657Slinton * If the left operand is not a record, but rather a procedure 10289657Slinton * or function, then we interpret the "." as referencing an 10299657Slinton * "invisible" variable; i.e. a variable within a dynamically 10309657Slinton * active block but not within the static scope of the current procedure. 10319657Slinton */ 10329657Slinton 10339657Slinton public Node dot(record, fieldname) 10349657Slinton Node record; 10359657Slinton Name fieldname; 10369657Slinton { 10379657Slinton register Node p; 10389657Slinton register Symbol s, t; 10399657Slinton 10409657Slinton if (isblock(record->nodetype)) { 10419657Slinton find(s, fieldname) where 10429657Slinton s->block == record->nodetype and 10439657Slinton s->class != FIELD and s->class != TAG 10449657Slinton endfind(s); 10459657Slinton if (s == nil) { 10469657Slinton beginerrmsg(); 10479657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 10489657Slinton printname(stderr, record->nodetype); 10499657Slinton enderrmsg(); 10509657Slinton } 10519657Slinton p = new(Node); 10529657Slinton p->op = O_SYM; 10539657Slinton p->value.sym = s; 10549657Slinton p->nodetype = namenode(p); 10559657Slinton } else { 10569657Slinton p = record; 10579657Slinton t = rtype(p->nodetype); 10589657Slinton if (t->class == PTR) { 10599657Slinton s = findfield(fieldname, t->type); 10609657Slinton } else { 10619657Slinton s = findfield(fieldname, t); 10629657Slinton } 10639657Slinton if (s == nil) { 10649657Slinton beginerrmsg(); 10659657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 10669657Slinton prtree(stderr, record); 10679657Slinton enderrmsg(); 10689657Slinton } 10699657Slinton if (t->class == PTR and not isreg(record->nodetype)) { 10709657Slinton p = build(O_INDIR, record); 10719657Slinton } 10729657Slinton p = build(O_DOT, p, build(O_SYM, s)); 10739657Slinton } 10749657Slinton return p; 10759657Slinton } 10769657Slinton 10779657Slinton /* 10789657Slinton * Return a tree corresponding to an array reference and do the 10799657Slinton * error checking. 10809657Slinton */ 10819657Slinton 10829657Slinton public Node subscript(a, slist) 10839657Slinton Node a, slist; 10849657Slinton { 1085*12547Scsvaf Symbol t; 10869657Slinton 1087*12547Scsvaf t = rtype(a->nodetype); 1088*12547Scsvaf if(t->language == nil) { 1089*12547Scsvaf error("unknown language"); 1090*12547Scsvaf } 1091*12547Scsvaf else { 1092*12547Scsvaf return ( (Node) 1093*12547Scsvaf (*language_op(t->language, L_BUILDAREF)) (a,slist) 1094*12547Scsvaf ); 1095*12547Scsvaf } 10969657Slinton } 10979657Slinton 10989657Slinton /* 10999657Slinton * Evaluate a subscript index. 11009657Slinton */ 11019657Slinton 11029657Slinton public int evalindex(s, i) 11039657Slinton Symbol s; 11049657Slinton long i; 11059657Slinton { 1106*12547Scsvaf Symbol t; 11079657Slinton 1108*12547Scsvaf t = rtype(s); 1109*12547Scsvaf if(t->language == nil) { 1110*12547Scsvaf error("unknown language"); 1111*12547Scsvaf } 1112*12547Scsvaf else { 1113*12547Scsvaf return ( 1114*12547Scsvaf (*language_op(t->language, L_EVALAREF)) (s,i) 1115*12547Scsvaf ); 1116*12547Scsvaf } 11179657Slinton } 11189657Slinton 11199657Slinton /* 11209657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 11219657Slinton */ 11229657Slinton 11239657Slinton public chkboolean(p) 11249657Slinton register Node p; 11259657Slinton { 11269657Slinton if (p->nodetype != t_boolean) { 11279657Slinton beginerrmsg(); 11289657Slinton fprintf(stderr, "found "); 11299657Slinton prtree(stderr, p); 11309657Slinton fprintf(stderr, ", expected boolean expression"); 11319657Slinton enderrmsg(); 11329657Slinton } 11339657Slinton } 11349657Slinton 11359657Slinton /* 11369657Slinton * Check to make sure the given tree has a type of the given class. 11379657Slinton */ 11389657Slinton 11399657Slinton private chkclass(p, class) 11409657Slinton Node p; 11419657Slinton Symclass class; 11429657Slinton { 11439657Slinton struct Symbol tmpsym; 11449657Slinton 11459657Slinton tmpsym.class = class; 11469657Slinton if (rtype(p->nodetype)->class != class) { 11479657Slinton beginerrmsg(); 11489657Slinton fprintf(stderr, "\""); 11499657Slinton prtree(stderr, p); 11509657Slinton fprintf(stderr, "\" is not a %s", classname(&tmpsym)); 11519657Slinton enderrmsg(); 11529657Slinton } 11539657Slinton } 11549657Slinton 11559657Slinton /* 11569657Slinton * Construct a node for the type of a string. While we're at it, 11579657Slinton * scan the string for '' that collapse to ', and chop off the ends. 11589657Slinton */ 11599657Slinton 11609657Slinton private Symbol mkstring(str) 11619657Slinton String str; 11629657Slinton { 11639657Slinton register char *p, *q; 11649657Slinton register Symbol s; 11659657Slinton 11669657Slinton p = str; 11679657Slinton q = str; 11689657Slinton while (*p != '\0') { 11699657Slinton if (*p == '\\') { 11709657Slinton ++p; 11719657Slinton } 11729657Slinton *q = *p; 11739657Slinton ++p; 11749657Slinton ++q; 11759657Slinton } 11769657Slinton *q = '\0'; 11779657Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 11789657Slinton s->language = findlanguage(".s"); 11799657Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 11809657Slinton s->chain->language = s->language; 11819657Slinton s->chain->symvalue.rangev.lower = 1; 11829657Slinton s->chain->symvalue.rangev.upper = p - str + 1; 11839657Slinton return s; 11849657Slinton } 11859657Slinton 11869657Slinton /* 11879657Slinton * Free up the space allocated for a string type. 11889657Slinton */ 11899657Slinton 11909657Slinton public unmkstring(s) 11919657Slinton Symbol s; 11929657Slinton { 11939657Slinton dispose(s->chain); 11949657Slinton } 11959657Slinton 11969657Slinton /* 11979657Slinton * Figure out the "current" variable or function being referred to, 11989657Slinton * this is either the active one or the most visible from the 11999657Slinton * current scope. 12009657Slinton */ 12019657Slinton 12029657Slinton public Symbol which(n) 12039657Slinton Name n; 12049657Slinton { 12059657Slinton register Symbol s, p, t, f; 12069657Slinton 12079657Slinton find(s, n) where s->class != FIELD and s->class != TAG endfind(s); 12089657Slinton if (s == nil) { 12099657Slinton s = lookup(n); 12109657Slinton } 12119657Slinton if (s == nil) { 12129657Slinton error("\"%s\" is not defined", ident(n)); 12139657Slinton } else if (s == program or isbuiltin(s)) { 12149657Slinton t = s; 12159657Slinton } else { 12169657Slinton /* 12179657Slinton * Old way 12189657Slinton * 12199657Slinton if (not isactive(program)) { 12209657Slinton f = program; 12219657Slinton } else { 12229657Slinton f = whatblock(pc); 12239657Slinton if (f == nil) { 12249657Slinton panic("no block for addr 0x%x", pc); 12259657Slinton } 12269657Slinton } 12279657Slinton * 12289657Slinton * Now start with curfunc. 12299657Slinton */ 12309657Slinton p = curfunc; 12319657Slinton do { 12329657Slinton find(t, n) where 12339657Slinton t->block == p and t->class != FIELD and t->class != TAG 12349657Slinton endfind(t); 12359657Slinton p = p->block; 12369657Slinton } while (t == nil and p != nil); 12379657Slinton if (t == nil) { 12389657Slinton t = s; 12399657Slinton } 12409657Slinton } 12419657Slinton return t; 12429657Slinton } 12439657Slinton 12449657Slinton /* 12459657Slinton * Find the symbol which is has the same name and scope as the 12469657Slinton * given symbol but is of the given field. Return nil if there is none. 12479657Slinton */ 12489657Slinton 12499657Slinton public Symbol findfield(fieldname, record) 12509657Slinton Name fieldname; 12519657Slinton Symbol record; 12529657Slinton { 12539657Slinton register Symbol t; 12549657Slinton 12559657Slinton t = rtype(record)->chain; 12569657Slinton while (t != nil and t->name != fieldname) { 12579657Slinton t = t->chain; 12589657Slinton } 12599657Slinton return t; 12609657Slinton } 1261*12547Scsvaf 1262*12547Scsvaf public Boolean getbound(s,off,type,valp) 1263*12547Scsvaf Symbol s; 1264*12547Scsvaf int off; 1265*12547Scsvaf Rangetype type; 1266*12547Scsvaf int *valp; 1267*12547Scsvaf { 1268*12547Scsvaf Frame frp; 1269*12547Scsvaf Address addr; 1270*12547Scsvaf Symbol cur; 1271*12547Scsvaf 1272*12547Scsvaf if (not isactive(s->block)) { 1273*12547Scsvaf return(false); 1274*12547Scsvaf } 1275*12547Scsvaf cur = s->block; 1276*12547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 1277*12547Scsvaf cur = cur->block; 1278*12547Scsvaf } 1279*12547Scsvaf if(cur == nil) { 1280*12547Scsvaf cur = whatblock(pc); 1281*12547Scsvaf } 1282*12547Scsvaf frp = findframe(cur); 1283*12547Scsvaf if (frp == nil) { 1284*12547Scsvaf return(false); 1285*12547Scsvaf } 1286*12547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 1287*12547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 1288*12547Scsvaf else return(false); 1289*12547Scsvaf dread(valp,addr,sizeof(long)); 1290*12547Scsvaf return(true); 1291*12547Scsvaf } 1292