121625Sdist /* 221625Sdist * Copyright (c) 1983 Regents of the University of California. 321625Sdist * All rights reserved. The Berkeley software License Agreement 421625Sdist * specifies the terms and conditions for redistribution. 521625Sdist */ 69657Slinton 721625Sdist #ifndef lint 8*34257Sdonn static char sccsid[] = "@(#)symbols.c 5.5 (Berkeley) 05/11/88"; 921625Sdist #endif not lint 109657Slinton 11*34257Sdonn static char rcsid[] = "$Header: symbols.c,v 1.4 88/04/02 01:29:03 donn Exp $"; 1218235Slinton 139657Slinton /* 149657Slinton * Symbol management. 159657Slinton */ 169657Slinton 179657Slinton #include "defs.h" 189657Slinton #include "symbols.h" 199657Slinton #include "languages.h" 209657Slinton #include "printsym.h" 219657Slinton #include "tree.h" 229657Slinton #include "operators.h" 239657Slinton #include "eval.h" 249657Slinton #include "mappings.h" 259657Slinton #include "events.h" 269657Slinton #include "process.h" 279657Slinton #include "runtime.h" 289657Slinton #include "machine.h" 299657Slinton #include "names.h" 309657Slinton 319657Slinton #ifndef public 329657Slinton typedef struct Symbol *Symbol; 339657Slinton 349657Slinton #include "machine.h" 359657Slinton #include "names.h" 369657Slinton #include "languages.h" 3718235Slinton #include "tree.h" 389657Slinton 399657Slinton /* 409657Slinton * Symbol classes 419657Slinton */ 429657Slinton 439657Slinton typedef enum { 4433337Sdonn BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY, 4533337Sdonn PTRFILE, RECORD, FIELD, 4612547Scsvaf PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 479657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 4816620Ssam FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF 499657Slinton } Symclass; 509657Slinton 5112547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 5212547Scsvaf 5333337Sdonn #define INREG 0 5433337Sdonn #define STK 1 5533337Sdonn #define EXT 2 5633337Sdonn 5733337Sdonn typedef unsigned integer Storage; 5833337Sdonn 599657Slinton struct Symbol { 609657Slinton Name name; 619657Slinton Language language; 6233337Sdonn Symclass class : 8; 6333337Sdonn Storage storage : 2; 6433337Sdonn unsigned int level : 6; /* for variables stored on stack only */ 659657Slinton Symbol type; 669657Slinton Symbol chain; 679657Slinton union { 6818235Slinton Node constval; /* value of constant symbol */ 699657Slinton int offset; /* variable address */ 709657Slinton long iconval; /* integer constant value */ 719657Slinton double fconval; /* floating constant value */ 7218235Slinton int ndims; /* no. of dimensions for dynamic/sub-arrays */ 739657Slinton struct { /* field offset and size (both in bits) */ 749657Slinton int offset; 759657Slinton int length; 769657Slinton } field; 7712547Scsvaf struct { /* common offset and chain; used to relocate */ 7812547Scsvaf int offset; /* vars in global BSS */ 7912547Scsvaf Symbol chain; 8012547Scsvaf } common; 819657Slinton struct { /* range bounds */ 8212547Scsvaf Rangetype lowertype : 16; 8312547Scsvaf Rangetype uppertype : 16; 849657Slinton long lower; 859657Slinton long upper; 869657Slinton } rangev; 8711865Slinton struct { 8811865Slinton int offset : 16; /* offset for of function value */ 8916620Ssam Boolean src : 1; /* true if there is source line info */ 9016620Ssam Boolean inline : 1; /* true if no separate act. rec. */ 9116620Ssam Boolean intern : 1; /* internal calling sequence */ 9216620Ssam int unused : 13; 9311865Slinton Address beginaddr; /* address of function code */ 949657Slinton } funcv; 959657Slinton struct { /* variant record info */ 969657Slinton int size; 979657Slinton Symbol vtorec; 989657Slinton Symbol vtag; 999657Slinton } varnt; 10016620Ssam String typeref; /* type defined by "<module>:<type>" */ 10116620Ssam Symbol extref; /* indirect symbol for external reference */ 1029657Slinton } symvalue; 1039657Slinton Symbol block; /* symbol containing this symbol */ 1049657Slinton Symbol next_sym; /* hash chain */ 1059657Slinton }; 1069657Slinton 1079657Slinton /* 1089657Slinton * Basic types. 1099657Slinton */ 1109657Slinton 1119657Slinton Symbol t_boolean; 1129657Slinton Symbol t_char; 1139657Slinton Symbol t_int; 1149657Slinton Symbol t_real; 1159657Slinton Symbol t_nil; 11618235Slinton Symbol t_addr; 1179657Slinton 1189657Slinton Symbol program; 1199657Slinton Symbol curfunc; 1209657Slinton 12118235Slinton boolean showaggrs; 12218235Slinton 1239657Slinton #define symname(s) ident(s->name) 1249657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 1259657Slinton #define isblock(s) (Boolean) ( \ 1269657Slinton s->class == FUNC or s->class == PROC or \ 1279657Slinton s->class == MODULE or s->class == PROG \ 1289657Slinton ) 12916620Ssam #define isroutine(s) (Boolean) ( \ 13016620Ssam s->class == FUNC or s->class == PROC \ 13116620Ssam ) 1329657Slinton 13311865Slinton #define nosource(f) (not (f)->symvalue.funcv.src) 13414441Slinton #define isinline(f) ((f)->symvalue.funcv.inline) 13511865Slinton 13633337Sdonn #define isreg(s) (s->storage == INREG) 13724554Smckusick 1389657Slinton #include "tree.h" 1399657Slinton 1409657Slinton /* 1419657Slinton * Some macros to make finding a symbol with certain attributes. 1429657Slinton */ 1439657Slinton 1449657Slinton #define find(s, withname) \ 1459657Slinton { \ 1469657Slinton s = lookup(withname); \ 1479657Slinton while (s != nil and not (s->name == (withname) and 1489657Slinton 1499657Slinton #define where /* qualification */ 1509657Slinton 1519657Slinton #define endfind(s) )) { \ 1529657Slinton s = s->next_sym; \ 1539657Slinton } \ 1549657Slinton } 1559657Slinton 1569657Slinton #endif 1579657Slinton 1589657Slinton /* 1599657Slinton * Symbol table structure currently does not support deletions. 16033337Sdonn * Hash table size is a power of two to make hashing faster. 16133337Sdonn * Using a non-prime is ok since we aren't doing rehashing. 1629657Slinton */ 1639657Slinton 16433337Sdonn #define HASHTABLESIZE 8192 1659657Slinton 1669657Slinton private Symbol hashtab[HASHTABLESIZE]; 1679657Slinton 16833337Sdonn #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1)) 1699657Slinton 1709657Slinton /* 1719657Slinton * Allocate a new symbol. 1729657Slinton */ 1739657Slinton 17433337Sdonn #define SYMBLOCKSIZE 1000 1759657Slinton 1769657Slinton typedef struct Sympool { 1779657Slinton struct Symbol sym[SYMBLOCKSIZE]; 1789657Slinton struct Sympool *prevpool; 1799657Slinton } *Sympool; 1809657Slinton 1819657Slinton private Sympool sympool = nil; 1829657Slinton private Integer nleft = 0; 1839657Slinton 1849657Slinton public Symbol symbol_alloc() 1859657Slinton { 1869657Slinton register Sympool newpool; 1879657Slinton 1889657Slinton if (nleft <= 0) { 1899657Slinton newpool = new(Sympool); 19033337Sdonn bzero(newpool, sizeof(*newpool)); 1919657Slinton newpool->prevpool = sympool; 1929657Slinton sympool = newpool; 1939657Slinton nleft = SYMBLOCKSIZE; 1949657Slinton } 1959657Slinton --nleft; 1969657Slinton return &(sympool->sym[nleft]); 1979657Slinton } 1989657Slinton 19918235Slinton public symbol_dump (func) 20012547Scsvaf Symbol func; 20112547Scsvaf { 20218235Slinton register Symbol s; 20318235Slinton register integer i; 20412547Scsvaf 20518235Slinton printf(" symbols in %s \n",symname(func)); 20618235Slinton for (i = 0; i < HASHTABLESIZE; i++) { 20718235Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 20818235Slinton if (s->block == func) { 20918235Slinton psym(s); 21018235Slinton } 21118235Slinton } 21218235Slinton } 21312547Scsvaf } 21412547Scsvaf 2159657Slinton /* 2169657Slinton * Free all the symbols currently allocated. 2179657Slinton */ 21818235Slinton 2199657Slinton public symbol_free() 2209657Slinton { 2219657Slinton Sympool s, t; 2229657Slinton register Integer i; 2239657Slinton 2249657Slinton s = sympool; 2259657Slinton while (s != nil) { 2269657Slinton t = s->prevpool; 2279657Slinton dispose(s); 2289657Slinton s = t; 2299657Slinton } 2309657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 2319657Slinton hashtab[i] = nil; 2329657Slinton } 2339657Slinton sympool = nil; 2349657Slinton nleft = 0; 2359657Slinton } 2369657Slinton 2379657Slinton /* 2389657Slinton * Create a new symbol with the given attributes. 2399657Slinton */ 2409657Slinton 2419657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 2429657Slinton Name name; 2439657Slinton Integer blevel; 2449657Slinton Symclass class; 2459657Slinton Symbol type; 2469657Slinton Symbol chain; 2479657Slinton { 2489657Slinton register Symbol s; 2499657Slinton 2509657Slinton s = symbol_alloc(); 2519657Slinton s->name = name; 25218235Slinton s->language = primlang; 25333337Sdonn s->storage = EXT; 2549657Slinton s->level = blevel; 2559657Slinton s->class = class; 2569657Slinton s->type = type; 2579657Slinton s->chain = chain; 2589657Slinton return s; 2599657Slinton } 2609657Slinton 2619657Slinton /* 2629657Slinton * Insert a symbol into the hash table. 2639657Slinton */ 2649657Slinton 2659657Slinton public Symbol insert(name) 2669657Slinton Name name; 2679657Slinton { 2689657Slinton register Symbol s; 2699657Slinton register unsigned int h; 2709657Slinton 2719657Slinton h = hash(name); 2729657Slinton s = symbol_alloc(); 2739657Slinton s->name = name; 2749657Slinton s->next_sym = hashtab[h]; 2759657Slinton hashtab[h] = s; 2769657Slinton return s; 2779657Slinton } 2789657Slinton 2799657Slinton /* 2809657Slinton * Symbol lookup. 2819657Slinton */ 2829657Slinton 2839657Slinton public Symbol lookup(name) 2849657Slinton Name name; 2859657Slinton { 2869657Slinton register Symbol s; 2879657Slinton register unsigned int h; 2889657Slinton 2899657Slinton h = hash(name); 2909657Slinton s = hashtab[h]; 2919657Slinton while (s != nil and s->name != name) { 2929657Slinton s = s->next_sym; 2939657Slinton } 2949657Slinton return s; 2959657Slinton } 2969657Slinton 2979657Slinton /* 29816620Ssam * Delete a symbol from the symbol table. 29916620Ssam */ 30016620Ssam 30116620Ssam public delete (s) 30216620Ssam Symbol s; 30316620Ssam { 30416620Ssam register Symbol t; 30516620Ssam register unsigned int h; 30616620Ssam 30716620Ssam h = hash(s->name); 30816620Ssam t = hashtab[h]; 30916620Ssam if (t == nil) { 31016620Ssam panic("delete of non-symbol '%s'", symname(s)); 31116620Ssam } else if (t == s) { 31216620Ssam hashtab[h] = s->next_sym; 31316620Ssam } else { 31416620Ssam while (t->next_sym != s) { 31516620Ssam t = t->next_sym; 31616620Ssam if (t == nil) { 31716620Ssam panic("delete of non-symbol '%s'", symname(s)); 31816620Ssam } 31916620Ssam } 32016620Ssam t->next_sym = s->next_sym; 32116620Ssam } 32216620Ssam } 32316620Ssam 32416620Ssam /* 3259657Slinton * Dump out all the variables associated with the given 32618235Slinton * procedure, function, or program associated with the given stack frame. 3279657Slinton * 3289657Slinton * This is quite inefficient. We traverse the entire symbol table 3299657Slinton * each time we're called. The assumption is that this routine 3309657Slinton * won't be called frequently enough to merit improved performance. 3319657Slinton */ 3329657Slinton 3339657Slinton public dumpvars(f, frame) 3349657Slinton Symbol f; 3359657Slinton Frame frame; 3369657Slinton { 3379657Slinton register Integer i; 3389657Slinton register Symbol s; 3399657Slinton 3409657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 3419657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 3429657Slinton if (container(s) == f) { 3439657Slinton if (should_print(s)) { 3449657Slinton printv(s, frame); 3459657Slinton putchar('\n'); 3469657Slinton } else if (s->class == MODULE) { 3479657Slinton dumpvars(s, frame); 3489657Slinton } 3499657Slinton } 3509657Slinton } 3519657Slinton } 3529657Slinton } 3539657Slinton 3549657Slinton /* 3559657Slinton * Create a builtin type. 3569657Slinton * Builtin types are circular in that btype->type->type = btype. 3579657Slinton */ 3589657Slinton 35918235Slinton private Symbol maketype(name, lower, upper) 3609657Slinton String name; 3619657Slinton long lower; 3629657Slinton long upper; 3639657Slinton { 3649657Slinton register Symbol s; 36518235Slinton Name n; 3669657Slinton 36718235Slinton if (name == nil) { 36818235Slinton n = nil; 36918235Slinton } else { 37018235Slinton n = identname(name, true); 37118235Slinton } 37218235Slinton s = insert(n); 37316620Ssam s->language = primlang; 37418235Slinton s->level = 0; 37518235Slinton s->class = TYPE; 37618235Slinton s->type = nil; 37718235Slinton s->chain = nil; 3789657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 3799657Slinton s->type->symvalue.rangev.lower = lower; 3809657Slinton s->type->symvalue.rangev.upper = upper; 3819657Slinton return s; 3829657Slinton } 3839657Slinton 3849657Slinton /* 38518235Slinton * Create the builtin symbols. 38618235Slinton */ 38718235Slinton 38818235Slinton public symbols_init () 3899657Slinton { 39018235Slinton Symbol s; 3919657Slinton 39218235Slinton t_boolean = maketype("$boolean", 0L, 1L); 39318235Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 39418235Slinton t_char = maketype("$char", 0L, 255L); 39518235Slinton t_real = maketype("$real", 8L, 0L); 39618235Slinton t_nil = maketype("$nil", 0L, 0L); 39718235Slinton t_addr = insert(identname("$address", true)); 39818235Slinton t_addr->language = primlang; 39918235Slinton t_addr->level = 0; 40018235Slinton t_addr->class = TYPE; 40118235Slinton t_addr->type = newSymbol(nil, 1, PTR, t_int, nil); 40218235Slinton s = insert(identname("true", true)); 40318235Slinton s->class = CONST; 40418235Slinton s->type = t_boolean; 40518235Slinton s->symvalue.constval = build(O_LCON, 1L); 40618235Slinton s->symvalue.constval->nodetype = t_boolean; 40718235Slinton s = insert(identname("false", true)); 40818235Slinton s->class = CONST; 40918235Slinton s->type = t_boolean; 41018235Slinton s->symvalue.constval = build(O_LCON, 0L); 41118235Slinton s->symvalue.constval->nodetype = t_boolean; 4129657Slinton } 4139657Slinton 4149657Slinton /* 4159657Slinton * Reduce type to avoid worrying about type names. 4169657Slinton */ 4179657Slinton 4189657Slinton public Symbol rtype(type) 4199657Slinton Symbol type; 4209657Slinton { 4219657Slinton register Symbol t; 4229657Slinton 4239657Slinton t = type; 4249657Slinton if (t != nil) { 42518235Slinton if (t->class == VAR or t->class == CONST or 42618235Slinton t->class == FIELD or t->class == REF 42718235Slinton ) { 4289657Slinton t = t->type; 4299657Slinton } 43016620Ssam if (t->class == TYPEREF) { 43116620Ssam resolveRef(t); 43216620Ssam } 4339657Slinton while (t->class == TYPE or t->class == TAG) { 4349657Slinton t = t->type; 43516620Ssam if (t->class == TYPEREF) { 43616620Ssam resolveRef(t); 43716620Ssam } 4389657Slinton } 4399657Slinton } 4409657Slinton return t; 4419657Slinton } 4429657Slinton 44316620Ssam /* 44416620Ssam * Find the end of a module name. Return nil if there is none 44516620Ssam * in the given string. 44616620Ssam */ 44716620Ssam 44816620Ssam private String findModuleMark (s) 44916620Ssam String s; 45016620Ssam { 45116620Ssam register char *p, *r; 45216620Ssam register boolean done; 45316620Ssam 45416620Ssam p = s; 45516620Ssam done = false; 45616620Ssam do { 45716620Ssam if (*p == ':') { 45816620Ssam done = true; 45916620Ssam r = p; 46016620Ssam } else if (*p == '\0') { 46116620Ssam done = true; 46216620Ssam r = nil; 46316620Ssam } else { 46416620Ssam ++p; 46516620Ssam } 46616620Ssam } while (not done); 46716620Ssam return r; 46816620Ssam } 46916620Ssam 47016620Ssam /* 47116620Ssam * Resolve a type reference by modifying to be the appropriate type. 47216620Ssam * 47316620Ssam * If the reference has a name, then it refers to an opaque type and 47416620Ssam * the actual type is directly accessible. Otherwise, we must use 47516620Ssam * the type reference string, which is of the form "module:{module:}name". 47616620Ssam */ 47716620Ssam 47816620Ssam public resolveRef (t) 47916620Ssam Symbol t; 48016620Ssam { 48116620Ssam register char *p; 48216620Ssam char *start; 48316620Ssam Symbol s, m, outer; 48416620Ssam Name n; 48516620Ssam 48616620Ssam if (t->name != nil) { 48716620Ssam s = t; 48816620Ssam } else { 48916620Ssam start = t->symvalue.typeref; 49016620Ssam outer = program; 49116620Ssam p = findModuleMark(start); 49216620Ssam while (p != nil) { 49316620Ssam *p = '\0'; 49416620Ssam n = identname(start, true); 49516620Ssam find(m, n) where m->block == outer endfind(m); 49616620Ssam if (m == nil) { 49716620Ssam p = nil; 49816620Ssam outer = nil; 49916620Ssam s = nil; 50016620Ssam } else { 50116620Ssam outer = m; 50216620Ssam start = p + 1; 50316620Ssam p = findModuleMark(start); 50416620Ssam } 50516620Ssam } 50616620Ssam if (outer != nil) { 50716620Ssam n = identname(start, true); 50816620Ssam find(s, n) where s->block == outer endfind(s); 50916620Ssam } 51016620Ssam } 51116620Ssam if (s != nil and s->type != nil) { 51216620Ssam t->name = s->type->name; 51316620Ssam t->class = s->type->class; 51416620Ssam t->type = s->type->type; 51516620Ssam t->chain = s->type->chain; 51616620Ssam t->symvalue = s->type->symvalue; 51716620Ssam t->block = s->type->block; 51816620Ssam } 51916620Ssam } 52016620Ssam 52118235Slinton public integer regnum (s) 5229657Slinton Symbol s; 5239657Slinton { 52418235Slinton integer r; 52518235Slinton 5269657Slinton checkref(s); 52733337Sdonn if (s->storage == INREG) { 52818235Slinton r = s->symvalue.offset; 52918235Slinton } else { 53018235Slinton r = -1; 53118235Slinton } 53218235Slinton return r; 5339657Slinton } 5349657Slinton 5359657Slinton public Symbol container(s) 5369657Slinton Symbol s; 5379657Slinton { 5389657Slinton checkref(s); 5399657Slinton return s->block; 5409657Slinton } 5419657Slinton 54218235Slinton public Node constval(s) 54318235Slinton Symbol s; 54418235Slinton { 54518235Slinton checkref(s); 54618235Slinton if (s->class != CONST) { 54718235Slinton error("[internal error: constval(non-CONST)]"); 54818235Slinton } 54918235Slinton return s->symvalue.constval; 55018235Slinton } 55118235Slinton 5529657Slinton /* 5539657Slinton * Return the object address of the given symbol. 5549657Slinton * 5559657Slinton * There are the following possibilities: 5569657Slinton * 5579657Slinton * globals - just take offset 5589657Slinton * locals - take offset from locals base 5599657Slinton * arguments - take offset from argument base 5609657Slinton * register - offset is register number 5619657Slinton */ 5629657Slinton 56333337Sdonn #define isglobal(s) (s->storage == EXT) 56433337Sdonn #define islocaloff(s) (s->storage == STK and s->symvalue.offset < 0) 56533337Sdonn #define isparamoff(s) (s->storage == STK and s->symvalue.offset >= 0) 5669657Slinton 56718235Slinton public Address address (s, frame) 5689657Slinton Symbol s; 5699657Slinton Frame frame; 5709657Slinton { 5719657Slinton register Frame frp; 5729657Slinton register Address addr; 5739657Slinton register Symbol cur; 5749657Slinton 5759657Slinton checkref(s); 5769657Slinton if (not isactive(s->block)) { 5779657Slinton error("\"%s\" is not currently defined", symname(s)); 5789657Slinton } else if (isglobal(s)) { 5799657Slinton addr = s->symvalue.offset; 5809657Slinton } else { 5819657Slinton frp = frame; 5829657Slinton if (frp == nil) { 5839657Slinton cur = s->block; 5849657Slinton while (cur != nil and cur->class == MODULE) { 5859657Slinton cur = cur->block; 5869657Slinton } 5879657Slinton if (cur == nil) { 58818235Slinton frp = nil; 58918235Slinton } else { 59018235Slinton frp = findframe(cur); 59118235Slinton if (frp == nil) { 59218235Slinton error("[internal error: unexpected nil frame for \"%s\"]", 59318235Slinton symname(s) 59418235Slinton ); 59518235Slinton } 5969657Slinton } 5979657Slinton } 5989657Slinton if (islocaloff(s)) { 5999657Slinton addr = locals_base(frp) + s->symvalue.offset; 6009657Slinton } else if (isparamoff(s)) { 6019657Slinton addr = args_base(frp) + s->symvalue.offset; 6029657Slinton } else if (isreg(s)) { 6039657Slinton addr = savereg(s->symvalue.offset, frp); 6049657Slinton } else { 6059657Slinton panic("address: bad symbol \"%s\"", symname(s)); 6069657Slinton } 6079657Slinton } 6089657Slinton return addr; 6099657Slinton } 6109657Slinton 6119657Slinton /* 6129657Slinton * Define a symbol used to access register values. 6139657Slinton */ 6149657Slinton 61518235Slinton public defregname (n, r) 6169657Slinton Name n; 61718235Slinton integer r; 6189657Slinton { 61918235Slinton Symbol s; 6209657Slinton 6219657Slinton s = insert(n); 62218235Slinton s->language = t_addr->language; 6239657Slinton s->class = VAR; 62433337Sdonn s->storage = INREG; 62533337Sdonn s->level = 3; 62618235Slinton s->type = t_addr; 6279657Slinton s->symvalue.offset = r; 6289657Slinton } 6299657Slinton 6309657Slinton /* 6319657Slinton * Resolve an "abstract" type reference. 6329657Slinton * 6339657Slinton * It is possible in C to define a pointer to a type, but never define 6349657Slinton * the type in a particular source file. Here we try to resolve 6359657Slinton * the type definition. This is problematic, it is possible to 6369657Slinton * have multiple, different definitions for the same name type. 6379657Slinton */ 6389657Slinton 6399657Slinton public findtype(s) 6409657Slinton Symbol s; 6419657Slinton { 6429657Slinton register Symbol t, u, prev; 6439657Slinton 6449657Slinton u = s; 6459657Slinton prev = nil; 6469657Slinton while (u != nil and u->class != BADUSE) { 6479657Slinton if (u->name != nil) { 6489657Slinton prev = u; 6499657Slinton } 6509657Slinton u = u->type; 6519657Slinton } 6529657Slinton if (prev == nil) { 6539657Slinton error("couldn't find link to type reference"); 6549657Slinton } 65518235Slinton t = lookup(prev->name); 65618235Slinton while (t != nil and 65718235Slinton not ( 65818235Slinton t != prev and t->name == prev->name and 65918235Slinton t->block->class == MODULE and t->class == prev->class and 66018235Slinton t->type != nil and t->type->type != nil and 66118235Slinton t->type->type->class != BADUSE 66218235Slinton ) 66318235Slinton ) { 66418235Slinton t = t->next_sym; 66518235Slinton } 6669657Slinton if (t == nil) { 6679657Slinton error("couldn't resolve reference"); 6689657Slinton } else { 6699657Slinton prev->type = t->type; 6709657Slinton } 6719657Slinton } 6729657Slinton 6739657Slinton /* 6749657Slinton * Find the size in bytes of the given type. 6759657Slinton * 6769657Slinton * This is probably the WRONG thing to do. The size should be kept 6779657Slinton * as an attribute in the symbol information as is done for structures 6789657Slinton * and fields. I haven't gotten around to cleaning this up yet. 6799657Slinton */ 6809657Slinton 68112547Scsvaf #define MAXUCHAR 255 68212547Scsvaf #define MAXUSHORT 65535L 6839657Slinton #define MINCHAR -128 6849657Slinton #define MAXCHAR 127 6859657Slinton #define MINSHORT -32768 6869657Slinton #define MAXSHORT 32767 6879657Slinton 68816620Ssam public findbounds (u, lower, upper) 68916620Ssam Symbol u; 69016620Ssam long *lower, *upper; 69116620Ssam { 69216620Ssam Rangetype lbt, ubt; 69316620Ssam long lb, ub; 69416620Ssam 69516620Ssam if (u->class == RANGE) { 69616620Ssam lbt = u->symvalue.rangev.lowertype; 69716620Ssam ubt = u->symvalue.rangev.uppertype; 69816620Ssam lb = u->symvalue.rangev.lower; 69916620Ssam ub = u->symvalue.rangev.upper; 70016620Ssam if (lbt == R_ARG or lbt == R_TEMP) { 70116620Ssam if (not getbound(u, lb, lbt, lower)) { 70216620Ssam error("dynamic bounds not currently available"); 70316620Ssam } 70416620Ssam } else { 70516620Ssam *lower = lb; 70616620Ssam } 70716620Ssam if (ubt == R_ARG or ubt == R_TEMP) { 70816620Ssam if (not getbound(u, ub, ubt, upper)) { 70916620Ssam error("dynamic bounds not currently available"); 71016620Ssam } 71116620Ssam } else { 71216620Ssam *upper = ub; 71316620Ssam } 71416620Ssam } else if (u->class == SCAL) { 71516620Ssam *lower = 0; 71616620Ssam *upper = u->symvalue.iconval - 1; 71716620Ssam } else { 71818235Slinton error("[internal error: unexpected array bound type]"); 71916620Ssam } 72016620Ssam } 72116620Ssam 72216620Ssam public integer size(sym) 72316620Ssam Symbol sym; 72416620Ssam { 72516620Ssam register Symbol s, t, u; 72616620Ssam register integer nel, elsize; 7279657Slinton long lower, upper; 72816620Ssam integer r, off, len; 7299657Slinton 7309657Slinton t = sym; 7319657Slinton checkref(t); 73216620Ssam if (t->class == TYPEREF) { 73316620Ssam resolveRef(t); 73416620Ssam } 7359657Slinton switch (t->class) { 7369657Slinton case RANGE: 7379657Slinton lower = t->symvalue.rangev.lower; 7389657Slinton upper = t->symvalue.rangev.upper; 73916620Ssam if (upper == 0 and lower > 0) { 74016620Ssam /* real */ 7419657Slinton r = lower; 74216620Ssam } else if (lower > upper) { 74316620Ssam /* unsigned long */ 74416620Ssam r = sizeof(long); 74512045Slinton } else if ( 74612547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or 74712547Scsvaf (lower >= 0 and upper <= MAXUCHAR) 74812547Scsvaf ) { 7499657Slinton r = sizeof(char); 75012547Scsvaf } else if ( 75112547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or 75212547Scsvaf (lower >= 0 and upper <= MAXUSHORT) 75312547Scsvaf ) { 7549657Slinton r = sizeof(short); 7559657Slinton } else { 7569657Slinton r = sizeof(long); 7579657Slinton } 7589657Slinton break; 7599657Slinton 7609657Slinton case ARRAY: 7619657Slinton elsize = size(t->type); 7629657Slinton nel = 1; 7639657Slinton for (t = t->chain; t != nil; t = t->chain) { 76416620Ssam u = rtype(t); 76516620Ssam findbounds(u, &lower, &upper); 7669657Slinton nel *= (upper-lower+1); 7679657Slinton } 7689657Slinton r = nel*elsize; 7699657Slinton break; 7709657Slinton 77133337Sdonn case OPENARRAY: 77218235Slinton case DYNARRAY: 77318235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 77418235Slinton break; 77518235Slinton 77618235Slinton case SUBARRAY: 77718235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 77818235Slinton break; 77918235Slinton 78012547Scsvaf case REF: 7819657Slinton case VAR: 7829657Slinton r = size(t->type); 78312127Slinton /* 78412127Slinton * 78512045Slinton if (r < sizeof(Word) and isparam(t)) { 7869657Slinton r = sizeof(Word); 7879657Slinton } 78812547Scsvaf */ 7899657Slinton break; 7909657Slinton 79118235Slinton case FVAR: 7929657Slinton case CONST: 79318235Slinton case TAG: 7949657Slinton r = size(t->type); 7959657Slinton break; 7969657Slinton 7979657Slinton case TYPE: 79833337Sdonn /* 79933337Sdonn * This causes problems on the IRIS because of the compiler bug 80033337Sdonn * with stab offsets for parameters. Not sure it's really 80133337Sdonn * necessary anyway. 80233337Sdonn */ 80333337Sdonn # ifndef IRIS 8049657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 8059657Slinton findtype(t); 8069657Slinton } 80733337Sdonn # endif 8089657Slinton r = size(t->type); 8099657Slinton break; 8109657Slinton 8119657Slinton case FIELD: 81216620Ssam off = t->symvalue.field.offset; 81316620Ssam len = t->symvalue.field.length; 81416620Ssam r = (off + len + 7) div 8 - (off div 8); 8159657Slinton break; 8169657Slinton 8179657Slinton case RECORD: 8189657Slinton case VARNT: 8199657Slinton r = t->symvalue.offset; 8209657Slinton if (r == 0 and t->chain != nil) { 8219657Slinton panic("missing size information for record"); 8229657Slinton } 8239657Slinton break; 8249657Slinton 8259657Slinton case PTR: 82618235Slinton case TYPEREF: 8279657Slinton case FILET: 8289657Slinton r = sizeof(Word); 8299657Slinton break; 8309657Slinton 8319657Slinton case SCAL: 83212609Slinton r = sizeof(Word); 83312609Slinton /* 83412609Slinton * 8359657Slinton if (t->symvalue.iconval > 255) { 8369657Slinton r = sizeof(short); 8379657Slinton } else { 8389657Slinton r = sizeof(char); 8399657Slinton } 84012609Slinton * 84112609Slinton */ 8429657Slinton break; 8439657Slinton 8449657Slinton case FPROC: 8459657Slinton case FFUNC: 8469657Slinton r = sizeof(Word); 8479657Slinton break; 8489657Slinton 8499657Slinton case PROC: 8509657Slinton case FUNC: 8519657Slinton case MODULE: 8529657Slinton case PROG: 8539657Slinton r = sizeof(Symbol); 8549657Slinton break; 8559657Slinton 85616620Ssam case SET: 85716620Ssam u = rtype(t->type); 85816620Ssam switch (u->class) { 85916620Ssam case RANGE: 86016620Ssam r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; 86116620Ssam break; 86216620Ssam 86316620Ssam case SCAL: 86416620Ssam r = u->symvalue.iconval; 86516620Ssam break; 86616620Ssam 86716620Ssam default: 86816620Ssam error("expected range for set base type"); 86916620Ssam break; 87016620Ssam } 87116620Ssam r = (r + BITSPERBYTE - 1) div BITSPERBYTE; 87216620Ssam break; 87316620Ssam 87418235Slinton /* 87518235Slinton * These can happen in C (unfortunately) for unresolved type references 87618235Slinton * Assume they are pointers. 87718235Slinton */ 87818235Slinton case BADUSE: 87918235Slinton r = sizeof(Address); 88018235Slinton break; 88118235Slinton 8829657Slinton default: 8839657Slinton if (ord(t->class) > ord(TYPEREF)) { 8849657Slinton panic("size: bad class (%d)", ord(t->class)); 8859657Slinton } else { 88618235Slinton fprintf(stderr, "can't compute size of a %s\n", classname(t)); 8879657Slinton } 88816620Ssam r = 0; 88916620Ssam break; 8909657Slinton } 8919657Slinton return r; 8929657Slinton } 8939657Slinton 8949657Slinton /* 89518235Slinton * Return the size associated with a symbol that takes into account 89618235Slinton * reference parameters. This might be better as the normal size function, but 89718235Slinton * too many places already depend on it working the way it does. 89818235Slinton */ 89918235Slinton 90018235Slinton public integer psize (s) 90118235Slinton Symbol s; 90218235Slinton { 90318235Slinton integer r; 90418235Slinton Symbol t; 90518235Slinton 90618235Slinton if (s->class == REF) { 90718235Slinton t = rtype(s->type); 90833337Sdonn if (t->class == OPENARRAY) { 90918235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 91018235Slinton } else if (t->class == SUBARRAY) { 91118235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 91218235Slinton } else { 91318235Slinton r = sizeof(Word); 91418235Slinton } 91518235Slinton } else { 91618235Slinton r = size(s); 91718235Slinton } 91818235Slinton return r; 91918235Slinton } 92018235Slinton 92118235Slinton /* 9229657Slinton * Test if a symbol is a parameter. This is true if there 9239657Slinton * is a cycle from s->block to s via chain pointers. 9249657Slinton */ 9259657Slinton 9269657Slinton public Boolean isparam(s) 9279657Slinton Symbol s; 9289657Slinton { 9299657Slinton register Symbol t; 9309657Slinton 9319657Slinton t = s->block; 9329657Slinton while (t != nil and t != s) { 9339657Slinton t = t->chain; 9349657Slinton } 9359657Slinton return (Boolean) (t != nil); 9369657Slinton } 9379657Slinton 9389657Slinton /* 93916620Ssam * Test if a type is an open array parameter type. 9409657Slinton */ 9419657Slinton 94218235Slinton public boolean isopenarray (type) 94318235Slinton Symbol type; 94416620Ssam { 94518235Slinton Symbol t; 94618235Slinton 94718235Slinton t = rtype(type); 94833337Sdonn return (boolean) (t->class == OPENARRAY); 94916620Ssam } 95016620Ssam 95116620Ssam /* 95218235Slinton * Test if a symbol is a var parameter, i.e. has class REF. 95316620Ssam */ 95416620Ssam 9559657Slinton public Boolean isvarparam(s) 9569657Slinton Symbol s; 9579657Slinton { 9589657Slinton return (Boolean) (s->class == REF); 9599657Slinton } 9609657Slinton 9619657Slinton /* 9629657Slinton * Test if a symbol is a variable (actually any addressible quantity 9639657Slinton * with do). 9649657Slinton */ 9659657Slinton 9669657Slinton public Boolean isvariable(s) 96718235Slinton Symbol s; 9689657Slinton { 9699657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 9709657Slinton } 9719657Slinton 9729657Slinton /* 97318235Slinton * Test if a symbol is a constant. 97418235Slinton */ 97518235Slinton 97618235Slinton public Boolean isconst(s) 97718235Slinton Symbol s; 9789657Slinton { 97918235Slinton return (Boolean) (s->class == CONST); 9809657Slinton } 9819657Slinton 9829657Slinton /* 9839657Slinton * Test if a symbol is a module. 9849657Slinton */ 9859657Slinton 9869657Slinton public Boolean ismodule(s) 9879657Slinton register Symbol s; 9889657Slinton { 9899657Slinton return (Boolean) (s->class == MODULE); 9909657Slinton } 9919657Slinton 9929657Slinton /* 99316620Ssam * Mark a procedure or function as internal, meaning that it is called 99416620Ssam * with a different calling sequence. 99516620Ssam */ 99616620Ssam 99716620Ssam public markInternal (s) 99816620Ssam Symbol s; 99916620Ssam { 100016620Ssam s->symvalue.funcv.intern = true; 100116620Ssam } 100216620Ssam 100316620Ssam public boolean isinternal (s) 100416620Ssam Symbol s; 100516620Ssam { 100616620Ssam return s->symvalue.funcv.intern; 100716620Ssam } 100816620Ssam 100916620Ssam /* 101018235Slinton * Decide if a field begins or ends on a bit rather than byte boundary. 101118235Slinton */ 101218235Slinton 101318235Slinton public Boolean isbitfield(s) 101418235Slinton register Symbol s; 101518235Slinton { 101618235Slinton boolean b; 101718235Slinton register integer off, len; 101818235Slinton register Symbol t; 101918235Slinton 102018235Slinton off = s->symvalue.field.offset; 102118235Slinton len = s->symvalue.field.length; 102218235Slinton if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { 102318235Slinton b = true; 102418235Slinton } else { 102518235Slinton t = rtype(s->type); 102618235Slinton b = (Boolean) ( 102718235Slinton (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or 102818235Slinton len != (size(t)*BITSPERBYTE) 102918235Slinton ); 103018235Slinton } 103118235Slinton return b; 103218235Slinton } 103318235Slinton 103418235Slinton private boolean primlang_typematch (t1, t2) 103518235Slinton Symbol t1, t2; 103618235Slinton { 103718235Slinton return (boolean) ( 103818235Slinton (t1 == t2) or 103918235Slinton ( 104018235Slinton t1->class == RANGE and t2->class == RANGE and 104118235Slinton t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 104218235Slinton t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 104318235Slinton ) or ( 104418235Slinton t1->class == PTR and t2->class == RANGE and 104518235Slinton t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower 104618235Slinton ) or ( 104718235Slinton t2->class == PTR and t1->class == RANGE and 104818235Slinton t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower 104918235Slinton ) 105018235Slinton ); 105118235Slinton } 105218235Slinton 105318235Slinton /* 10549657Slinton * Test if two types match. 10559657Slinton * Equivalent names implies a match in any language. 10569657Slinton * 10579657Slinton * Special symbols must be handled with care. 10589657Slinton */ 10599657Slinton 10609657Slinton public Boolean compatible(t1, t2) 10619657Slinton register Symbol t1, t2; 10629657Slinton { 10639657Slinton Boolean b; 106416620Ssam Symbol rt1, rt2; 10659657Slinton 10669657Slinton if (t1 == t2) { 10679657Slinton b = true; 10689657Slinton } else if (t1 == nil or t2 == nil) { 10699657Slinton b = false; 10709657Slinton } else if (t1 == procsym) { 10719657Slinton b = isblock(t2); 10729657Slinton } else if (t2 == procsym) { 10739657Slinton b = isblock(t1); 10749657Slinton } else if (t1->language == nil) { 107516620Ssam if (t2->language == nil) { 107616620Ssam b = false; 107733337Sdonn } else if (t2->language == primlang) { 107833337Sdonn b = (boolean) primlang_typematch(rtype(t1), rtype(t2)); 107916620Ssam } else { 108016620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 108116620Ssam } 108233337Sdonn } else if (t1->language == primlang) { 108333337Sdonn if (t2->language == primlang or t2->language == nil) { 108433337Sdonn b = primlang_typematch(rtype(t1), rtype(t2)); 108533337Sdonn } else { 108633337Sdonn b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 108733337Sdonn } 10889657Slinton } else { 108916620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 10909657Slinton } 10919657Slinton return b; 10929657Slinton } 10939657Slinton 10949657Slinton /* 10959657Slinton * Check for a type of the given name. 10969657Slinton */ 10979657Slinton 10989657Slinton public Boolean istypename(type, name) 10999657Slinton Symbol type; 11009657Slinton String name; 11019657Slinton { 110218235Slinton register Symbol t; 11039657Slinton Boolean b; 11049657Slinton 11059657Slinton t = type; 110618235Slinton if (t == nil) { 110718235Slinton b = false; 110818235Slinton } else { 110918235Slinton b = (Boolean) ( 111018235Slinton t->class == TYPE and streq(ident(t->name), name) 111118235Slinton ); 111218235Slinton } 11139657Slinton return b; 11149657Slinton } 11159657Slinton 11169657Slinton /* 111716620Ssam * Determine if a (value) parameter should actually be passed by address. 111816620Ssam */ 111916620Ssam 112016620Ssam public boolean passaddr (p, exprtype) 112116620Ssam Symbol p, exprtype; 112216620Ssam { 112316620Ssam boolean b; 112416620Ssam Language def; 112516620Ssam 112616620Ssam if (p == nil) { 112716620Ssam def = findlanguage(".c"); 112816620Ssam b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); 112916620Ssam } else if (p->language == nil or p->language == primlang) { 113016620Ssam b = false; 113116620Ssam } else if (isopenarray(p->type)) { 113216620Ssam b = true; 113316620Ssam } else { 113416620Ssam b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); 113516620Ssam } 113616620Ssam return b; 113716620Ssam } 113816620Ssam 113916620Ssam /* 11409657Slinton * Test if the name of a symbol is uniquely defined or not. 11419657Slinton */ 11429657Slinton 11439657Slinton public Boolean isambiguous(s) 11449657Slinton register Symbol s; 11459657Slinton { 11469657Slinton register Symbol t; 11479657Slinton 11489657Slinton find(t, s->name) where t != s endfind(t); 11499657Slinton return (Boolean) (t != nil); 11509657Slinton } 11519657Slinton 11529657Slinton typedef char *Arglist; 11539657Slinton 11549657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 11559657Slinton 11569657Slinton private Symbol mkstring(); 11579657Slinton 11589657Slinton /* 11599657Slinton * Determine the type of a parse tree. 116018235Slinton * 11619657Slinton * Also make some symbol-dependent changes to the tree such as 116218235Slinton * removing indirection for constant or register symbols. 11639657Slinton */ 11649657Slinton 116518235Slinton public assigntypes (p) 11669657Slinton register Node p; 11679657Slinton { 11689657Slinton register Node p1; 11699657Slinton register Symbol s; 11709657Slinton 11719657Slinton switch (p->op) { 11729657Slinton case O_SYM: 117318235Slinton p->nodetype = p->value.sym; 11749657Slinton break; 11759657Slinton 11769657Slinton case O_LCON: 11779657Slinton p->nodetype = t_int; 11789657Slinton break; 11799657Slinton 118018235Slinton case O_CCON: 118118235Slinton p->nodetype = t_char; 118218235Slinton break; 118318235Slinton 11849657Slinton case O_FCON: 11859657Slinton p->nodetype = t_real; 11869657Slinton break; 11879657Slinton 11889657Slinton case O_SCON: 118918235Slinton p->nodetype = mkstring(p->value.scon); 11909657Slinton break; 11919657Slinton 11929657Slinton case O_INDIR: 11939657Slinton p1 = p->value.arg[0]; 119418235Slinton s = rtype(p1->nodetype); 119518235Slinton if (s->class != PTR) { 119618235Slinton beginerrmsg(); 119718235Slinton fprintf(stderr, "\""); 119818235Slinton prtree(stderr, p1); 119918235Slinton fprintf(stderr, "\" is not a pointer"); 120018235Slinton enderrmsg(); 120118235Slinton } 12029657Slinton p->nodetype = rtype(p1->nodetype)->type; 12039657Slinton break; 12049657Slinton 12059657Slinton case O_DOT: 12069657Slinton p->nodetype = p->value.arg[1]->value.sym; 12079657Slinton break; 12089657Slinton 12099657Slinton case O_RVAL: 12109657Slinton p1 = p->value.arg[0]; 12119657Slinton p->nodetype = p1->nodetype; 12129657Slinton if (p1->op == O_SYM) { 121318235Slinton if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) { 121418235Slinton p->op = p1->op; 121518235Slinton p->value.sym = p1->value.sym; 121618235Slinton p->nodetype = p1->nodetype; 121718235Slinton dispose(p1); 12189657Slinton } else if (p1->value.sym->class == CONST) { 121918235Slinton p->op = p1->op; 122018235Slinton p->value = p1->value; 122118235Slinton p->nodetype = p1->nodetype; 122218235Slinton dispose(p1); 12239657Slinton } else if (isreg(p1->value.sym)) { 12249657Slinton p->op = O_SYM; 12259657Slinton p->value.sym = p1->value.sym; 12269657Slinton dispose(p1); 12279657Slinton } 12289657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 12299657Slinton s = p1->value.arg[0]->value.sym; 12309657Slinton if (isreg(s)) { 12319657Slinton p1->op = O_SYM; 12329657Slinton dispose(p1->value.arg[0]); 12339657Slinton p1->value.sym = s; 12349657Slinton p1->nodetype = s; 12359657Slinton } 12369657Slinton } 12379657Slinton break; 12389657Slinton 123918235Slinton case O_COMMA: 124018235Slinton p->nodetype = p->value.arg[0]->nodetype; 124118235Slinton break; 124218235Slinton 124318235Slinton case O_CALLPROC: 12449657Slinton case O_CALL: 12459657Slinton p1 = p->value.arg[0]; 124611171Slinton p->nodetype = rtype(p1->nodetype)->type; 12479657Slinton break; 12489657Slinton 124911171Slinton case O_TYPERENAME: 125011171Slinton p->nodetype = p->value.arg[1]->nodetype; 125111171Slinton break; 125211171Slinton 12539657Slinton case O_ITOF: 12549657Slinton p->nodetype = t_real; 12559657Slinton break; 12569657Slinton 12579657Slinton case O_NEG: 12589657Slinton s = p->value.arg[0]->nodetype; 12599657Slinton if (not compatible(s, t_int)) { 12609657Slinton if (not compatible(s, t_real)) { 12619657Slinton beginerrmsg(); 126216620Ssam fprintf(stderr, "\""); 12639657Slinton prtree(stderr, p->value.arg[0]); 126416620Ssam fprintf(stderr, "\" is improper type"); 12659657Slinton enderrmsg(); 12669657Slinton } else { 12679657Slinton p->op = O_NEGF; 12689657Slinton } 12699657Slinton } 12709657Slinton p->nodetype = s; 12719657Slinton break; 12729657Slinton 12739657Slinton case O_ADD: 12749657Slinton case O_SUB: 12759657Slinton case O_MUL: 127616620Ssam binaryop(p, nil); 127716620Ssam break; 127816620Ssam 12799657Slinton case O_LT: 12809657Slinton case O_LE: 12819657Slinton case O_GT: 12829657Slinton case O_GE: 12839657Slinton case O_EQ: 12849657Slinton case O_NE: 128516620Ssam binaryop(p, t_boolean); 12869657Slinton break; 12879657Slinton 12889657Slinton case O_DIVF: 12899657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 12909657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 12919657Slinton p->nodetype = t_real; 12929657Slinton break; 12939657Slinton 12949657Slinton case O_DIV: 12959657Slinton case O_MOD: 12969657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 12979657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 12989657Slinton p->nodetype = t_int; 12999657Slinton break; 13009657Slinton 13019657Slinton case O_AND: 13029657Slinton case O_OR: 13039657Slinton chkboolean(p->value.arg[0]); 13049657Slinton chkboolean(p->value.arg[1]); 13059657Slinton p->nodetype = t_boolean; 13069657Slinton break; 13079657Slinton 13089657Slinton case O_QLINE: 13099657Slinton p->nodetype = t_int; 13109657Slinton break; 13119657Slinton 13129657Slinton default: 13139657Slinton p->nodetype = nil; 13149657Slinton break; 13159657Slinton } 13169657Slinton } 13179657Slinton 13189657Slinton /* 131916620Ssam * Process a binary arithmetic or relational operator. 132016620Ssam * Convert from integer to real if necessary. 132116620Ssam */ 132216620Ssam 132316620Ssam private binaryop (p, t) 132416620Ssam Node p; 132516620Ssam Symbol t; 132616620Ssam { 132716620Ssam Node p1, p2; 132816620Ssam Boolean t1real, t2real; 132916620Ssam Symbol t1, t2; 133016620Ssam 133116620Ssam p1 = p->value.arg[0]; 133216620Ssam p2 = p->value.arg[1]; 133316620Ssam t1 = rtype(p1->nodetype); 133416620Ssam t2 = rtype(p2->nodetype); 133516620Ssam t1real = compatible(t1, t_real); 133616620Ssam t2real = compatible(t2, t_real); 133716620Ssam if (t1real or t2real) { 133816620Ssam p->op = (Operator) (ord(p->op) + 1); 133916620Ssam if (not t1real) { 134016620Ssam p->value.arg[0] = build(O_ITOF, p1); 134116620Ssam } else if (not t2real) { 134216620Ssam p->value.arg[1] = build(O_ITOF, p2); 134316620Ssam } 134416620Ssam p->nodetype = t_real; 134516620Ssam } else { 134616620Ssam if (size(p1->nodetype) > sizeof(integer)) { 134716620Ssam beginerrmsg(); 134816620Ssam fprintf(stderr, "operation not defined on \""); 134916620Ssam prtree(stderr, p1); 135016620Ssam fprintf(stderr, "\""); 135116620Ssam enderrmsg(); 135216620Ssam } else if (size(p2->nodetype) > sizeof(integer)) { 135316620Ssam beginerrmsg(); 135416620Ssam fprintf(stderr, "operation not defined on \""); 135516620Ssam prtree(stderr, p2); 135616620Ssam fprintf(stderr, "\""); 135716620Ssam enderrmsg(); 135816620Ssam } 135916620Ssam p->nodetype = t_int; 136016620Ssam } 136116620Ssam if (t != nil) { 136216620Ssam p->nodetype = t; 136316620Ssam } 136416620Ssam } 136516620Ssam 136616620Ssam /* 13679657Slinton * Convert a tree to a type via a conversion operator; 13689657Slinton * if this isn't possible generate an error. 13699657Slinton */ 13709657Slinton 13719657Slinton private convert(tp, typeto, op) 13729657Slinton Node *tp; 13739657Slinton Symbol typeto; 13749657Slinton Operator op; 13759657Slinton { 137616620Ssam Node tree; 137716620Ssam Symbol s, t; 13789657Slinton 137916620Ssam tree = *tp; 13809657Slinton s = rtype(tree->nodetype); 138116620Ssam t = rtype(typeto); 138216620Ssam if (compatible(t, t_real) and compatible(s, t_int)) { 1383*34257Sdonn /* we can convert int => floating but not the reverse */ 13849657Slinton tree = build(op, tree); 138516620Ssam } else if (not compatible(s, t)) { 13869657Slinton beginerrmsg(); 138716620Ssam prtree(stderr, tree); 1388*34257Sdonn fprintf(stderr, ": illegal type in operation"); 13899657Slinton enderrmsg(); 13909657Slinton } 139116620Ssam *tp = tree; 13929657Slinton } 13939657Slinton 13949657Slinton /* 13959657Slinton * Construct a node for the dot operator. 13969657Slinton * 13979657Slinton * If the left operand is not a record, but rather a procedure 13989657Slinton * or function, then we interpret the "." as referencing an 13999657Slinton * "invisible" variable; i.e. a variable within a dynamically 14009657Slinton * active block but not within the static scope of the current procedure. 14019657Slinton */ 14029657Slinton 14039657Slinton public Node dot(record, fieldname) 14049657Slinton Node record; 14059657Slinton Name fieldname; 14069657Slinton { 140718235Slinton register Node rec, p; 14089657Slinton register Symbol s, t; 14099657Slinton 141018235Slinton rec = record; 141118235Slinton if (isblock(rec->nodetype)) { 14129657Slinton find(s, fieldname) where 141318235Slinton s->block == rec->nodetype and 141418235Slinton s->class != FIELD 14159657Slinton endfind(s); 14169657Slinton if (s == nil) { 14179657Slinton beginerrmsg(); 14189657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 141918235Slinton printname(stderr, rec->nodetype); 14209657Slinton enderrmsg(); 14219657Slinton } 14229657Slinton p = new(Node); 14239657Slinton p->op = O_SYM; 14249657Slinton p->value.sym = s; 142518235Slinton p->nodetype = s; 14269657Slinton } else { 142718235Slinton p = rec; 14289657Slinton t = rtype(p->nodetype); 14299657Slinton if (t->class == PTR) { 14309657Slinton s = findfield(fieldname, t->type); 14319657Slinton } else { 14329657Slinton s = findfield(fieldname, t); 14339657Slinton } 14349657Slinton if (s == nil) { 14359657Slinton beginerrmsg(); 14369657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 143718235Slinton prtree(stderr, rec); 14389657Slinton enderrmsg(); 14399657Slinton } 144018235Slinton if (t->class != PTR or isreg(rec->nodetype)) { 144118235Slinton p = unrval(p); 14429657Slinton } 144318235Slinton p->nodetype = t_addr; 14449657Slinton p = build(O_DOT, p, build(O_SYM, s)); 14459657Slinton } 144618235Slinton return build(O_RVAL, p); 14479657Slinton } 14489657Slinton 14499657Slinton /* 14509657Slinton * Return a tree corresponding to an array reference and do the 14519657Slinton * error checking. 14529657Slinton */ 14539657Slinton 14549657Slinton public Node subscript(a, slist) 14559657Slinton Node a, slist; 14569657Slinton { 145716620Ssam Symbol t; 145818235Slinton Node p; 14599657Slinton 146016620Ssam t = rtype(a->nodetype); 146118235Slinton if (t->language == nil or t->language == primlang) { 146218235Slinton p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); 146316620Ssam } else { 146418235Slinton p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); 146516620Ssam } 146618235Slinton return build(O_RVAL, p); 14679657Slinton } 14689657Slinton 14699657Slinton /* 14709657Slinton * Evaluate a subscript index. 14719657Slinton */ 14729657Slinton 147318235Slinton public int evalindex(s, base, i) 14749657Slinton Symbol s; 147518235Slinton Address base; 14769657Slinton long i; 14779657Slinton { 147816620Ssam Symbol t; 147918235Slinton int r; 14809657Slinton 148116620Ssam t = rtype(s); 148218235Slinton if (t->language == nil or t->language == primlang) { 148318235Slinton r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); 148416620Ssam } else { 148518235Slinton r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); 148616620Ssam } 148718235Slinton return r; 14889657Slinton } 14899657Slinton 14909657Slinton /* 14919657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 14929657Slinton */ 14939657Slinton 14949657Slinton public chkboolean(p) 14959657Slinton register Node p; 14969657Slinton { 14979657Slinton if (p->nodetype != t_boolean) { 14989657Slinton beginerrmsg(); 14999657Slinton fprintf(stderr, "found "); 15009657Slinton prtree(stderr, p); 15019657Slinton fprintf(stderr, ", expected boolean expression"); 15029657Slinton enderrmsg(); 15039657Slinton } 15049657Slinton } 15059657Slinton 15069657Slinton /* 150716620Ssam * Construct a node for the type of a string. 15089657Slinton */ 15099657Slinton 15109657Slinton private Symbol mkstring(str) 15119657Slinton String str; 15129657Slinton { 15139657Slinton register Symbol s; 15149657Slinton 151518235Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 151618235Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 151718235Slinton s->chain->language = s->language; 151818235Slinton s->chain->symvalue.rangev.lower = 1; 151918235Slinton s->chain->symvalue.rangev.upper = strlen(str) + 1; 15209657Slinton return s; 15219657Slinton } 15229657Slinton 15239657Slinton /* 15249657Slinton * Free up the space allocated for a string type. 15259657Slinton */ 15269657Slinton 15279657Slinton public unmkstring(s) 15289657Slinton Symbol s; 15299657Slinton { 15309657Slinton dispose(s->chain); 15319657Slinton } 15329657Slinton 15339657Slinton /* 153418235Slinton * Figure out the "current" variable or function being referred to 153518235Slinton * by the name n. 15369657Slinton */ 15379657Slinton 153818235Slinton private boolean stwhich(), dynwhich(); 153918235Slinton 154018235Slinton public Symbol which (n) 15419657Slinton Name n; 15429657Slinton { 154318235Slinton Symbol s; 15449657Slinton 154518235Slinton s = lookup(n); 15469657Slinton if (s == nil) { 154718235Slinton error("\"%s\" is not defined", ident(n)); 154818235Slinton } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { 154918235Slinton printf("[using "); 155018235Slinton printname(stdout, s); 155118235Slinton printf("]\n"); 15529657Slinton } 155318235Slinton return s; 155418235Slinton } 155518235Slinton 155618235Slinton /* 155718235Slinton * Static search. 155818235Slinton */ 155918235Slinton 156018235Slinton private boolean stwhich (var_s) 156118235Slinton Symbol *var_s; 156218235Slinton { 156318235Slinton Name n; /* name of desired symbol */ 156418235Slinton Symbol s; /* iteration variable for symbols with name n */ 156518235Slinton Symbol f; /* iteration variable for blocks containing s */ 156618235Slinton integer count; /* number of levels from s->block to curfunc */ 156718235Slinton Symbol t; /* current best answer for stwhich(n) */ 156818235Slinton integer mincount; /* relative level for current best answer (t) */ 156918235Slinton boolean b; /* return value, true if symbol found */ 157018235Slinton 157118235Slinton s = *var_s; 157218235Slinton n = s->name; 157318235Slinton t = s; 157418235Slinton mincount = 10000; /* force first match to set mincount */ 157518235Slinton do { 157618235Slinton if (s->name == n and s->class != FIELD and s->class != TAG) { 157718235Slinton f = curfunc; 157818235Slinton count = 0; 157918235Slinton while (f != nil and f != s->block) { 158018235Slinton ++count; 158118235Slinton f = f->block; 158218235Slinton } 158318235Slinton if (f != nil and count < mincount) { 158418235Slinton t = s; 158518235Slinton mincount = count; 158618235Slinton b = true; 158718235Slinton } 158818235Slinton } 158918235Slinton s = s->next_sym; 159018235Slinton } while (s != nil); 159118235Slinton if (mincount != 10000) { 159218235Slinton *var_s = t; 159318235Slinton b = true; 15949657Slinton } else { 159518235Slinton b = false; 159618235Slinton } 159718235Slinton return b; 159818235Slinton } 159918235Slinton 160018235Slinton /* 160118235Slinton * Dynamic search. 160218235Slinton */ 160318235Slinton 160418235Slinton private boolean dynwhich (var_s) 160518235Slinton Symbol *var_s; 160618235Slinton { 160718235Slinton Name n; /* name of desired symbol */ 160818235Slinton Symbol s; /* iteration variable for possible symbols */ 160918235Slinton Symbol f; /* iteration variable for active functions */ 161018235Slinton Frame frp; /* frame associated with stack walk */ 161118235Slinton boolean b; /* return value */ 161218235Slinton 161318235Slinton f = curfunc; 161418235Slinton frp = curfuncframe(); 161518235Slinton n = (*var_s)->name; 161618235Slinton b = false; 161718235Slinton if (frp != nil) { 161818235Slinton frp = nextfunc(frp, &f); 161918235Slinton while (frp != nil) { 162018235Slinton s = *var_s; 162118235Slinton while (s != nil and 162218235Slinton ( 162318235Slinton s->name != n or s->block != f or 162418235Slinton s->class == FIELD or s->class == TAG 162518235Slinton ) 162618235Slinton ) { 162718235Slinton s = s->next_sym; 162818235Slinton } 162918235Slinton if (s != nil) { 163018235Slinton *var_s = s; 163118235Slinton b = true; 163218235Slinton break; 163318235Slinton } 163418235Slinton if (f == program) { 163518235Slinton break; 163618235Slinton } 163718235Slinton frp = nextfunc(frp, &f); 16389657Slinton } 16399657Slinton } 164018235Slinton return b; 16419657Slinton } 16429657Slinton 16439657Slinton /* 164418235Slinton * Find the symbol that has the same name and scope as the 16459657Slinton * given symbol but is of the given field. Return nil if there is none. 16469657Slinton */ 16479657Slinton 164818235Slinton public Symbol findfield (fieldname, record) 16499657Slinton Name fieldname; 16509657Slinton Symbol record; 16519657Slinton { 16529657Slinton register Symbol t; 16539657Slinton 16549657Slinton t = rtype(record)->chain; 16559657Slinton while (t != nil and t->name != fieldname) { 16569657Slinton t = t->chain; 16579657Slinton } 16589657Slinton return t; 16599657Slinton } 166012547Scsvaf 166112547Scsvaf public Boolean getbound(s,off,type,valp) 166212547Scsvaf Symbol s; 166312547Scsvaf int off; 166412547Scsvaf Rangetype type; 166512547Scsvaf int *valp; 166612547Scsvaf { 166712547Scsvaf Frame frp; 166812547Scsvaf Address addr; 166912547Scsvaf Symbol cur; 167012547Scsvaf 167112547Scsvaf if (not isactive(s->block)) { 167212547Scsvaf return(false); 167312547Scsvaf } 167412547Scsvaf cur = s->block; 167512547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 167612547Scsvaf cur = cur->block; 167712547Scsvaf } 167812547Scsvaf if(cur == nil) { 167912547Scsvaf cur = whatblock(pc); 168012547Scsvaf } 168112547Scsvaf frp = findframe(cur); 168212547Scsvaf if (frp == nil) { 168312547Scsvaf return(false); 168412547Scsvaf } 168512547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 168612547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 168712547Scsvaf else return(false); 168812547Scsvaf dread(valp,addr,sizeof(long)); 168912547Scsvaf return(true); 169012547Scsvaf } 1691