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*24554Smckusick static char sccsid[] = "@(#)symbols.c 5.2 (Berkeley) 09/05/85"; 921625Sdist #endif not lint 109657Slinton 1118235Slinton static char rcsid[] = "$Header: symbols.c,v 1.6 84/12/26 10:42:31 linton 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 { 4418235Slinton BADUSE, CONST, TYPE, VAR, ARRAY, DYNARRAY, SUBARRAY, PTRFILE, RECORD, FIELD, 4512547Scsvaf PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 469657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 4716620Ssam FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF 489657Slinton } Symclass; 499657Slinton 5012547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 5112547Scsvaf 529657Slinton struct Symbol { 539657Slinton Name name; 549657Slinton Language language; 559657Slinton Symclass class : 8; 569657Slinton Integer level : 8; 579657Slinton Symbol type; 589657Slinton Symbol chain; 599657Slinton union { 6018235Slinton Node constval; /* value of constant symbol */ 619657Slinton int offset; /* variable address */ 629657Slinton long iconval; /* integer constant value */ 639657Slinton double fconval; /* floating constant value */ 6418235Slinton int ndims; /* no. of dimensions for dynamic/sub-arrays */ 659657Slinton struct { /* field offset and size (both in bits) */ 669657Slinton int offset; 679657Slinton int length; 689657Slinton } field; 6912547Scsvaf struct { /* common offset and chain; used to relocate */ 7012547Scsvaf int offset; /* vars in global BSS */ 7112547Scsvaf Symbol chain; 7212547Scsvaf } common; 739657Slinton struct { /* range bounds */ 7412547Scsvaf Rangetype lowertype : 16; 7512547Scsvaf Rangetype uppertype : 16; 769657Slinton long lower; 779657Slinton long upper; 789657Slinton } rangev; 7911865Slinton struct { 8011865Slinton int offset : 16; /* offset for of function value */ 8116620Ssam Boolean src : 1; /* true if there is source line info */ 8216620Ssam Boolean inline : 1; /* true if no separate act. rec. */ 8316620Ssam Boolean intern : 1; /* internal calling sequence */ 8416620Ssam int unused : 13; 8511865Slinton Address beginaddr; /* address of function code */ 869657Slinton } funcv; 879657Slinton struct { /* variant record info */ 889657Slinton int size; 899657Slinton Symbol vtorec; 909657Slinton Symbol vtag; 919657Slinton } varnt; 9216620Ssam String typeref; /* type defined by "<module>:<type>" */ 9316620Ssam Symbol extref; /* indirect symbol for external reference */ 949657Slinton } symvalue; 959657Slinton Symbol block; /* symbol containing this symbol */ 969657Slinton Symbol next_sym; /* hash chain */ 979657Slinton }; 989657Slinton 999657Slinton /* 1009657Slinton * Basic types. 1019657Slinton */ 1029657Slinton 1039657Slinton Symbol t_boolean; 1049657Slinton Symbol t_char; 1059657Slinton Symbol t_int; 1069657Slinton Symbol t_real; 1079657Slinton Symbol t_nil; 10818235Slinton Symbol t_addr; 1099657Slinton 1109657Slinton Symbol program; 1119657Slinton Symbol curfunc; 1129657Slinton 11318235Slinton boolean showaggrs; 11418235Slinton 1159657Slinton #define symname(s) ident(s->name) 1169657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 1179657Slinton #define isblock(s) (Boolean) ( \ 1189657Slinton s->class == FUNC or s->class == PROC or \ 1199657Slinton s->class == MODULE or s->class == PROG \ 1209657Slinton ) 12116620Ssam #define isroutine(s) (Boolean) ( \ 12216620Ssam s->class == FUNC or s->class == PROC \ 12316620Ssam ) 1249657Slinton 12511865Slinton #define nosource(f) (not (f)->symvalue.funcv.src) 12614441Slinton #define isinline(f) ((f)->symvalue.funcv.inline) 12711865Slinton 128*24554Smckusick #define isreg(s) (s->level < 0) 129*24554Smckusick 1309657Slinton #include "tree.h" 1319657Slinton 1329657Slinton /* 1339657Slinton * Some macros to make finding a symbol with certain attributes. 1349657Slinton */ 1359657Slinton 1369657Slinton #define find(s, withname) \ 1379657Slinton { \ 1389657Slinton s = lookup(withname); \ 1399657Slinton while (s != nil and not (s->name == (withname) and 1409657Slinton 1419657Slinton #define where /* qualification */ 1429657Slinton 1439657Slinton #define endfind(s) )) { \ 1449657Slinton s = s->next_sym; \ 1459657Slinton } \ 1469657Slinton } 1479657Slinton 1489657Slinton #endif 1499657Slinton 1509657Slinton /* 1519657Slinton * Symbol table structure currently does not support deletions. 1529657Slinton */ 1539657Slinton 1549657Slinton #define HASHTABLESIZE 2003 1559657Slinton 1569657Slinton private Symbol hashtab[HASHTABLESIZE]; 1579657Slinton 1589657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 1599657Slinton 1609657Slinton /* 1619657Slinton * Allocate a new symbol. 1629657Slinton */ 1639657Slinton 16411171Slinton #define SYMBLOCKSIZE 100 1659657Slinton 1669657Slinton typedef struct Sympool { 1679657Slinton struct Symbol sym[SYMBLOCKSIZE]; 1689657Slinton struct Sympool *prevpool; 1699657Slinton } *Sympool; 1709657Slinton 1719657Slinton private Sympool sympool = nil; 1729657Slinton private Integer nleft = 0; 1739657Slinton 1749657Slinton public Symbol symbol_alloc() 1759657Slinton { 1769657Slinton register Sympool newpool; 1779657Slinton 1789657Slinton if (nleft <= 0) { 1799657Slinton newpool = new(Sympool); 18011171Slinton bzero(newpool, sizeof(newpool)); 1819657Slinton newpool->prevpool = sympool; 1829657Slinton sympool = newpool; 1839657Slinton nleft = SYMBLOCKSIZE; 1849657Slinton } 1859657Slinton --nleft; 1869657Slinton return &(sympool->sym[nleft]); 1879657Slinton } 1889657Slinton 18918235Slinton public symbol_dump (func) 19012547Scsvaf Symbol func; 19112547Scsvaf { 19218235Slinton register Symbol s; 19318235Slinton register integer i; 19412547Scsvaf 19518235Slinton printf(" symbols in %s \n",symname(func)); 19618235Slinton for (i = 0; i < HASHTABLESIZE; i++) { 19718235Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 19818235Slinton if (s->block == func) { 19918235Slinton psym(s); 20018235Slinton } 20118235Slinton } 20218235Slinton } 20312547Scsvaf } 20412547Scsvaf 2059657Slinton /* 2069657Slinton * Free all the symbols currently allocated. 2079657Slinton */ 20818235Slinton 2099657Slinton public symbol_free() 2109657Slinton { 2119657Slinton Sympool s, t; 2129657Slinton register Integer i; 2139657Slinton 2149657Slinton s = sympool; 2159657Slinton while (s != nil) { 2169657Slinton t = s->prevpool; 2179657Slinton dispose(s); 2189657Slinton s = t; 2199657Slinton } 2209657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 2219657Slinton hashtab[i] = nil; 2229657Slinton } 2239657Slinton sympool = nil; 2249657Slinton nleft = 0; 2259657Slinton } 2269657Slinton 2279657Slinton /* 2289657Slinton * Create a new symbol with the given attributes. 2299657Slinton */ 2309657Slinton 2319657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 2329657Slinton Name name; 2339657Slinton Integer blevel; 2349657Slinton Symclass class; 2359657Slinton Symbol type; 2369657Slinton Symbol chain; 2379657Slinton { 2389657Slinton register Symbol s; 2399657Slinton 2409657Slinton s = symbol_alloc(); 2419657Slinton s->name = name; 24218235Slinton s->language = primlang; 2439657Slinton s->level = blevel; 2449657Slinton s->class = class; 2459657Slinton s->type = type; 2469657Slinton s->chain = chain; 2479657Slinton return s; 2489657Slinton } 2499657Slinton 2509657Slinton /* 2519657Slinton * Insert a symbol into the hash table. 2529657Slinton */ 2539657Slinton 2549657Slinton public Symbol insert(name) 2559657Slinton Name name; 2569657Slinton { 2579657Slinton register Symbol s; 2589657Slinton register unsigned int h; 2599657Slinton 2609657Slinton h = hash(name); 2619657Slinton s = symbol_alloc(); 2629657Slinton s->name = name; 2639657Slinton s->next_sym = hashtab[h]; 2649657Slinton hashtab[h] = s; 2659657Slinton return s; 2669657Slinton } 2679657Slinton 2689657Slinton /* 2699657Slinton * Symbol lookup. 2709657Slinton */ 2719657Slinton 2729657Slinton public Symbol lookup(name) 2739657Slinton Name name; 2749657Slinton { 2759657Slinton register Symbol s; 2769657Slinton register unsigned int h; 2779657Slinton 2789657Slinton h = hash(name); 2799657Slinton s = hashtab[h]; 2809657Slinton while (s != nil and s->name != name) { 2819657Slinton s = s->next_sym; 2829657Slinton } 2839657Slinton return s; 2849657Slinton } 2859657Slinton 2869657Slinton /* 28716620Ssam * Delete a symbol from the symbol table. 28816620Ssam */ 28916620Ssam 29016620Ssam public delete (s) 29116620Ssam Symbol s; 29216620Ssam { 29316620Ssam register Symbol t; 29416620Ssam register unsigned int h; 29516620Ssam 29616620Ssam h = hash(s->name); 29716620Ssam t = hashtab[h]; 29816620Ssam if (t == nil) { 29916620Ssam panic("delete of non-symbol '%s'", symname(s)); 30016620Ssam } else if (t == s) { 30116620Ssam hashtab[h] = s->next_sym; 30216620Ssam } else { 30316620Ssam while (t->next_sym != s) { 30416620Ssam t = t->next_sym; 30516620Ssam if (t == nil) { 30616620Ssam panic("delete of non-symbol '%s'", symname(s)); 30716620Ssam } 30816620Ssam } 30916620Ssam t->next_sym = s->next_sym; 31016620Ssam } 31116620Ssam } 31216620Ssam 31316620Ssam /* 3149657Slinton * Dump out all the variables associated with the given 31518235Slinton * procedure, function, or program associated with the given stack frame. 3169657Slinton * 3179657Slinton * This is quite inefficient. We traverse the entire symbol table 3189657Slinton * each time we're called. The assumption is that this routine 3199657Slinton * won't be called frequently enough to merit improved performance. 3209657Slinton */ 3219657Slinton 3229657Slinton public dumpvars(f, frame) 3239657Slinton Symbol f; 3249657Slinton Frame frame; 3259657Slinton { 3269657Slinton register Integer i; 3279657Slinton register Symbol s; 3289657Slinton 3299657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 3309657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 3319657Slinton if (container(s) == f) { 3329657Slinton if (should_print(s)) { 3339657Slinton printv(s, frame); 3349657Slinton putchar('\n'); 3359657Slinton } else if (s->class == MODULE) { 3369657Slinton dumpvars(s, frame); 3379657Slinton } 3389657Slinton } 3399657Slinton } 3409657Slinton } 3419657Slinton } 3429657Slinton 3439657Slinton /* 3449657Slinton * Create a builtin type. 3459657Slinton * Builtin types are circular in that btype->type->type = btype. 3469657Slinton */ 3479657Slinton 34818235Slinton private Symbol maketype(name, lower, upper) 3499657Slinton String name; 3509657Slinton long lower; 3519657Slinton long upper; 3529657Slinton { 3539657Slinton register Symbol s; 35418235Slinton Name n; 3559657Slinton 35618235Slinton if (name == nil) { 35718235Slinton n = nil; 35818235Slinton } else { 35918235Slinton n = identname(name, true); 36018235Slinton } 36118235Slinton s = insert(n); 36216620Ssam s->language = primlang; 36318235Slinton s->level = 0; 36418235Slinton s->class = TYPE; 36518235Slinton s->type = nil; 36618235Slinton s->chain = nil; 3679657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 3689657Slinton s->type->symvalue.rangev.lower = lower; 3699657Slinton s->type->symvalue.rangev.upper = upper; 3709657Slinton return s; 3719657Slinton } 3729657Slinton 3739657Slinton /* 37418235Slinton * Create the builtin symbols. 37518235Slinton */ 37618235Slinton 37718235Slinton public symbols_init () 3789657Slinton { 37918235Slinton Symbol s; 3809657Slinton 38118235Slinton t_boolean = maketype("$boolean", 0L, 1L); 38218235Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 38318235Slinton t_char = maketype("$char", 0L, 255L); 38418235Slinton t_real = maketype("$real", 8L, 0L); 38518235Slinton t_nil = maketype("$nil", 0L, 0L); 38618235Slinton t_addr = insert(identname("$address", true)); 38718235Slinton t_addr->language = primlang; 38818235Slinton t_addr->level = 0; 38918235Slinton t_addr->class = TYPE; 39018235Slinton t_addr->type = newSymbol(nil, 1, PTR, t_int, nil); 39118235Slinton s = insert(identname("true", true)); 39218235Slinton s->class = CONST; 39318235Slinton s->type = t_boolean; 39418235Slinton s->symvalue.constval = build(O_LCON, 1L); 39518235Slinton s->symvalue.constval->nodetype = t_boolean; 39618235Slinton s = insert(identname("false", true)); 39718235Slinton s->class = CONST; 39818235Slinton s->type = t_boolean; 39918235Slinton s->symvalue.constval = build(O_LCON, 0L); 40018235Slinton s->symvalue.constval->nodetype = t_boolean; 4019657Slinton } 4029657Slinton 4039657Slinton /* 4049657Slinton * Reduce type to avoid worrying about type names. 4059657Slinton */ 4069657Slinton 4079657Slinton public Symbol rtype(type) 4089657Slinton Symbol type; 4099657Slinton { 4109657Slinton register Symbol t; 4119657Slinton 4129657Slinton t = type; 4139657Slinton if (t != nil) { 41418235Slinton if (t->class == VAR or t->class == CONST or 41518235Slinton t->class == FIELD or t->class == REF 41618235Slinton ) { 4179657Slinton t = t->type; 4189657Slinton } 41916620Ssam if (t->class == TYPEREF) { 42016620Ssam resolveRef(t); 42116620Ssam } 4229657Slinton while (t->class == TYPE or t->class == TAG) { 4239657Slinton t = t->type; 42416620Ssam if (t->class == TYPEREF) { 42516620Ssam resolveRef(t); 42616620Ssam } 4279657Slinton } 4289657Slinton } 4299657Slinton return t; 4309657Slinton } 4319657Slinton 43216620Ssam /* 43316620Ssam * Find the end of a module name. Return nil if there is none 43416620Ssam * in the given string. 43516620Ssam */ 43616620Ssam 43716620Ssam private String findModuleMark (s) 43816620Ssam String s; 43916620Ssam { 44016620Ssam register char *p, *r; 44116620Ssam register boolean done; 44216620Ssam 44316620Ssam p = s; 44416620Ssam done = false; 44516620Ssam do { 44616620Ssam if (*p == ':') { 44716620Ssam done = true; 44816620Ssam r = p; 44916620Ssam } else if (*p == '\0') { 45016620Ssam done = true; 45116620Ssam r = nil; 45216620Ssam } else { 45316620Ssam ++p; 45416620Ssam } 45516620Ssam } while (not done); 45616620Ssam return r; 45716620Ssam } 45816620Ssam 45916620Ssam /* 46016620Ssam * Resolve a type reference by modifying to be the appropriate type. 46116620Ssam * 46216620Ssam * If the reference has a name, then it refers to an opaque type and 46316620Ssam * the actual type is directly accessible. Otherwise, we must use 46416620Ssam * the type reference string, which is of the form "module:{module:}name". 46516620Ssam */ 46616620Ssam 46716620Ssam public resolveRef (t) 46816620Ssam Symbol t; 46916620Ssam { 47016620Ssam register char *p; 47116620Ssam char *start; 47216620Ssam Symbol s, m, outer; 47316620Ssam Name n; 47416620Ssam 47516620Ssam if (t->name != nil) { 47616620Ssam s = t; 47716620Ssam } else { 47816620Ssam start = t->symvalue.typeref; 47916620Ssam outer = program; 48016620Ssam p = findModuleMark(start); 48116620Ssam while (p != nil) { 48216620Ssam *p = '\0'; 48316620Ssam n = identname(start, true); 48416620Ssam find(m, n) where m->block == outer endfind(m); 48516620Ssam if (m == nil) { 48616620Ssam p = nil; 48716620Ssam outer = nil; 48816620Ssam s = nil; 48916620Ssam } else { 49016620Ssam outer = m; 49116620Ssam start = p + 1; 49216620Ssam p = findModuleMark(start); 49316620Ssam } 49416620Ssam } 49516620Ssam if (outer != nil) { 49616620Ssam n = identname(start, true); 49716620Ssam find(s, n) where s->block == outer endfind(s); 49816620Ssam } 49916620Ssam } 50016620Ssam if (s != nil and s->type != nil) { 50116620Ssam t->name = s->type->name; 50216620Ssam t->class = s->type->class; 50316620Ssam t->type = s->type->type; 50416620Ssam t->chain = s->type->chain; 50516620Ssam t->symvalue = s->type->symvalue; 50616620Ssam t->block = s->type->block; 50716620Ssam } 50816620Ssam } 50916620Ssam 51018235Slinton public integer regnum (s) 5119657Slinton Symbol s; 5129657Slinton { 51318235Slinton integer r; 51418235Slinton 5159657Slinton checkref(s); 51618235Slinton if (s->level < 0) { 51718235Slinton r = s->symvalue.offset; 51818235Slinton } else { 51918235Slinton r = -1; 52018235Slinton } 52118235Slinton return r; 5229657Slinton } 5239657Slinton 5249657Slinton public Symbol container(s) 5259657Slinton Symbol s; 5269657Slinton { 5279657Slinton checkref(s); 5289657Slinton return s->block; 5299657Slinton } 5309657Slinton 53118235Slinton public Node constval(s) 53218235Slinton Symbol s; 53318235Slinton { 53418235Slinton checkref(s); 53518235Slinton if (s->class != CONST) { 53618235Slinton error("[internal error: constval(non-CONST)]"); 53718235Slinton } 53818235Slinton return s->symvalue.constval; 53918235Slinton } 54018235Slinton 5419657Slinton /* 5429657Slinton * Return the object address of the given symbol. 5439657Slinton * 5449657Slinton * There are the following possibilities: 5459657Slinton * 5469657Slinton * globals - just take offset 5479657Slinton * locals - take offset from locals base 5489657Slinton * arguments - take offset from argument base 5499657Slinton * register - offset is register number 5509657Slinton */ 5519657Slinton 55216620Ssam #define isglobal(s) (s->level == 1) 55316620Ssam #define islocaloff(s) (s->level >= 2 and s->symvalue.offset < 0) 55416620Ssam #define isparamoff(s) (s->level >= 2 and s->symvalue.offset >= 0) 5559657Slinton 55618235Slinton public Address address (s, frame) 5579657Slinton Symbol s; 5589657Slinton Frame frame; 5599657Slinton { 5609657Slinton register Frame frp; 5619657Slinton register Address addr; 5629657Slinton register Symbol cur; 5639657Slinton 5649657Slinton checkref(s); 5659657Slinton if (not isactive(s->block)) { 5669657Slinton error("\"%s\" is not currently defined", symname(s)); 5679657Slinton } else if (isglobal(s)) { 5689657Slinton addr = s->symvalue.offset; 5699657Slinton } else { 5709657Slinton frp = frame; 5719657Slinton if (frp == nil) { 5729657Slinton cur = s->block; 5739657Slinton while (cur != nil and cur->class == MODULE) { 5749657Slinton cur = cur->block; 5759657Slinton } 5769657Slinton if (cur == nil) { 57718235Slinton frp = nil; 57818235Slinton } else { 57918235Slinton frp = findframe(cur); 58018235Slinton if (frp == nil) { 58118235Slinton error("[internal error: unexpected nil frame for \"%s\"]", 58218235Slinton symname(s) 58318235Slinton ); 58418235Slinton } 5859657Slinton } 5869657Slinton } 5879657Slinton if (islocaloff(s)) { 5889657Slinton addr = locals_base(frp) + s->symvalue.offset; 5899657Slinton } else if (isparamoff(s)) { 5909657Slinton addr = args_base(frp) + s->symvalue.offset; 5919657Slinton } else if (isreg(s)) { 5929657Slinton addr = savereg(s->symvalue.offset, frp); 5939657Slinton } else { 5949657Slinton panic("address: bad symbol \"%s\"", symname(s)); 5959657Slinton } 5969657Slinton } 5979657Slinton return addr; 5989657Slinton } 5999657Slinton 6009657Slinton /* 6019657Slinton * Define a symbol used to access register values. 6029657Slinton */ 6039657Slinton 60418235Slinton public defregname (n, r) 6059657Slinton Name n; 60618235Slinton integer r; 6079657Slinton { 60818235Slinton Symbol s; 6099657Slinton 6109657Slinton s = insert(n); 61118235Slinton s->language = t_addr->language; 6129657Slinton s->class = VAR; 6139657Slinton s->level = -3; 61418235Slinton s->type = t_addr; 6159657Slinton s->symvalue.offset = r; 6169657Slinton } 6179657Slinton 6189657Slinton /* 6199657Slinton * Resolve an "abstract" type reference. 6209657Slinton * 6219657Slinton * It is possible in C to define a pointer to a type, but never define 6229657Slinton * the type in a particular source file. Here we try to resolve 6239657Slinton * the type definition. This is problematic, it is possible to 6249657Slinton * have multiple, different definitions for the same name type. 6259657Slinton */ 6269657Slinton 6279657Slinton public findtype(s) 6289657Slinton Symbol s; 6299657Slinton { 6309657Slinton register Symbol t, u, prev; 6319657Slinton 6329657Slinton u = s; 6339657Slinton prev = nil; 6349657Slinton while (u != nil and u->class != BADUSE) { 6359657Slinton if (u->name != nil) { 6369657Slinton prev = u; 6379657Slinton } 6389657Slinton u = u->type; 6399657Slinton } 6409657Slinton if (prev == nil) { 6419657Slinton error("couldn't find link to type reference"); 6429657Slinton } 64318235Slinton t = lookup(prev->name); 64418235Slinton while (t != nil and 64518235Slinton not ( 64618235Slinton t != prev and t->name == prev->name and 64718235Slinton t->block->class == MODULE and t->class == prev->class and 64818235Slinton t->type != nil and t->type->type != nil and 64918235Slinton t->type->type->class != BADUSE 65018235Slinton ) 65118235Slinton ) { 65218235Slinton t = t->next_sym; 65318235Slinton } 6549657Slinton if (t == nil) { 6559657Slinton error("couldn't resolve reference"); 6569657Slinton } else { 6579657Slinton prev->type = t->type; 6589657Slinton } 6599657Slinton } 6609657Slinton 6619657Slinton /* 6629657Slinton * Find the size in bytes of the given type. 6639657Slinton * 6649657Slinton * This is probably the WRONG thing to do. The size should be kept 6659657Slinton * as an attribute in the symbol information as is done for structures 6669657Slinton * and fields. I haven't gotten around to cleaning this up yet. 6679657Slinton */ 6689657Slinton 66912547Scsvaf #define MAXUCHAR 255 67012547Scsvaf #define MAXUSHORT 65535L 6719657Slinton #define MINCHAR -128 6729657Slinton #define MAXCHAR 127 6739657Slinton #define MINSHORT -32768 6749657Slinton #define MAXSHORT 32767 6759657Slinton 67616620Ssam public findbounds (u, lower, upper) 67716620Ssam Symbol u; 67816620Ssam long *lower, *upper; 67916620Ssam { 68016620Ssam Rangetype lbt, ubt; 68116620Ssam long lb, ub; 68216620Ssam 68316620Ssam if (u->class == RANGE) { 68416620Ssam lbt = u->symvalue.rangev.lowertype; 68516620Ssam ubt = u->symvalue.rangev.uppertype; 68616620Ssam lb = u->symvalue.rangev.lower; 68716620Ssam ub = u->symvalue.rangev.upper; 68816620Ssam if (lbt == R_ARG or lbt == R_TEMP) { 68916620Ssam if (not getbound(u, lb, lbt, lower)) { 69016620Ssam error("dynamic bounds not currently available"); 69116620Ssam } 69216620Ssam } else { 69316620Ssam *lower = lb; 69416620Ssam } 69516620Ssam if (ubt == R_ARG or ubt == R_TEMP) { 69616620Ssam if (not getbound(u, ub, ubt, upper)) { 69716620Ssam error("dynamic bounds not currently available"); 69816620Ssam } 69916620Ssam } else { 70016620Ssam *upper = ub; 70116620Ssam } 70216620Ssam } else if (u->class == SCAL) { 70316620Ssam *lower = 0; 70416620Ssam *upper = u->symvalue.iconval - 1; 70516620Ssam } else { 70618235Slinton error("[internal error: unexpected array bound type]"); 70716620Ssam } 70816620Ssam } 70916620Ssam 71016620Ssam public integer size(sym) 71116620Ssam Symbol sym; 71216620Ssam { 71316620Ssam register Symbol s, t, u; 71416620Ssam register integer nel, elsize; 7159657Slinton long lower, upper; 71616620Ssam integer r, off, len; 7179657Slinton 7189657Slinton t = sym; 7199657Slinton checkref(t); 72016620Ssam if (t->class == TYPEREF) { 72116620Ssam resolveRef(t); 72216620Ssam } 7239657Slinton switch (t->class) { 7249657Slinton case RANGE: 7259657Slinton lower = t->symvalue.rangev.lower; 7269657Slinton upper = t->symvalue.rangev.upper; 72716620Ssam if (upper == 0 and lower > 0) { 72816620Ssam /* real */ 7299657Slinton r = lower; 73016620Ssam } else if (lower > upper) { 73116620Ssam /* unsigned long */ 73216620Ssam r = sizeof(long); 73312045Slinton } else if ( 73412547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or 73512547Scsvaf (lower >= 0 and upper <= MAXUCHAR) 73612547Scsvaf ) { 7379657Slinton r = sizeof(char); 73812547Scsvaf } else if ( 73912547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or 74012547Scsvaf (lower >= 0 and upper <= MAXUSHORT) 74112547Scsvaf ) { 7429657Slinton r = sizeof(short); 7439657Slinton } else { 7449657Slinton r = sizeof(long); 7459657Slinton } 7469657Slinton break; 7479657Slinton 7489657Slinton case ARRAY: 7499657Slinton elsize = size(t->type); 7509657Slinton nel = 1; 7519657Slinton for (t = t->chain; t != nil; t = t->chain) { 75216620Ssam u = rtype(t); 75316620Ssam findbounds(u, &lower, &upper); 7549657Slinton nel *= (upper-lower+1); 7559657Slinton } 7569657Slinton r = nel*elsize; 7579657Slinton break; 7589657Slinton 75918235Slinton case DYNARRAY: 76018235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 76118235Slinton break; 76218235Slinton 76318235Slinton case SUBARRAY: 76418235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 76518235Slinton break; 76618235Slinton 76712547Scsvaf case REF: 7689657Slinton case VAR: 7699657Slinton r = size(t->type); 77012127Slinton /* 77112127Slinton * 77212045Slinton if (r < sizeof(Word) and isparam(t)) { 7739657Slinton r = sizeof(Word); 7749657Slinton } 77512547Scsvaf */ 7769657Slinton break; 7779657Slinton 77818235Slinton case FVAR: 7799657Slinton case CONST: 78018235Slinton case TAG: 7819657Slinton r = size(t->type); 7829657Slinton break; 7839657Slinton 7849657Slinton case TYPE: 7859657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 7869657Slinton findtype(t); 7879657Slinton } 7889657Slinton r = size(t->type); 7899657Slinton break; 7909657Slinton 7919657Slinton case FIELD: 79216620Ssam off = t->symvalue.field.offset; 79316620Ssam len = t->symvalue.field.length; 79416620Ssam r = (off + len + 7) div 8 - (off div 8); 7959657Slinton break; 7969657Slinton 7979657Slinton case RECORD: 7989657Slinton case VARNT: 7999657Slinton r = t->symvalue.offset; 8009657Slinton if (r == 0 and t->chain != nil) { 8019657Slinton panic("missing size information for record"); 8029657Slinton } 8039657Slinton break; 8049657Slinton 8059657Slinton case PTR: 80618235Slinton case TYPEREF: 8079657Slinton case FILET: 8089657Slinton r = sizeof(Word); 8099657Slinton break; 8109657Slinton 8119657Slinton case SCAL: 81212609Slinton r = sizeof(Word); 81312609Slinton /* 81412609Slinton * 8159657Slinton if (t->symvalue.iconval > 255) { 8169657Slinton r = sizeof(short); 8179657Slinton } else { 8189657Slinton r = sizeof(char); 8199657Slinton } 82012609Slinton * 82112609Slinton */ 8229657Slinton break; 8239657Slinton 8249657Slinton case FPROC: 8259657Slinton case FFUNC: 8269657Slinton r = sizeof(Word); 8279657Slinton break; 8289657Slinton 8299657Slinton case PROC: 8309657Slinton case FUNC: 8319657Slinton case MODULE: 8329657Slinton case PROG: 8339657Slinton r = sizeof(Symbol); 8349657Slinton break; 8359657Slinton 83616620Ssam case SET: 83716620Ssam u = rtype(t->type); 83816620Ssam switch (u->class) { 83916620Ssam case RANGE: 84016620Ssam r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; 84116620Ssam break; 84216620Ssam 84316620Ssam case SCAL: 84416620Ssam r = u->symvalue.iconval; 84516620Ssam break; 84616620Ssam 84716620Ssam default: 84816620Ssam error("expected range for set base type"); 84916620Ssam break; 85016620Ssam } 85116620Ssam r = (r + BITSPERBYTE - 1) div BITSPERBYTE; 85216620Ssam break; 85316620Ssam 85418235Slinton /* 85518235Slinton * These can happen in C (unfortunately) for unresolved type references 85618235Slinton * Assume they are pointers. 85718235Slinton */ 85818235Slinton case BADUSE: 85918235Slinton r = sizeof(Address); 86018235Slinton break; 86118235Slinton 8629657Slinton default: 8639657Slinton if (ord(t->class) > ord(TYPEREF)) { 8649657Slinton panic("size: bad class (%d)", ord(t->class)); 8659657Slinton } else { 86618235Slinton fprintf(stderr, "can't compute size of a %s\n", classname(t)); 8679657Slinton } 86816620Ssam r = 0; 86916620Ssam break; 8709657Slinton } 8719657Slinton return r; 8729657Slinton } 8739657Slinton 8749657Slinton /* 87518235Slinton * Return the size associated with a symbol that takes into account 87618235Slinton * reference parameters. This might be better as the normal size function, but 87718235Slinton * too many places already depend on it working the way it does. 87818235Slinton */ 87918235Slinton 88018235Slinton public integer psize (s) 88118235Slinton Symbol s; 88218235Slinton { 88318235Slinton integer r; 88418235Slinton Symbol t; 88518235Slinton 88618235Slinton if (s->class == REF) { 88718235Slinton t = rtype(s->type); 88818235Slinton if (t->class == DYNARRAY) { 88918235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 89018235Slinton } else if (t->class == SUBARRAY) { 89118235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 89218235Slinton } else { 89318235Slinton r = sizeof(Word); 89418235Slinton } 89518235Slinton } else { 89618235Slinton r = size(s); 89718235Slinton } 89818235Slinton return r; 89918235Slinton } 90018235Slinton 90118235Slinton /* 9029657Slinton * Test if a symbol is a parameter. This is true if there 9039657Slinton * is a cycle from s->block to s via chain pointers. 9049657Slinton */ 9059657Slinton 9069657Slinton public Boolean isparam(s) 9079657Slinton Symbol s; 9089657Slinton { 9099657Slinton register Symbol t; 9109657Slinton 9119657Slinton t = s->block; 9129657Slinton while (t != nil and t != s) { 9139657Slinton t = t->chain; 9149657Slinton } 9159657Slinton return (Boolean) (t != nil); 9169657Slinton } 9179657Slinton 9189657Slinton /* 91916620Ssam * Test if a type is an open array parameter type. 9209657Slinton */ 9219657Slinton 92218235Slinton public boolean isopenarray (type) 92318235Slinton Symbol type; 92416620Ssam { 92518235Slinton Symbol t; 92618235Slinton 92718235Slinton t = rtype(type); 92818235Slinton return (boolean) (t->class == DYNARRAY); 92916620Ssam } 93016620Ssam 93116620Ssam /* 93218235Slinton * Test if a symbol is a var parameter, i.e. has class REF. 93316620Ssam */ 93416620Ssam 9359657Slinton public Boolean isvarparam(s) 9369657Slinton Symbol s; 9379657Slinton { 9389657Slinton return (Boolean) (s->class == REF); 9399657Slinton } 9409657Slinton 9419657Slinton /* 9429657Slinton * Test if a symbol is a variable (actually any addressible quantity 9439657Slinton * with do). 9449657Slinton */ 9459657Slinton 9469657Slinton public Boolean isvariable(s) 94718235Slinton Symbol s; 9489657Slinton { 9499657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 9509657Slinton } 9519657Slinton 9529657Slinton /* 95318235Slinton * Test if a symbol is a constant. 95418235Slinton */ 95518235Slinton 95618235Slinton public Boolean isconst(s) 95718235Slinton Symbol s; 9589657Slinton { 95918235Slinton return (Boolean) (s->class == CONST); 9609657Slinton } 9619657Slinton 9629657Slinton /* 9639657Slinton * Test if a symbol is a module. 9649657Slinton */ 9659657Slinton 9669657Slinton public Boolean ismodule(s) 9679657Slinton register Symbol s; 9689657Slinton { 9699657Slinton return (Boolean) (s->class == MODULE); 9709657Slinton } 9719657Slinton 9729657Slinton /* 97316620Ssam * Mark a procedure or function as internal, meaning that it is called 97416620Ssam * with a different calling sequence. 97516620Ssam */ 97616620Ssam 97716620Ssam public markInternal (s) 97816620Ssam Symbol s; 97916620Ssam { 98016620Ssam s->symvalue.funcv.intern = true; 98116620Ssam } 98216620Ssam 98316620Ssam public boolean isinternal (s) 98416620Ssam Symbol s; 98516620Ssam { 98616620Ssam return s->symvalue.funcv.intern; 98716620Ssam } 98816620Ssam 98916620Ssam /* 99018235Slinton * Decide if a field begins or ends on a bit rather than byte boundary. 99118235Slinton */ 99218235Slinton 99318235Slinton public Boolean isbitfield(s) 99418235Slinton register Symbol s; 99518235Slinton { 99618235Slinton boolean b; 99718235Slinton register integer off, len; 99818235Slinton register Symbol t; 99918235Slinton 100018235Slinton off = s->symvalue.field.offset; 100118235Slinton len = s->symvalue.field.length; 100218235Slinton if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { 100318235Slinton b = true; 100418235Slinton } else { 100518235Slinton t = rtype(s->type); 100618235Slinton b = (Boolean) ( 100718235Slinton (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or 100818235Slinton len != (size(t)*BITSPERBYTE) 100918235Slinton ); 101018235Slinton } 101118235Slinton return b; 101218235Slinton } 101318235Slinton 101418235Slinton private boolean primlang_typematch (t1, t2) 101518235Slinton Symbol t1, t2; 101618235Slinton { 101718235Slinton return (boolean) ( 101818235Slinton (t1 == t2) or 101918235Slinton ( 102018235Slinton t1->class == RANGE and t2->class == RANGE and 102118235Slinton t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 102218235Slinton t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 102318235Slinton ) or ( 102418235Slinton t1->class == PTR and t2->class == RANGE and 102518235Slinton t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower 102618235Slinton ) or ( 102718235Slinton t2->class == PTR and t1->class == RANGE and 102818235Slinton t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower 102918235Slinton ) 103018235Slinton ); 103118235Slinton } 103218235Slinton 103318235Slinton /* 10349657Slinton * Test if two types match. 10359657Slinton * Equivalent names implies a match in any language. 10369657Slinton * 10379657Slinton * Special symbols must be handled with care. 10389657Slinton */ 10399657Slinton 10409657Slinton public Boolean compatible(t1, t2) 10419657Slinton register Symbol t1, t2; 10429657Slinton { 10439657Slinton Boolean b; 104416620Ssam Symbol rt1, rt2; 10459657Slinton 10469657Slinton if (t1 == t2) { 10479657Slinton b = true; 10489657Slinton } else if (t1 == nil or t2 == nil) { 10499657Slinton b = false; 10509657Slinton } else if (t1 == procsym) { 10519657Slinton b = isblock(t2); 10529657Slinton } else if (t2 == procsym) { 10539657Slinton b = isblock(t1); 105416620Ssam } else if (t1->language == primlang) { 105516620Ssam if (t2->language == primlang) { 105618235Slinton b = primlang_typematch(rtype(t1), rtype(t2)); 105716620Ssam } else { 105816620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 105916620Ssam } 106016620Ssam } else if (t2->language == primlang) { 106116620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 10629657Slinton } else if (t1->language == nil) { 106316620Ssam if (t2->language == nil) { 106416620Ssam b = false; 106516620Ssam } else { 106616620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 106716620Ssam } 10689657Slinton } else { 106916620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 10709657Slinton } 10719657Slinton return b; 10729657Slinton } 10739657Slinton 10749657Slinton /* 10759657Slinton * Check for a type of the given name. 10769657Slinton */ 10779657Slinton 10789657Slinton public Boolean istypename(type, name) 10799657Slinton Symbol type; 10809657Slinton String name; 10819657Slinton { 108218235Slinton register Symbol t; 10839657Slinton Boolean b; 10849657Slinton 10859657Slinton t = type; 108618235Slinton if (t == nil) { 108718235Slinton b = false; 108818235Slinton } else { 108918235Slinton b = (Boolean) ( 109018235Slinton t->class == TYPE and streq(ident(t->name), name) 109118235Slinton ); 109218235Slinton } 10939657Slinton return b; 10949657Slinton } 10959657Slinton 10969657Slinton /* 109716620Ssam * Determine if a (value) parameter should actually be passed by address. 109816620Ssam */ 109916620Ssam 110016620Ssam public boolean passaddr (p, exprtype) 110116620Ssam Symbol p, exprtype; 110216620Ssam { 110316620Ssam boolean b; 110416620Ssam Language def; 110516620Ssam 110616620Ssam if (p == nil) { 110716620Ssam def = findlanguage(".c"); 110816620Ssam b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); 110916620Ssam } else if (p->language == nil or p->language == primlang) { 111016620Ssam b = false; 111116620Ssam } else if (isopenarray(p->type)) { 111216620Ssam b = true; 111316620Ssam } else { 111416620Ssam b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); 111516620Ssam } 111616620Ssam return b; 111716620Ssam } 111816620Ssam 111916620Ssam /* 11209657Slinton * Test if the name of a symbol is uniquely defined or not. 11219657Slinton */ 11229657Slinton 11239657Slinton public Boolean isambiguous(s) 11249657Slinton register Symbol s; 11259657Slinton { 11269657Slinton register Symbol t; 11279657Slinton 11289657Slinton find(t, s->name) where t != s endfind(t); 11299657Slinton return (Boolean) (t != nil); 11309657Slinton } 11319657Slinton 11329657Slinton typedef char *Arglist; 11339657Slinton 11349657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 11359657Slinton 11369657Slinton private Symbol mkstring(); 11379657Slinton 11389657Slinton /* 11399657Slinton * Determine the type of a parse tree. 114018235Slinton * 11419657Slinton * Also make some symbol-dependent changes to the tree such as 114218235Slinton * removing indirection for constant or register symbols. 11439657Slinton */ 11449657Slinton 114518235Slinton public assigntypes (p) 11469657Slinton register Node p; 11479657Slinton { 11489657Slinton register Node p1; 11499657Slinton register Symbol s; 11509657Slinton 11519657Slinton switch (p->op) { 11529657Slinton case O_SYM: 115318235Slinton p->nodetype = p->value.sym; 11549657Slinton break; 11559657Slinton 11569657Slinton case O_LCON: 11579657Slinton p->nodetype = t_int; 11589657Slinton break; 11599657Slinton 116018235Slinton case O_CCON: 116118235Slinton p->nodetype = t_char; 116218235Slinton break; 116318235Slinton 11649657Slinton case O_FCON: 11659657Slinton p->nodetype = t_real; 11669657Slinton break; 11679657Slinton 11689657Slinton case O_SCON: 116918235Slinton p->nodetype = mkstring(p->value.scon); 11709657Slinton break; 11719657Slinton 11729657Slinton case O_INDIR: 11739657Slinton p1 = p->value.arg[0]; 117418235Slinton s = rtype(p1->nodetype); 117518235Slinton if (s->class != PTR) { 117618235Slinton beginerrmsg(); 117718235Slinton fprintf(stderr, "\""); 117818235Slinton prtree(stderr, p1); 117918235Slinton fprintf(stderr, "\" is not a pointer"); 118018235Slinton enderrmsg(); 118118235Slinton } 11829657Slinton p->nodetype = rtype(p1->nodetype)->type; 11839657Slinton break; 11849657Slinton 11859657Slinton case O_DOT: 11869657Slinton p->nodetype = p->value.arg[1]->value.sym; 11879657Slinton break; 11889657Slinton 11899657Slinton case O_RVAL: 11909657Slinton p1 = p->value.arg[0]; 11919657Slinton p->nodetype = p1->nodetype; 11929657Slinton if (p1->op == O_SYM) { 119318235Slinton if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) { 119418235Slinton p->op = p1->op; 119518235Slinton p->value.sym = p1->value.sym; 119618235Slinton p->nodetype = p1->nodetype; 119718235Slinton dispose(p1); 11989657Slinton } else if (p1->value.sym->class == CONST) { 119918235Slinton p->op = p1->op; 120018235Slinton p->value = p1->value; 120118235Slinton p->nodetype = p1->nodetype; 120218235Slinton dispose(p1); 12039657Slinton } else if (isreg(p1->value.sym)) { 12049657Slinton p->op = O_SYM; 12059657Slinton p->value.sym = p1->value.sym; 12069657Slinton dispose(p1); 12079657Slinton } 12089657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 12099657Slinton s = p1->value.arg[0]->value.sym; 12109657Slinton if (isreg(s)) { 12119657Slinton p1->op = O_SYM; 12129657Slinton dispose(p1->value.arg[0]); 12139657Slinton p1->value.sym = s; 12149657Slinton p1->nodetype = s; 12159657Slinton } 12169657Slinton } 12179657Slinton break; 12189657Slinton 121918235Slinton case O_COMMA: 122018235Slinton p->nodetype = p->value.arg[0]->nodetype; 122118235Slinton break; 122218235Slinton 122318235Slinton case O_CALLPROC: 12249657Slinton case O_CALL: 12259657Slinton p1 = p->value.arg[0]; 122611171Slinton p->nodetype = rtype(p1->nodetype)->type; 12279657Slinton break; 12289657Slinton 122911171Slinton case O_TYPERENAME: 123011171Slinton p->nodetype = p->value.arg[1]->nodetype; 123111171Slinton break; 123211171Slinton 12339657Slinton case O_ITOF: 12349657Slinton p->nodetype = t_real; 12359657Slinton break; 12369657Slinton 12379657Slinton case O_NEG: 12389657Slinton s = p->value.arg[0]->nodetype; 12399657Slinton if (not compatible(s, t_int)) { 12409657Slinton if (not compatible(s, t_real)) { 12419657Slinton beginerrmsg(); 124216620Ssam fprintf(stderr, "\""); 12439657Slinton prtree(stderr, p->value.arg[0]); 124416620Ssam fprintf(stderr, "\" is improper type"); 12459657Slinton enderrmsg(); 12469657Slinton } else { 12479657Slinton p->op = O_NEGF; 12489657Slinton } 12499657Slinton } 12509657Slinton p->nodetype = s; 12519657Slinton break; 12529657Slinton 12539657Slinton case O_ADD: 12549657Slinton case O_SUB: 12559657Slinton case O_MUL: 125616620Ssam binaryop(p, nil); 125716620Ssam break; 125816620Ssam 12599657Slinton case O_LT: 12609657Slinton case O_LE: 12619657Slinton case O_GT: 12629657Slinton case O_GE: 12639657Slinton case O_EQ: 12649657Slinton case O_NE: 126516620Ssam binaryop(p, t_boolean); 12669657Slinton break; 12679657Slinton 12689657Slinton case O_DIVF: 12699657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 12709657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 12719657Slinton p->nodetype = t_real; 12729657Slinton break; 12739657Slinton 12749657Slinton case O_DIV: 12759657Slinton case O_MOD: 12769657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 12779657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 12789657Slinton p->nodetype = t_int; 12799657Slinton break; 12809657Slinton 12819657Slinton case O_AND: 12829657Slinton case O_OR: 12839657Slinton chkboolean(p->value.arg[0]); 12849657Slinton chkboolean(p->value.arg[1]); 12859657Slinton p->nodetype = t_boolean; 12869657Slinton break; 12879657Slinton 12889657Slinton case O_QLINE: 12899657Slinton p->nodetype = t_int; 12909657Slinton break; 12919657Slinton 12929657Slinton default: 12939657Slinton p->nodetype = nil; 12949657Slinton break; 12959657Slinton } 12969657Slinton } 12979657Slinton 12989657Slinton /* 129916620Ssam * Process a binary arithmetic or relational operator. 130016620Ssam * Convert from integer to real if necessary. 130116620Ssam */ 130216620Ssam 130316620Ssam private binaryop (p, t) 130416620Ssam Node p; 130516620Ssam Symbol t; 130616620Ssam { 130716620Ssam Node p1, p2; 130816620Ssam Boolean t1real, t2real; 130916620Ssam Symbol t1, t2; 131016620Ssam 131116620Ssam p1 = p->value.arg[0]; 131216620Ssam p2 = p->value.arg[1]; 131316620Ssam t1 = rtype(p1->nodetype); 131416620Ssam t2 = rtype(p2->nodetype); 131516620Ssam t1real = compatible(t1, t_real); 131616620Ssam t2real = compatible(t2, t_real); 131716620Ssam if (t1real or t2real) { 131816620Ssam p->op = (Operator) (ord(p->op) + 1); 131916620Ssam if (not t1real) { 132016620Ssam p->value.arg[0] = build(O_ITOF, p1); 132116620Ssam } else if (not t2real) { 132216620Ssam p->value.arg[1] = build(O_ITOF, p2); 132316620Ssam } 132416620Ssam p->nodetype = t_real; 132516620Ssam } else { 132616620Ssam if (size(p1->nodetype) > sizeof(integer)) { 132716620Ssam beginerrmsg(); 132816620Ssam fprintf(stderr, "operation not defined on \""); 132916620Ssam prtree(stderr, p1); 133016620Ssam fprintf(stderr, "\""); 133116620Ssam enderrmsg(); 133216620Ssam } else if (size(p2->nodetype) > sizeof(integer)) { 133316620Ssam beginerrmsg(); 133416620Ssam fprintf(stderr, "operation not defined on \""); 133516620Ssam prtree(stderr, p2); 133616620Ssam fprintf(stderr, "\""); 133716620Ssam enderrmsg(); 133816620Ssam } 133916620Ssam p->nodetype = t_int; 134016620Ssam } 134116620Ssam if (t != nil) { 134216620Ssam p->nodetype = t; 134316620Ssam } 134416620Ssam } 134516620Ssam 134616620Ssam /* 13479657Slinton * Convert a tree to a type via a conversion operator; 13489657Slinton * if this isn't possible generate an error. 13499657Slinton * 13509657Slinton * Note the tree is call by address, hence the #define below. 13519657Slinton */ 13529657Slinton 13539657Slinton private convert(tp, typeto, op) 13549657Slinton Node *tp; 13559657Slinton Symbol typeto; 13569657Slinton Operator op; 13579657Slinton { 135816620Ssam Node tree; 135916620Ssam Symbol s, t; 13609657Slinton 136116620Ssam tree = *tp; 13629657Slinton s = rtype(tree->nodetype); 136316620Ssam t = rtype(typeto); 136416620Ssam if (compatible(t, t_real) and compatible(s, t_int)) { 13659657Slinton tree = build(op, tree); 136616620Ssam } else if (not compatible(s, t)) { 13679657Slinton beginerrmsg(); 136816620Ssam fprintf(stderr, "expected integer or real, found \""); 136916620Ssam prtree(stderr, tree); 137016620Ssam fprintf(stderr, "\""); 13719657Slinton enderrmsg(); 137216620Ssam } else if (op != O_NOP and s != t) { 13739657Slinton tree = build(op, tree); 13749657Slinton } 137516620Ssam *tp = tree; 13769657Slinton } 13779657Slinton 13789657Slinton /* 13799657Slinton * Construct a node for the dot operator. 13809657Slinton * 13819657Slinton * If the left operand is not a record, but rather a procedure 13829657Slinton * or function, then we interpret the "." as referencing an 13839657Slinton * "invisible" variable; i.e. a variable within a dynamically 13849657Slinton * active block but not within the static scope of the current procedure. 13859657Slinton */ 13869657Slinton 13879657Slinton public Node dot(record, fieldname) 13889657Slinton Node record; 13899657Slinton Name fieldname; 13909657Slinton { 139118235Slinton register Node rec, p; 13929657Slinton register Symbol s, t; 13939657Slinton 139418235Slinton rec = record; 139518235Slinton if (isblock(rec->nodetype)) { 13969657Slinton find(s, fieldname) where 139718235Slinton s->block == rec->nodetype and 139818235Slinton s->class != FIELD 13999657Slinton endfind(s); 14009657Slinton if (s == nil) { 14019657Slinton beginerrmsg(); 14029657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 140318235Slinton printname(stderr, rec->nodetype); 14049657Slinton enderrmsg(); 14059657Slinton } 14069657Slinton p = new(Node); 14079657Slinton p->op = O_SYM; 14089657Slinton p->value.sym = s; 140918235Slinton p->nodetype = s; 14109657Slinton } else { 141118235Slinton p = rec; 14129657Slinton t = rtype(p->nodetype); 14139657Slinton if (t->class == PTR) { 14149657Slinton s = findfield(fieldname, t->type); 14159657Slinton } else { 14169657Slinton s = findfield(fieldname, t); 14179657Slinton } 14189657Slinton if (s == nil) { 14199657Slinton beginerrmsg(); 14209657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 142118235Slinton prtree(stderr, rec); 14229657Slinton enderrmsg(); 14239657Slinton } 142418235Slinton if (t->class != PTR or isreg(rec->nodetype)) { 142518235Slinton p = unrval(p); 14269657Slinton } 142718235Slinton p->nodetype = t_addr; 14289657Slinton p = build(O_DOT, p, build(O_SYM, s)); 14299657Slinton } 143018235Slinton return build(O_RVAL, p); 14319657Slinton } 14329657Slinton 14339657Slinton /* 14349657Slinton * Return a tree corresponding to an array reference and do the 14359657Slinton * error checking. 14369657Slinton */ 14379657Slinton 14389657Slinton public Node subscript(a, slist) 14399657Slinton Node a, slist; 14409657Slinton { 144116620Ssam Symbol t; 144218235Slinton Node p; 14439657Slinton 144416620Ssam t = rtype(a->nodetype); 144518235Slinton if (t->language == nil or t->language == primlang) { 144618235Slinton p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); 144716620Ssam } else { 144818235Slinton p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); 144916620Ssam } 145018235Slinton return build(O_RVAL, p); 14519657Slinton } 14529657Slinton 14539657Slinton /* 14549657Slinton * Evaluate a subscript index. 14559657Slinton */ 14569657Slinton 145718235Slinton public int evalindex(s, base, i) 14589657Slinton Symbol s; 145918235Slinton Address base; 14609657Slinton long i; 14619657Slinton { 146216620Ssam Symbol t; 146318235Slinton int r; 14649657Slinton 146516620Ssam t = rtype(s); 146618235Slinton if (t->language == nil or t->language == primlang) { 146718235Slinton r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); 146816620Ssam } else { 146918235Slinton r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); 147016620Ssam } 147118235Slinton return r; 14729657Slinton } 14739657Slinton 14749657Slinton /* 14759657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 14769657Slinton */ 14779657Slinton 14789657Slinton public chkboolean(p) 14799657Slinton register Node p; 14809657Slinton { 14819657Slinton if (p->nodetype != t_boolean) { 14829657Slinton beginerrmsg(); 14839657Slinton fprintf(stderr, "found "); 14849657Slinton prtree(stderr, p); 14859657Slinton fprintf(stderr, ", expected boolean expression"); 14869657Slinton enderrmsg(); 14879657Slinton } 14889657Slinton } 14899657Slinton 14909657Slinton /* 149116620Ssam * Construct a node for the type of a string. 14929657Slinton */ 14939657Slinton 14949657Slinton private Symbol mkstring(str) 14959657Slinton String str; 14969657Slinton { 14979657Slinton register Symbol s; 14989657Slinton 149918235Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 150018235Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 150118235Slinton s->chain->language = s->language; 150218235Slinton s->chain->symvalue.rangev.lower = 1; 150318235Slinton s->chain->symvalue.rangev.upper = strlen(str) + 1; 15049657Slinton return s; 15059657Slinton } 15069657Slinton 15079657Slinton /* 15089657Slinton * Free up the space allocated for a string type. 15099657Slinton */ 15109657Slinton 15119657Slinton public unmkstring(s) 15129657Slinton Symbol s; 15139657Slinton { 15149657Slinton dispose(s->chain); 15159657Slinton } 15169657Slinton 15179657Slinton /* 151818235Slinton * Figure out the "current" variable or function being referred to 151918235Slinton * by the name n. 15209657Slinton */ 15219657Slinton 152218235Slinton private boolean stwhich(), dynwhich(); 152318235Slinton 152418235Slinton public Symbol which (n) 15259657Slinton Name n; 15269657Slinton { 152718235Slinton Symbol s; 15289657Slinton 152918235Slinton s = lookup(n); 15309657Slinton if (s == nil) { 153118235Slinton error("\"%s\" is not defined", ident(n)); 153218235Slinton } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { 153318235Slinton printf("[using "); 153418235Slinton printname(stdout, s); 153518235Slinton printf("]\n"); 15369657Slinton } 153718235Slinton return s; 153818235Slinton } 153918235Slinton 154018235Slinton /* 154118235Slinton * Static search. 154218235Slinton */ 154318235Slinton 154418235Slinton private boolean stwhich (var_s) 154518235Slinton Symbol *var_s; 154618235Slinton { 154718235Slinton Name n; /* name of desired symbol */ 154818235Slinton Symbol s; /* iteration variable for symbols with name n */ 154918235Slinton Symbol f; /* iteration variable for blocks containing s */ 155018235Slinton integer count; /* number of levels from s->block to curfunc */ 155118235Slinton Symbol t; /* current best answer for stwhich(n) */ 155218235Slinton integer mincount; /* relative level for current best answer (t) */ 155318235Slinton boolean b; /* return value, true if symbol found */ 155418235Slinton 155518235Slinton s = *var_s; 155618235Slinton n = s->name; 155718235Slinton t = s; 155818235Slinton mincount = 10000; /* force first match to set mincount */ 155918235Slinton do { 156018235Slinton if (s->name == n and s->class != FIELD and s->class != TAG) { 156118235Slinton f = curfunc; 156218235Slinton count = 0; 156318235Slinton while (f != nil and f != s->block) { 156418235Slinton ++count; 156518235Slinton f = f->block; 156618235Slinton } 156718235Slinton if (f != nil and count < mincount) { 156818235Slinton t = s; 156918235Slinton mincount = count; 157018235Slinton b = true; 157118235Slinton } 157218235Slinton } 157318235Slinton s = s->next_sym; 157418235Slinton } while (s != nil); 157518235Slinton if (mincount != 10000) { 157618235Slinton *var_s = t; 157718235Slinton b = true; 15789657Slinton } else { 157918235Slinton b = false; 158018235Slinton } 158118235Slinton return b; 158218235Slinton } 158318235Slinton 158418235Slinton /* 158518235Slinton * Dynamic search. 158618235Slinton */ 158718235Slinton 158818235Slinton private boolean dynwhich (var_s) 158918235Slinton Symbol *var_s; 159018235Slinton { 159118235Slinton Name n; /* name of desired symbol */ 159218235Slinton Symbol s; /* iteration variable for possible symbols */ 159318235Slinton Symbol f; /* iteration variable for active functions */ 159418235Slinton Frame frp; /* frame associated with stack walk */ 159518235Slinton boolean b; /* return value */ 159618235Slinton 159718235Slinton f = curfunc; 159818235Slinton frp = curfuncframe(); 159918235Slinton n = (*var_s)->name; 160018235Slinton b = false; 160118235Slinton if (frp != nil) { 160218235Slinton frp = nextfunc(frp, &f); 160318235Slinton while (frp != nil) { 160418235Slinton s = *var_s; 160518235Slinton while (s != nil and 160618235Slinton ( 160718235Slinton s->name != n or s->block != f or 160818235Slinton s->class == FIELD or s->class == TAG 160918235Slinton ) 161018235Slinton ) { 161118235Slinton s = s->next_sym; 161218235Slinton } 161318235Slinton if (s != nil) { 161418235Slinton *var_s = s; 161518235Slinton b = true; 161618235Slinton break; 161718235Slinton } 161818235Slinton if (f == program) { 161918235Slinton break; 162018235Slinton } 162118235Slinton frp = nextfunc(frp, &f); 16229657Slinton } 16239657Slinton } 162418235Slinton return b; 16259657Slinton } 16269657Slinton 16279657Slinton /* 162818235Slinton * Find the symbol that has the same name and scope as the 16299657Slinton * given symbol but is of the given field. Return nil if there is none. 16309657Slinton */ 16319657Slinton 163218235Slinton public Symbol findfield (fieldname, record) 16339657Slinton Name fieldname; 16349657Slinton Symbol record; 16359657Slinton { 16369657Slinton register Symbol t; 16379657Slinton 16389657Slinton t = rtype(record)->chain; 16399657Slinton while (t != nil and t->name != fieldname) { 16409657Slinton t = t->chain; 16419657Slinton } 16429657Slinton return t; 16439657Slinton } 164412547Scsvaf 164512547Scsvaf public Boolean getbound(s,off,type,valp) 164612547Scsvaf Symbol s; 164712547Scsvaf int off; 164812547Scsvaf Rangetype type; 164912547Scsvaf int *valp; 165012547Scsvaf { 165112547Scsvaf Frame frp; 165212547Scsvaf Address addr; 165312547Scsvaf Symbol cur; 165412547Scsvaf 165512547Scsvaf if (not isactive(s->block)) { 165612547Scsvaf return(false); 165712547Scsvaf } 165812547Scsvaf cur = s->block; 165912547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 166012547Scsvaf cur = cur->block; 166112547Scsvaf } 166212547Scsvaf if(cur == nil) { 166312547Scsvaf cur = whatblock(pc); 166412547Scsvaf } 166512547Scsvaf frp = findframe(cur); 166612547Scsvaf if (frp == nil) { 166712547Scsvaf return(false); 166812547Scsvaf } 166912547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 167012547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 167112547Scsvaf else return(false); 167212547Scsvaf dread(valp,addr,sizeof(long)); 167312547Scsvaf return(true); 167412547Scsvaf } 1675