19657Slinton /* Copyright (c) 1982 Regents of the University of California */ 29657Slinton 3*14441Slinton static char sccsid[] = "@(#)symbols.c 1.10 08/10/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, 3612547Scsvaf PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 379657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 3812547Scsvaf FPROC, FFUNC, MODULE, TAG, COMMON, TYPEREF 399657Slinton } Symclass; 409657Slinton 4112547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 4212547Scsvaf 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; 5812547Scsvaf struct { /* common offset and chain; used to relocate */ 5912547Scsvaf int offset; /* vars in global BSS */ 6012547Scsvaf Symbol chain; 6112547Scsvaf } common; 629657Slinton struct { /* range bounds */ 6312547Scsvaf Rangetype lowertype : 16; 6412547Scsvaf Rangetype uppertype : 16; 659657Slinton long lower; 669657Slinton long upper; 679657Slinton } rangev; 6811865Slinton struct { 6911865Slinton int offset : 16; /* offset for of function value */ 70*14441Slinton Boolean src : 8; /* true if there is source line info */ 71*14441Slinton Boolean inline : 8; /* true if no separate act. rec. */ 7211865Slinton Address beginaddr; /* address of function code */ 739657Slinton } funcv; 749657Slinton struct { /* variant record info */ 759657Slinton int size; 769657Slinton Symbol vtorec; 779657Slinton Symbol vtag; 789657Slinton } varnt; 799657Slinton } symvalue; 809657Slinton Symbol block; /* symbol containing this symbol */ 819657Slinton Symbol next_sym; /* hash chain */ 829657Slinton }; 839657Slinton 849657Slinton /* 859657Slinton * Basic types. 869657Slinton */ 879657Slinton 889657Slinton Symbol t_boolean; 899657Slinton Symbol t_char; 909657Slinton Symbol t_int; 919657Slinton Symbol t_real; 929657Slinton Symbol t_nil; 939657Slinton 949657Slinton Symbol program; 959657Slinton Symbol curfunc; 969657Slinton 979657Slinton #define symname(s) ident(s->name) 989657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 999657Slinton #define isblock(s) (Boolean) ( \ 1009657Slinton s->class == FUNC or s->class == PROC or \ 1019657Slinton s->class == MODULE or s->class == PROG \ 1029657Slinton ) 1039657Slinton 10411865Slinton #define nosource(f) (not (f)->symvalue.funcv.src) 105*14441Slinton #define isinline(f) ((f)->symvalue.funcv.inline) 10611865Slinton 1079657Slinton #include "tree.h" 1089657Slinton 1099657Slinton /* 1109657Slinton * Some macros to make finding a symbol with certain attributes. 1119657Slinton */ 1129657Slinton 1139657Slinton #define find(s, withname) \ 1149657Slinton { \ 1159657Slinton s = lookup(withname); \ 1169657Slinton while (s != nil and not (s->name == (withname) and 1179657Slinton 1189657Slinton #define where /* qualification */ 1199657Slinton 1209657Slinton #define endfind(s) )) { \ 1219657Slinton s = s->next_sym; \ 1229657Slinton } \ 1239657Slinton } 1249657Slinton 1259657Slinton #endif 1269657Slinton 1279657Slinton /* 1289657Slinton * Symbol table structure currently does not support deletions. 1299657Slinton */ 1309657Slinton 1319657Slinton #define HASHTABLESIZE 2003 1329657Slinton 1339657Slinton private Symbol hashtab[HASHTABLESIZE]; 1349657Slinton 1359657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 1369657Slinton 1379657Slinton /* 1389657Slinton * Allocate a new symbol. 1399657Slinton */ 1409657Slinton 14111171Slinton #define SYMBLOCKSIZE 100 1429657Slinton 1439657Slinton typedef struct Sympool { 1449657Slinton struct Symbol sym[SYMBLOCKSIZE]; 1459657Slinton struct Sympool *prevpool; 1469657Slinton } *Sympool; 1479657Slinton 1489657Slinton private Sympool sympool = nil; 1499657Slinton private Integer nleft = 0; 1509657Slinton 1519657Slinton public Symbol symbol_alloc() 1529657Slinton { 1539657Slinton register Sympool newpool; 1549657Slinton 1559657Slinton if (nleft <= 0) { 1569657Slinton newpool = new(Sympool); 15711171Slinton bzero(newpool, sizeof(newpool)); 1589657Slinton newpool->prevpool = sympool; 1599657Slinton sympool = newpool; 1609657Slinton nleft = SYMBLOCKSIZE; 1619657Slinton } 1629657Slinton --nleft; 1639657Slinton return &(sympool->sym[nleft]); 1649657Slinton } 1659657Slinton 16612547Scsvaf 16712547Scsvaf public symbol_dump(func) 16812547Scsvaf Symbol func; 16912547Scsvaf { 17012547Scsvaf register Symbol s; 17112547Scsvaf register Integer i; 17212547Scsvaf 17312547Scsvaf printf(" symbols in %s \n",symname(func)); 17412547Scsvaf for(i=0; i< HASHTABLESIZE; i++) 17512547Scsvaf for(s=hashtab[i]; s != nil; s=s->next_sym) { 17612547Scsvaf if (s->block == func) psym(s); 17712547Scsvaf } 17812547Scsvaf } 17912547Scsvaf 1809657Slinton /* 1819657Slinton * Free all the symbols currently allocated. 1829657Slinton */ 1839657Slinton public symbol_free() 1849657Slinton { 1859657Slinton Sympool s, t; 1869657Slinton register Integer i; 1879657Slinton 1889657Slinton s = sympool; 1899657Slinton while (s != nil) { 1909657Slinton t = s->prevpool; 1919657Slinton dispose(s); 1929657Slinton s = t; 1939657Slinton } 1949657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 1959657Slinton hashtab[i] = nil; 1969657Slinton } 1979657Slinton sympool = nil; 1989657Slinton nleft = 0; 1999657Slinton } 2009657Slinton 2019657Slinton /* 2029657Slinton * Create a new symbol with the given attributes. 2039657Slinton */ 2049657Slinton 2059657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 2069657Slinton Name name; 2079657Slinton Integer blevel; 2089657Slinton Symclass class; 2099657Slinton Symbol type; 2109657Slinton Symbol chain; 2119657Slinton { 2129657Slinton register Symbol s; 2139657Slinton 2149657Slinton s = symbol_alloc(); 2159657Slinton s->name = name; 2169657Slinton s->level = blevel; 2179657Slinton s->class = class; 2189657Slinton s->type = type; 2199657Slinton s->chain = chain; 2209657Slinton return s; 2219657Slinton } 2229657Slinton 2239657Slinton /* 2249657Slinton * Insert a symbol into the hash table. 2259657Slinton */ 2269657Slinton 2279657Slinton public Symbol insert(name) 2289657Slinton Name name; 2299657Slinton { 2309657Slinton register Symbol s; 2319657Slinton register unsigned int h; 2329657Slinton 2339657Slinton h = hash(name); 2349657Slinton s = symbol_alloc(); 2359657Slinton s->name = name; 2369657Slinton s->next_sym = hashtab[h]; 2379657Slinton hashtab[h] = s; 2389657Slinton return s; 2399657Slinton } 2409657Slinton 2419657Slinton /* 2429657Slinton * Symbol lookup. 2439657Slinton */ 2449657Slinton 2459657Slinton public Symbol lookup(name) 2469657Slinton Name name; 2479657Slinton { 2489657Slinton register Symbol s; 2499657Slinton register unsigned int h; 2509657Slinton 2519657Slinton h = hash(name); 2529657Slinton s = hashtab[h]; 2539657Slinton while (s != nil and s->name != name) { 2549657Slinton s = s->next_sym; 2559657Slinton } 2569657Slinton return s; 2579657Slinton } 2589657Slinton 2599657Slinton /* 2609657Slinton * Dump out all the variables associated with the given 2619657Slinton * procedure, function, or program at the given recursive level. 2629657Slinton * 2639657Slinton * This is quite inefficient. We traverse the entire symbol table 2649657Slinton * each time we're called. The assumption is that this routine 2659657Slinton * won't be called frequently enough to merit improved performance. 2669657Slinton */ 2679657Slinton 2689657Slinton public dumpvars(f, frame) 2699657Slinton Symbol f; 2709657Slinton Frame frame; 2719657Slinton { 2729657Slinton register Integer i; 2739657Slinton register Symbol s; 2749657Slinton 2759657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 2769657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 2779657Slinton if (container(s) == f) { 2789657Slinton if (should_print(s)) { 2799657Slinton printv(s, frame); 2809657Slinton putchar('\n'); 2819657Slinton } else if (s->class == MODULE) { 2829657Slinton dumpvars(s, frame); 2839657Slinton } 2849657Slinton } 2859657Slinton } 2869657Slinton } 2879657Slinton } 2889657Slinton 2899657Slinton /* 2909657Slinton * Create a builtin type. 2919657Slinton * Builtin types are circular in that btype->type->type = btype. 2929657Slinton */ 2939657Slinton 2949657Slinton public Symbol maketype(name, lower, upper) 2959657Slinton String name; 2969657Slinton long lower; 2979657Slinton long upper; 2989657Slinton { 2999657Slinton register Symbol s; 3009657Slinton 3019657Slinton s = newSymbol(identname(name, true), 0, TYPE, nil, nil); 3029657Slinton s->language = findlanguage(".c"); 3039657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 3049657Slinton s->type->symvalue.rangev.lower = lower; 3059657Slinton s->type->symvalue.rangev.upper = upper; 3069657Slinton return s; 3079657Slinton } 3089657Slinton 3099657Slinton /* 3109657Slinton * These functions are now compiled inline. 3119657Slinton * 3129657Slinton * public String symname(s) 3139657Slinton Symbol s; 3149657Slinton { 3159657Slinton checkref(s); 3169657Slinton return ident(s->name); 3179657Slinton } 3189657Slinton 3199657Slinton * 3209657Slinton * public Address codeloc(f) 3219657Slinton Symbol f; 3229657Slinton { 3239657Slinton checkref(f); 3249657Slinton if (not isblock(f)) { 3259657Slinton panic("codeloc: \"%s\" is not a block", ident(f->name)); 3269657Slinton } 3279657Slinton return f->symvalue.funcv.beginaddr; 3289657Slinton } 3299657Slinton * 3309657Slinton */ 3319657Slinton 3329657Slinton /* 3339657Slinton * Reduce type to avoid worrying about type names. 3349657Slinton */ 3359657Slinton 3369657Slinton public Symbol rtype(type) 3379657Slinton Symbol type; 3389657Slinton { 3399657Slinton register Symbol t; 3409657Slinton 3419657Slinton t = type; 3429657Slinton if (t != nil) { 34312547Scsvaf if (t->class == VAR or t->class == FIELD or t->class == REF ) { 3449657Slinton t = t->type; 3459657Slinton } 3469657Slinton while (t->class == TYPE or t->class == TAG) { 3479657Slinton t = t->type; 3489657Slinton } 3499657Slinton } 3509657Slinton return t; 3519657Slinton } 3529657Slinton 3539657Slinton public Integer level(s) 3549657Slinton Symbol s; 3559657Slinton { 3569657Slinton checkref(s); 3579657Slinton return s->level; 3589657Slinton } 3599657Slinton 3609657Slinton public Symbol container(s) 3619657Slinton Symbol s; 3629657Slinton { 3639657Slinton checkref(s); 3649657Slinton return s->block; 3659657Slinton } 3669657Slinton 3679657Slinton /* 3689657Slinton * Return the object address of the given symbol. 3699657Slinton * 3709657Slinton * There are the following possibilities: 3719657Slinton * 3729657Slinton * globals - just take offset 3739657Slinton * locals - take offset from locals base 3749657Slinton * arguments - take offset from argument base 3759657Slinton * register - offset is register number 3769657Slinton */ 3779657Slinton 3789657Slinton #define isglobal(s) (s->level == 1 or s->level == 2) 3799657Slinton #define islocaloff(s) (s->level >= 3 and s->symvalue.offset < 0) 3809657Slinton #define isparamoff(s) (s->level >= 3 and s->symvalue.offset >= 0) 3819657Slinton #define isreg(s) (s->level < 0) 3829657Slinton 3839657Slinton public Address address(s, frame) 3849657Slinton Symbol s; 3859657Slinton Frame frame; 3869657Slinton { 3879657Slinton register Frame frp; 3889657Slinton register Address addr; 3899657Slinton register Symbol cur; 3909657Slinton 3919657Slinton checkref(s); 3929657Slinton if (not isactive(s->block)) { 3939657Slinton error("\"%s\" is not currently defined", symname(s)); 3949657Slinton } else if (isglobal(s)) { 3959657Slinton addr = s->symvalue.offset; 3969657Slinton } else { 3979657Slinton frp = frame; 3989657Slinton if (frp == nil) { 3999657Slinton cur = s->block; 4009657Slinton while (cur != nil and cur->class == MODULE) { 4019657Slinton cur = cur->block; 4029657Slinton } 4039657Slinton if (cur == nil) { 4049657Slinton cur = whatblock(pc); 4059657Slinton } 4069657Slinton frp = findframe(cur); 4079657Slinton if (frp == nil) { 4089657Slinton panic("unexpected nil frame for \"%s\"", symname(s)); 4099657Slinton } 4109657Slinton } 4119657Slinton if (islocaloff(s)) { 4129657Slinton addr = locals_base(frp) + s->symvalue.offset; 4139657Slinton } else if (isparamoff(s)) { 4149657Slinton addr = args_base(frp) + s->symvalue.offset; 4159657Slinton } else if (isreg(s)) { 4169657Slinton addr = savereg(s->symvalue.offset, frp); 4179657Slinton } else { 4189657Slinton panic("address: bad symbol \"%s\"", symname(s)); 4199657Slinton } 4209657Slinton } 4219657Slinton return addr; 4229657Slinton } 4239657Slinton 4249657Slinton /* 4259657Slinton * Define a symbol used to access register values. 4269657Slinton */ 4279657Slinton 4289657Slinton public defregname(n, r) 4299657Slinton Name n; 4309657Slinton Integer r; 4319657Slinton { 4329657Slinton register Symbol s, t; 4339657Slinton 4349657Slinton s = insert(n); 4359657Slinton t = newSymbol(nil, 0, PTR, t_int, nil); 4369657Slinton t->language = findlanguage(".s"); 4379657Slinton s->language = t->language; 4389657Slinton s->class = VAR; 4399657Slinton s->level = -3; 4409657Slinton s->type = t; 4419657Slinton s->block = program; 4429657Slinton s->symvalue.offset = r; 4439657Slinton } 4449657Slinton 4459657Slinton /* 4469657Slinton * Resolve an "abstract" type reference. 4479657Slinton * 4489657Slinton * It is possible in C to define a pointer to a type, but never define 4499657Slinton * the type in a particular source file. Here we try to resolve 4509657Slinton * the type definition. This is problematic, it is possible to 4519657Slinton * have multiple, different definitions for the same name type. 4529657Slinton */ 4539657Slinton 4549657Slinton public findtype(s) 4559657Slinton Symbol s; 4569657Slinton { 4579657Slinton register Symbol t, u, prev; 4589657Slinton 4599657Slinton u = s; 4609657Slinton prev = nil; 4619657Slinton while (u != nil and u->class != BADUSE) { 4629657Slinton if (u->name != nil) { 4639657Slinton prev = u; 4649657Slinton } 4659657Slinton u = u->type; 4669657Slinton } 4679657Slinton if (prev == nil) { 4689657Slinton error("couldn't find link to type reference"); 4699657Slinton } 4709657Slinton find(t, prev->name) where 4719657Slinton t->type != nil and t->class == prev->class and 4729657Slinton t->type->class != BADUSE and t->block->class == MODULE 4739657Slinton endfind(t); 4749657Slinton if (t == nil) { 4759657Slinton error("couldn't resolve reference"); 4769657Slinton } else { 4779657Slinton prev->type = t->type; 4789657Slinton } 4799657Slinton } 4809657Slinton 4819657Slinton /* 4829657Slinton * Find the size in bytes of the given type. 4839657Slinton * 4849657Slinton * This is probably the WRONG thing to do. The size should be kept 4859657Slinton * as an attribute in the symbol information as is done for structures 4869657Slinton * and fields. I haven't gotten around to cleaning this up yet. 4879657Slinton */ 4889657Slinton 48912547Scsvaf #define MAXUCHAR 255 49012547Scsvaf #define MAXUSHORT 65535L 4919657Slinton #define MINCHAR -128 4929657Slinton #define MAXCHAR 127 4939657Slinton #define MINSHORT -32768 4949657Slinton #define MAXSHORT 32767 4959657Slinton 4969657Slinton public Integer size(sym) 4979657Slinton Symbol sym; 4989657Slinton { 4999657Slinton register Symbol s, t; 5009657Slinton register int nel, elsize; 5019657Slinton long lower, upper; 5029657Slinton int r; 5039657Slinton 5049657Slinton t = sym; 5059657Slinton checkref(t); 5069657Slinton switch (t->class) { 5079657Slinton case RANGE: 5089657Slinton lower = t->symvalue.rangev.lower; 5099657Slinton upper = t->symvalue.rangev.upper; 5109657Slinton if (upper == 0 and lower > 0) { /* real */ 5119657Slinton r = lower; 51212045Slinton } else if ( 51312547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or 51412547Scsvaf (lower >= 0 and upper <= MAXUCHAR) 51512547Scsvaf ) { 5169657Slinton r = sizeof(char); 51712547Scsvaf } else if ( 51812547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or 51912547Scsvaf (lower >= 0 and upper <= MAXUSHORT) 52012547Scsvaf ) { 5219657Slinton r = sizeof(short); 5229657Slinton } else { 5239657Slinton r = sizeof(long); 5249657Slinton } 5259657Slinton break; 5269657Slinton 5279657Slinton case ARRAY: 5289657Slinton elsize = size(t->type); 5299657Slinton nel = 1; 5309657Slinton for (t = t->chain; t != nil; t = t->chain) { 53112609Slinton if (t->symvalue.rangev.lowertype == R_ARG or 53212609Slinton t->symvalue.rangev.lowertype == R_TEMP) { 53312609Slinton if (not getbound(t, t->symvalue.rangev.lower, 53412609Slinton t->symvalue.rangev.lowertype, &lower)) { 53512609Slinton error("dynamic bounds not currently available"); 53612609Slinton } 53712609Slinton } else { 53812609Slinton lower = t->symvalue.rangev.lower; 53912547Scsvaf } 54012609Slinton if (t->symvalue.rangev.uppertype == R_ARG or 54112609Slinton t->symvalue.rangev.uppertype == R_TEMP) { 54212609Slinton if (not getbound(t, t->symvalue.rangev.upper, 54312609Slinton t->symvalue.rangev.uppertype, &upper)) { 54412609Slinton error("dynamic bounds nor currently available"); 54512609Slinton } 54612609Slinton } else { 54712609Slinton upper = t->symvalue.rangev.upper; 54812547Scsvaf } 5499657Slinton nel *= (upper-lower+1); 5509657Slinton } 5519657Slinton r = nel*elsize; 5529657Slinton break; 5539657Slinton 55412547Scsvaf case REF: 5559657Slinton case VAR: 5569657Slinton case FVAR: 5579657Slinton r = size(t->type); 55812127Slinton /* 55912127Slinton * 56012045Slinton if (r < sizeof(Word) and isparam(t)) { 5619657Slinton r = sizeof(Word); 5629657Slinton } 56312547Scsvaf */ 5649657Slinton break; 5659657Slinton 5669657Slinton case CONST: 5679657Slinton r = size(t->type); 5689657Slinton break; 5699657Slinton 5709657Slinton case TYPE: 5719657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 5729657Slinton findtype(t); 5739657Slinton } 5749657Slinton r = size(t->type); 5759657Slinton break; 5769657Slinton 5779657Slinton case TAG: 5789657Slinton r = size(t->type); 5799657Slinton break; 5809657Slinton 5819657Slinton case FIELD: 5829657Slinton r = (t->symvalue.field.length + 7) div 8; 5839657Slinton break; 5849657Slinton 5859657Slinton case RECORD: 5869657Slinton case VARNT: 5879657Slinton r = t->symvalue.offset; 5889657Slinton if (r == 0 and t->chain != nil) { 5899657Slinton panic("missing size information for record"); 5909657Slinton } 5919657Slinton break; 5929657Slinton 5939657Slinton case PTR: 5949657Slinton case FILET: 5959657Slinton r = sizeof(Word); 5969657Slinton break; 5979657Slinton 5989657Slinton case SCAL: 59912609Slinton r = sizeof(Word); 60012609Slinton /* 60112609Slinton * 6029657Slinton if (t->symvalue.iconval > 255) { 6039657Slinton r = sizeof(short); 6049657Slinton } else { 6059657Slinton r = sizeof(char); 6069657Slinton } 60712609Slinton * 60812609Slinton */ 6099657Slinton break; 6109657Slinton 6119657Slinton case FPROC: 6129657Slinton case FFUNC: 6139657Slinton r = sizeof(Word); 6149657Slinton break; 6159657Slinton 6169657Slinton case PROC: 6179657Slinton case FUNC: 6189657Slinton case MODULE: 6199657Slinton case PROG: 6209657Slinton r = sizeof(Symbol); 6219657Slinton break; 6229657Slinton 6239657Slinton default: 6249657Slinton if (ord(t->class) > ord(TYPEREF)) { 6259657Slinton panic("size: bad class (%d)", ord(t->class)); 6269657Slinton } else { 6279657Slinton error("improper operation on a %s", classname(t)); 6289657Slinton } 6299657Slinton /* NOTREACHED */ 6309657Slinton } 6319657Slinton return r; 6329657Slinton } 6339657Slinton 6349657Slinton /* 6359657Slinton * Test if a symbol is a parameter. This is true if there 6369657Slinton * is a cycle from s->block to s via chain pointers. 6379657Slinton */ 6389657Slinton 6399657Slinton public Boolean isparam(s) 6409657Slinton Symbol s; 6419657Slinton { 6429657Slinton register Symbol t; 6439657Slinton 6449657Slinton t = s->block; 6459657Slinton while (t != nil and t != s) { 6469657Slinton t = t->chain; 6479657Slinton } 6489657Slinton return (Boolean) (t != nil); 6499657Slinton } 6509657Slinton 6519657Slinton /* 6529657Slinton * Test if a symbol is a var parameter, i.e. has class REF. 6539657Slinton */ 6549657Slinton 6559657Slinton public Boolean isvarparam(s) 6569657Slinton Symbol s; 6579657Slinton { 6589657Slinton return (Boolean) (s->class == REF); 6599657Slinton } 6609657Slinton 6619657Slinton /* 6629657Slinton * Test if a symbol is a variable (actually any addressible quantity 6639657Slinton * with do). 6649657Slinton */ 6659657Slinton 6669657Slinton public Boolean isvariable(s) 6679657Slinton register Symbol s; 6689657Slinton { 6699657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 6709657Slinton } 6719657Slinton 6729657Slinton /* 6739657Slinton * Test if a symbol is a block, e.g. function, procedure, or the 6749657Slinton * main program. 6759657Slinton * 6769657Slinton * This function is now expanded inline for efficiency. 6779657Slinton * 6789657Slinton * public Boolean isblock(s) 6799657Slinton register Symbol s; 6809657Slinton { 6819657Slinton return (Boolean) ( 6829657Slinton s->class == FUNC or s->class == PROC or 6839657Slinton s->class == MODULE or s->class == PROG 6849657Slinton ); 6859657Slinton } 6869657Slinton * 6879657Slinton */ 6889657Slinton 6899657Slinton /* 6909657Slinton * Test if a symbol is a module. 6919657Slinton */ 6929657Slinton 6939657Slinton public Boolean ismodule(s) 6949657Slinton register Symbol s; 6959657Slinton { 6969657Slinton return (Boolean) (s->class == MODULE); 6979657Slinton } 6989657Slinton 6999657Slinton /* 7009657Slinton * Test if a symbol is builtin, that is, a predefined type or 7019657Slinton * reserved word. 7029657Slinton */ 7039657Slinton 7049657Slinton public Boolean isbuiltin(s) 7059657Slinton register Symbol s; 7069657Slinton { 7079657Slinton return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); 7089657Slinton } 7099657Slinton 7109657Slinton /* 7119657Slinton * Test if two types match. 7129657Slinton * Equivalent names implies a match in any language. 7139657Slinton * 7149657Slinton * Special symbols must be handled with care. 7159657Slinton */ 7169657Slinton 7179657Slinton public Boolean compatible(t1, t2) 7189657Slinton register Symbol t1, t2; 7199657Slinton { 7209657Slinton Boolean b; 7219657Slinton 7229657Slinton if (t1 == t2) { 7239657Slinton b = true; 7249657Slinton } else if (t1 == nil or t2 == nil) { 7259657Slinton b = false; 7269657Slinton } else if (t1 == procsym) { 7279657Slinton b = isblock(t2); 7289657Slinton } else if (t2 == procsym) { 7299657Slinton b = isblock(t1); 7309657Slinton } else if (t1->language == nil) { 7319657Slinton b = (Boolean) (t2->language == nil or 7329657Slinton (*language_op(t2->language, L_TYPEMATCH))(t1, t2)); 73312547Scsvaf } else if (t2->language == nil) { 73412547Scsvaf b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 73512547Scsvaf } else if ( isbuiltin(t1) or isbuiltin(t1->type) ) { 73612547Scsvaf b = (Boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 7379657Slinton } else { 7389657Slinton b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 7399657Slinton } 7409657Slinton return b; 7419657Slinton } 7429657Slinton 7439657Slinton /* 7449657Slinton * Check for a type of the given name. 7459657Slinton */ 7469657Slinton 7479657Slinton public Boolean istypename(type, name) 7489657Slinton Symbol type; 7499657Slinton String name; 7509657Slinton { 7519657Slinton Symbol t; 7529657Slinton Boolean b; 7539657Slinton 7549657Slinton t = type; 7559657Slinton checkref(t); 7569657Slinton b = (Boolean) ( 7579657Slinton t->class == TYPE and t->name == identname(name, true) 7589657Slinton ); 7599657Slinton return b; 7609657Slinton } 7619657Slinton 7629657Slinton /* 7639657Slinton * Test if the name of a symbol is uniquely defined or not. 7649657Slinton */ 7659657Slinton 7669657Slinton public Boolean isambiguous(s) 7679657Slinton register Symbol s; 7689657Slinton { 7699657Slinton register Symbol t; 7709657Slinton 7719657Slinton find(t, s->name) where t != s endfind(t); 7729657Slinton return (Boolean) (t != nil); 7739657Slinton } 7749657Slinton 7759657Slinton typedef char *Arglist; 7769657Slinton 7779657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 7789657Slinton 7799657Slinton private Symbol mkstring(); 7809657Slinton private Symbol namenode(); 7819657Slinton 7829657Slinton /* 7839657Slinton * Determine the type of a parse tree. 7849657Slinton * Also make some symbol-dependent changes to the tree such as 7859657Slinton * changing removing RVAL nodes for constant symbols. 7869657Slinton */ 7879657Slinton 7889657Slinton public assigntypes(p) 7899657Slinton register Node p; 7909657Slinton { 7919657Slinton register Node p1; 7929657Slinton register Symbol s; 7939657Slinton 7949657Slinton switch (p->op) { 7959657Slinton case O_SYM: 7969657Slinton p->nodetype = namenode(p); 7979657Slinton break; 7989657Slinton 7999657Slinton case O_LCON: 8009657Slinton p->nodetype = t_int; 8019657Slinton break; 8029657Slinton 8039657Slinton case O_FCON: 8049657Slinton p->nodetype = t_real; 8059657Slinton break; 8069657Slinton 8079657Slinton case O_SCON: 8089657Slinton p->value.scon = strdup(p->value.scon); 8099657Slinton s = mkstring(p->value.scon); 8109657Slinton if (s == t_char) { 8119657Slinton p->op = O_LCON; 8129657Slinton p->value.lcon = p->value.scon[0]; 8139657Slinton } 8149657Slinton p->nodetype = s; 8159657Slinton break; 8169657Slinton 8179657Slinton case O_INDIR: 8189657Slinton p1 = p->value.arg[0]; 8199657Slinton chkclass(p1, PTR); 8209657Slinton p->nodetype = rtype(p1->nodetype)->type; 8219657Slinton break; 8229657Slinton 8239657Slinton case O_DOT: 8249657Slinton p->nodetype = p->value.arg[1]->value.sym; 8259657Slinton break; 8269657Slinton 8279657Slinton case O_RVAL: 8289657Slinton p1 = p->value.arg[0]; 8299657Slinton p->nodetype = p1->nodetype; 8309657Slinton if (p1->op == O_SYM) { 8319657Slinton if (p1->nodetype->class == FUNC) { 8329657Slinton p->op = O_CALL; 8339657Slinton p->value.arg[1] = nil; 8349657Slinton } else if (p1->value.sym->class == CONST) { 8359657Slinton if (compatible(p1->value.sym->type, t_real)) { 8369657Slinton p->op = O_FCON; 8379657Slinton p->value.fcon = p1->value.sym->symvalue.fconval; 8389657Slinton p->nodetype = t_real; 8399657Slinton dispose(p1); 8409657Slinton } else { 8419657Slinton p->op = O_LCON; 8429657Slinton p->value.lcon = p1->value.sym->symvalue.iconval; 8439657Slinton p->nodetype = p1->value.sym->type; 8449657Slinton dispose(p1); 8459657Slinton } 8469657Slinton } else if (isreg(p1->value.sym)) { 8479657Slinton p->op = O_SYM; 8489657Slinton p->value.sym = p1->value.sym; 8499657Slinton dispose(p1); 8509657Slinton } 8519657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 8529657Slinton s = p1->value.arg[0]->value.sym; 8539657Slinton if (isreg(s)) { 8549657Slinton p1->op = O_SYM; 8559657Slinton dispose(p1->value.arg[0]); 8569657Slinton p1->value.sym = s; 8579657Slinton p1->nodetype = s; 8589657Slinton } 8599657Slinton } 8609657Slinton break; 8619657Slinton 8629657Slinton /* 8639657Slinton * Perform a cast if the call is of the form "type(expr)". 8649657Slinton */ 8659657Slinton case O_CALL: 8669657Slinton p1 = p->value.arg[0]; 86711171Slinton p->nodetype = rtype(p1->nodetype)->type; 8689657Slinton break; 8699657Slinton 87011171Slinton case O_TYPERENAME: 87111171Slinton p->nodetype = p->value.arg[1]->nodetype; 87211171Slinton break; 87311171Slinton 8749657Slinton case O_ITOF: 8759657Slinton p->nodetype = t_real; 8769657Slinton break; 8779657Slinton 8789657Slinton case O_NEG: 8799657Slinton s = p->value.arg[0]->nodetype; 8809657Slinton if (not compatible(s, t_int)) { 8819657Slinton if (not compatible(s, t_real)) { 8829657Slinton beginerrmsg(); 8839657Slinton prtree(stderr, p->value.arg[0]); 8849657Slinton fprintf(stderr, "is improper type"); 8859657Slinton enderrmsg(); 8869657Slinton } else { 8879657Slinton p->op = O_NEGF; 8889657Slinton } 8899657Slinton } 8909657Slinton p->nodetype = s; 8919657Slinton break; 8929657Slinton 8939657Slinton case O_ADD: 8949657Slinton case O_SUB: 8959657Slinton case O_MUL: 8969657Slinton case O_LT: 8979657Slinton case O_LE: 8989657Slinton case O_GT: 8999657Slinton case O_GE: 9009657Slinton case O_EQ: 9019657Slinton case O_NE: 9029657Slinton { 9039657Slinton Boolean t1real, t2real; 9049657Slinton Symbol t1, t2; 9059657Slinton 9069657Slinton t1 = rtype(p->value.arg[0]->nodetype); 9079657Slinton t2 = rtype(p->value.arg[1]->nodetype); 9089657Slinton t1real = compatible(t1, t_real); 9099657Slinton t2real = compatible(t2, t_real); 9109657Slinton if (t1real or t2real) { 9119657Slinton p->op = (Operator) (ord(p->op) + 1); 9129657Slinton if (not t1real) { 9139657Slinton p->value.arg[0] = build(O_ITOF, p->value.arg[0]); 9149657Slinton } else if (not t2real) { 9159657Slinton p->value.arg[1] = build(O_ITOF, p->value.arg[1]); 9169657Slinton } 9179657Slinton } else { 9189657Slinton if (t1real) { 9199657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 9209657Slinton } 9219657Slinton if (t2real) { 9229657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 9239657Slinton } 9249657Slinton } 9259657Slinton if (ord(p->op) >= ord(O_LT)) { 9269657Slinton p->nodetype = t_boolean; 9279657Slinton } else { 9289657Slinton if (t1real or t2real) { 9299657Slinton p->nodetype = t_real; 9309657Slinton } else { 9319657Slinton p->nodetype = t_int; 9329657Slinton } 9339657Slinton } 9349657Slinton break; 9359657Slinton } 9369657Slinton 9379657Slinton case O_DIVF: 9389657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 9399657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 9409657Slinton p->nodetype = t_real; 9419657Slinton break; 9429657Slinton 9439657Slinton case O_DIV: 9449657Slinton case O_MOD: 9459657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 9469657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 9479657Slinton p->nodetype = t_int; 9489657Slinton break; 9499657Slinton 9509657Slinton case O_AND: 9519657Slinton case O_OR: 9529657Slinton chkboolean(p->value.arg[0]); 9539657Slinton chkboolean(p->value.arg[1]); 9549657Slinton p->nodetype = t_boolean; 9559657Slinton break; 9569657Slinton 9579657Slinton case O_QLINE: 9589657Slinton p->nodetype = t_int; 9599657Slinton break; 9609657Slinton 9619657Slinton default: 9629657Slinton p->nodetype = nil; 9639657Slinton break; 9649657Slinton } 9659657Slinton } 9669657Slinton 9679657Slinton /* 9689657Slinton * Create a node for a name. The symbol for the name has already 9699657Slinton * been chosen, either implicitly with "which" or explicitly from 9709657Slinton * the dot routine. 9719657Slinton */ 9729657Slinton 9739657Slinton private Symbol namenode(p) 9749657Slinton Node p; 9759657Slinton { 9769657Slinton register Symbol r, s; 9779657Slinton register Node np; 9789657Slinton 9799657Slinton s = p->value.sym; 9809657Slinton if (s->class == REF) { 9819657Slinton np = new(Node); 9829657Slinton np->op = p->op; 9839657Slinton np->nodetype = s; 9849657Slinton np->value.sym = s; 9859657Slinton p->op = O_INDIR; 9869657Slinton p->value.arg[0] = np; 9879657Slinton } 9889657Slinton /* 9899657Slinton * Old way 9909657Slinton * 9919657Slinton if (s->class == CONST or s->class == VAR or s->class == FVAR) { 9929657Slinton r = s->type; 9939657Slinton } else { 9949657Slinton r = s; 9959657Slinton } 9969657Slinton * 9979657Slinton */ 9989657Slinton return s; 9999657Slinton } 10009657Slinton 10019657Slinton /* 10029657Slinton * Convert a tree to a type via a conversion operator; 10039657Slinton * if this isn't possible generate an error. 10049657Slinton * 10059657Slinton * Note the tree is call by address, hence the #define below. 10069657Slinton */ 10079657Slinton 10089657Slinton private convert(tp, typeto, op) 10099657Slinton Node *tp; 10109657Slinton Symbol typeto; 10119657Slinton Operator op; 10129657Slinton { 10139657Slinton #define tree (*tp) 10149657Slinton 10159657Slinton Symbol s; 10169657Slinton 10179657Slinton s = rtype(tree->nodetype); 10189657Slinton typeto = rtype(typeto); 10199657Slinton if (compatible(typeto, t_real) and compatible(s, t_int)) { 10209657Slinton tree = build(op, tree); 10219657Slinton } else if (not compatible(s, typeto)) { 10229657Slinton beginerrmsg(); 10239657Slinton prtree(stderr, s); 10249657Slinton fprintf(stderr, " is improper type"); 10259657Slinton enderrmsg(); 10269657Slinton } else if (op != O_NOP and s != typeto) { 10279657Slinton tree = build(op, tree); 10289657Slinton } 10299657Slinton 10309657Slinton #undef tree 10319657Slinton } 10329657Slinton 10339657Slinton /* 10349657Slinton * Construct a node for the dot operator. 10359657Slinton * 10369657Slinton * If the left operand is not a record, but rather a procedure 10379657Slinton * or function, then we interpret the "." as referencing an 10389657Slinton * "invisible" variable; i.e. a variable within a dynamically 10399657Slinton * active block but not within the static scope of the current procedure. 10409657Slinton */ 10419657Slinton 10429657Slinton public Node dot(record, fieldname) 10439657Slinton Node record; 10449657Slinton Name fieldname; 10459657Slinton { 10469657Slinton register Node p; 10479657Slinton register Symbol s, t; 10489657Slinton 10499657Slinton if (isblock(record->nodetype)) { 10509657Slinton find(s, fieldname) where 10519657Slinton s->block == record->nodetype and 10529657Slinton s->class != FIELD and s->class != TAG 10539657Slinton endfind(s); 10549657Slinton if (s == nil) { 10559657Slinton beginerrmsg(); 10569657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 10579657Slinton printname(stderr, record->nodetype); 10589657Slinton enderrmsg(); 10599657Slinton } 10609657Slinton p = new(Node); 10619657Slinton p->op = O_SYM; 10629657Slinton p->value.sym = s; 10639657Slinton p->nodetype = namenode(p); 10649657Slinton } else { 10659657Slinton p = record; 10669657Slinton t = rtype(p->nodetype); 10679657Slinton if (t->class == PTR) { 10689657Slinton s = findfield(fieldname, t->type); 10699657Slinton } else { 10709657Slinton s = findfield(fieldname, t); 10719657Slinton } 10729657Slinton if (s == nil) { 10739657Slinton beginerrmsg(); 10749657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 10759657Slinton prtree(stderr, record); 10769657Slinton enderrmsg(); 10779657Slinton } 10789657Slinton if (t->class == PTR and not isreg(record->nodetype)) { 10799657Slinton p = build(O_INDIR, record); 10809657Slinton } 10819657Slinton p = build(O_DOT, p, build(O_SYM, s)); 10829657Slinton } 10839657Slinton return p; 10849657Slinton } 10859657Slinton 10869657Slinton /* 10879657Slinton * Return a tree corresponding to an array reference and do the 10889657Slinton * error checking. 10899657Slinton */ 10909657Slinton 10919657Slinton public Node subscript(a, slist) 10929657Slinton Node a, slist; 10939657Slinton { 109412547Scsvaf Symbol t; 10959657Slinton 109612547Scsvaf t = rtype(a->nodetype); 109712547Scsvaf if(t->language == nil) { 109812547Scsvaf error("unknown language"); 109912547Scsvaf } 110012547Scsvaf else { 110112547Scsvaf return ( (Node) 110212547Scsvaf (*language_op(t->language, L_BUILDAREF)) (a,slist) 110312547Scsvaf ); 110412547Scsvaf } 11059657Slinton } 11069657Slinton 11079657Slinton /* 11089657Slinton * Evaluate a subscript index. 11099657Slinton */ 11109657Slinton 11119657Slinton public int evalindex(s, i) 11129657Slinton Symbol s; 11139657Slinton long i; 11149657Slinton { 111512547Scsvaf Symbol t; 11169657Slinton 111712547Scsvaf t = rtype(s); 111812547Scsvaf if(t->language == nil) { 111912547Scsvaf error("unknown language"); 112012547Scsvaf } 112112547Scsvaf else { 112212547Scsvaf return ( 112312547Scsvaf (*language_op(t->language, L_EVALAREF)) (s,i) 112412547Scsvaf ); 112512547Scsvaf } 11269657Slinton } 11279657Slinton 11289657Slinton /* 11299657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 11309657Slinton */ 11319657Slinton 11329657Slinton public chkboolean(p) 11339657Slinton register Node p; 11349657Slinton { 11359657Slinton if (p->nodetype != t_boolean) { 11369657Slinton beginerrmsg(); 11379657Slinton fprintf(stderr, "found "); 11389657Slinton prtree(stderr, p); 11399657Slinton fprintf(stderr, ", expected boolean expression"); 11409657Slinton enderrmsg(); 11419657Slinton } 11429657Slinton } 11439657Slinton 11449657Slinton /* 11459657Slinton * Check to make sure the given tree has a type of the given class. 11469657Slinton */ 11479657Slinton 11489657Slinton private chkclass(p, class) 11499657Slinton Node p; 11509657Slinton Symclass class; 11519657Slinton { 11529657Slinton struct Symbol tmpsym; 11539657Slinton 11549657Slinton tmpsym.class = class; 11559657Slinton if (rtype(p->nodetype)->class != class) { 11569657Slinton beginerrmsg(); 11579657Slinton fprintf(stderr, "\""); 11589657Slinton prtree(stderr, p); 11599657Slinton fprintf(stderr, "\" is not a %s", classname(&tmpsym)); 11609657Slinton enderrmsg(); 11619657Slinton } 11629657Slinton } 11639657Slinton 11649657Slinton /* 11659657Slinton * Construct a node for the type of a string. While we're at it, 11669657Slinton * scan the string for '' that collapse to ', and chop off the ends. 11679657Slinton */ 11689657Slinton 11699657Slinton private Symbol mkstring(str) 11709657Slinton String str; 11719657Slinton { 11729657Slinton register char *p, *q; 11739657Slinton register Symbol s; 11749657Slinton 11759657Slinton p = str; 11769657Slinton q = str; 11779657Slinton while (*p != '\0') { 11789657Slinton if (*p == '\\') { 11799657Slinton ++p; 11809657Slinton } 11819657Slinton *q = *p; 11829657Slinton ++p; 11839657Slinton ++q; 11849657Slinton } 11859657Slinton *q = '\0'; 11869657Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 11879657Slinton s->language = findlanguage(".s"); 11889657Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 11899657Slinton s->chain->language = s->language; 11909657Slinton s->chain->symvalue.rangev.lower = 1; 11919657Slinton s->chain->symvalue.rangev.upper = p - str + 1; 11929657Slinton return s; 11939657Slinton } 11949657Slinton 11959657Slinton /* 11969657Slinton * Free up the space allocated for a string type. 11979657Slinton */ 11989657Slinton 11999657Slinton public unmkstring(s) 12009657Slinton Symbol s; 12019657Slinton { 12029657Slinton dispose(s->chain); 12039657Slinton } 12049657Slinton 12059657Slinton /* 12069657Slinton * Figure out the "current" variable or function being referred to, 12079657Slinton * this is either the active one or the most visible from the 12089657Slinton * current scope. 12099657Slinton */ 12109657Slinton 12119657Slinton public Symbol which(n) 12129657Slinton Name n; 12139657Slinton { 12149657Slinton register Symbol s, p, t, f; 12159657Slinton 12169657Slinton find(s, n) where s->class != FIELD and s->class != TAG endfind(s); 12179657Slinton if (s == nil) { 12189657Slinton s = lookup(n); 12199657Slinton } 12209657Slinton if (s == nil) { 12219657Slinton error("\"%s\" is not defined", ident(n)); 12229657Slinton } else if (s == program or isbuiltin(s)) { 12239657Slinton t = s; 12249657Slinton } else { 12259657Slinton /* 12269657Slinton * Old way 12279657Slinton * 12289657Slinton if (not isactive(program)) { 12299657Slinton f = program; 12309657Slinton } else { 12319657Slinton f = whatblock(pc); 12329657Slinton if (f == nil) { 12339657Slinton panic("no block for addr 0x%x", pc); 12349657Slinton } 12359657Slinton } 12369657Slinton * 12379657Slinton * Now start with curfunc. 12389657Slinton */ 12399657Slinton p = curfunc; 12409657Slinton do { 12419657Slinton find(t, n) where 12429657Slinton t->block == p and t->class != FIELD and t->class != TAG 12439657Slinton endfind(t); 12449657Slinton p = p->block; 12459657Slinton } while (t == nil and p != nil); 12469657Slinton if (t == nil) { 12479657Slinton t = s; 12489657Slinton } 12499657Slinton } 12509657Slinton return t; 12519657Slinton } 12529657Slinton 12539657Slinton /* 12549657Slinton * Find the symbol which is has the same name and scope as the 12559657Slinton * given symbol but is of the given field. Return nil if there is none. 12569657Slinton */ 12579657Slinton 12589657Slinton public Symbol findfield(fieldname, record) 12599657Slinton Name fieldname; 12609657Slinton Symbol record; 12619657Slinton { 12629657Slinton register Symbol t; 12639657Slinton 12649657Slinton t = rtype(record)->chain; 12659657Slinton while (t != nil and t->name != fieldname) { 12669657Slinton t = t->chain; 12679657Slinton } 12689657Slinton return t; 12699657Slinton } 127012547Scsvaf 127112547Scsvaf public Boolean getbound(s,off,type,valp) 127212547Scsvaf Symbol s; 127312547Scsvaf int off; 127412547Scsvaf Rangetype type; 127512547Scsvaf int *valp; 127612547Scsvaf { 127712547Scsvaf Frame frp; 127812547Scsvaf Address addr; 127912547Scsvaf Symbol cur; 128012547Scsvaf 128112547Scsvaf if (not isactive(s->block)) { 128212547Scsvaf return(false); 128312547Scsvaf } 128412547Scsvaf cur = s->block; 128512547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 128612547Scsvaf cur = cur->block; 128712547Scsvaf } 128812547Scsvaf if(cur == nil) { 128912547Scsvaf cur = whatblock(pc); 129012547Scsvaf } 129112547Scsvaf frp = findframe(cur); 129212547Scsvaf if (frp == nil) { 129312547Scsvaf return(false); 129412547Scsvaf } 129512547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 129612547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 129712547Scsvaf else return(false); 129812547Scsvaf dread(valp,addr,sizeof(long)); 129912547Scsvaf return(true); 130012547Scsvaf } 1301