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*33337Sdonn static char sccsid[] = "@(#)symbols.c 5.4 (Berkeley) 01/12/88"; 921625Sdist #endif not lint 109657Slinton 11*33337Sdonn static char rcsid[] = "$Header: symbols.c,v 1.3 87/03/26 23:17:35 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 { 44*33337Sdonn BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY, 45*33337Sdonn 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 53*33337Sdonn #define INREG 0 54*33337Sdonn #define STK 1 55*33337Sdonn #define EXT 2 56*33337Sdonn 57*33337Sdonn typedef unsigned integer Storage; 58*33337Sdonn 599657Slinton struct Symbol { 609657Slinton Name name; 619657Slinton Language language; 62*33337Sdonn Symclass class : 8; 63*33337Sdonn Storage storage : 2; 64*33337Sdonn 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 136*33337Sdonn #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. 160*33337Sdonn * Hash table size is a power of two to make hashing faster. 161*33337Sdonn * Using a non-prime is ok since we aren't doing rehashing. 1629657Slinton */ 1639657Slinton 164*33337Sdonn #define HASHTABLESIZE 8192 1659657Slinton 1669657Slinton private Symbol hashtab[HASHTABLESIZE]; 1679657Slinton 168*33337Sdonn #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1)) 1699657Slinton 1709657Slinton /* 1719657Slinton * Allocate a new symbol. 1729657Slinton */ 1739657Slinton 174*33337Sdonn #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); 190*33337Sdonn 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; 253*33337Sdonn 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); 527*33337Sdonn 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 563*33337Sdonn #define isglobal(s) (s->storage == EXT) 564*33337Sdonn #define islocaloff(s) (s->storage == STK and s->symvalue.offset < 0) 565*33337Sdonn #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; 624*33337Sdonn s->storage = INREG; 625*33337Sdonn 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 771*33337Sdonn 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: 798*33337Sdonn /* 799*33337Sdonn * This causes problems on the IRIS because of the compiler bug 800*33337Sdonn * with stab offsets for parameters. Not sure it's really 801*33337Sdonn * necessary anyway. 802*33337Sdonn */ 803*33337Sdonn # ifndef IRIS 8049657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 8059657Slinton findtype(t); 8069657Slinton } 807*33337Sdonn # 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); 908*33337Sdonn 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); 948*33337Sdonn 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; 1077*33337Sdonn } else if (t2->language == primlang) { 1078*33337Sdonn b = (boolean) primlang_typematch(rtype(t1), rtype(t2)); 107916620Ssam } else { 108016620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 108116620Ssam } 1082*33337Sdonn } else if (t1->language == primlang) { 1083*33337Sdonn if (t2->language == primlang or t2->language == nil) { 1084*33337Sdonn b = primlang_typematch(rtype(t1), rtype(t2)); 1085*33337Sdonn } else { 1086*33337Sdonn b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 1087*33337Sdonn } 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 * Note the tree is call by address, hence the #define below. 13719657Slinton */ 13729657Slinton 13739657Slinton private convert(tp, typeto, op) 13749657Slinton Node *tp; 13759657Slinton Symbol typeto; 13769657Slinton Operator op; 13779657Slinton { 137816620Ssam Node tree; 137916620Ssam Symbol s, t; 13809657Slinton 138116620Ssam tree = *tp; 13829657Slinton s = rtype(tree->nodetype); 138316620Ssam t = rtype(typeto); 138416620Ssam if (compatible(t, t_real) and compatible(s, t_int)) { 13859657Slinton tree = build(op, tree); 138616620Ssam } else if (not compatible(s, t)) { 13879657Slinton beginerrmsg(); 138816620Ssam fprintf(stderr, "expected integer or real, found \""); 138916620Ssam prtree(stderr, tree); 139016620Ssam fprintf(stderr, "\""); 13919657Slinton enderrmsg(); 139216620Ssam } else if (op != O_NOP and s != t) { 13939657Slinton tree = build(op, tree); 13949657Slinton } 139516620Ssam *tp = tree; 13969657Slinton } 13979657Slinton 13989657Slinton /* 13999657Slinton * Construct a node for the dot operator. 14009657Slinton * 14019657Slinton * If the left operand is not a record, but rather a procedure 14029657Slinton * or function, then we interpret the "." as referencing an 14039657Slinton * "invisible" variable; i.e. a variable within a dynamically 14049657Slinton * active block but not within the static scope of the current procedure. 14059657Slinton */ 14069657Slinton 14079657Slinton public Node dot(record, fieldname) 14089657Slinton Node record; 14099657Slinton Name fieldname; 14109657Slinton { 141118235Slinton register Node rec, p; 14129657Slinton register Symbol s, t; 14139657Slinton 141418235Slinton rec = record; 141518235Slinton if (isblock(rec->nodetype)) { 14169657Slinton find(s, fieldname) where 141718235Slinton s->block == rec->nodetype and 141818235Slinton s->class != FIELD 14199657Slinton endfind(s); 14209657Slinton if (s == nil) { 14219657Slinton beginerrmsg(); 14229657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 142318235Slinton printname(stderr, rec->nodetype); 14249657Slinton enderrmsg(); 14259657Slinton } 14269657Slinton p = new(Node); 14279657Slinton p->op = O_SYM; 14289657Slinton p->value.sym = s; 142918235Slinton p->nodetype = s; 14309657Slinton } else { 143118235Slinton p = rec; 14329657Slinton t = rtype(p->nodetype); 14339657Slinton if (t->class == PTR) { 14349657Slinton s = findfield(fieldname, t->type); 14359657Slinton } else { 14369657Slinton s = findfield(fieldname, t); 14379657Slinton } 14389657Slinton if (s == nil) { 14399657Slinton beginerrmsg(); 14409657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 144118235Slinton prtree(stderr, rec); 14429657Slinton enderrmsg(); 14439657Slinton } 144418235Slinton if (t->class != PTR or isreg(rec->nodetype)) { 144518235Slinton p = unrval(p); 14469657Slinton } 144718235Slinton p->nodetype = t_addr; 14489657Slinton p = build(O_DOT, p, build(O_SYM, s)); 14499657Slinton } 145018235Slinton return build(O_RVAL, p); 14519657Slinton } 14529657Slinton 14539657Slinton /* 14549657Slinton * Return a tree corresponding to an array reference and do the 14559657Slinton * error checking. 14569657Slinton */ 14579657Slinton 14589657Slinton public Node subscript(a, slist) 14599657Slinton Node a, slist; 14609657Slinton { 146116620Ssam Symbol t; 146218235Slinton Node p; 14639657Slinton 146416620Ssam t = rtype(a->nodetype); 146518235Slinton if (t->language == nil or t->language == primlang) { 146618235Slinton p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); 146716620Ssam } else { 146818235Slinton p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); 146916620Ssam } 147018235Slinton return build(O_RVAL, p); 14719657Slinton } 14729657Slinton 14739657Slinton /* 14749657Slinton * Evaluate a subscript index. 14759657Slinton */ 14769657Slinton 147718235Slinton public int evalindex(s, base, i) 14789657Slinton Symbol s; 147918235Slinton Address base; 14809657Slinton long i; 14819657Slinton { 148216620Ssam Symbol t; 148318235Slinton int r; 14849657Slinton 148516620Ssam t = rtype(s); 148618235Slinton if (t->language == nil or t->language == primlang) { 148718235Slinton r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); 148816620Ssam } else { 148918235Slinton r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); 149016620Ssam } 149118235Slinton return r; 14929657Slinton } 14939657Slinton 14949657Slinton /* 14959657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 14969657Slinton */ 14979657Slinton 14989657Slinton public chkboolean(p) 14999657Slinton register Node p; 15009657Slinton { 15019657Slinton if (p->nodetype != t_boolean) { 15029657Slinton beginerrmsg(); 15039657Slinton fprintf(stderr, "found "); 15049657Slinton prtree(stderr, p); 15059657Slinton fprintf(stderr, ", expected boolean expression"); 15069657Slinton enderrmsg(); 15079657Slinton } 15089657Slinton } 15099657Slinton 15109657Slinton /* 151116620Ssam * Construct a node for the type of a string. 15129657Slinton */ 15139657Slinton 15149657Slinton private Symbol mkstring(str) 15159657Slinton String str; 15169657Slinton { 15179657Slinton register Symbol s; 15189657Slinton 151918235Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 152018235Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 152118235Slinton s->chain->language = s->language; 152218235Slinton s->chain->symvalue.rangev.lower = 1; 152318235Slinton s->chain->symvalue.rangev.upper = strlen(str) + 1; 15249657Slinton return s; 15259657Slinton } 15269657Slinton 15279657Slinton /* 15289657Slinton * Free up the space allocated for a string type. 15299657Slinton */ 15309657Slinton 15319657Slinton public unmkstring(s) 15329657Slinton Symbol s; 15339657Slinton { 15349657Slinton dispose(s->chain); 15359657Slinton } 15369657Slinton 15379657Slinton /* 153818235Slinton * Figure out the "current" variable or function being referred to 153918235Slinton * by the name n. 15409657Slinton */ 15419657Slinton 154218235Slinton private boolean stwhich(), dynwhich(); 154318235Slinton 154418235Slinton public Symbol which (n) 15459657Slinton Name n; 15469657Slinton { 154718235Slinton Symbol s; 15489657Slinton 154918235Slinton s = lookup(n); 15509657Slinton if (s == nil) { 155118235Slinton error("\"%s\" is not defined", ident(n)); 155218235Slinton } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { 155318235Slinton printf("[using "); 155418235Slinton printname(stdout, s); 155518235Slinton printf("]\n"); 15569657Slinton } 155718235Slinton return s; 155818235Slinton } 155918235Slinton 156018235Slinton /* 156118235Slinton * Static search. 156218235Slinton */ 156318235Slinton 156418235Slinton private boolean stwhich (var_s) 156518235Slinton Symbol *var_s; 156618235Slinton { 156718235Slinton Name n; /* name of desired symbol */ 156818235Slinton Symbol s; /* iteration variable for symbols with name n */ 156918235Slinton Symbol f; /* iteration variable for blocks containing s */ 157018235Slinton integer count; /* number of levels from s->block to curfunc */ 157118235Slinton Symbol t; /* current best answer for stwhich(n) */ 157218235Slinton integer mincount; /* relative level for current best answer (t) */ 157318235Slinton boolean b; /* return value, true if symbol found */ 157418235Slinton 157518235Slinton s = *var_s; 157618235Slinton n = s->name; 157718235Slinton t = s; 157818235Slinton mincount = 10000; /* force first match to set mincount */ 157918235Slinton do { 158018235Slinton if (s->name == n and s->class != FIELD and s->class != TAG) { 158118235Slinton f = curfunc; 158218235Slinton count = 0; 158318235Slinton while (f != nil and f != s->block) { 158418235Slinton ++count; 158518235Slinton f = f->block; 158618235Slinton } 158718235Slinton if (f != nil and count < mincount) { 158818235Slinton t = s; 158918235Slinton mincount = count; 159018235Slinton b = true; 159118235Slinton } 159218235Slinton } 159318235Slinton s = s->next_sym; 159418235Slinton } while (s != nil); 159518235Slinton if (mincount != 10000) { 159618235Slinton *var_s = t; 159718235Slinton b = true; 15989657Slinton } else { 159918235Slinton b = false; 160018235Slinton } 160118235Slinton return b; 160218235Slinton } 160318235Slinton 160418235Slinton /* 160518235Slinton * Dynamic search. 160618235Slinton */ 160718235Slinton 160818235Slinton private boolean dynwhich (var_s) 160918235Slinton Symbol *var_s; 161018235Slinton { 161118235Slinton Name n; /* name of desired symbol */ 161218235Slinton Symbol s; /* iteration variable for possible symbols */ 161318235Slinton Symbol f; /* iteration variable for active functions */ 161418235Slinton Frame frp; /* frame associated with stack walk */ 161518235Slinton boolean b; /* return value */ 161618235Slinton 161718235Slinton f = curfunc; 161818235Slinton frp = curfuncframe(); 161918235Slinton n = (*var_s)->name; 162018235Slinton b = false; 162118235Slinton if (frp != nil) { 162218235Slinton frp = nextfunc(frp, &f); 162318235Slinton while (frp != nil) { 162418235Slinton s = *var_s; 162518235Slinton while (s != nil and 162618235Slinton ( 162718235Slinton s->name != n or s->block != f or 162818235Slinton s->class == FIELD or s->class == TAG 162918235Slinton ) 163018235Slinton ) { 163118235Slinton s = s->next_sym; 163218235Slinton } 163318235Slinton if (s != nil) { 163418235Slinton *var_s = s; 163518235Slinton b = true; 163618235Slinton break; 163718235Slinton } 163818235Slinton if (f == program) { 163918235Slinton break; 164018235Slinton } 164118235Slinton frp = nextfunc(frp, &f); 16429657Slinton } 16439657Slinton } 164418235Slinton return b; 16459657Slinton } 16469657Slinton 16479657Slinton /* 164818235Slinton * Find the symbol that has the same name and scope as the 16499657Slinton * given symbol but is of the given field. Return nil if there is none. 16509657Slinton */ 16519657Slinton 165218235Slinton public Symbol findfield (fieldname, record) 16539657Slinton Name fieldname; 16549657Slinton Symbol record; 16559657Slinton { 16569657Slinton register Symbol t; 16579657Slinton 16589657Slinton t = rtype(record)->chain; 16599657Slinton while (t != nil and t->name != fieldname) { 16609657Slinton t = t->chain; 16619657Slinton } 16629657Slinton return t; 16639657Slinton } 166412547Scsvaf 166512547Scsvaf public Boolean getbound(s,off,type,valp) 166612547Scsvaf Symbol s; 166712547Scsvaf int off; 166812547Scsvaf Rangetype type; 166912547Scsvaf int *valp; 167012547Scsvaf { 167112547Scsvaf Frame frp; 167212547Scsvaf Address addr; 167312547Scsvaf Symbol cur; 167412547Scsvaf 167512547Scsvaf if (not isactive(s->block)) { 167612547Scsvaf return(false); 167712547Scsvaf } 167812547Scsvaf cur = s->block; 167912547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 168012547Scsvaf cur = cur->block; 168112547Scsvaf } 168212547Scsvaf if(cur == nil) { 168312547Scsvaf cur = whatblock(pc); 168412547Scsvaf } 168512547Scsvaf frp = findframe(cur); 168612547Scsvaf if (frp == nil) { 168712547Scsvaf return(false); 168812547Scsvaf } 168912547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 169012547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 169112547Scsvaf else return(false); 169212547Scsvaf dread(valp,addr,sizeof(long)); 169312547Scsvaf return(true); 169412547Scsvaf } 1695