19657Slinton /* Copyright (c) 1982 Regents of the University of California */ 29657Slinton 3*18235Slinton static char sccsid[] = "@(#)symbols.c 1.17 (Berkeley) 03/01/85"; 49657Slinton 5*18235Slinton static char rcsid[] = "$Header: symbols.c,v 1.6 84/12/26 10:42:31 linton Exp $"; 6*18235Slinton 79657Slinton /* 89657Slinton * Symbol management. 99657Slinton */ 109657Slinton 119657Slinton #include "defs.h" 129657Slinton #include "symbols.h" 139657Slinton #include "languages.h" 149657Slinton #include "printsym.h" 159657Slinton #include "tree.h" 169657Slinton #include "operators.h" 179657Slinton #include "eval.h" 189657Slinton #include "mappings.h" 199657Slinton #include "events.h" 209657Slinton #include "process.h" 219657Slinton #include "runtime.h" 229657Slinton #include "machine.h" 239657Slinton #include "names.h" 249657Slinton 259657Slinton #ifndef public 269657Slinton typedef struct Symbol *Symbol; 279657Slinton 289657Slinton #include "machine.h" 299657Slinton #include "names.h" 309657Slinton #include "languages.h" 31*18235Slinton #include "tree.h" 329657Slinton 339657Slinton /* 349657Slinton * Symbol classes 359657Slinton */ 369657Slinton 379657Slinton typedef enum { 38*18235Slinton BADUSE, CONST, TYPE, VAR, ARRAY, DYNARRAY, SUBARRAY, PTRFILE, RECORD, FIELD, 3912547Scsvaf PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 409657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 4116620Ssam FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF 429657Slinton } Symclass; 439657Slinton 4412547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 4512547Scsvaf 469657Slinton struct Symbol { 479657Slinton Name name; 489657Slinton Language language; 499657Slinton Symclass class : 8; 509657Slinton Integer level : 8; 519657Slinton Symbol type; 529657Slinton Symbol chain; 539657Slinton union { 54*18235Slinton Node constval; /* value of constant symbol */ 559657Slinton int offset; /* variable address */ 569657Slinton long iconval; /* integer constant value */ 579657Slinton double fconval; /* floating constant value */ 58*18235Slinton int ndims; /* no. of dimensions for dynamic/sub-arrays */ 599657Slinton struct { /* field offset and size (both in bits) */ 609657Slinton int offset; 619657Slinton int length; 629657Slinton } field; 6312547Scsvaf struct { /* common offset and chain; used to relocate */ 6412547Scsvaf int offset; /* vars in global BSS */ 6512547Scsvaf Symbol chain; 6612547Scsvaf } common; 679657Slinton struct { /* range bounds */ 6812547Scsvaf Rangetype lowertype : 16; 6912547Scsvaf Rangetype uppertype : 16; 709657Slinton long lower; 719657Slinton long upper; 729657Slinton } rangev; 7311865Slinton struct { 7411865Slinton int offset : 16; /* offset for of function value */ 7516620Ssam Boolean src : 1; /* true if there is source line info */ 7616620Ssam Boolean inline : 1; /* true if no separate act. rec. */ 7716620Ssam Boolean intern : 1; /* internal calling sequence */ 7816620Ssam int unused : 13; 7911865Slinton Address beginaddr; /* address of function code */ 809657Slinton } funcv; 819657Slinton struct { /* variant record info */ 829657Slinton int size; 839657Slinton Symbol vtorec; 849657Slinton Symbol vtag; 859657Slinton } varnt; 8616620Ssam String typeref; /* type defined by "<module>:<type>" */ 8716620Ssam Symbol extref; /* indirect symbol for external reference */ 889657Slinton } symvalue; 899657Slinton Symbol block; /* symbol containing this symbol */ 909657Slinton Symbol next_sym; /* hash chain */ 919657Slinton }; 929657Slinton 939657Slinton /* 949657Slinton * Basic types. 959657Slinton */ 969657Slinton 979657Slinton Symbol t_boolean; 989657Slinton Symbol t_char; 999657Slinton Symbol t_int; 1009657Slinton Symbol t_real; 1019657Slinton Symbol t_nil; 102*18235Slinton Symbol t_addr; 1039657Slinton 1049657Slinton Symbol program; 1059657Slinton Symbol curfunc; 1069657Slinton 107*18235Slinton boolean showaggrs; 108*18235Slinton 1099657Slinton #define symname(s) ident(s->name) 1109657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 1119657Slinton #define isblock(s) (Boolean) ( \ 1129657Slinton s->class == FUNC or s->class == PROC or \ 1139657Slinton s->class == MODULE or s->class == PROG \ 1149657Slinton ) 11516620Ssam #define isroutine(s) (Boolean) ( \ 11616620Ssam s->class == FUNC or s->class == PROC \ 11716620Ssam ) 1189657Slinton 11911865Slinton #define nosource(f) (not (f)->symvalue.funcv.src) 12014441Slinton #define isinline(f) ((f)->symvalue.funcv.inline) 12111865Slinton 1229657Slinton #include "tree.h" 1239657Slinton 1249657Slinton /* 1259657Slinton * Some macros to make finding a symbol with certain attributes. 1269657Slinton */ 1279657Slinton 1289657Slinton #define find(s, withname) \ 1299657Slinton { \ 1309657Slinton s = lookup(withname); \ 1319657Slinton while (s != nil and not (s->name == (withname) and 1329657Slinton 1339657Slinton #define where /* qualification */ 1349657Slinton 1359657Slinton #define endfind(s) )) { \ 1369657Slinton s = s->next_sym; \ 1379657Slinton } \ 1389657Slinton } 1399657Slinton 1409657Slinton #endif 1419657Slinton 1429657Slinton /* 1439657Slinton * Symbol table structure currently does not support deletions. 1449657Slinton */ 1459657Slinton 1469657Slinton #define HASHTABLESIZE 2003 1479657Slinton 1489657Slinton private Symbol hashtab[HASHTABLESIZE]; 1499657Slinton 1509657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 1519657Slinton 1529657Slinton /* 1539657Slinton * Allocate a new symbol. 1549657Slinton */ 1559657Slinton 15611171Slinton #define SYMBLOCKSIZE 100 1579657Slinton 1589657Slinton typedef struct Sympool { 1599657Slinton struct Symbol sym[SYMBLOCKSIZE]; 1609657Slinton struct Sympool *prevpool; 1619657Slinton } *Sympool; 1629657Slinton 1639657Slinton private Sympool sympool = nil; 1649657Slinton private Integer nleft = 0; 1659657Slinton 1669657Slinton public Symbol symbol_alloc() 1679657Slinton { 1689657Slinton register Sympool newpool; 1699657Slinton 1709657Slinton if (nleft <= 0) { 1719657Slinton newpool = new(Sympool); 17211171Slinton bzero(newpool, sizeof(newpool)); 1739657Slinton newpool->prevpool = sympool; 1749657Slinton sympool = newpool; 1759657Slinton nleft = SYMBLOCKSIZE; 1769657Slinton } 1779657Slinton --nleft; 1789657Slinton return &(sympool->sym[nleft]); 1799657Slinton } 1809657Slinton 181*18235Slinton public symbol_dump (func) 18212547Scsvaf Symbol func; 18312547Scsvaf { 184*18235Slinton register Symbol s; 185*18235Slinton register integer i; 18612547Scsvaf 187*18235Slinton printf(" symbols in %s \n",symname(func)); 188*18235Slinton for (i = 0; i < HASHTABLESIZE; i++) { 189*18235Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 190*18235Slinton if (s->block == func) { 191*18235Slinton psym(s); 192*18235Slinton } 193*18235Slinton } 194*18235Slinton } 19512547Scsvaf } 19612547Scsvaf 1979657Slinton /* 1989657Slinton * Free all the symbols currently allocated. 1999657Slinton */ 200*18235Slinton 2019657Slinton public symbol_free() 2029657Slinton { 2039657Slinton Sympool s, t; 2049657Slinton register Integer i; 2059657Slinton 2069657Slinton s = sympool; 2079657Slinton while (s != nil) { 2089657Slinton t = s->prevpool; 2099657Slinton dispose(s); 2109657Slinton s = t; 2119657Slinton } 2129657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 2139657Slinton hashtab[i] = nil; 2149657Slinton } 2159657Slinton sympool = nil; 2169657Slinton nleft = 0; 2179657Slinton } 2189657Slinton 2199657Slinton /* 2209657Slinton * Create a new symbol with the given attributes. 2219657Slinton */ 2229657Slinton 2239657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 2249657Slinton Name name; 2259657Slinton Integer blevel; 2269657Slinton Symclass class; 2279657Slinton Symbol type; 2289657Slinton Symbol chain; 2299657Slinton { 2309657Slinton register Symbol s; 2319657Slinton 2329657Slinton s = symbol_alloc(); 2339657Slinton s->name = name; 234*18235Slinton s->language = primlang; 2359657Slinton s->level = blevel; 2369657Slinton s->class = class; 2379657Slinton s->type = type; 2389657Slinton s->chain = chain; 2399657Slinton return s; 2409657Slinton } 2419657Slinton 2429657Slinton /* 2439657Slinton * Insert a symbol into the hash table. 2449657Slinton */ 2459657Slinton 2469657Slinton public Symbol insert(name) 2479657Slinton Name name; 2489657Slinton { 2499657Slinton register Symbol s; 2509657Slinton register unsigned int h; 2519657Slinton 2529657Slinton h = hash(name); 2539657Slinton s = symbol_alloc(); 2549657Slinton s->name = name; 2559657Slinton s->next_sym = hashtab[h]; 2569657Slinton hashtab[h] = s; 2579657Slinton return s; 2589657Slinton } 2599657Slinton 2609657Slinton /* 2619657Slinton * Symbol lookup. 2629657Slinton */ 2639657Slinton 2649657Slinton public Symbol lookup(name) 2659657Slinton Name name; 2669657Slinton { 2679657Slinton register Symbol s; 2689657Slinton register unsigned int h; 2699657Slinton 2709657Slinton h = hash(name); 2719657Slinton s = hashtab[h]; 2729657Slinton while (s != nil and s->name != name) { 2739657Slinton s = s->next_sym; 2749657Slinton } 2759657Slinton return s; 2769657Slinton } 2779657Slinton 2789657Slinton /* 27916620Ssam * Delete a symbol from the symbol table. 28016620Ssam */ 28116620Ssam 28216620Ssam public delete (s) 28316620Ssam Symbol s; 28416620Ssam { 28516620Ssam register Symbol t; 28616620Ssam register unsigned int h; 28716620Ssam 28816620Ssam h = hash(s->name); 28916620Ssam t = hashtab[h]; 29016620Ssam if (t == nil) { 29116620Ssam panic("delete of non-symbol '%s'", symname(s)); 29216620Ssam } else if (t == s) { 29316620Ssam hashtab[h] = s->next_sym; 29416620Ssam } else { 29516620Ssam while (t->next_sym != s) { 29616620Ssam t = t->next_sym; 29716620Ssam if (t == nil) { 29816620Ssam panic("delete of non-symbol '%s'", symname(s)); 29916620Ssam } 30016620Ssam } 30116620Ssam t->next_sym = s->next_sym; 30216620Ssam } 30316620Ssam } 30416620Ssam 30516620Ssam /* 3069657Slinton * Dump out all the variables associated with the given 307*18235Slinton * procedure, function, or program associated with the given stack frame. 3089657Slinton * 3099657Slinton * This is quite inefficient. We traverse the entire symbol table 3109657Slinton * each time we're called. The assumption is that this routine 3119657Slinton * won't be called frequently enough to merit improved performance. 3129657Slinton */ 3139657Slinton 3149657Slinton public dumpvars(f, frame) 3159657Slinton Symbol f; 3169657Slinton Frame frame; 3179657Slinton { 3189657Slinton register Integer i; 3199657Slinton register Symbol s; 3209657Slinton 3219657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 3229657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 3239657Slinton if (container(s) == f) { 3249657Slinton if (should_print(s)) { 3259657Slinton printv(s, frame); 3269657Slinton putchar('\n'); 3279657Slinton } else if (s->class == MODULE) { 3289657Slinton dumpvars(s, frame); 3299657Slinton } 3309657Slinton } 3319657Slinton } 3329657Slinton } 3339657Slinton } 3349657Slinton 3359657Slinton /* 3369657Slinton * Create a builtin type. 3379657Slinton * Builtin types are circular in that btype->type->type = btype. 3389657Slinton */ 3399657Slinton 340*18235Slinton private Symbol maketype(name, lower, upper) 3419657Slinton String name; 3429657Slinton long lower; 3439657Slinton long upper; 3449657Slinton { 3459657Slinton register Symbol s; 346*18235Slinton Name n; 3479657Slinton 348*18235Slinton if (name == nil) { 349*18235Slinton n = nil; 350*18235Slinton } else { 351*18235Slinton n = identname(name, true); 352*18235Slinton } 353*18235Slinton s = insert(n); 35416620Ssam s->language = primlang; 355*18235Slinton s->level = 0; 356*18235Slinton s->class = TYPE; 357*18235Slinton s->type = nil; 358*18235Slinton s->chain = nil; 3599657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 3609657Slinton s->type->symvalue.rangev.lower = lower; 3619657Slinton s->type->symvalue.rangev.upper = upper; 3629657Slinton return s; 3639657Slinton } 3649657Slinton 3659657Slinton /* 366*18235Slinton * Create the builtin symbols. 367*18235Slinton */ 368*18235Slinton 369*18235Slinton public symbols_init () 3709657Slinton { 371*18235Slinton Symbol s; 3729657Slinton 373*18235Slinton t_boolean = maketype("$boolean", 0L, 1L); 374*18235Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 375*18235Slinton t_char = maketype("$char", 0L, 255L); 376*18235Slinton t_real = maketype("$real", 8L, 0L); 377*18235Slinton t_nil = maketype("$nil", 0L, 0L); 378*18235Slinton t_addr = insert(identname("$address", true)); 379*18235Slinton t_addr->language = primlang; 380*18235Slinton t_addr->level = 0; 381*18235Slinton t_addr->class = TYPE; 382*18235Slinton t_addr->type = newSymbol(nil, 1, PTR, t_int, nil); 383*18235Slinton s = insert(identname("true", true)); 384*18235Slinton s->class = CONST; 385*18235Slinton s->type = t_boolean; 386*18235Slinton s->symvalue.constval = build(O_LCON, 1L); 387*18235Slinton s->symvalue.constval->nodetype = t_boolean; 388*18235Slinton s = insert(identname("false", true)); 389*18235Slinton s->class = CONST; 390*18235Slinton s->type = t_boolean; 391*18235Slinton s->symvalue.constval = build(O_LCON, 0L); 392*18235Slinton s->symvalue.constval->nodetype = t_boolean; 3939657Slinton } 3949657Slinton 3959657Slinton /* 3969657Slinton * Reduce type to avoid worrying about type names. 3979657Slinton */ 3989657Slinton 3999657Slinton public Symbol rtype(type) 4009657Slinton Symbol type; 4019657Slinton { 4029657Slinton register Symbol t; 4039657Slinton 4049657Slinton t = type; 4059657Slinton if (t != nil) { 406*18235Slinton if (t->class == VAR or t->class == CONST or 407*18235Slinton t->class == FIELD or t->class == REF 408*18235Slinton ) { 4099657Slinton t = t->type; 4109657Slinton } 41116620Ssam if (t->class == TYPEREF) { 41216620Ssam resolveRef(t); 41316620Ssam } 4149657Slinton while (t->class == TYPE or t->class == TAG) { 4159657Slinton t = t->type; 41616620Ssam if (t->class == TYPEREF) { 41716620Ssam resolveRef(t); 41816620Ssam } 4199657Slinton } 4209657Slinton } 4219657Slinton return t; 4229657Slinton } 4239657Slinton 42416620Ssam /* 42516620Ssam * Find the end of a module name. Return nil if there is none 42616620Ssam * in the given string. 42716620Ssam */ 42816620Ssam 42916620Ssam private String findModuleMark (s) 43016620Ssam String s; 43116620Ssam { 43216620Ssam register char *p, *r; 43316620Ssam register boolean done; 43416620Ssam 43516620Ssam p = s; 43616620Ssam done = false; 43716620Ssam do { 43816620Ssam if (*p == ':') { 43916620Ssam done = true; 44016620Ssam r = p; 44116620Ssam } else if (*p == '\0') { 44216620Ssam done = true; 44316620Ssam r = nil; 44416620Ssam } else { 44516620Ssam ++p; 44616620Ssam } 44716620Ssam } while (not done); 44816620Ssam return r; 44916620Ssam } 45016620Ssam 45116620Ssam /* 45216620Ssam * Resolve a type reference by modifying to be the appropriate type. 45316620Ssam * 45416620Ssam * If the reference has a name, then it refers to an opaque type and 45516620Ssam * the actual type is directly accessible. Otherwise, we must use 45616620Ssam * the type reference string, which is of the form "module:{module:}name". 45716620Ssam */ 45816620Ssam 45916620Ssam public resolveRef (t) 46016620Ssam Symbol t; 46116620Ssam { 46216620Ssam register char *p; 46316620Ssam char *start; 46416620Ssam Symbol s, m, outer; 46516620Ssam Name n; 46616620Ssam 46716620Ssam if (t->name != nil) { 46816620Ssam s = t; 46916620Ssam } else { 47016620Ssam start = t->symvalue.typeref; 47116620Ssam outer = program; 47216620Ssam p = findModuleMark(start); 47316620Ssam while (p != nil) { 47416620Ssam *p = '\0'; 47516620Ssam n = identname(start, true); 47616620Ssam find(m, n) where m->block == outer endfind(m); 47716620Ssam if (m == nil) { 47816620Ssam p = nil; 47916620Ssam outer = nil; 48016620Ssam s = nil; 48116620Ssam } else { 48216620Ssam outer = m; 48316620Ssam start = p + 1; 48416620Ssam p = findModuleMark(start); 48516620Ssam } 48616620Ssam } 48716620Ssam if (outer != nil) { 48816620Ssam n = identname(start, true); 48916620Ssam find(s, n) where s->block == outer endfind(s); 49016620Ssam } 49116620Ssam } 49216620Ssam if (s != nil and s->type != nil) { 49316620Ssam t->name = s->type->name; 49416620Ssam t->class = s->type->class; 49516620Ssam t->type = s->type->type; 49616620Ssam t->chain = s->type->chain; 49716620Ssam t->symvalue = s->type->symvalue; 49816620Ssam t->block = s->type->block; 49916620Ssam } 50016620Ssam } 50116620Ssam 502*18235Slinton public integer regnum (s) 5039657Slinton Symbol s; 5049657Slinton { 505*18235Slinton integer r; 506*18235Slinton 5079657Slinton checkref(s); 508*18235Slinton if (s->level < 0) { 509*18235Slinton r = s->symvalue.offset; 510*18235Slinton } else { 511*18235Slinton r = -1; 512*18235Slinton } 513*18235Slinton return r; 5149657Slinton } 5159657Slinton 5169657Slinton public Symbol container(s) 5179657Slinton Symbol s; 5189657Slinton { 5199657Slinton checkref(s); 5209657Slinton return s->block; 5219657Slinton } 5229657Slinton 523*18235Slinton public Node constval(s) 524*18235Slinton Symbol s; 525*18235Slinton { 526*18235Slinton checkref(s); 527*18235Slinton if (s->class != CONST) { 528*18235Slinton error("[internal error: constval(non-CONST)]"); 529*18235Slinton } 530*18235Slinton return s->symvalue.constval; 531*18235Slinton } 532*18235Slinton 5339657Slinton /* 5349657Slinton * Return the object address of the given symbol. 5359657Slinton * 5369657Slinton * There are the following possibilities: 5379657Slinton * 5389657Slinton * globals - just take offset 5399657Slinton * locals - take offset from locals base 5409657Slinton * arguments - take offset from argument base 5419657Slinton * register - offset is register number 5429657Slinton */ 5439657Slinton 54416620Ssam #define isglobal(s) (s->level == 1) 54516620Ssam #define islocaloff(s) (s->level >= 2 and s->symvalue.offset < 0) 54616620Ssam #define isparamoff(s) (s->level >= 2 and s->symvalue.offset >= 0) 547*18235Slinton #define isreg(s) (s->level < 0) 5489657Slinton 549*18235Slinton public Address address (s, frame) 5509657Slinton Symbol s; 5519657Slinton Frame frame; 5529657Slinton { 5539657Slinton register Frame frp; 5549657Slinton register Address addr; 5559657Slinton register Symbol cur; 5569657Slinton 5579657Slinton checkref(s); 5589657Slinton if (not isactive(s->block)) { 5599657Slinton error("\"%s\" is not currently defined", symname(s)); 5609657Slinton } else if (isglobal(s)) { 5619657Slinton addr = s->symvalue.offset; 5629657Slinton } else { 5639657Slinton frp = frame; 5649657Slinton if (frp == nil) { 5659657Slinton cur = s->block; 5669657Slinton while (cur != nil and cur->class == MODULE) { 5679657Slinton cur = cur->block; 5689657Slinton } 5699657Slinton if (cur == nil) { 570*18235Slinton frp = nil; 571*18235Slinton } else { 572*18235Slinton frp = findframe(cur); 573*18235Slinton if (frp == nil) { 574*18235Slinton error("[internal error: unexpected nil frame for \"%s\"]", 575*18235Slinton symname(s) 576*18235Slinton ); 577*18235Slinton } 5789657Slinton } 5799657Slinton } 5809657Slinton if (islocaloff(s)) { 5819657Slinton addr = locals_base(frp) + s->symvalue.offset; 5829657Slinton } else if (isparamoff(s)) { 5839657Slinton addr = args_base(frp) + s->symvalue.offset; 5849657Slinton } else if (isreg(s)) { 5859657Slinton addr = savereg(s->symvalue.offset, frp); 5869657Slinton } else { 5879657Slinton panic("address: bad symbol \"%s\"", symname(s)); 5889657Slinton } 5899657Slinton } 5909657Slinton return addr; 5919657Slinton } 5929657Slinton 5939657Slinton /* 5949657Slinton * Define a symbol used to access register values. 5959657Slinton */ 5969657Slinton 597*18235Slinton public defregname (n, r) 5989657Slinton Name n; 599*18235Slinton integer r; 6009657Slinton { 601*18235Slinton Symbol s; 6029657Slinton 6039657Slinton s = insert(n); 604*18235Slinton s->language = t_addr->language; 6059657Slinton s->class = VAR; 6069657Slinton s->level = -3; 607*18235Slinton s->type = t_addr; 6089657Slinton s->symvalue.offset = r; 6099657Slinton } 6109657Slinton 6119657Slinton /* 6129657Slinton * Resolve an "abstract" type reference. 6139657Slinton * 6149657Slinton * It is possible in C to define a pointer to a type, but never define 6159657Slinton * the type in a particular source file. Here we try to resolve 6169657Slinton * the type definition. This is problematic, it is possible to 6179657Slinton * have multiple, different definitions for the same name type. 6189657Slinton */ 6199657Slinton 6209657Slinton public findtype(s) 6219657Slinton Symbol s; 6229657Slinton { 6239657Slinton register Symbol t, u, prev; 6249657Slinton 6259657Slinton u = s; 6269657Slinton prev = nil; 6279657Slinton while (u != nil and u->class != BADUSE) { 6289657Slinton if (u->name != nil) { 6299657Slinton prev = u; 6309657Slinton } 6319657Slinton u = u->type; 6329657Slinton } 6339657Slinton if (prev == nil) { 6349657Slinton error("couldn't find link to type reference"); 6359657Slinton } 636*18235Slinton t = lookup(prev->name); 637*18235Slinton while (t != nil and 638*18235Slinton not ( 639*18235Slinton t != prev and t->name == prev->name and 640*18235Slinton t->block->class == MODULE and t->class == prev->class and 641*18235Slinton t->type != nil and t->type->type != nil and 642*18235Slinton t->type->type->class != BADUSE 643*18235Slinton ) 644*18235Slinton ) { 645*18235Slinton t = t->next_sym; 646*18235Slinton } 6479657Slinton if (t == nil) { 6489657Slinton error("couldn't resolve reference"); 6499657Slinton } else { 6509657Slinton prev->type = t->type; 6519657Slinton } 6529657Slinton } 6539657Slinton 6549657Slinton /* 6559657Slinton * Find the size in bytes of the given type. 6569657Slinton * 6579657Slinton * This is probably the WRONG thing to do. The size should be kept 6589657Slinton * as an attribute in the symbol information as is done for structures 6599657Slinton * and fields. I haven't gotten around to cleaning this up yet. 6609657Slinton */ 6619657Slinton 66212547Scsvaf #define MAXUCHAR 255 66312547Scsvaf #define MAXUSHORT 65535L 6649657Slinton #define MINCHAR -128 6659657Slinton #define MAXCHAR 127 6669657Slinton #define MINSHORT -32768 6679657Slinton #define MAXSHORT 32767 6689657Slinton 66916620Ssam public findbounds (u, lower, upper) 67016620Ssam Symbol u; 67116620Ssam long *lower, *upper; 67216620Ssam { 67316620Ssam Rangetype lbt, ubt; 67416620Ssam long lb, ub; 67516620Ssam 67616620Ssam if (u->class == RANGE) { 67716620Ssam lbt = u->symvalue.rangev.lowertype; 67816620Ssam ubt = u->symvalue.rangev.uppertype; 67916620Ssam lb = u->symvalue.rangev.lower; 68016620Ssam ub = u->symvalue.rangev.upper; 68116620Ssam if (lbt == R_ARG or lbt == R_TEMP) { 68216620Ssam if (not getbound(u, lb, lbt, lower)) { 68316620Ssam error("dynamic bounds not currently available"); 68416620Ssam } 68516620Ssam } else { 68616620Ssam *lower = lb; 68716620Ssam } 68816620Ssam if (ubt == R_ARG or ubt == R_TEMP) { 68916620Ssam if (not getbound(u, ub, ubt, upper)) { 69016620Ssam error("dynamic bounds not currently available"); 69116620Ssam } 69216620Ssam } else { 69316620Ssam *upper = ub; 69416620Ssam } 69516620Ssam } else if (u->class == SCAL) { 69616620Ssam *lower = 0; 69716620Ssam *upper = u->symvalue.iconval - 1; 69816620Ssam } else { 699*18235Slinton error("[internal error: unexpected array bound type]"); 70016620Ssam } 70116620Ssam } 70216620Ssam 70316620Ssam public integer size(sym) 70416620Ssam Symbol sym; 70516620Ssam { 70616620Ssam register Symbol s, t, u; 70716620Ssam register integer nel, elsize; 7089657Slinton long lower, upper; 70916620Ssam integer r, off, len; 7109657Slinton 7119657Slinton t = sym; 7129657Slinton checkref(t); 71316620Ssam if (t->class == TYPEREF) { 71416620Ssam resolveRef(t); 71516620Ssam } 7169657Slinton switch (t->class) { 7179657Slinton case RANGE: 7189657Slinton lower = t->symvalue.rangev.lower; 7199657Slinton upper = t->symvalue.rangev.upper; 72016620Ssam if (upper == 0 and lower > 0) { 72116620Ssam /* real */ 7229657Slinton r = lower; 72316620Ssam } else if (lower > upper) { 72416620Ssam /* unsigned long */ 72516620Ssam r = sizeof(long); 72612045Slinton } else if ( 72712547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or 72812547Scsvaf (lower >= 0 and upper <= MAXUCHAR) 72912547Scsvaf ) { 7309657Slinton r = sizeof(char); 73112547Scsvaf } else if ( 73212547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or 73312547Scsvaf (lower >= 0 and upper <= MAXUSHORT) 73412547Scsvaf ) { 7359657Slinton r = sizeof(short); 7369657Slinton } else { 7379657Slinton r = sizeof(long); 7389657Slinton } 7399657Slinton break; 7409657Slinton 7419657Slinton case ARRAY: 7429657Slinton elsize = size(t->type); 7439657Slinton nel = 1; 7449657Slinton for (t = t->chain; t != nil; t = t->chain) { 74516620Ssam u = rtype(t); 74616620Ssam findbounds(u, &lower, &upper); 7479657Slinton nel *= (upper-lower+1); 7489657Slinton } 7499657Slinton r = nel*elsize; 7509657Slinton break; 7519657Slinton 752*18235Slinton case DYNARRAY: 753*18235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 754*18235Slinton break; 755*18235Slinton 756*18235Slinton case SUBARRAY: 757*18235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 758*18235Slinton break; 759*18235Slinton 76012547Scsvaf case REF: 7619657Slinton case VAR: 7629657Slinton r = size(t->type); 76312127Slinton /* 76412127Slinton * 76512045Slinton if (r < sizeof(Word) and isparam(t)) { 7669657Slinton r = sizeof(Word); 7679657Slinton } 76812547Scsvaf */ 7699657Slinton break; 7709657Slinton 771*18235Slinton case FVAR: 7729657Slinton case CONST: 773*18235Slinton case TAG: 7749657Slinton r = size(t->type); 7759657Slinton break; 7769657Slinton 7779657Slinton case TYPE: 7789657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 7799657Slinton findtype(t); 7809657Slinton } 7819657Slinton r = size(t->type); 7829657Slinton break; 7839657Slinton 7849657Slinton case FIELD: 78516620Ssam off = t->symvalue.field.offset; 78616620Ssam len = t->symvalue.field.length; 78716620Ssam r = (off + len + 7) div 8 - (off div 8); 7889657Slinton break; 7899657Slinton 7909657Slinton case RECORD: 7919657Slinton case VARNT: 7929657Slinton r = t->symvalue.offset; 7939657Slinton if (r == 0 and t->chain != nil) { 7949657Slinton panic("missing size information for record"); 7959657Slinton } 7969657Slinton break; 7979657Slinton 7989657Slinton case PTR: 799*18235Slinton case TYPEREF: 8009657Slinton case FILET: 8019657Slinton r = sizeof(Word); 8029657Slinton break; 8039657Slinton 8049657Slinton case SCAL: 80512609Slinton r = sizeof(Word); 80612609Slinton /* 80712609Slinton * 8089657Slinton if (t->symvalue.iconval > 255) { 8099657Slinton r = sizeof(short); 8109657Slinton } else { 8119657Slinton r = sizeof(char); 8129657Slinton } 81312609Slinton * 81412609Slinton */ 8159657Slinton break; 8169657Slinton 8179657Slinton case FPROC: 8189657Slinton case FFUNC: 8199657Slinton r = sizeof(Word); 8209657Slinton break; 8219657Slinton 8229657Slinton case PROC: 8239657Slinton case FUNC: 8249657Slinton case MODULE: 8259657Slinton case PROG: 8269657Slinton r = sizeof(Symbol); 8279657Slinton break; 8289657Slinton 82916620Ssam case SET: 83016620Ssam u = rtype(t->type); 83116620Ssam switch (u->class) { 83216620Ssam case RANGE: 83316620Ssam r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; 83416620Ssam break; 83516620Ssam 83616620Ssam case SCAL: 83716620Ssam r = u->symvalue.iconval; 83816620Ssam break; 83916620Ssam 84016620Ssam default: 84116620Ssam error("expected range for set base type"); 84216620Ssam break; 84316620Ssam } 84416620Ssam r = (r + BITSPERBYTE - 1) div BITSPERBYTE; 84516620Ssam break; 84616620Ssam 847*18235Slinton /* 848*18235Slinton * These can happen in C (unfortunately) for unresolved type references 849*18235Slinton * Assume they are pointers. 850*18235Slinton */ 851*18235Slinton case BADUSE: 852*18235Slinton r = sizeof(Address); 853*18235Slinton break; 854*18235Slinton 8559657Slinton default: 8569657Slinton if (ord(t->class) > ord(TYPEREF)) { 8579657Slinton panic("size: bad class (%d)", ord(t->class)); 8589657Slinton } else { 859*18235Slinton fprintf(stderr, "can't compute size of a %s\n", classname(t)); 8609657Slinton } 86116620Ssam r = 0; 86216620Ssam break; 8639657Slinton } 8649657Slinton return r; 8659657Slinton } 8669657Slinton 8679657Slinton /* 868*18235Slinton * Return the size associated with a symbol that takes into account 869*18235Slinton * reference parameters. This might be better as the normal size function, but 870*18235Slinton * too many places already depend on it working the way it does. 871*18235Slinton */ 872*18235Slinton 873*18235Slinton public integer psize (s) 874*18235Slinton Symbol s; 875*18235Slinton { 876*18235Slinton integer r; 877*18235Slinton Symbol t; 878*18235Slinton 879*18235Slinton if (s->class == REF) { 880*18235Slinton t = rtype(s->type); 881*18235Slinton if (t->class == DYNARRAY) { 882*18235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 883*18235Slinton } else if (t->class == SUBARRAY) { 884*18235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 885*18235Slinton } else { 886*18235Slinton r = sizeof(Word); 887*18235Slinton } 888*18235Slinton } else { 889*18235Slinton r = size(s); 890*18235Slinton } 891*18235Slinton return r; 892*18235Slinton } 893*18235Slinton 894*18235Slinton /* 8959657Slinton * Test if a symbol is a parameter. This is true if there 8969657Slinton * is a cycle from s->block to s via chain pointers. 8979657Slinton */ 8989657Slinton 8999657Slinton public Boolean isparam(s) 9009657Slinton Symbol s; 9019657Slinton { 9029657Slinton register Symbol t; 9039657Slinton 9049657Slinton t = s->block; 9059657Slinton while (t != nil and t != s) { 9069657Slinton t = t->chain; 9079657Slinton } 9089657Slinton return (Boolean) (t != nil); 9099657Slinton } 9109657Slinton 9119657Slinton /* 91216620Ssam * Test if a type is an open array parameter type. 9139657Slinton */ 9149657Slinton 915*18235Slinton public boolean isopenarray (type) 916*18235Slinton Symbol type; 91716620Ssam { 918*18235Slinton Symbol t; 919*18235Slinton 920*18235Slinton t = rtype(type); 921*18235Slinton return (boolean) (t->class == DYNARRAY); 92216620Ssam } 92316620Ssam 92416620Ssam /* 925*18235Slinton * Test if a symbol is a var parameter, i.e. has class REF. 92616620Ssam */ 92716620Ssam 9289657Slinton public Boolean isvarparam(s) 9299657Slinton Symbol s; 9309657Slinton { 9319657Slinton return (Boolean) (s->class == REF); 9329657Slinton } 9339657Slinton 9349657Slinton /* 9359657Slinton * Test if a symbol is a variable (actually any addressible quantity 9369657Slinton * with do). 9379657Slinton */ 9389657Slinton 9399657Slinton public Boolean isvariable(s) 940*18235Slinton Symbol s; 9419657Slinton { 9429657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 9439657Slinton } 9449657Slinton 9459657Slinton /* 946*18235Slinton * Test if a symbol is a constant. 947*18235Slinton */ 948*18235Slinton 949*18235Slinton public Boolean isconst(s) 950*18235Slinton Symbol s; 9519657Slinton { 952*18235Slinton return (Boolean) (s->class == CONST); 9539657Slinton } 9549657Slinton 9559657Slinton /* 9569657Slinton * Test if a symbol is a module. 9579657Slinton */ 9589657Slinton 9599657Slinton public Boolean ismodule(s) 9609657Slinton register Symbol s; 9619657Slinton { 9629657Slinton return (Boolean) (s->class == MODULE); 9639657Slinton } 9649657Slinton 9659657Slinton /* 96616620Ssam * Mark a procedure or function as internal, meaning that it is called 96716620Ssam * with a different calling sequence. 96816620Ssam */ 96916620Ssam 97016620Ssam public markInternal (s) 97116620Ssam Symbol s; 97216620Ssam { 97316620Ssam s->symvalue.funcv.intern = true; 97416620Ssam } 97516620Ssam 97616620Ssam public boolean isinternal (s) 97716620Ssam Symbol s; 97816620Ssam { 97916620Ssam return s->symvalue.funcv.intern; 98016620Ssam } 98116620Ssam 98216620Ssam /* 983*18235Slinton * Decide if a field begins or ends on a bit rather than byte boundary. 984*18235Slinton */ 985*18235Slinton 986*18235Slinton public Boolean isbitfield(s) 987*18235Slinton register Symbol s; 988*18235Slinton { 989*18235Slinton boolean b; 990*18235Slinton register integer off, len; 991*18235Slinton register Symbol t; 992*18235Slinton 993*18235Slinton off = s->symvalue.field.offset; 994*18235Slinton len = s->symvalue.field.length; 995*18235Slinton if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { 996*18235Slinton b = true; 997*18235Slinton } else { 998*18235Slinton t = rtype(s->type); 999*18235Slinton b = (Boolean) ( 1000*18235Slinton (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or 1001*18235Slinton len != (size(t)*BITSPERBYTE) 1002*18235Slinton ); 1003*18235Slinton } 1004*18235Slinton return b; 1005*18235Slinton } 1006*18235Slinton 1007*18235Slinton private boolean primlang_typematch (t1, t2) 1008*18235Slinton Symbol t1, t2; 1009*18235Slinton { 1010*18235Slinton return (boolean) ( 1011*18235Slinton (t1 == t2) or 1012*18235Slinton ( 1013*18235Slinton t1->class == RANGE and t2->class == RANGE and 1014*18235Slinton t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 1015*18235Slinton t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 1016*18235Slinton ) or ( 1017*18235Slinton t1->class == PTR and t2->class == RANGE and 1018*18235Slinton t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower 1019*18235Slinton ) or ( 1020*18235Slinton t2->class == PTR and t1->class == RANGE and 1021*18235Slinton t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower 1022*18235Slinton ) 1023*18235Slinton ); 1024*18235Slinton } 1025*18235Slinton 1026*18235Slinton /* 10279657Slinton * Test if two types match. 10289657Slinton * Equivalent names implies a match in any language. 10299657Slinton * 10309657Slinton * Special symbols must be handled with care. 10319657Slinton */ 10329657Slinton 10339657Slinton public Boolean compatible(t1, t2) 10349657Slinton register Symbol t1, t2; 10359657Slinton { 10369657Slinton Boolean b; 103716620Ssam Symbol rt1, rt2; 10389657Slinton 10399657Slinton if (t1 == t2) { 10409657Slinton b = true; 10419657Slinton } else if (t1 == nil or t2 == nil) { 10429657Slinton b = false; 10439657Slinton } else if (t1 == procsym) { 10449657Slinton b = isblock(t2); 10459657Slinton } else if (t2 == procsym) { 10469657Slinton b = isblock(t1); 104716620Ssam } else if (t1->language == primlang) { 104816620Ssam if (t2->language == primlang) { 1049*18235Slinton b = primlang_typematch(rtype(t1), rtype(t2)); 105016620Ssam } else { 105116620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 105216620Ssam } 105316620Ssam } else if (t2->language == primlang) { 105416620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 10559657Slinton } else if (t1->language == nil) { 105616620Ssam if (t2->language == nil) { 105716620Ssam b = false; 105816620Ssam } else { 105916620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 106016620Ssam } 10619657Slinton } else { 106216620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 10639657Slinton } 10649657Slinton return b; 10659657Slinton } 10669657Slinton 10679657Slinton /* 10689657Slinton * Check for a type of the given name. 10699657Slinton */ 10709657Slinton 10719657Slinton public Boolean istypename(type, name) 10729657Slinton Symbol type; 10739657Slinton String name; 10749657Slinton { 1075*18235Slinton register Symbol t; 10769657Slinton Boolean b; 10779657Slinton 10789657Slinton t = type; 1079*18235Slinton if (t == nil) { 1080*18235Slinton b = false; 1081*18235Slinton } else { 1082*18235Slinton b = (Boolean) ( 1083*18235Slinton t->class == TYPE and streq(ident(t->name), name) 1084*18235Slinton ); 1085*18235Slinton } 10869657Slinton return b; 10879657Slinton } 10889657Slinton 10899657Slinton /* 109016620Ssam * Determine if a (value) parameter should actually be passed by address. 109116620Ssam */ 109216620Ssam 109316620Ssam public boolean passaddr (p, exprtype) 109416620Ssam Symbol p, exprtype; 109516620Ssam { 109616620Ssam boolean b; 109716620Ssam Language def; 109816620Ssam 109916620Ssam if (p == nil) { 110016620Ssam def = findlanguage(".c"); 110116620Ssam b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); 110216620Ssam } else if (p->language == nil or p->language == primlang) { 110316620Ssam b = false; 110416620Ssam } else if (isopenarray(p->type)) { 110516620Ssam b = true; 110616620Ssam } else { 110716620Ssam b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); 110816620Ssam } 110916620Ssam return b; 111016620Ssam } 111116620Ssam 111216620Ssam /* 11139657Slinton * Test if the name of a symbol is uniquely defined or not. 11149657Slinton */ 11159657Slinton 11169657Slinton public Boolean isambiguous(s) 11179657Slinton register Symbol s; 11189657Slinton { 11199657Slinton register Symbol t; 11209657Slinton 11219657Slinton find(t, s->name) where t != s endfind(t); 11229657Slinton return (Boolean) (t != nil); 11239657Slinton } 11249657Slinton 11259657Slinton typedef char *Arglist; 11269657Slinton 11279657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 11289657Slinton 11299657Slinton private Symbol mkstring(); 11309657Slinton 11319657Slinton /* 11329657Slinton * Determine the type of a parse tree. 1133*18235Slinton * 11349657Slinton * Also make some symbol-dependent changes to the tree such as 1135*18235Slinton * removing indirection for constant or register symbols. 11369657Slinton */ 11379657Slinton 1138*18235Slinton public assigntypes (p) 11399657Slinton register Node p; 11409657Slinton { 11419657Slinton register Node p1; 11429657Slinton register Symbol s; 11439657Slinton 11449657Slinton switch (p->op) { 11459657Slinton case O_SYM: 1146*18235Slinton p->nodetype = p->value.sym; 11479657Slinton break; 11489657Slinton 11499657Slinton case O_LCON: 11509657Slinton p->nodetype = t_int; 11519657Slinton break; 11529657Slinton 1153*18235Slinton case O_CCON: 1154*18235Slinton p->nodetype = t_char; 1155*18235Slinton break; 1156*18235Slinton 11579657Slinton case O_FCON: 11589657Slinton p->nodetype = t_real; 11599657Slinton break; 11609657Slinton 11619657Slinton case O_SCON: 1162*18235Slinton p->nodetype = mkstring(p->value.scon); 11639657Slinton break; 11649657Slinton 11659657Slinton case O_INDIR: 11669657Slinton p1 = p->value.arg[0]; 1167*18235Slinton s = rtype(p1->nodetype); 1168*18235Slinton if (s->class != PTR) { 1169*18235Slinton beginerrmsg(); 1170*18235Slinton fprintf(stderr, "\""); 1171*18235Slinton prtree(stderr, p1); 1172*18235Slinton fprintf(stderr, "\" is not a pointer"); 1173*18235Slinton enderrmsg(); 1174*18235Slinton } 11759657Slinton p->nodetype = rtype(p1->nodetype)->type; 11769657Slinton break; 11779657Slinton 11789657Slinton case O_DOT: 11799657Slinton p->nodetype = p->value.arg[1]->value.sym; 11809657Slinton break; 11819657Slinton 11829657Slinton case O_RVAL: 11839657Slinton p1 = p->value.arg[0]; 11849657Slinton p->nodetype = p1->nodetype; 11859657Slinton if (p1->op == O_SYM) { 1186*18235Slinton if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) { 1187*18235Slinton p->op = p1->op; 1188*18235Slinton p->value.sym = p1->value.sym; 1189*18235Slinton p->nodetype = p1->nodetype; 1190*18235Slinton dispose(p1); 11919657Slinton } else if (p1->value.sym->class == CONST) { 1192*18235Slinton p->op = p1->op; 1193*18235Slinton p->value = p1->value; 1194*18235Slinton p->nodetype = p1->nodetype; 1195*18235Slinton dispose(p1); 11969657Slinton } else if (isreg(p1->value.sym)) { 11979657Slinton p->op = O_SYM; 11989657Slinton p->value.sym = p1->value.sym; 11999657Slinton dispose(p1); 12009657Slinton } 12019657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 12029657Slinton s = p1->value.arg[0]->value.sym; 12039657Slinton if (isreg(s)) { 12049657Slinton p1->op = O_SYM; 12059657Slinton dispose(p1->value.arg[0]); 12069657Slinton p1->value.sym = s; 12079657Slinton p1->nodetype = s; 12089657Slinton } 12099657Slinton } 12109657Slinton break; 12119657Slinton 1212*18235Slinton case O_COMMA: 1213*18235Slinton p->nodetype = p->value.arg[0]->nodetype; 1214*18235Slinton break; 1215*18235Slinton 1216*18235Slinton case O_CALLPROC: 12179657Slinton case O_CALL: 12189657Slinton p1 = p->value.arg[0]; 121911171Slinton p->nodetype = rtype(p1->nodetype)->type; 12209657Slinton break; 12219657Slinton 122211171Slinton case O_TYPERENAME: 122311171Slinton p->nodetype = p->value.arg[1]->nodetype; 122411171Slinton break; 122511171Slinton 12269657Slinton case O_ITOF: 12279657Slinton p->nodetype = t_real; 12289657Slinton break; 12299657Slinton 12309657Slinton case O_NEG: 12319657Slinton s = p->value.arg[0]->nodetype; 12329657Slinton if (not compatible(s, t_int)) { 12339657Slinton if (not compatible(s, t_real)) { 12349657Slinton beginerrmsg(); 123516620Ssam fprintf(stderr, "\""); 12369657Slinton prtree(stderr, p->value.arg[0]); 123716620Ssam fprintf(stderr, "\" is improper type"); 12389657Slinton enderrmsg(); 12399657Slinton } else { 12409657Slinton p->op = O_NEGF; 12419657Slinton } 12429657Slinton } 12439657Slinton p->nodetype = s; 12449657Slinton break; 12459657Slinton 12469657Slinton case O_ADD: 12479657Slinton case O_SUB: 12489657Slinton case O_MUL: 124916620Ssam binaryop(p, nil); 125016620Ssam break; 125116620Ssam 12529657Slinton case O_LT: 12539657Slinton case O_LE: 12549657Slinton case O_GT: 12559657Slinton case O_GE: 12569657Slinton case O_EQ: 12579657Slinton case O_NE: 125816620Ssam binaryop(p, t_boolean); 12599657Slinton break; 12609657Slinton 12619657Slinton case O_DIVF: 12629657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 12639657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 12649657Slinton p->nodetype = t_real; 12659657Slinton break; 12669657Slinton 12679657Slinton case O_DIV: 12689657Slinton case O_MOD: 12699657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 12709657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 12719657Slinton p->nodetype = t_int; 12729657Slinton break; 12739657Slinton 12749657Slinton case O_AND: 12759657Slinton case O_OR: 12769657Slinton chkboolean(p->value.arg[0]); 12779657Slinton chkboolean(p->value.arg[1]); 12789657Slinton p->nodetype = t_boolean; 12799657Slinton break; 12809657Slinton 12819657Slinton case O_QLINE: 12829657Slinton p->nodetype = t_int; 12839657Slinton break; 12849657Slinton 12859657Slinton default: 12869657Slinton p->nodetype = nil; 12879657Slinton break; 12889657Slinton } 12899657Slinton } 12909657Slinton 12919657Slinton /* 129216620Ssam * Process a binary arithmetic or relational operator. 129316620Ssam * Convert from integer to real if necessary. 129416620Ssam */ 129516620Ssam 129616620Ssam private binaryop (p, t) 129716620Ssam Node p; 129816620Ssam Symbol t; 129916620Ssam { 130016620Ssam Node p1, p2; 130116620Ssam Boolean t1real, t2real; 130216620Ssam Symbol t1, t2; 130316620Ssam 130416620Ssam p1 = p->value.arg[0]; 130516620Ssam p2 = p->value.arg[1]; 130616620Ssam t1 = rtype(p1->nodetype); 130716620Ssam t2 = rtype(p2->nodetype); 130816620Ssam t1real = compatible(t1, t_real); 130916620Ssam t2real = compatible(t2, t_real); 131016620Ssam if (t1real or t2real) { 131116620Ssam p->op = (Operator) (ord(p->op) + 1); 131216620Ssam if (not t1real) { 131316620Ssam p->value.arg[0] = build(O_ITOF, p1); 131416620Ssam } else if (not t2real) { 131516620Ssam p->value.arg[1] = build(O_ITOF, p2); 131616620Ssam } 131716620Ssam p->nodetype = t_real; 131816620Ssam } else { 131916620Ssam if (size(p1->nodetype) > sizeof(integer)) { 132016620Ssam beginerrmsg(); 132116620Ssam fprintf(stderr, "operation not defined on \""); 132216620Ssam prtree(stderr, p1); 132316620Ssam fprintf(stderr, "\""); 132416620Ssam enderrmsg(); 132516620Ssam } else if (size(p2->nodetype) > sizeof(integer)) { 132616620Ssam beginerrmsg(); 132716620Ssam fprintf(stderr, "operation not defined on \""); 132816620Ssam prtree(stderr, p2); 132916620Ssam fprintf(stderr, "\""); 133016620Ssam enderrmsg(); 133116620Ssam } 133216620Ssam p->nodetype = t_int; 133316620Ssam } 133416620Ssam if (t != nil) { 133516620Ssam p->nodetype = t; 133616620Ssam } 133716620Ssam } 133816620Ssam 133916620Ssam /* 13409657Slinton * Convert a tree to a type via a conversion operator; 13419657Slinton * if this isn't possible generate an error. 13429657Slinton * 13439657Slinton * Note the tree is call by address, hence the #define below. 13449657Slinton */ 13459657Slinton 13469657Slinton private convert(tp, typeto, op) 13479657Slinton Node *tp; 13489657Slinton Symbol typeto; 13499657Slinton Operator op; 13509657Slinton { 135116620Ssam Node tree; 135216620Ssam Symbol s, t; 13539657Slinton 135416620Ssam tree = *tp; 13559657Slinton s = rtype(tree->nodetype); 135616620Ssam t = rtype(typeto); 135716620Ssam if (compatible(t, t_real) and compatible(s, t_int)) { 13589657Slinton tree = build(op, tree); 135916620Ssam } else if (not compatible(s, t)) { 13609657Slinton beginerrmsg(); 136116620Ssam fprintf(stderr, "expected integer or real, found \""); 136216620Ssam prtree(stderr, tree); 136316620Ssam fprintf(stderr, "\""); 13649657Slinton enderrmsg(); 136516620Ssam } else if (op != O_NOP and s != t) { 13669657Slinton tree = build(op, tree); 13679657Slinton } 136816620Ssam *tp = tree; 13699657Slinton } 13709657Slinton 13719657Slinton /* 13729657Slinton * Construct a node for the dot operator. 13739657Slinton * 13749657Slinton * If the left operand is not a record, but rather a procedure 13759657Slinton * or function, then we interpret the "." as referencing an 13769657Slinton * "invisible" variable; i.e. a variable within a dynamically 13779657Slinton * active block but not within the static scope of the current procedure. 13789657Slinton */ 13799657Slinton 13809657Slinton public Node dot(record, fieldname) 13819657Slinton Node record; 13829657Slinton Name fieldname; 13839657Slinton { 1384*18235Slinton register Node rec, p; 13859657Slinton register Symbol s, t; 13869657Slinton 1387*18235Slinton rec = record; 1388*18235Slinton if (isblock(rec->nodetype)) { 13899657Slinton find(s, fieldname) where 1390*18235Slinton s->block == rec->nodetype and 1391*18235Slinton s->class != FIELD 13929657Slinton endfind(s); 13939657Slinton if (s == nil) { 13949657Slinton beginerrmsg(); 13959657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 1396*18235Slinton printname(stderr, rec->nodetype); 13979657Slinton enderrmsg(); 13989657Slinton } 13999657Slinton p = new(Node); 14009657Slinton p->op = O_SYM; 14019657Slinton p->value.sym = s; 1402*18235Slinton p->nodetype = s; 14039657Slinton } else { 1404*18235Slinton p = rec; 14059657Slinton t = rtype(p->nodetype); 14069657Slinton if (t->class == PTR) { 14079657Slinton s = findfield(fieldname, t->type); 14089657Slinton } else { 14099657Slinton s = findfield(fieldname, t); 14109657Slinton } 14119657Slinton if (s == nil) { 14129657Slinton beginerrmsg(); 14139657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 1414*18235Slinton prtree(stderr, rec); 14159657Slinton enderrmsg(); 14169657Slinton } 1417*18235Slinton if (t->class != PTR or isreg(rec->nodetype)) { 1418*18235Slinton p = unrval(p); 14199657Slinton } 1420*18235Slinton p->nodetype = t_addr; 14219657Slinton p = build(O_DOT, p, build(O_SYM, s)); 14229657Slinton } 1423*18235Slinton return build(O_RVAL, p); 14249657Slinton } 14259657Slinton 14269657Slinton /* 14279657Slinton * Return a tree corresponding to an array reference and do the 14289657Slinton * error checking. 14299657Slinton */ 14309657Slinton 14319657Slinton public Node subscript(a, slist) 14329657Slinton Node a, slist; 14339657Slinton { 143416620Ssam Symbol t; 1435*18235Slinton Node p; 14369657Slinton 143716620Ssam t = rtype(a->nodetype); 1438*18235Slinton if (t->language == nil or t->language == primlang) { 1439*18235Slinton p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); 144016620Ssam } else { 1441*18235Slinton p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); 144216620Ssam } 1443*18235Slinton return build(O_RVAL, p); 14449657Slinton } 14459657Slinton 14469657Slinton /* 14479657Slinton * Evaluate a subscript index. 14489657Slinton */ 14499657Slinton 1450*18235Slinton public int evalindex(s, base, i) 14519657Slinton Symbol s; 1452*18235Slinton Address base; 14539657Slinton long i; 14549657Slinton { 145516620Ssam Symbol t; 1456*18235Slinton int r; 14579657Slinton 145816620Ssam t = rtype(s); 1459*18235Slinton if (t->language == nil or t->language == primlang) { 1460*18235Slinton r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); 146116620Ssam } else { 1462*18235Slinton r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); 146316620Ssam } 1464*18235Slinton return r; 14659657Slinton } 14669657Slinton 14679657Slinton /* 14689657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 14699657Slinton */ 14709657Slinton 14719657Slinton public chkboolean(p) 14729657Slinton register Node p; 14739657Slinton { 14749657Slinton if (p->nodetype != t_boolean) { 14759657Slinton beginerrmsg(); 14769657Slinton fprintf(stderr, "found "); 14779657Slinton prtree(stderr, p); 14789657Slinton fprintf(stderr, ", expected boolean expression"); 14799657Slinton enderrmsg(); 14809657Slinton } 14819657Slinton } 14829657Slinton 14839657Slinton /* 148416620Ssam * Construct a node for the type of a string. 14859657Slinton */ 14869657Slinton 14879657Slinton private Symbol mkstring(str) 14889657Slinton String str; 14899657Slinton { 14909657Slinton register Symbol s; 14919657Slinton 1492*18235Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 1493*18235Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 1494*18235Slinton s->chain->language = s->language; 1495*18235Slinton s->chain->symvalue.rangev.lower = 1; 1496*18235Slinton s->chain->symvalue.rangev.upper = strlen(str) + 1; 14979657Slinton return s; 14989657Slinton } 14999657Slinton 15009657Slinton /* 15019657Slinton * Free up the space allocated for a string type. 15029657Slinton */ 15039657Slinton 15049657Slinton public unmkstring(s) 15059657Slinton Symbol s; 15069657Slinton { 15079657Slinton dispose(s->chain); 15089657Slinton } 15099657Slinton 15109657Slinton /* 1511*18235Slinton * Figure out the "current" variable or function being referred to 1512*18235Slinton * by the name n. 15139657Slinton */ 15149657Slinton 1515*18235Slinton private boolean stwhich(), dynwhich(); 1516*18235Slinton 1517*18235Slinton public Symbol which (n) 15189657Slinton Name n; 15199657Slinton { 1520*18235Slinton Symbol s; 15219657Slinton 1522*18235Slinton s = lookup(n); 15239657Slinton if (s == nil) { 1524*18235Slinton error("\"%s\" is not defined", ident(n)); 1525*18235Slinton } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { 1526*18235Slinton printf("[using "); 1527*18235Slinton printname(stdout, s); 1528*18235Slinton printf("]\n"); 15299657Slinton } 1530*18235Slinton return s; 1531*18235Slinton } 1532*18235Slinton 1533*18235Slinton /* 1534*18235Slinton * Static search. 1535*18235Slinton */ 1536*18235Slinton 1537*18235Slinton private boolean stwhich (var_s) 1538*18235Slinton Symbol *var_s; 1539*18235Slinton { 1540*18235Slinton Name n; /* name of desired symbol */ 1541*18235Slinton Symbol s; /* iteration variable for symbols with name n */ 1542*18235Slinton Symbol f; /* iteration variable for blocks containing s */ 1543*18235Slinton integer count; /* number of levels from s->block to curfunc */ 1544*18235Slinton Symbol t; /* current best answer for stwhich(n) */ 1545*18235Slinton integer mincount; /* relative level for current best answer (t) */ 1546*18235Slinton boolean b; /* return value, true if symbol found */ 1547*18235Slinton 1548*18235Slinton s = *var_s; 1549*18235Slinton n = s->name; 1550*18235Slinton t = s; 1551*18235Slinton mincount = 10000; /* force first match to set mincount */ 1552*18235Slinton do { 1553*18235Slinton if (s->name == n and s->class != FIELD and s->class != TAG) { 1554*18235Slinton f = curfunc; 1555*18235Slinton count = 0; 1556*18235Slinton while (f != nil and f != s->block) { 1557*18235Slinton ++count; 1558*18235Slinton f = f->block; 1559*18235Slinton } 1560*18235Slinton if (f != nil and count < mincount) { 1561*18235Slinton t = s; 1562*18235Slinton mincount = count; 1563*18235Slinton b = true; 1564*18235Slinton } 1565*18235Slinton } 1566*18235Slinton s = s->next_sym; 1567*18235Slinton } while (s != nil); 1568*18235Slinton if (mincount != 10000) { 1569*18235Slinton *var_s = t; 1570*18235Slinton b = true; 15719657Slinton } else { 1572*18235Slinton b = false; 1573*18235Slinton } 1574*18235Slinton return b; 1575*18235Slinton } 1576*18235Slinton 1577*18235Slinton /* 1578*18235Slinton * Dynamic search. 1579*18235Slinton */ 1580*18235Slinton 1581*18235Slinton private boolean dynwhich (var_s) 1582*18235Slinton Symbol *var_s; 1583*18235Slinton { 1584*18235Slinton Name n; /* name of desired symbol */ 1585*18235Slinton Symbol s; /* iteration variable for possible symbols */ 1586*18235Slinton Symbol f; /* iteration variable for active functions */ 1587*18235Slinton Frame frp; /* frame associated with stack walk */ 1588*18235Slinton boolean b; /* return value */ 1589*18235Slinton 1590*18235Slinton f = curfunc; 1591*18235Slinton frp = curfuncframe(); 1592*18235Slinton n = (*var_s)->name; 1593*18235Slinton b = false; 1594*18235Slinton if (frp != nil) { 1595*18235Slinton frp = nextfunc(frp, &f); 1596*18235Slinton while (frp != nil) { 1597*18235Slinton s = *var_s; 1598*18235Slinton while (s != nil and 1599*18235Slinton ( 1600*18235Slinton s->name != n or s->block != f or 1601*18235Slinton s->class == FIELD or s->class == TAG 1602*18235Slinton ) 1603*18235Slinton ) { 1604*18235Slinton s = s->next_sym; 1605*18235Slinton } 1606*18235Slinton if (s != nil) { 1607*18235Slinton *var_s = s; 1608*18235Slinton b = true; 1609*18235Slinton break; 1610*18235Slinton } 1611*18235Slinton if (f == program) { 1612*18235Slinton break; 1613*18235Slinton } 1614*18235Slinton frp = nextfunc(frp, &f); 16159657Slinton } 16169657Slinton } 1617*18235Slinton return b; 16189657Slinton } 16199657Slinton 16209657Slinton /* 1621*18235Slinton * Find the symbol that has the same name and scope as the 16229657Slinton * given symbol but is of the given field. Return nil if there is none. 16239657Slinton */ 16249657Slinton 1625*18235Slinton public Symbol findfield (fieldname, record) 16269657Slinton Name fieldname; 16279657Slinton Symbol record; 16289657Slinton { 16299657Slinton register Symbol t; 16309657Slinton 16319657Slinton t = rtype(record)->chain; 16329657Slinton while (t != nil and t->name != fieldname) { 16339657Slinton t = t->chain; 16349657Slinton } 16359657Slinton return t; 16369657Slinton } 163712547Scsvaf 163812547Scsvaf public Boolean getbound(s,off,type,valp) 163912547Scsvaf Symbol s; 164012547Scsvaf int off; 164112547Scsvaf Rangetype type; 164212547Scsvaf int *valp; 164312547Scsvaf { 164412547Scsvaf Frame frp; 164512547Scsvaf Address addr; 164612547Scsvaf Symbol cur; 164712547Scsvaf 164812547Scsvaf if (not isactive(s->block)) { 164912547Scsvaf return(false); 165012547Scsvaf } 165112547Scsvaf cur = s->block; 165212547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 165312547Scsvaf cur = cur->block; 165412547Scsvaf } 165512547Scsvaf if(cur == nil) { 165612547Scsvaf cur = whatblock(pc); 165712547Scsvaf } 165812547Scsvaf frp = findframe(cur); 165912547Scsvaf if (frp == nil) { 166012547Scsvaf return(false); 166112547Scsvaf } 166212547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 166312547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 166412547Scsvaf else return(false); 166512547Scsvaf dread(valp,addr,sizeof(long)); 166612547Scsvaf return(true); 166712547Scsvaf } 1668