1*21625Sdist /* 2*21625Sdist * Copyright (c) 1983 Regents of the University of California. 3*21625Sdist * All rights reserved. The Berkeley software License Agreement 4*21625Sdist * specifies the terms and conditions for redistribution. 5*21625Sdist */ 69657Slinton 7*21625Sdist #ifndef lint 8*21625Sdist static char sccsid[] = "@(#)symbols.c 5.1 (Berkeley) 05/31/85"; 9*21625Sdist #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 1289657Slinton #include "tree.h" 1299657Slinton 1309657Slinton /* 1319657Slinton * Some macros to make finding a symbol with certain attributes. 1329657Slinton */ 1339657Slinton 1349657Slinton #define find(s, withname) \ 1359657Slinton { \ 1369657Slinton s = lookup(withname); \ 1379657Slinton while (s != nil and not (s->name == (withname) and 1389657Slinton 1399657Slinton #define where /* qualification */ 1409657Slinton 1419657Slinton #define endfind(s) )) { \ 1429657Slinton s = s->next_sym; \ 1439657Slinton } \ 1449657Slinton } 1459657Slinton 1469657Slinton #endif 1479657Slinton 1489657Slinton /* 1499657Slinton * Symbol table structure currently does not support deletions. 1509657Slinton */ 1519657Slinton 1529657Slinton #define HASHTABLESIZE 2003 1539657Slinton 1549657Slinton private Symbol hashtab[HASHTABLESIZE]; 1559657Slinton 1569657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 1579657Slinton 1589657Slinton /* 1599657Slinton * Allocate a new symbol. 1609657Slinton */ 1619657Slinton 16211171Slinton #define SYMBLOCKSIZE 100 1639657Slinton 1649657Slinton typedef struct Sympool { 1659657Slinton struct Symbol sym[SYMBLOCKSIZE]; 1669657Slinton struct Sympool *prevpool; 1679657Slinton } *Sympool; 1689657Slinton 1699657Slinton private Sympool sympool = nil; 1709657Slinton private Integer nleft = 0; 1719657Slinton 1729657Slinton public Symbol symbol_alloc() 1739657Slinton { 1749657Slinton register Sympool newpool; 1759657Slinton 1769657Slinton if (nleft <= 0) { 1779657Slinton newpool = new(Sympool); 17811171Slinton bzero(newpool, sizeof(newpool)); 1799657Slinton newpool->prevpool = sympool; 1809657Slinton sympool = newpool; 1819657Slinton nleft = SYMBLOCKSIZE; 1829657Slinton } 1839657Slinton --nleft; 1849657Slinton return &(sympool->sym[nleft]); 1859657Slinton } 1869657Slinton 18718235Slinton public symbol_dump (func) 18812547Scsvaf Symbol func; 18912547Scsvaf { 19018235Slinton register Symbol s; 19118235Slinton register integer i; 19212547Scsvaf 19318235Slinton printf(" symbols in %s \n",symname(func)); 19418235Slinton for (i = 0; i < HASHTABLESIZE; i++) { 19518235Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 19618235Slinton if (s->block == func) { 19718235Slinton psym(s); 19818235Slinton } 19918235Slinton } 20018235Slinton } 20112547Scsvaf } 20212547Scsvaf 2039657Slinton /* 2049657Slinton * Free all the symbols currently allocated. 2059657Slinton */ 20618235Slinton 2079657Slinton public symbol_free() 2089657Slinton { 2099657Slinton Sympool s, t; 2109657Slinton register Integer i; 2119657Slinton 2129657Slinton s = sympool; 2139657Slinton while (s != nil) { 2149657Slinton t = s->prevpool; 2159657Slinton dispose(s); 2169657Slinton s = t; 2179657Slinton } 2189657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 2199657Slinton hashtab[i] = nil; 2209657Slinton } 2219657Slinton sympool = nil; 2229657Slinton nleft = 0; 2239657Slinton } 2249657Slinton 2259657Slinton /* 2269657Slinton * Create a new symbol with the given attributes. 2279657Slinton */ 2289657Slinton 2299657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 2309657Slinton Name name; 2319657Slinton Integer blevel; 2329657Slinton Symclass class; 2339657Slinton Symbol type; 2349657Slinton Symbol chain; 2359657Slinton { 2369657Slinton register Symbol s; 2379657Slinton 2389657Slinton s = symbol_alloc(); 2399657Slinton s->name = name; 24018235Slinton s->language = primlang; 2419657Slinton s->level = blevel; 2429657Slinton s->class = class; 2439657Slinton s->type = type; 2449657Slinton s->chain = chain; 2459657Slinton return s; 2469657Slinton } 2479657Slinton 2489657Slinton /* 2499657Slinton * Insert a symbol into the hash table. 2509657Slinton */ 2519657Slinton 2529657Slinton public Symbol insert(name) 2539657Slinton Name name; 2549657Slinton { 2559657Slinton register Symbol s; 2569657Slinton register unsigned int h; 2579657Slinton 2589657Slinton h = hash(name); 2599657Slinton s = symbol_alloc(); 2609657Slinton s->name = name; 2619657Slinton s->next_sym = hashtab[h]; 2629657Slinton hashtab[h] = s; 2639657Slinton return s; 2649657Slinton } 2659657Slinton 2669657Slinton /* 2679657Slinton * Symbol lookup. 2689657Slinton */ 2699657Slinton 2709657Slinton public Symbol lookup(name) 2719657Slinton Name name; 2729657Slinton { 2739657Slinton register Symbol s; 2749657Slinton register unsigned int h; 2759657Slinton 2769657Slinton h = hash(name); 2779657Slinton s = hashtab[h]; 2789657Slinton while (s != nil and s->name != name) { 2799657Slinton s = s->next_sym; 2809657Slinton } 2819657Slinton return s; 2829657Slinton } 2839657Slinton 2849657Slinton /* 28516620Ssam * Delete a symbol from the symbol table. 28616620Ssam */ 28716620Ssam 28816620Ssam public delete (s) 28916620Ssam Symbol s; 29016620Ssam { 29116620Ssam register Symbol t; 29216620Ssam register unsigned int h; 29316620Ssam 29416620Ssam h = hash(s->name); 29516620Ssam t = hashtab[h]; 29616620Ssam if (t == nil) { 29716620Ssam panic("delete of non-symbol '%s'", symname(s)); 29816620Ssam } else if (t == s) { 29916620Ssam hashtab[h] = s->next_sym; 30016620Ssam } else { 30116620Ssam while (t->next_sym != s) { 30216620Ssam t = t->next_sym; 30316620Ssam if (t == nil) { 30416620Ssam panic("delete of non-symbol '%s'", symname(s)); 30516620Ssam } 30616620Ssam } 30716620Ssam t->next_sym = s->next_sym; 30816620Ssam } 30916620Ssam } 31016620Ssam 31116620Ssam /* 3129657Slinton * Dump out all the variables associated with the given 31318235Slinton * procedure, function, or program associated with the given stack frame. 3149657Slinton * 3159657Slinton * This is quite inefficient. We traverse the entire symbol table 3169657Slinton * each time we're called. The assumption is that this routine 3179657Slinton * won't be called frequently enough to merit improved performance. 3189657Slinton */ 3199657Slinton 3209657Slinton public dumpvars(f, frame) 3219657Slinton Symbol f; 3229657Slinton Frame frame; 3239657Slinton { 3249657Slinton register Integer i; 3259657Slinton register Symbol s; 3269657Slinton 3279657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 3289657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 3299657Slinton if (container(s) == f) { 3309657Slinton if (should_print(s)) { 3319657Slinton printv(s, frame); 3329657Slinton putchar('\n'); 3339657Slinton } else if (s->class == MODULE) { 3349657Slinton dumpvars(s, frame); 3359657Slinton } 3369657Slinton } 3379657Slinton } 3389657Slinton } 3399657Slinton } 3409657Slinton 3419657Slinton /* 3429657Slinton * Create a builtin type. 3439657Slinton * Builtin types are circular in that btype->type->type = btype. 3449657Slinton */ 3459657Slinton 34618235Slinton private Symbol maketype(name, lower, upper) 3479657Slinton String name; 3489657Slinton long lower; 3499657Slinton long upper; 3509657Slinton { 3519657Slinton register Symbol s; 35218235Slinton Name n; 3539657Slinton 35418235Slinton if (name == nil) { 35518235Slinton n = nil; 35618235Slinton } else { 35718235Slinton n = identname(name, true); 35818235Slinton } 35918235Slinton s = insert(n); 36016620Ssam s->language = primlang; 36118235Slinton s->level = 0; 36218235Slinton s->class = TYPE; 36318235Slinton s->type = nil; 36418235Slinton s->chain = nil; 3659657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 3669657Slinton s->type->symvalue.rangev.lower = lower; 3679657Slinton s->type->symvalue.rangev.upper = upper; 3689657Slinton return s; 3699657Slinton } 3709657Slinton 3719657Slinton /* 37218235Slinton * Create the builtin symbols. 37318235Slinton */ 37418235Slinton 37518235Slinton public symbols_init () 3769657Slinton { 37718235Slinton Symbol s; 3789657Slinton 37918235Slinton t_boolean = maketype("$boolean", 0L, 1L); 38018235Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 38118235Slinton t_char = maketype("$char", 0L, 255L); 38218235Slinton t_real = maketype("$real", 8L, 0L); 38318235Slinton t_nil = maketype("$nil", 0L, 0L); 38418235Slinton t_addr = insert(identname("$address", true)); 38518235Slinton t_addr->language = primlang; 38618235Slinton t_addr->level = 0; 38718235Slinton t_addr->class = TYPE; 38818235Slinton t_addr->type = newSymbol(nil, 1, PTR, t_int, nil); 38918235Slinton s = insert(identname("true", true)); 39018235Slinton s->class = CONST; 39118235Slinton s->type = t_boolean; 39218235Slinton s->symvalue.constval = build(O_LCON, 1L); 39318235Slinton s->symvalue.constval->nodetype = t_boolean; 39418235Slinton s = insert(identname("false", true)); 39518235Slinton s->class = CONST; 39618235Slinton s->type = t_boolean; 39718235Slinton s->symvalue.constval = build(O_LCON, 0L); 39818235Slinton s->symvalue.constval->nodetype = t_boolean; 3999657Slinton } 4009657Slinton 4019657Slinton /* 4029657Slinton * Reduce type to avoid worrying about type names. 4039657Slinton */ 4049657Slinton 4059657Slinton public Symbol rtype(type) 4069657Slinton Symbol type; 4079657Slinton { 4089657Slinton register Symbol t; 4099657Slinton 4109657Slinton t = type; 4119657Slinton if (t != nil) { 41218235Slinton if (t->class == VAR or t->class == CONST or 41318235Slinton t->class == FIELD or t->class == REF 41418235Slinton ) { 4159657Slinton t = t->type; 4169657Slinton } 41716620Ssam if (t->class == TYPEREF) { 41816620Ssam resolveRef(t); 41916620Ssam } 4209657Slinton while (t->class == TYPE or t->class == TAG) { 4219657Slinton t = t->type; 42216620Ssam if (t->class == TYPEREF) { 42316620Ssam resolveRef(t); 42416620Ssam } 4259657Slinton } 4269657Slinton } 4279657Slinton return t; 4289657Slinton } 4299657Slinton 43016620Ssam /* 43116620Ssam * Find the end of a module name. Return nil if there is none 43216620Ssam * in the given string. 43316620Ssam */ 43416620Ssam 43516620Ssam private String findModuleMark (s) 43616620Ssam String s; 43716620Ssam { 43816620Ssam register char *p, *r; 43916620Ssam register boolean done; 44016620Ssam 44116620Ssam p = s; 44216620Ssam done = false; 44316620Ssam do { 44416620Ssam if (*p == ':') { 44516620Ssam done = true; 44616620Ssam r = p; 44716620Ssam } else if (*p == '\0') { 44816620Ssam done = true; 44916620Ssam r = nil; 45016620Ssam } else { 45116620Ssam ++p; 45216620Ssam } 45316620Ssam } while (not done); 45416620Ssam return r; 45516620Ssam } 45616620Ssam 45716620Ssam /* 45816620Ssam * Resolve a type reference by modifying to be the appropriate type. 45916620Ssam * 46016620Ssam * If the reference has a name, then it refers to an opaque type and 46116620Ssam * the actual type is directly accessible. Otherwise, we must use 46216620Ssam * the type reference string, which is of the form "module:{module:}name". 46316620Ssam */ 46416620Ssam 46516620Ssam public resolveRef (t) 46616620Ssam Symbol t; 46716620Ssam { 46816620Ssam register char *p; 46916620Ssam char *start; 47016620Ssam Symbol s, m, outer; 47116620Ssam Name n; 47216620Ssam 47316620Ssam if (t->name != nil) { 47416620Ssam s = t; 47516620Ssam } else { 47616620Ssam start = t->symvalue.typeref; 47716620Ssam outer = program; 47816620Ssam p = findModuleMark(start); 47916620Ssam while (p != nil) { 48016620Ssam *p = '\0'; 48116620Ssam n = identname(start, true); 48216620Ssam find(m, n) where m->block == outer endfind(m); 48316620Ssam if (m == nil) { 48416620Ssam p = nil; 48516620Ssam outer = nil; 48616620Ssam s = nil; 48716620Ssam } else { 48816620Ssam outer = m; 48916620Ssam start = p + 1; 49016620Ssam p = findModuleMark(start); 49116620Ssam } 49216620Ssam } 49316620Ssam if (outer != nil) { 49416620Ssam n = identname(start, true); 49516620Ssam find(s, n) where s->block == outer endfind(s); 49616620Ssam } 49716620Ssam } 49816620Ssam if (s != nil and s->type != nil) { 49916620Ssam t->name = s->type->name; 50016620Ssam t->class = s->type->class; 50116620Ssam t->type = s->type->type; 50216620Ssam t->chain = s->type->chain; 50316620Ssam t->symvalue = s->type->symvalue; 50416620Ssam t->block = s->type->block; 50516620Ssam } 50616620Ssam } 50716620Ssam 50818235Slinton public integer regnum (s) 5099657Slinton Symbol s; 5109657Slinton { 51118235Slinton integer r; 51218235Slinton 5139657Slinton checkref(s); 51418235Slinton if (s->level < 0) { 51518235Slinton r = s->symvalue.offset; 51618235Slinton } else { 51718235Slinton r = -1; 51818235Slinton } 51918235Slinton return r; 5209657Slinton } 5219657Slinton 5229657Slinton public Symbol container(s) 5239657Slinton Symbol s; 5249657Slinton { 5259657Slinton checkref(s); 5269657Slinton return s->block; 5279657Slinton } 5289657Slinton 52918235Slinton public Node constval(s) 53018235Slinton Symbol s; 53118235Slinton { 53218235Slinton checkref(s); 53318235Slinton if (s->class != CONST) { 53418235Slinton error("[internal error: constval(non-CONST)]"); 53518235Slinton } 53618235Slinton return s->symvalue.constval; 53718235Slinton } 53818235Slinton 5399657Slinton /* 5409657Slinton * Return the object address of the given symbol. 5419657Slinton * 5429657Slinton * There are the following possibilities: 5439657Slinton * 5449657Slinton * globals - just take offset 5459657Slinton * locals - take offset from locals base 5469657Slinton * arguments - take offset from argument base 5479657Slinton * register - offset is register number 5489657Slinton */ 5499657Slinton 55016620Ssam #define isglobal(s) (s->level == 1) 55116620Ssam #define islocaloff(s) (s->level >= 2 and s->symvalue.offset < 0) 55216620Ssam #define isparamoff(s) (s->level >= 2 and s->symvalue.offset >= 0) 55318235Slinton #define isreg(s) (s->level < 0) 5549657Slinton 55518235Slinton public Address address (s, frame) 5569657Slinton Symbol s; 5579657Slinton Frame frame; 5589657Slinton { 5599657Slinton register Frame frp; 5609657Slinton register Address addr; 5619657Slinton register Symbol cur; 5629657Slinton 5639657Slinton checkref(s); 5649657Slinton if (not isactive(s->block)) { 5659657Slinton error("\"%s\" is not currently defined", symname(s)); 5669657Slinton } else if (isglobal(s)) { 5679657Slinton addr = s->symvalue.offset; 5689657Slinton } else { 5699657Slinton frp = frame; 5709657Slinton if (frp == nil) { 5719657Slinton cur = s->block; 5729657Slinton while (cur != nil and cur->class == MODULE) { 5739657Slinton cur = cur->block; 5749657Slinton } 5759657Slinton if (cur == nil) { 57618235Slinton frp = nil; 57718235Slinton } else { 57818235Slinton frp = findframe(cur); 57918235Slinton if (frp == nil) { 58018235Slinton error("[internal error: unexpected nil frame for \"%s\"]", 58118235Slinton symname(s) 58218235Slinton ); 58318235Slinton } 5849657Slinton } 5859657Slinton } 5869657Slinton if (islocaloff(s)) { 5879657Slinton addr = locals_base(frp) + s->symvalue.offset; 5889657Slinton } else if (isparamoff(s)) { 5899657Slinton addr = args_base(frp) + s->symvalue.offset; 5909657Slinton } else if (isreg(s)) { 5919657Slinton addr = savereg(s->symvalue.offset, frp); 5929657Slinton } else { 5939657Slinton panic("address: bad symbol \"%s\"", symname(s)); 5949657Slinton } 5959657Slinton } 5969657Slinton return addr; 5979657Slinton } 5989657Slinton 5999657Slinton /* 6009657Slinton * Define a symbol used to access register values. 6019657Slinton */ 6029657Slinton 60318235Slinton public defregname (n, r) 6049657Slinton Name n; 60518235Slinton integer r; 6069657Slinton { 60718235Slinton Symbol s; 6089657Slinton 6099657Slinton s = insert(n); 61018235Slinton s->language = t_addr->language; 6119657Slinton s->class = VAR; 6129657Slinton s->level = -3; 61318235Slinton s->type = t_addr; 6149657Slinton s->symvalue.offset = r; 6159657Slinton } 6169657Slinton 6179657Slinton /* 6189657Slinton * Resolve an "abstract" type reference. 6199657Slinton * 6209657Slinton * It is possible in C to define a pointer to a type, but never define 6219657Slinton * the type in a particular source file. Here we try to resolve 6229657Slinton * the type definition. This is problematic, it is possible to 6239657Slinton * have multiple, different definitions for the same name type. 6249657Slinton */ 6259657Slinton 6269657Slinton public findtype(s) 6279657Slinton Symbol s; 6289657Slinton { 6299657Slinton register Symbol t, u, prev; 6309657Slinton 6319657Slinton u = s; 6329657Slinton prev = nil; 6339657Slinton while (u != nil and u->class != BADUSE) { 6349657Slinton if (u->name != nil) { 6359657Slinton prev = u; 6369657Slinton } 6379657Slinton u = u->type; 6389657Slinton } 6399657Slinton if (prev == nil) { 6409657Slinton error("couldn't find link to type reference"); 6419657Slinton } 64218235Slinton t = lookup(prev->name); 64318235Slinton while (t != nil and 64418235Slinton not ( 64518235Slinton t != prev and t->name == prev->name and 64618235Slinton t->block->class == MODULE and t->class == prev->class and 64718235Slinton t->type != nil and t->type->type != nil and 64818235Slinton t->type->type->class != BADUSE 64918235Slinton ) 65018235Slinton ) { 65118235Slinton t = t->next_sym; 65218235Slinton } 6539657Slinton if (t == nil) { 6549657Slinton error("couldn't resolve reference"); 6559657Slinton } else { 6569657Slinton prev->type = t->type; 6579657Slinton } 6589657Slinton } 6599657Slinton 6609657Slinton /* 6619657Slinton * Find the size in bytes of the given type. 6629657Slinton * 6639657Slinton * This is probably the WRONG thing to do. The size should be kept 6649657Slinton * as an attribute in the symbol information as is done for structures 6659657Slinton * and fields. I haven't gotten around to cleaning this up yet. 6669657Slinton */ 6679657Slinton 66812547Scsvaf #define MAXUCHAR 255 66912547Scsvaf #define MAXUSHORT 65535L 6709657Slinton #define MINCHAR -128 6719657Slinton #define MAXCHAR 127 6729657Slinton #define MINSHORT -32768 6739657Slinton #define MAXSHORT 32767 6749657Slinton 67516620Ssam public findbounds (u, lower, upper) 67616620Ssam Symbol u; 67716620Ssam long *lower, *upper; 67816620Ssam { 67916620Ssam Rangetype lbt, ubt; 68016620Ssam long lb, ub; 68116620Ssam 68216620Ssam if (u->class == RANGE) { 68316620Ssam lbt = u->symvalue.rangev.lowertype; 68416620Ssam ubt = u->symvalue.rangev.uppertype; 68516620Ssam lb = u->symvalue.rangev.lower; 68616620Ssam ub = u->symvalue.rangev.upper; 68716620Ssam if (lbt == R_ARG or lbt == R_TEMP) { 68816620Ssam if (not getbound(u, lb, lbt, lower)) { 68916620Ssam error("dynamic bounds not currently available"); 69016620Ssam } 69116620Ssam } else { 69216620Ssam *lower = lb; 69316620Ssam } 69416620Ssam if (ubt == R_ARG or ubt == R_TEMP) { 69516620Ssam if (not getbound(u, ub, ubt, upper)) { 69616620Ssam error("dynamic bounds not currently available"); 69716620Ssam } 69816620Ssam } else { 69916620Ssam *upper = ub; 70016620Ssam } 70116620Ssam } else if (u->class == SCAL) { 70216620Ssam *lower = 0; 70316620Ssam *upper = u->symvalue.iconval - 1; 70416620Ssam } else { 70518235Slinton error("[internal error: unexpected array bound type]"); 70616620Ssam } 70716620Ssam } 70816620Ssam 70916620Ssam public integer size(sym) 71016620Ssam Symbol sym; 71116620Ssam { 71216620Ssam register Symbol s, t, u; 71316620Ssam register integer nel, elsize; 7149657Slinton long lower, upper; 71516620Ssam integer r, off, len; 7169657Slinton 7179657Slinton t = sym; 7189657Slinton checkref(t); 71916620Ssam if (t->class == TYPEREF) { 72016620Ssam resolveRef(t); 72116620Ssam } 7229657Slinton switch (t->class) { 7239657Slinton case RANGE: 7249657Slinton lower = t->symvalue.rangev.lower; 7259657Slinton upper = t->symvalue.rangev.upper; 72616620Ssam if (upper == 0 and lower > 0) { 72716620Ssam /* real */ 7289657Slinton r = lower; 72916620Ssam } else if (lower > upper) { 73016620Ssam /* unsigned long */ 73116620Ssam r = sizeof(long); 73212045Slinton } else if ( 73312547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or 73412547Scsvaf (lower >= 0 and upper <= MAXUCHAR) 73512547Scsvaf ) { 7369657Slinton r = sizeof(char); 73712547Scsvaf } else if ( 73812547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or 73912547Scsvaf (lower >= 0 and upper <= MAXUSHORT) 74012547Scsvaf ) { 7419657Slinton r = sizeof(short); 7429657Slinton } else { 7439657Slinton r = sizeof(long); 7449657Slinton } 7459657Slinton break; 7469657Slinton 7479657Slinton case ARRAY: 7489657Slinton elsize = size(t->type); 7499657Slinton nel = 1; 7509657Slinton for (t = t->chain; t != nil; t = t->chain) { 75116620Ssam u = rtype(t); 75216620Ssam findbounds(u, &lower, &upper); 7539657Slinton nel *= (upper-lower+1); 7549657Slinton } 7559657Slinton r = nel*elsize; 7569657Slinton break; 7579657Slinton 75818235Slinton case DYNARRAY: 75918235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 76018235Slinton break; 76118235Slinton 76218235Slinton case SUBARRAY: 76318235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 76418235Slinton break; 76518235Slinton 76612547Scsvaf case REF: 7679657Slinton case VAR: 7689657Slinton r = size(t->type); 76912127Slinton /* 77012127Slinton * 77112045Slinton if (r < sizeof(Word) and isparam(t)) { 7729657Slinton r = sizeof(Word); 7739657Slinton } 77412547Scsvaf */ 7759657Slinton break; 7769657Slinton 77718235Slinton case FVAR: 7789657Slinton case CONST: 77918235Slinton case TAG: 7809657Slinton r = size(t->type); 7819657Slinton break; 7829657Slinton 7839657Slinton case TYPE: 7849657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 7859657Slinton findtype(t); 7869657Slinton } 7879657Slinton r = size(t->type); 7889657Slinton break; 7899657Slinton 7909657Slinton case FIELD: 79116620Ssam off = t->symvalue.field.offset; 79216620Ssam len = t->symvalue.field.length; 79316620Ssam r = (off + len + 7) div 8 - (off div 8); 7949657Slinton break; 7959657Slinton 7969657Slinton case RECORD: 7979657Slinton case VARNT: 7989657Slinton r = t->symvalue.offset; 7999657Slinton if (r == 0 and t->chain != nil) { 8009657Slinton panic("missing size information for record"); 8019657Slinton } 8029657Slinton break; 8039657Slinton 8049657Slinton case PTR: 80518235Slinton case TYPEREF: 8069657Slinton case FILET: 8079657Slinton r = sizeof(Word); 8089657Slinton break; 8099657Slinton 8109657Slinton case SCAL: 81112609Slinton r = sizeof(Word); 81212609Slinton /* 81312609Slinton * 8149657Slinton if (t->symvalue.iconval > 255) { 8159657Slinton r = sizeof(short); 8169657Slinton } else { 8179657Slinton r = sizeof(char); 8189657Slinton } 81912609Slinton * 82012609Slinton */ 8219657Slinton break; 8229657Slinton 8239657Slinton case FPROC: 8249657Slinton case FFUNC: 8259657Slinton r = sizeof(Word); 8269657Slinton break; 8279657Slinton 8289657Slinton case PROC: 8299657Slinton case FUNC: 8309657Slinton case MODULE: 8319657Slinton case PROG: 8329657Slinton r = sizeof(Symbol); 8339657Slinton break; 8349657Slinton 83516620Ssam case SET: 83616620Ssam u = rtype(t->type); 83716620Ssam switch (u->class) { 83816620Ssam case RANGE: 83916620Ssam r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; 84016620Ssam break; 84116620Ssam 84216620Ssam case SCAL: 84316620Ssam r = u->symvalue.iconval; 84416620Ssam break; 84516620Ssam 84616620Ssam default: 84716620Ssam error("expected range for set base type"); 84816620Ssam break; 84916620Ssam } 85016620Ssam r = (r + BITSPERBYTE - 1) div BITSPERBYTE; 85116620Ssam break; 85216620Ssam 85318235Slinton /* 85418235Slinton * These can happen in C (unfortunately) for unresolved type references 85518235Slinton * Assume they are pointers. 85618235Slinton */ 85718235Slinton case BADUSE: 85818235Slinton r = sizeof(Address); 85918235Slinton break; 86018235Slinton 8619657Slinton default: 8629657Slinton if (ord(t->class) > ord(TYPEREF)) { 8639657Slinton panic("size: bad class (%d)", ord(t->class)); 8649657Slinton } else { 86518235Slinton fprintf(stderr, "can't compute size of a %s\n", classname(t)); 8669657Slinton } 86716620Ssam r = 0; 86816620Ssam break; 8699657Slinton } 8709657Slinton return r; 8719657Slinton } 8729657Slinton 8739657Slinton /* 87418235Slinton * Return the size associated with a symbol that takes into account 87518235Slinton * reference parameters. This might be better as the normal size function, but 87618235Slinton * too many places already depend on it working the way it does. 87718235Slinton */ 87818235Slinton 87918235Slinton public integer psize (s) 88018235Slinton Symbol s; 88118235Slinton { 88218235Slinton integer r; 88318235Slinton Symbol t; 88418235Slinton 88518235Slinton if (s->class == REF) { 88618235Slinton t = rtype(s->type); 88718235Slinton if (t->class == DYNARRAY) { 88818235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 88918235Slinton } else if (t->class == SUBARRAY) { 89018235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 89118235Slinton } else { 89218235Slinton r = sizeof(Word); 89318235Slinton } 89418235Slinton } else { 89518235Slinton r = size(s); 89618235Slinton } 89718235Slinton return r; 89818235Slinton } 89918235Slinton 90018235Slinton /* 9019657Slinton * Test if a symbol is a parameter. This is true if there 9029657Slinton * is a cycle from s->block to s via chain pointers. 9039657Slinton */ 9049657Slinton 9059657Slinton public Boolean isparam(s) 9069657Slinton Symbol s; 9079657Slinton { 9089657Slinton register Symbol t; 9099657Slinton 9109657Slinton t = s->block; 9119657Slinton while (t != nil and t != s) { 9129657Slinton t = t->chain; 9139657Slinton } 9149657Slinton return (Boolean) (t != nil); 9159657Slinton } 9169657Slinton 9179657Slinton /* 91816620Ssam * Test if a type is an open array parameter type. 9199657Slinton */ 9209657Slinton 92118235Slinton public boolean isopenarray (type) 92218235Slinton Symbol type; 92316620Ssam { 92418235Slinton Symbol t; 92518235Slinton 92618235Slinton t = rtype(type); 92718235Slinton return (boolean) (t->class == DYNARRAY); 92816620Ssam } 92916620Ssam 93016620Ssam /* 93118235Slinton * Test if a symbol is a var parameter, i.e. has class REF. 93216620Ssam */ 93316620Ssam 9349657Slinton public Boolean isvarparam(s) 9359657Slinton Symbol s; 9369657Slinton { 9379657Slinton return (Boolean) (s->class == REF); 9389657Slinton } 9399657Slinton 9409657Slinton /* 9419657Slinton * Test if a symbol is a variable (actually any addressible quantity 9429657Slinton * with do). 9439657Slinton */ 9449657Slinton 9459657Slinton public Boolean isvariable(s) 94618235Slinton Symbol s; 9479657Slinton { 9489657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 9499657Slinton } 9509657Slinton 9519657Slinton /* 95218235Slinton * Test if a symbol is a constant. 95318235Slinton */ 95418235Slinton 95518235Slinton public Boolean isconst(s) 95618235Slinton Symbol s; 9579657Slinton { 95818235Slinton return (Boolean) (s->class == CONST); 9599657Slinton } 9609657Slinton 9619657Slinton /* 9629657Slinton * Test if a symbol is a module. 9639657Slinton */ 9649657Slinton 9659657Slinton public Boolean ismodule(s) 9669657Slinton register Symbol s; 9679657Slinton { 9689657Slinton return (Boolean) (s->class == MODULE); 9699657Slinton } 9709657Slinton 9719657Slinton /* 97216620Ssam * Mark a procedure or function as internal, meaning that it is called 97316620Ssam * with a different calling sequence. 97416620Ssam */ 97516620Ssam 97616620Ssam public markInternal (s) 97716620Ssam Symbol s; 97816620Ssam { 97916620Ssam s->symvalue.funcv.intern = true; 98016620Ssam } 98116620Ssam 98216620Ssam public boolean isinternal (s) 98316620Ssam Symbol s; 98416620Ssam { 98516620Ssam return s->symvalue.funcv.intern; 98616620Ssam } 98716620Ssam 98816620Ssam /* 98918235Slinton * Decide if a field begins or ends on a bit rather than byte boundary. 99018235Slinton */ 99118235Slinton 99218235Slinton public Boolean isbitfield(s) 99318235Slinton register Symbol s; 99418235Slinton { 99518235Slinton boolean b; 99618235Slinton register integer off, len; 99718235Slinton register Symbol t; 99818235Slinton 99918235Slinton off = s->symvalue.field.offset; 100018235Slinton len = s->symvalue.field.length; 100118235Slinton if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { 100218235Slinton b = true; 100318235Slinton } else { 100418235Slinton t = rtype(s->type); 100518235Slinton b = (Boolean) ( 100618235Slinton (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or 100718235Slinton len != (size(t)*BITSPERBYTE) 100818235Slinton ); 100918235Slinton } 101018235Slinton return b; 101118235Slinton } 101218235Slinton 101318235Slinton private boolean primlang_typematch (t1, t2) 101418235Slinton Symbol t1, t2; 101518235Slinton { 101618235Slinton return (boolean) ( 101718235Slinton (t1 == t2) or 101818235Slinton ( 101918235Slinton t1->class == RANGE and t2->class == RANGE and 102018235Slinton t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 102118235Slinton t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 102218235Slinton ) or ( 102318235Slinton t1->class == PTR and t2->class == RANGE and 102418235Slinton t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower 102518235Slinton ) or ( 102618235Slinton t2->class == PTR and t1->class == RANGE and 102718235Slinton t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower 102818235Slinton ) 102918235Slinton ); 103018235Slinton } 103118235Slinton 103218235Slinton /* 10339657Slinton * Test if two types match. 10349657Slinton * Equivalent names implies a match in any language. 10359657Slinton * 10369657Slinton * Special symbols must be handled with care. 10379657Slinton */ 10389657Slinton 10399657Slinton public Boolean compatible(t1, t2) 10409657Slinton register Symbol t1, t2; 10419657Slinton { 10429657Slinton Boolean b; 104316620Ssam Symbol rt1, rt2; 10449657Slinton 10459657Slinton if (t1 == t2) { 10469657Slinton b = true; 10479657Slinton } else if (t1 == nil or t2 == nil) { 10489657Slinton b = false; 10499657Slinton } else if (t1 == procsym) { 10509657Slinton b = isblock(t2); 10519657Slinton } else if (t2 == procsym) { 10529657Slinton b = isblock(t1); 105316620Ssam } else if (t1->language == primlang) { 105416620Ssam if (t2->language == primlang) { 105518235Slinton b = primlang_typematch(rtype(t1), rtype(t2)); 105616620Ssam } else { 105716620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 105816620Ssam } 105916620Ssam } else if (t2->language == primlang) { 106016620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 10619657Slinton } else if (t1->language == nil) { 106216620Ssam if (t2->language == nil) { 106316620Ssam b = false; 106416620Ssam } else { 106516620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 106616620Ssam } 10679657Slinton } else { 106816620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 10699657Slinton } 10709657Slinton return b; 10719657Slinton } 10729657Slinton 10739657Slinton /* 10749657Slinton * Check for a type of the given name. 10759657Slinton */ 10769657Slinton 10779657Slinton public Boolean istypename(type, name) 10789657Slinton Symbol type; 10799657Slinton String name; 10809657Slinton { 108118235Slinton register Symbol t; 10829657Slinton Boolean b; 10839657Slinton 10849657Slinton t = type; 108518235Slinton if (t == nil) { 108618235Slinton b = false; 108718235Slinton } else { 108818235Slinton b = (Boolean) ( 108918235Slinton t->class == TYPE and streq(ident(t->name), name) 109018235Slinton ); 109118235Slinton } 10929657Slinton return b; 10939657Slinton } 10949657Slinton 10959657Slinton /* 109616620Ssam * Determine if a (value) parameter should actually be passed by address. 109716620Ssam */ 109816620Ssam 109916620Ssam public boolean passaddr (p, exprtype) 110016620Ssam Symbol p, exprtype; 110116620Ssam { 110216620Ssam boolean b; 110316620Ssam Language def; 110416620Ssam 110516620Ssam if (p == nil) { 110616620Ssam def = findlanguage(".c"); 110716620Ssam b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); 110816620Ssam } else if (p->language == nil or p->language == primlang) { 110916620Ssam b = false; 111016620Ssam } else if (isopenarray(p->type)) { 111116620Ssam b = true; 111216620Ssam } else { 111316620Ssam b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); 111416620Ssam } 111516620Ssam return b; 111616620Ssam } 111716620Ssam 111816620Ssam /* 11199657Slinton * Test if the name of a symbol is uniquely defined or not. 11209657Slinton */ 11219657Slinton 11229657Slinton public Boolean isambiguous(s) 11239657Slinton register Symbol s; 11249657Slinton { 11259657Slinton register Symbol t; 11269657Slinton 11279657Slinton find(t, s->name) where t != s endfind(t); 11289657Slinton return (Boolean) (t != nil); 11299657Slinton } 11309657Slinton 11319657Slinton typedef char *Arglist; 11329657Slinton 11339657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 11349657Slinton 11359657Slinton private Symbol mkstring(); 11369657Slinton 11379657Slinton /* 11389657Slinton * Determine the type of a parse tree. 113918235Slinton * 11409657Slinton * Also make some symbol-dependent changes to the tree such as 114118235Slinton * removing indirection for constant or register symbols. 11429657Slinton */ 11439657Slinton 114418235Slinton public assigntypes (p) 11459657Slinton register Node p; 11469657Slinton { 11479657Slinton register Node p1; 11489657Slinton register Symbol s; 11499657Slinton 11509657Slinton switch (p->op) { 11519657Slinton case O_SYM: 115218235Slinton p->nodetype = p->value.sym; 11539657Slinton break; 11549657Slinton 11559657Slinton case O_LCON: 11569657Slinton p->nodetype = t_int; 11579657Slinton break; 11589657Slinton 115918235Slinton case O_CCON: 116018235Slinton p->nodetype = t_char; 116118235Slinton break; 116218235Slinton 11639657Slinton case O_FCON: 11649657Slinton p->nodetype = t_real; 11659657Slinton break; 11669657Slinton 11679657Slinton case O_SCON: 116818235Slinton p->nodetype = mkstring(p->value.scon); 11699657Slinton break; 11709657Slinton 11719657Slinton case O_INDIR: 11729657Slinton p1 = p->value.arg[0]; 117318235Slinton s = rtype(p1->nodetype); 117418235Slinton if (s->class != PTR) { 117518235Slinton beginerrmsg(); 117618235Slinton fprintf(stderr, "\""); 117718235Slinton prtree(stderr, p1); 117818235Slinton fprintf(stderr, "\" is not a pointer"); 117918235Slinton enderrmsg(); 118018235Slinton } 11819657Slinton p->nodetype = rtype(p1->nodetype)->type; 11829657Slinton break; 11839657Slinton 11849657Slinton case O_DOT: 11859657Slinton p->nodetype = p->value.arg[1]->value.sym; 11869657Slinton break; 11879657Slinton 11889657Slinton case O_RVAL: 11899657Slinton p1 = p->value.arg[0]; 11909657Slinton p->nodetype = p1->nodetype; 11919657Slinton if (p1->op == O_SYM) { 119218235Slinton if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) { 119318235Slinton p->op = p1->op; 119418235Slinton p->value.sym = p1->value.sym; 119518235Slinton p->nodetype = p1->nodetype; 119618235Slinton dispose(p1); 11979657Slinton } else if (p1->value.sym->class == CONST) { 119818235Slinton p->op = p1->op; 119918235Slinton p->value = p1->value; 120018235Slinton p->nodetype = p1->nodetype; 120118235Slinton dispose(p1); 12029657Slinton } else if (isreg(p1->value.sym)) { 12039657Slinton p->op = O_SYM; 12049657Slinton p->value.sym = p1->value.sym; 12059657Slinton dispose(p1); 12069657Slinton } 12079657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 12089657Slinton s = p1->value.arg[0]->value.sym; 12099657Slinton if (isreg(s)) { 12109657Slinton p1->op = O_SYM; 12119657Slinton dispose(p1->value.arg[0]); 12129657Slinton p1->value.sym = s; 12139657Slinton p1->nodetype = s; 12149657Slinton } 12159657Slinton } 12169657Slinton break; 12179657Slinton 121818235Slinton case O_COMMA: 121918235Slinton p->nodetype = p->value.arg[0]->nodetype; 122018235Slinton break; 122118235Slinton 122218235Slinton case O_CALLPROC: 12239657Slinton case O_CALL: 12249657Slinton p1 = p->value.arg[0]; 122511171Slinton p->nodetype = rtype(p1->nodetype)->type; 12269657Slinton break; 12279657Slinton 122811171Slinton case O_TYPERENAME: 122911171Slinton p->nodetype = p->value.arg[1]->nodetype; 123011171Slinton break; 123111171Slinton 12329657Slinton case O_ITOF: 12339657Slinton p->nodetype = t_real; 12349657Slinton break; 12359657Slinton 12369657Slinton case O_NEG: 12379657Slinton s = p->value.arg[0]->nodetype; 12389657Slinton if (not compatible(s, t_int)) { 12399657Slinton if (not compatible(s, t_real)) { 12409657Slinton beginerrmsg(); 124116620Ssam fprintf(stderr, "\""); 12429657Slinton prtree(stderr, p->value.arg[0]); 124316620Ssam fprintf(stderr, "\" is improper type"); 12449657Slinton enderrmsg(); 12459657Slinton } else { 12469657Slinton p->op = O_NEGF; 12479657Slinton } 12489657Slinton } 12499657Slinton p->nodetype = s; 12509657Slinton break; 12519657Slinton 12529657Slinton case O_ADD: 12539657Slinton case O_SUB: 12549657Slinton case O_MUL: 125516620Ssam binaryop(p, nil); 125616620Ssam break; 125716620Ssam 12589657Slinton case O_LT: 12599657Slinton case O_LE: 12609657Slinton case O_GT: 12619657Slinton case O_GE: 12629657Slinton case O_EQ: 12639657Slinton case O_NE: 126416620Ssam binaryop(p, t_boolean); 12659657Slinton break; 12669657Slinton 12679657Slinton case O_DIVF: 12689657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 12699657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 12709657Slinton p->nodetype = t_real; 12719657Slinton break; 12729657Slinton 12739657Slinton case O_DIV: 12749657Slinton case O_MOD: 12759657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 12769657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 12779657Slinton p->nodetype = t_int; 12789657Slinton break; 12799657Slinton 12809657Slinton case O_AND: 12819657Slinton case O_OR: 12829657Slinton chkboolean(p->value.arg[0]); 12839657Slinton chkboolean(p->value.arg[1]); 12849657Slinton p->nodetype = t_boolean; 12859657Slinton break; 12869657Slinton 12879657Slinton case O_QLINE: 12889657Slinton p->nodetype = t_int; 12899657Slinton break; 12909657Slinton 12919657Slinton default: 12929657Slinton p->nodetype = nil; 12939657Slinton break; 12949657Slinton } 12959657Slinton } 12969657Slinton 12979657Slinton /* 129816620Ssam * Process a binary arithmetic or relational operator. 129916620Ssam * Convert from integer to real if necessary. 130016620Ssam */ 130116620Ssam 130216620Ssam private binaryop (p, t) 130316620Ssam Node p; 130416620Ssam Symbol t; 130516620Ssam { 130616620Ssam Node p1, p2; 130716620Ssam Boolean t1real, t2real; 130816620Ssam Symbol t1, t2; 130916620Ssam 131016620Ssam p1 = p->value.arg[0]; 131116620Ssam p2 = p->value.arg[1]; 131216620Ssam t1 = rtype(p1->nodetype); 131316620Ssam t2 = rtype(p2->nodetype); 131416620Ssam t1real = compatible(t1, t_real); 131516620Ssam t2real = compatible(t2, t_real); 131616620Ssam if (t1real or t2real) { 131716620Ssam p->op = (Operator) (ord(p->op) + 1); 131816620Ssam if (not t1real) { 131916620Ssam p->value.arg[0] = build(O_ITOF, p1); 132016620Ssam } else if (not t2real) { 132116620Ssam p->value.arg[1] = build(O_ITOF, p2); 132216620Ssam } 132316620Ssam p->nodetype = t_real; 132416620Ssam } else { 132516620Ssam if (size(p1->nodetype) > sizeof(integer)) { 132616620Ssam beginerrmsg(); 132716620Ssam fprintf(stderr, "operation not defined on \""); 132816620Ssam prtree(stderr, p1); 132916620Ssam fprintf(stderr, "\""); 133016620Ssam enderrmsg(); 133116620Ssam } else if (size(p2->nodetype) > sizeof(integer)) { 133216620Ssam beginerrmsg(); 133316620Ssam fprintf(stderr, "operation not defined on \""); 133416620Ssam prtree(stderr, p2); 133516620Ssam fprintf(stderr, "\""); 133616620Ssam enderrmsg(); 133716620Ssam } 133816620Ssam p->nodetype = t_int; 133916620Ssam } 134016620Ssam if (t != nil) { 134116620Ssam p->nodetype = t; 134216620Ssam } 134316620Ssam } 134416620Ssam 134516620Ssam /* 13469657Slinton * Convert a tree to a type via a conversion operator; 13479657Slinton * if this isn't possible generate an error. 13489657Slinton * 13499657Slinton * Note the tree is call by address, hence the #define below. 13509657Slinton */ 13519657Slinton 13529657Slinton private convert(tp, typeto, op) 13539657Slinton Node *tp; 13549657Slinton Symbol typeto; 13559657Slinton Operator op; 13569657Slinton { 135716620Ssam Node tree; 135816620Ssam Symbol s, t; 13599657Slinton 136016620Ssam tree = *tp; 13619657Slinton s = rtype(tree->nodetype); 136216620Ssam t = rtype(typeto); 136316620Ssam if (compatible(t, t_real) and compatible(s, t_int)) { 13649657Slinton tree = build(op, tree); 136516620Ssam } else if (not compatible(s, t)) { 13669657Slinton beginerrmsg(); 136716620Ssam fprintf(stderr, "expected integer or real, found \""); 136816620Ssam prtree(stderr, tree); 136916620Ssam fprintf(stderr, "\""); 13709657Slinton enderrmsg(); 137116620Ssam } else if (op != O_NOP and s != t) { 13729657Slinton tree = build(op, tree); 13739657Slinton } 137416620Ssam *tp = tree; 13759657Slinton } 13769657Slinton 13779657Slinton /* 13789657Slinton * Construct a node for the dot operator. 13799657Slinton * 13809657Slinton * If the left operand is not a record, but rather a procedure 13819657Slinton * or function, then we interpret the "." as referencing an 13829657Slinton * "invisible" variable; i.e. a variable within a dynamically 13839657Slinton * active block but not within the static scope of the current procedure. 13849657Slinton */ 13859657Slinton 13869657Slinton public Node dot(record, fieldname) 13879657Slinton Node record; 13889657Slinton Name fieldname; 13899657Slinton { 139018235Slinton register Node rec, p; 13919657Slinton register Symbol s, t; 13929657Slinton 139318235Slinton rec = record; 139418235Slinton if (isblock(rec->nodetype)) { 13959657Slinton find(s, fieldname) where 139618235Slinton s->block == rec->nodetype and 139718235Slinton s->class != FIELD 13989657Slinton endfind(s); 13999657Slinton if (s == nil) { 14009657Slinton beginerrmsg(); 14019657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 140218235Slinton printname(stderr, rec->nodetype); 14039657Slinton enderrmsg(); 14049657Slinton } 14059657Slinton p = new(Node); 14069657Slinton p->op = O_SYM; 14079657Slinton p->value.sym = s; 140818235Slinton p->nodetype = s; 14099657Slinton } else { 141018235Slinton p = rec; 14119657Slinton t = rtype(p->nodetype); 14129657Slinton if (t->class == PTR) { 14139657Slinton s = findfield(fieldname, t->type); 14149657Slinton } else { 14159657Slinton s = findfield(fieldname, t); 14169657Slinton } 14179657Slinton if (s == nil) { 14189657Slinton beginerrmsg(); 14199657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 142018235Slinton prtree(stderr, rec); 14219657Slinton enderrmsg(); 14229657Slinton } 142318235Slinton if (t->class != PTR or isreg(rec->nodetype)) { 142418235Slinton p = unrval(p); 14259657Slinton } 142618235Slinton p->nodetype = t_addr; 14279657Slinton p = build(O_DOT, p, build(O_SYM, s)); 14289657Slinton } 142918235Slinton return build(O_RVAL, p); 14309657Slinton } 14319657Slinton 14329657Slinton /* 14339657Slinton * Return a tree corresponding to an array reference and do the 14349657Slinton * error checking. 14359657Slinton */ 14369657Slinton 14379657Slinton public Node subscript(a, slist) 14389657Slinton Node a, slist; 14399657Slinton { 144016620Ssam Symbol t; 144118235Slinton Node p; 14429657Slinton 144316620Ssam t = rtype(a->nodetype); 144418235Slinton if (t->language == nil or t->language == primlang) { 144518235Slinton p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); 144616620Ssam } else { 144718235Slinton p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); 144816620Ssam } 144918235Slinton return build(O_RVAL, p); 14509657Slinton } 14519657Slinton 14529657Slinton /* 14539657Slinton * Evaluate a subscript index. 14549657Slinton */ 14559657Slinton 145618235Slinton public int evalindex(s, base, i) 14579657Slinton Symbol s; 145818235Slinton Address base; 14599657Slinton long i; 14609657Slinton { 146116620Ssam Symbol t; 146218235Slinton int r; 14639657Slinton 146416620Ssam t = rtype(s); 146518235Slinton if (t->language == nil or t->language == primlang) { 146618235Slinton r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); 146716620Ssam } else { 146818235Slinton r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); 146916620Ssam } 147018235Slinton return r; 14719657Slinton } 14729657Slinton 14739657Slinton /* 14749657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 14759657Slinton */ 14769657Slinton 14779657Slinton public chkboolean(p) 14789657Slinton register Node p; 14799657Slinton { 14809657Slinton if (p->nodetype != t_boolean) { 14819657Slinton beginerrmsg(); 14829657Slinton fprintf(stderr, "found "); 14839657Slinton prtree(stderr, p); 14849657Slinton fprintf(stderr, ", expected boolean expression"); 14859657Slinton enderrmsg(); 14869657Slinton } 14879657Slinton } 14889657Slinton 14899657Slinton /* 149016620Ssam * Construct a node for the type of a string. 14919657Slinton */ 14929657Slinton 14939657Slinton private Symbol mkstring(str) 14949657Slinton String str; 14959657Slinton { 14969657Slinton register Symbol s; 14979657Slinton 149818235Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 149918235Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 150018235Slinton s->chain->language = s->language; 150118235Slinton s->chain->symvalue.rangev.lower = 1; 150218235Slinton s->chain->symvalue.rangev.upper = strlen(str) + 1; 15039657Slinton return s; 15049657Slinton } 15059657Slinton 15069657Slinton /* 15079657Slinton * Free up the space allocated for a string type. 15089657Slinton */ 15099657Slinton 15109657Slinton public unmkstring(s) 15119657Slinton Symbol s; 15129657Slinton { 15139657Slinton dispose(s->chain); 15149657Slinton } 15159657Slinton 15169657Slinton /* 151718235Slinton * Figure out the "current" variable or function being referred to 151818235Slinton * by the name n. 15199657Slinton */ 15209657Slinton 152118235Slinton private boolean stwhich(), dynwhich(); 152218235Slinton 152318235Slinton public Symbol which (n) 15249657Slinton Name n; 15259657Slinton { 152618235Slinton Symbol s; 15279657Slinton 152818235Slinton s = lookup(n); 15299657Slinton if (s == nil) { 153018235Slinton error("\"%s\" is not defined", ident(n)); 153118235Slinton } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { 153218235Slinton printf("[using "); 153318235Slinton printname(stdout, s); 153418235Slinton printf("]\n"); 15359657Slinton } 153618235Slinton return s; 153718235Slinton } 153818235Slinton 153918235Slinton /* 154018235Slinton * Static search. 154118235Slinton */ 154218235Slinton 154318235Slinton private boolean stwhich (var_s) 154418235Slinton Symbol *var_s; 154518235Slinton { 154618235Slinton Name n; /* name of desired symbol */ 154718235Slinton Symbol s; /* iteration variable for symbols with name n */ 154818235Slinton Symbol f; /* iteration variable for blocks containing s */ 154918235Slinton integer count; /* number of levels from s->block to curfunc */ 155018235Slinton Symbol t; /* current best answer for stwhich(n) */ 155118235Slinton integer mincount; /* relative level for current best answer (t) */ 155218235Slinton boolean b; /* return value, true if symbol found */ 155318235Slinton 155418235Slinton s = *var_s; 155518235Slinton n = s->name; 155618235Slinton t = s; 155718235Slinton mincount = 10000; /* force first match to set mincount */ 155818235Slinton do { 155918235Slinton if (s->name == n and s->class != FIELD and s->class != TAG) { 156018235Slinton f = curfunc; 156118235Slinton count = 0; 156218235Slinton while (f != nil and f != s->block) { 156318235Slinton ++count; 156418235Slinton f = f->block; 156518235Slinton } 156618235Slinton if (f != nil and count < mincount) { 156718235Slinton t = s; 156818235Slinton mincount = count; 156918235Slinton b = true; 157018235Slinton } 157118235Slinton } 157218235Slinton s = s->next_sym; 157318235Slinton } while (s != nil); 157418235Slinton if (mincount != 10000) { 157518235Slinton *var_s = t; 157618235Slinton b = true; 15779657Slinton } else { 157818235Slinton b = false; 157918235Slinton } 158018235Slinton return b; 158118235Slinton } 158218235Slinton 158318235Slinton /* 158418235Slinton * Dynamic search. 158518235Slinton */ 158618235Slinton 158718235Slinton private boolean dynwhich (var_s) 158818235Slinton Symbol *var_s; 158918235Slinton { 159018235Slinton Name n; /* name of desired symbol */ 159118235Slinton Symbol s; /* iteration variable for possible symbols */ 159218235Slinton Symbol f; /* iteration variable for active functions */ 159318235Slinton Frame frp; /* frame associated with stack walk */ 159418235Slinton boolean b; /* return value */ 159518235Slinton 159618235Slinton f = curfunc; 159718235Slinton frp = curfuncframe(); 159818235Slinton n = (*var_s)->name; 159918235Slinton b = false; 160018235Slinton if (frp != nil) { 160118235Slinton frp = nextfunc(frp, &f); 160218235Slinton while (frp != nil) { 160318235Slinton s = *var_s; 160418235Slinton while (s != nil and 160518235Slinton ( 160618235Slinton s->name != n or s->block != f or 160718235Slinton s->class == FIELD or s->class == TAG 160818235Slinton ) 160918235Slinton ) { 161018235Slinton s = s->next_sym; 161118235Slinton } 161218235Slinton if (s != nil) { 161318235Slinton *var_s = s; 161418235Slinton b = true; 161518235Slinton break; 161618235Slinton } 161718235Slinton if (f == program) { 161818235Slinton break; 161918235Slinton } 162018235Slinton frp = nextfunc(frp, &f); 16219657Slinton } 16229657Slinton } 162318235Slinton return b; 16249657Slinton } 16259657Slinton 16269657Slinton /* 162718235Slinton * Find the symbol that has the same name and scope as the 16289657Slinton * given symbol but is of the given field. Return nil if there is none. 16299657Slinton */ 16309657Slinton 163118235Slinton public Symbol findfield (fieldname, record) 16329657Slinton Name fieldname; 16339657Slinton Symbol record; 16349657Slinton { 16359657Slinton register Symbol t; 16369657Slinton 16379657Slinton t = rtype(record)->chain; 16389657Slinton while (t != nil and t->name != fieldname) { 16399657Slinton t = t->chain; 16409657Slinton } 16419657Slinton return t; 16429657Slinton } 164312547Scsvaf 164412547Scsvaf public Boolean getbound(s,off,type,valp) 164512547Scsvaf Symbol s; 164612547Scsvaf int off; 164712547Scsvaf Rangetype type; 164812547Scsvaf int *valp; 164912547Scsvaf { 165012547Scsvaf Frame frp; 165112547Scsvaf Address addr; 165212547Scsvaf Symbol cur; 165312547Scsvaf 165412547Scsvaf if (not isactive(s->block)) { 165512547Scsvaf return(false); 165612547Scsvaf } 165712547Scsvaf cur = s->block; 165812547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 165912547Scsvaf cur = cur->block; 166012547Scsvaf } 166112547Scsvaf if(cur == nil) { 166212547Scsvaf cur = whatblock(pc); 166312547Scsvaf } 166412547Scsvaf frp = findframe(cur); 166512547Scsvaf if (frp == nil) { 166612547Scsvaf return(false); 166712547Scsvaf } 166812547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 166912547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 167012547Scsvaf else return(false); 167112547Scsvaf dread(valp,addr,sizeof(long)); 167212547Scsvaf return(true); 167312547Scsvaf } 1674