121625Sdist /* 238105Sbostic * Copyright (c) 1983 The Regents of the University of California. 338105Sbostic * All rights reserved. 438105Sbostic * 538105Sbostic * Redistribution and use in source and binary forms are permitted 638105Sbostic * provided that the above copyright notice and this paragraph are 738105Sbostic * duplicated in all such forms and that any documentation, 838105Sbostic * advertising materials, and other materials related to such 938105Sbostic * distribution and use acknowledge that the software was developed 1038105Sbostic * by the University of California, Berkeley. The name of the 1138105Sbostic * University may not be used to endorse or promote products derived 1238105Sbostic * from this software without specific prior written permission. 1338105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1438105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1538105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621625Sdist */ 179657Slinton 1821625Sdist #ifndef lint 19*40260Sdonn static char sccsid[] = "@(#)symbols.c 5.7 (Berkeley) 03/03/90"; 2038105Sbostic #endif /* not lint */ 219657Slinton 229657Slinton /* 239657Slinton * Symbol management. 249657Slinton */ 259657Slinton 269657Slinton #include "defs.h" 279657Slinton #include "symbols.h" 289657Slinton #include "languages.h" 299657Slinton #include "printsym.h" 309657Slinton #include "tree.h" 319657Slinton #include "operators.h" 329657Slinton #include "eval.h" 339657Slinton #include "mappings.h" 349657Slinton #include "events.h" 359657Slinton #include "process.h" 369657Slinton #include "runtime.h" 379657Slinton #include "machine.h" 389657Slinton #include "names.h" 399657Slinton 409657Slinton #ifndef public 419657Slinton typedef struct Symbol *Symbol; 429657Slinton 439657Slinton #include "machine.h" 449657Slinton #include "names.h" 459657Slinton #include "languages.h" 4618235Slinton #include "tree.h" 479657Slinton 489657Slinton /* 499657Slinton * Symbol classes 509657Slinton */ 519657Slinton 529657Slinton typedef enum { 5333337Sdonn BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY, 5433337Sdonn PTRFILE, RECORD, FIELD, 5512547Scsvaf PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 569657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 5716620Ssam FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF 589657Slinton } Symclass; 599657Slinton 6012547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 6112547Scsvaf 6233337Sdonn #define INREG 0 6333337Sdonn #define STK 1 6433337Sdonn #define EXT 2 6533337Sdonn 66*40260Sdonn typedef unsigned int Storage; 6733337Sdonn 689657Slinton struct Symbol { 699657Slinton Name name; 709657Slinton Language language; 7133337Sdonn Symclass class : 8; 7233337Sdonn Storage storage : 2; 7333337Sdonn unsigned int level : 6; /* for variables stored on stack only */ 749657Slinton Symbol type; 759657Slinton Symbol chain; 769657Slinton union { 7718235Slinton Node constval; /* value of constant symbol */ 789657Slinton int offset; /* variable address */ 799657Slinton long iconval; /* integer constant value */ 809657Slinton double fconval; /* floating constant value */ 8118235Slinton int ndims; /* no. of dimensions for dynamic/sub-arrays */ 829657Slinton struct { /* field offset and size (both in bits) */ 839657Slinton int offset; 849657Slinton int length; 859657Slinton } field; 8612547Scsvaf struct { /* common offset and chain; used to relocate */ 8712547Scsvaf int offset; /* vars in global BSS */ 8812547Scsvaf Symbol chain; 8912547Scsvaf } common; 909657Slinton struct { /* range bounds */ 9112547Scsvaf Rangetype lowertype : 16; 9212547Scsvaf Rangetype uppertype : 16; 939657Slinton long lower; 949657Slinton long upper; 959657Slinton } rangev; 9611865Slinton struct { 9711865Slinton int offset : 16; /* offset for of function value */ 9816620Ssam Boolean src : 1; /* true if there is source line info */ 9916620Ssam Boolean inline : 1; /* true if no separate act. rec. */ 10016620Ssam Boolean intern : 1; /* internal calling sequence */ 10116620Ssam int unused : 13; 10211865Slinton Address beginaddr; /* address of function code */ 1039657Slinton } funcv; 1049657Slinton struct { /* variant record info */ 1059657Slinton int size; 1069657Slinton Symbol vtorec; 1079657Slinton Symbol vtag; 1089657Slinton } varnt; 10916620Ssam String typeref; /* type defined by "<module>:<type>" */ 11016620Ssam Symbol extref; /* indirect symbol for external reference */ 1119657Slinton } symvalue; 1129657Slinton Symbol block; /* symbol containing this symbol */ 1139657Slinton Symbol next_sym; /* hash chain */ 1149657Slinton }; 1159657Slinton 1169657Slinton /* 1179657Slinton * Basic types. 1189657Slinton */ 1199657Slinton 1209657Slinton Symbol t_boolean; 1219657Slinton Symbol t_char; 1229657Slinton Symbol t_int; 1239657Slinton Symbol t_real; 1249657Slinton Symbol t_nil; 12518235Slinton Symbol t_addr; 1269657Slinton 1279657Slinton Symbol program; 1289657Slinton Symbol curfunc; 1299657Slinton 13018235Slinton boolean showaggrs; 13118235Slinton 1329657Slinton #define symname(s) ident(s->name) 1339657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 1349657Slinton #define isblock(s) (Boolean) ( \ 1359657Slinton s->class == FUNC or s->class == PROC or \ 1369657Slinton s->class == MODULE or s->class == PROG \ 1379657Slinton ) 13816620Ssam #define isroutine(s) (Boolean) ( \ 13916620Ssam s->class == FUNC or s->class == PROC \ 14016620Ssam ) 1419657Slinton 14211865Slinton #define nosource(f) (not (f)->symvalue.funcv.src) 14314441Slinton #define isinline(f) ((f)->symvalue.funcv.inline) 14411865Slinton 14533337Sdonn #define isreg(s) (s->storage == INREG) 14624554Smckusick 1479657Slinton #include "tree.h" 1489657Slinton 1499657Slinton /* 1509657Slinton * Some macros to make finding a symbol with certain attributes. 1519657Slinton */ 1529657Slinton 1539657Slinton #define find(s, withname) \ 1549657Slinton { \ 1559657Slinton s = lookup(withname); \ 1569657Slinton while (s != nil and not (s->name == (withname) and 1579657Slinton 1589657Slinton #define where /* qualification */ 1599657Slinton 1609657Slinton #define endfind(s) )) { \ 1619657Slinton s = s->next_sym; \ 1629657Slinton } \ 1639657Slinton } 1649657Slinton 1659657Slinton #endif 1669657Slinton 1679657Slinton /* 1689657Slinton * Symbol table structure currently does not support deletions. 16933337Sdonn * Hash table size is a power of two to make hashing faster. 17033337Sdonn * Using a non-prime is ok since we aren't doing rehashing. 1719657Slinton */ 1729657Slinton 17333337Sdonn #define HASHTABLESIZE 8192 1749657Slinton 1759657Slinton private Symbol hashtab[HASHTABLESIZE]; 1769657Slinton 17733337Sdonn #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1)) 1789657Slinton 1799657Slinton /* 1809657Slinton * Allocate a new symbol. 1819657Slinton */ 1829657Slinton 18333337Sdonn #define SYMBLOCKSIZE 1000 1849657Slinton 1859657Slinton typedef struct Sympool { 1869657Slinton struct Symbol sym[SYMBLOCKSIZE]; 1879657Slinton struct Sympool *prevpool; 1889657Slinton } *Sympool; 1899657Slinton 1909657Slinton private Sympool sympool = nil; 1919657Slinton private Integer nleft = 0; 1929657Slinton 1939657Slinton public Symbol symbol_alloc() 1949657Slinton { 1959657Slinton register Sympool newpool; 1969657Slinton 1979657Slinton if (nleft <= 0) { 1989657Slinton newpool = new(Sympool); 19933337Sdonn bzero(newpool, sizeof(*newpool)); 2009657Slinton newpool->prevpool = sympool; 2019657Slinton sympool = newpool; 2029657Slinton nleft = SYMBLOCKSIZE; 2039657Slinton } 2049657Slinton --nleft; 2059657Slinton return &(sympool->sym[nleft]); 2069657Slinton } 2079657Slinton 20818235Slinton public symbol_dump (func) 20912547Scsvaf Symbol func; 21012547Scsvaf { 21118235Slinton register Symbol s; 21218235Slinton register integer i; 21312547Scsvaf 21418235Slinton printf(" symbols in %s \n",symname(func)); 21518235Slinton for (i = 0; i < HASHTABLESIZE; i++) { 21618235Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 21718235Slinton if (s->block == func) { 21818235Slinton psym(s); 21918235Slinton } 22018235Slinton } 22118235Slinton } 22212547Scsvaf } 22312547Scsvaf 2249657Slinton /* 2259657Slinton * Free all the symbols currently allocated. 2269657Slinton */ 22718235Slinton 2289657Slinton public symbol_free() 2299657Slinton { 2309657Slinton Sympool s, t; 2319657Slinton register Integer i; 2329657Slinton 2339657Slinton s = sympool; 2349657Slinton while (s != nil) { 2359657Slinton t = s->prevpool; 2369657Slinton dispose(s); 2379657Slinton s = t; 2389657Slinton } 2399657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 2409657Slinton hashtab[i] = nil; 2419657Slinton } 2429657Slinton sympool = nil; 2439657Slinton nleft = 0; 2449657Slinton } 2459657Slinton 2469657Slinton /* 2479657Slinton * Create a new symbol with the given attributes. 2489657Slinton */ 2499657Slinton 2509657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 2519657Slinton Name name; 2529657Slinton Integer blevel; 2539657Slinton Symclass class; 2549657Slinton Symbol type; 2559657Slinton Symbol chain; 2569657Slinton { 2579657Slinton register Symbol s; 2589657Slinton 2599657Slinton s = symbol_alloc(); 2609657Slinton s->name = name; 26118235Slinton s->language = primlang; 26233337Sdonn s->storage = EXT; 2639657Slinton s->level = blevel; 2649657Slinton s->class = class; 2659657Slinton s->type = type; 2669657Slinton s->chain = chain; 2679657Slinton return s; 2689657Slinton } 2699657Slinton 2709657Slinton /* 2719657Slinton * Insert a symbol into the hash table. 2729657Slinton */ 2739657Slinton 2749657Slinton public Symbol insert(name) 2759657Slinton Name name; 2769657Slinton { 2779657Slinton register Symbol s; 2789657Slinton register unsigned int h; 2799657Slinton 2809657Slinton h = hash(name); 2819657Slinton s = symbol_alloc(); 2829657Slinton s->name = name; 2839657Slinton s->next_sym = hashtab[h]; 2849657Slinton hashtab[h] = s; 2859657Slinton return s; 2869657Slinton } 2879657Slinton 2889657Slinton /* 2899657Slinton * Symbol lookup. 2909657Slinton */ 2919657Slinton 2929657Slinton public Symbol lookup(name) 2939657Slinton Name name; 2949657Slinton { 2959657Slinton register Symbol s; 2969657Slinton register unsigned int h; 2979657Slinton 2989657Slinton h = hash(name); 2999657Slinton s = hashtab[h]; 3009657Slinton while (s != nil and s->name != name) { 3019657Slinton s = s->next_sym; 3029657Slinton } 3039657Slinton return s; 3049657Slinton } 3059657Slinton 3069657Slinton /* 30716620Ssam * Delete a symbol from the symbol table. 30816620Ssam */ 30916620Ssam 31016620Ssam public delete (s) 31116620Ssam Symbol s; 31216620Ssam { 31316620Ssam register Symbol t; 31416620Ssam register unsigned int h; 31516620Ssam 31616620Ssam h = hash(s->name); 31716620Ssam t = hashtab[h]; 31816620Ssam if (t == nil) { 31916620Ssam panic("delete of non-symbol '%s'", symname(s)); 32016620Ssam } else if (t == s) { 32116620Ssam hashtab[h] = s->next_sym; 32216620Ssam } else { 32316620Ssam while (t->next_sym != s) { 32416620Ssam t = t->next_sym; 32516620Ssam if (t == nil) { 32616620Ssam panic("delete of non-symbol '%s'", symname(s)); 32716620Ssam } 32816620Ssam } 32916620Ssam t->next_sym = s->next_sym; 33016620Ssam } 33116620Ssam } 33216620Ssam 33316620Ssam /* 3349657Slinton * Dump out all the variables associated with the given 33518235Slinton * procedure, function, or program associated with the given stack frame. 3369657Slinton * 3379657Slinton * This is quite inefficient. We traverse the entire symbol table 3389657Slinton * each time we're called. The assumption is that this routine 3399657Slinton * won't be called frequently enough to merit improved performance. 3409657Slinton */ 3419657Slinton 3429657Slinton public dumpvars(f, frame) 3439657Slinton Symbol f; 3449657Slinton Frame frame; 3459657Slinton { 3469657Slinton register Integer i; 3479657Slinton register Symbol s; 3489657Slinton 3499657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 3509657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 3519657Slinton if (container(s) == f) { 3529657Slinton if (should_print(s)) { 3539657Slinton printv(s, frame); 3549657Slinton putchar('\n'); 3559657Slinton } else if (s->class == MODULE) { 3569657Slinton dumpvars(s, frame); 3579657Slinton } 3589657Slinton } 3599657Slinton } 3609657Slinton } 3619657Slinton } 3629657Slinton 3639657Slinton /* 3649657Slinton * Create a builtin type. 3659657Slinton * Builtin types are circular in that btype->type->type = btype. 3669657Slinton */ 3679657Slinton 36818235Slinton private Symbol maketype(name, lower, upper) 3699657Slinton String name; 3709657Slinton long lower; 3719657Slinton long upper; 3729657Slinton { 3739657Slinton register Symbol s; 37418235Slinton Name n; 3759657Slinton 37618235Slinton if (name == nil) { 37718235Slinton n = nil; 37818235Slinton } else { 37918235Slinton n = identname(name, true); 38018235Slinton } 38118235Slinton s = insert(n); 38216620Ssam s->language = primlang; 38318235Slinton s->level = 0; 38418235Slinton s->class = TYPE; 38518235Slinton s->type = nil; 38618235Slinton s->chain = nil; 3879657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 3889657Slinton s->type->symvalue.rangev.lower = lower; 3899657Slinton s->type->symvalue.rangev.upper = upper; 3909657Slinton return s; 3919657Slinton } 3929657Slinton 3939657Slinton /* 39418235Slinton * Create the builtin symbols. 39518235Slinton */ 39618235Slinton 39718235Slinton public symbols_init () 3989657Slinton { 39918235Slinton Symbol s; 4009657Slinton 40118235Slinton t_boolean = maketype("$boolean", 0L, 1L); 40218235Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 40318235Slinton t_char = maketype("$char", 0L, 255L); 40418235Slinton t_real = maketype("$real", 8L, 0L); 40518235Slinton t_nil = maketype("$nil", 0L, 0L); 40618235Slinton t_addr = insert(identname("$address", true)); 40718235Slinton t_addr->language = primlang; 40818235Slinton t_addr->level = 0; 40918235Slinton t_addr->class = TYPE; 41018235Slinton t_addr->type = newSymbol(nil, 1, PTR, t_int, nil); 41118235Slinton s = insert(identname("true", true)); 41218235Slinton s->class = CONST; 41318235Slinton s->type = t_boolean; 41418235Slinton s->symvalue.constval = build(O_LCON, 1L); 41518235Slinton s->symvalue.constval->nodetype = t_boolean; 41618235Slinton s = insert(identname("false", true)); 41718235Slinton s->class = CONST; 41818235Slinton s->type = t_boolean; 41918235Slinton s->symvalue.constval = build(O_LCON, 0L); 42018235Slinton s->symvalue.constval->nodetype = t_boolean; 4219657Slinton } 4229657Slinton 4239657Slinton /* 4249657Slinton * Reduce type to avoid worrying about type names. 4259657Slinton */ 4269657Slinton 4279657Slinton public Symbol rtype(type) 4289657Slinton Symbol type; 4299657Slinton { 4309657Slinton register Symbol t; 4319657Slinton 4329657Slinton t = type; 4339657Slinton if (t != nil) { 43418235Slinton if (t->class == VAR or t->class == CONST or 43518235Slinton t->class == FIELD or t->class == REF 43618235Slinton ) { 4379657Slinton t = t->type; 4389657Slinton } 43916620Ssam if (t->class == TYPEREF) { 44016620Ssam resolveRef(t); 44116620Ssam } 4429657Slinton while (t->class == TYPE or t->class == TAG) { 4439657Slinton t = t->type; 44416620Ssam if (t->class == TYPEREF) { 44516620Ssam resolveRef(t); 44616620Ssam } 4479657Slinton } 4489657Slinton } 4499657Slinton return t; 4509657Slinton } 4519657Slinton 45216620Ssam /* 45316620Ssam * Find the end of a module name. Return nil if there is none 45416620Ssam * in the given string. 45516620Ssam */ 45616620Ssam 45716620Ssam private String findModuleMark (s) 45816620Ssam String s; 45916620Ssam { 46016620Ssam register char *p, *r; 46116620Ssam register boolean done; 46216620Ssam 46316620Ssam p = s; 46416620Ssam done = false; 46516620Ssam do { 46616620Ssam if (*p == ':') { 46716620Ssam done = true; 46816620Ssam r = p; 46916620Ssam } else if (*p == '\0') { 47016620Ssam done = true; 47116620Ssam r = nil; 47216620Ssam } else { 47316620Ssam ++p; 47416620Ssam } 47516620Ssam } while (not done); 47616620Ssam return r; 47716620Ssam } 47816620Ssam 47916620Ssam /* 48016620Ssam * Resolve a type reference by modifying to be the appropriate type. 48116620Ssam * 48216620Ssam * If the reference has a name, then it refers to an opaque type and 48316620Ssam * the actual type is directly accessible. Otherwise, we must use 48416620Ssam * the type reference string, which is of the form "module:{module:}name". 48516620Ssam */ 48616620Ssam 48716620Ssam public resolveRef (t) 48816620Ssam Symbol t; 48916620Ssam { 49016620Ssam register char *p; 49116620Ssam char *start; 49216620Ssam Symbol s, m, outer; 49316620Ssam Name n; 49416620Ssam 49516620Ssam if (t->name != nil) { 49616620Ssam s = t; 49716620Ssam } else { 49816620Ssam start = t->symvalue.typeref; 49916620Ssam outer = program; 50016620Ssam p = findModuleMark(start); 50116620Ssam while (p != nil) { 50216620Ssam *p = '\0'; 50316620Ssam n = identname(start, true); 50416620Ssam find(m, n) where m->block == outer endfind(m); 50516620Ssam if (m == nil) { 50616620Ssam p = nil; 50716620Ssam outer = nil; 50816620Ssam s = nil; 50916620Ssam } else { 51016620Ssam outer = m; 51116620Ssam start = p + 1; 51216620Ssam p = findModuleMark(start); 51316620Ssam } 51416620Ssam } 51516620Ssam if (outer != nil) { 51616620Ssam n = identname(start, true); 51716620Ssam find(s, n) where s->block == outer endfind(s); 51816620Ssam } 51916620Ssam } 52016620Ssam if (s != nil and s->type != nil) { 52116620Ssam t->name = s->type->name; 52216620Ssam t->class = s->type->class; 52316620Ssam t->type = s->type->type; 52416620Ssam t->chain = s->type->chain; 52516620Ssam t->symvalue = s->type->symvalue; 52616620Ssam t->block = s->type->block; 52716620Ssam } 52816620Ssam } 52916620Ssam 53018235Slinton public integer regnum (s) 5319657Slinton Symbol s; 5329657Slinton { 53318235Slinton integer r; 53418235Slinton 5359657Slinton checkref(s); 53633337Sdonn if (s->storage == INREG) { 53718235Slinton r = s->symvalue.offset; 53818235Slinton } else { 53918235Slinton r = -1; 54018235Slinton } 54118235Slinton return r; 5429657Slinton } 5439657Slinton 5449657Slinton public Symbol container(s) 5459657Slinton Symbol s; 5469657Slinton { 5479657Slinton checkref(s); 5489657Slinton return s->block; 5499657Slinton } 5509657Slinton 55118235Slinton public Node constval(s) 55218235Slinton Symbol s; 55318235Slinton { 55418235Slinton checkref(s); 55518235Slinton if (s->class != CONST) { 55618235Slinton error("[internal error: constval(non-CONST)]"); 55718235Slinton } 55818235Slinton return s->symvalue.constval; 55918235Slinton } 56018235Slinton 5619657Slinton /* 5629657Slinton * Return the object address of the given symbol. 5639657Slinton * 5649657Slinton * There are the following possibilities: 5659657Slinton * 5669657Slinton * globals - just take offset 5679657Slinton * locals - take offset from locals base 5689657Slinton * arguments - take offset from argument base 5699657Slinton * register - offset is register number 5709657Slinton */ 5719657Slinton 57233337Sdonn #define isglobal(s) (s->storage == EXT) 57333337Sdonn #define islocaloff(s) (s->storage == STK and s->symvalue.offset < 0) 57433337Sdonn #define isparamoff(s) (s->storage == STK and s->symvalue.offset >= 0) 5759657Slinton 57618235Slinton public Address address (s, frame) 5779657Slinton Symbol s; 5789657Slinton Frame frame; 5799657Slinton { 5809657Slinton register Frame frp; 5819657Slinton register Address addr; 5829657Slinton register Symbol cur; 5839657Slinton 5849657Slinton checkref(s); 5859657Slinton if (not isactive(s->block)) { 5869657Slinton error("\"%s\" is not currently defined", symname(s)); 5879657Slinton } else if (isglobal(s)) { 5889657Slinton addr = s->symvalue.offset; 5899657Slinton } else { 5909657Slinton frp = frame; 5919657Slinton if (frp == nil) { 5929657Slinton cur = s->block; 5939657Slinton while (cur != nil and cur->class == MODULE) { 5949657Slinton cur = cur->block; 5959657Slinton } 5969657Slinton if (cur == nil) { 59718235Slinton frp = nil; 59818235Slinton } else { 59918235Slinton frp = findframe(cur); 60018235Slinton if (frp == nil) { 60118235Slinton error("[internal error: unexpected nil frame for \"%s\"]", 60218235Slinton symname(s) 60318235Slinton ); 60418235Slinton } 6059657Slinton } 6069657Slinton } 6079657Slinton if (islocaloff(s)) { 6089657Slinton addr = locals_base(frp) + s->symvalue.offset; 6099657Slinton } else if (isparamoff(s)) { 6109657Slinton addr = args_base(frp) + s->symvalue.offset; 6119657Slinton } else if (isreg(s)) { 6129657Slinton addr = savereg(s->symvalue.offset, frp); 6139657Slinton } else { 6149657Slinton panic("address: bad symbol \"%s\"", symname(s)); 6159657Slinton } 6169657Slinton } 6179657Slinton return addr; 6189657Slinton } 6199657Slinton 6209657Slinton /* 6219657Slinton * Define a symbol used to access register values. 6229657Slinton */ 6239657Slinton 62418235Slinton public defregname (n, r) 6259657Slinton Name n; 62618235Slinton integer r; 6279657Slinton { 62818235Slinton Symbol s; 6299657Slinton 6309657Slinton s = insert(n); 63118235Slinton s->language = t_addr->language; 6329657Slinton s->class = VAR; 63333337Sdonn s->storage = INREG; 63433337Sdonn s->level = 3; 63518235Slinton s->type = t_addr; 6369657Slinton s->symvalue.offset = r; 6379657Slinton } 6389657Slinton 6399657Slinton /* 6409657Slinton * Resolve an "abstract" type reference. 6419657Slinton * 6429657Slinton * It is possible in C to define a pointer to a type, but never define 6439657Slinton * the type in a particular source file. Here we try to resolve 6449657Slinton * the type definition. This is problematic, it is possible to 6459657Slinton * have multiple, different definitions for the same name type. 6469657Slinton */ 6479657Slinton 6489657Slinton public findtype(s) 6499657Slinton Symbol s; 6509657Slinton { 6519657Slinton register Symbol t, u, prev; 6529657Slinton 6539657Slinton u = s; 6549657Slinton prev = nil; 6559657Slinton while (u != nil and u->class != BADUSE) { 6569657Slinton if (u->name != nil) { 6579657Slinton prev = u; 6589657Slinton } 6599657Slinton u = u->type; 6609657Slinton } 6619657Slinton if (prev == nil) { 6629657Slinton error("couldn't find link to type reference"); 6639657Slinton } 66418235Slinton t = lookup(prev->name); 66518235Slinton while (t != nil and 66618235Slinton not ( 66718235Slinton t != prev and t->name == prev->name and 66818235Slinton t->block->class == MODULE and t->class == prev->class and 66918235Slinton t->type != nil and t->type->type != nil and 67018235Slinton t->type->type->class != BADUSE 67118235Slinton ) 67218235Slinton ) { 67318235Slinton t = t->next_sym; 67418235Slinton } 6759657Slinton if (t == nil) { 6769657Slinton error("couldn't resolve reference"); 6779657Slinton } else { 6789657Slinton prev->type = t->type; 6799657Slinton } 6809657Slinton } 6819657Slinton 6829657Slinton /* 6839657Slinton * Find the size in bytes of the given type. 6849657Slinton * 6859657Slinton * This is probably the WRONG thing to do. The size should be kept 6869657Slinton * as an attribute in the symbol information as is done for structures 6879657Slinton * and fields. I haven't gotten around to cleaning this up yet. 6889657Slinton */ 6899657Slinton 69012547Scsvaf #define MAXUCHAR 255 69112547Scsvaf #define MAXUSHORT 65535L 6929657Slinton #define MINCHAR -128 6939657Slinton #define MAXCHAR 127 6949657Slinton #define MINSHORT -32768 6959657Slinton #define MAXSHORT 32767 6969657Slinton 69716620Ssam public findbounds (u, lower, upper) 69816620Ssam Symbol u; 69916620Ssam long *lower, *upper; 70016620Ssam { 70116620Ssam Rangetype lbt, ubt; 70216620Ssam long lb, ub; 70316620Ssam 70416620Ssam if (u->class == RANGE) { 70516620Ssam lbt = u->symvalue.rangev.lowertype; 70616620Ssam ubt = u->symvalue.rangev.uppertype; 70716620Ssam lb = u->symvalue.rangev.lower; 70816620Ssam ub = u->symvalue.rangev.upper; 70916620Ssam if (lbt == R_ARG or lbt == R_TEMP) { 71016620Ssam if (not getbound(u, lb, lbt, lower)) { 71116620Ssam error("dynamic bounds not currently available"); 71216620Ssam } 71316620Ssam } else { 71416620Ssam *lower = lb; 71516620Ssam } 71616620Ssam if (ubt == R_ARG or ubt == R_TEMP) { 71716620Ssam if (not getbound(u, ub, ubt, upper)) { 71816620Ssam error("dynamic bounds not currently available"); 71916620Ssam } 72016620Ssam } else { 72116620Ssam *upper = ub; 72216620Ssam } 72316620Ssam } else if (u->class == SCAL) { 72416620Ssam *lower = 0; 72516620Ssam *upper = u->symvalue.iconval - 1; 72616620Ssam } else { 72718235Slinton error("[internal error: unexpected array bound type]"); 72816620Ssam } 72916620Ssam } 73016620Ssam 73116620Ssam public integer size(sym) 73216620Ssam Symbol sym; 73316620Ssam { 73416620Ssam register Symbol s, t, u; 73516620Ssam register integer nel, elsize; 7369657Slinton long lower, upper; 73716620Ssam integer r, off, len; 7389657Slinton 7399657Slinton t = sym; 7409657Slinton checkref(t); 74116620Ssam if (t->class == TYPEREF) { 74216620Ssam resolveRef(t); 74316620Ssam } 7449657Slinton switch (t->class) { 7459657Slinton case RANGE: 7469657Slinton lower = t->symvalue.rangev.lower; 7479657Slinton upper = t->symvalue.rangev.upper; 74816620Ssam if (upper == 0 and lower > 0) { 74916620Ssam /* real */ 7509657Slinton r = lower; 75116620Ssam } else if (lower > upper) { 75216620Ssam /* unsigned long */ 75316620Ssam r = sizeof(long); 75412045Slinton } else if ( 75512547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or 75612547Scsvaf (lower >= 0 and upper <= MAXUCHAR) 75712547Scsvaf ) { 7589657Slinton r = sizeof(char); 75912547Scsvaf } else if ( 76012547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or 76112547Scsvaf (lower >= 0 and upper <= MAXUSHORT) 76212547Scsvaf ) { 7639657Slinton r = sizeof(short); 7649657Slinton } else { 7659657Slinton r = sizeof(long); 7669657Slinton } 7679657Slinton break; 7689657Slinton 7699657Slinton case ARRAY: 7709657Slinton elsize = size(t->type); 7719657Slinton nel = 1; 7729657Slinton for (t = t->chain; t != nil; t = t->chain) { 77316620Ssam u = rtype(t); 77416620Ssam findbounds(u, &lower, &upper); 7759657Slinton nel *= (upper-lower+1); 7769657Slinton } 7779657Slinton r = nel*elsize; 7789657Slinton break; 7799657Slinton 78033337Sdonn case OPENARRAY: 78118235Slinton case DYNARRAY: 78218235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 78318235Slinton break; 78418235Slinton 78518235Slinton case SUBARRAY: 78618235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 78718235Slinton break; 78818235Slinton 78912547Scsvaf case REF: 7909657Slinton case VAR: 7919657Slinton r = size(t->type); 79212127Slinton /* 79312127Slinton * 79412045Slinton if (r < sizeof(Word) and isparam(t)) { 7959657Slinton r = sizeof(Word); 7969657Slinton } 79712547Scsvaf */ 7989657Slinton break; 7999657Slinton 80018235Slinton case FVAR: 8019657Slinton case CONST: 80218235Slinton case TAG: 8039657Slinton r = size(t->type); 8049657Slinton break; 8059657Slinton 8069657Slinton case TYPE: 80733337Sdonn /* 80833337Sdonn * This causes problems on the IRIS because of the compiler bug 80933337Sdonn * with stab offsets for parameters. Not sure it's really 81033337Sdonn * necessary anyway. 81133337Sdonn */ 81233337Sdonn # ifndef IRIS 8139657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 8149657Slinton findtype(t); 8159657Slinton } 81633337Sdonn # endif 8179657Slinton r = size(t->type); 8189657Slinton break; 8199657Slinton 8209657Slinton case FIELD: 82116620Ssam off = t->symvalue.field.offset; 82216620Ssam len = t->symvalue.field.length; 82316620Ssam r = (off + len + 7) div 8 - (off div 8); 8249657Slinton break; 8259657Slinton 8269657Slinton case RECORD: 8279657Slinton case VARNT: 8289657Slinton r = t->symvalue.offset; 8299657Slinton if (r == 0 and t->chain != nil) { 8309657Slinton panic("missing size information for record"); 8319657Slinton } 8329657Slinton break; 8339657Slinton 8349657Slinton case PTR: 83518235Slinton case TYPEREF: 8369657Slinton case FILET: 8379657Slinton r = sizeof(Word); 8389657Slinton break; 8399657Slinton 8409657Slinton case SCAL: 84112609Slinton r = sizeof(Word); 84212609Slinton /* 84312609Slinton * 8449657Slinton if (t->symvalue.iconval > 255) { 8459657Slinton r = sizeof(short); 8469657Slinton } else { 8479657Slinton r = sizeof(char); 8489657Slinton } 84912609Slinton * 85012609Slinton */ 8519657Slinton break; 8529657Slinton 8539657Slinton case FPROC: 8549657Slinton case FFUNC: 8559657Slinton r = sizeof(Word); 8569657Slinton break; 8579657Slinton 8589657Slinton case PROC: 8599657Slinton case FUNC: 8609657Slinton case MODULE: 8619657Slinton case PROG: 8629657Slinton r = sizeof(Symbol); 8639657Slinton break; 8649657Slinton 86516620Ssam case SET: 86616620Ssam u = rtype(t->type); 86716620Ssam switch (u->class) { 86816620Ssam case RANGE: 86916620Ssam r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; 87016620Ssam break; 87116620Ssam 87216620Ssam case SCAL: 87316620Ssam r = u->symvalue.iconval; 87416620Ssam break; 87516620Ssam 87616620Ssam default: 87716620Ssam error("expected range for set base type"); 87816620Ssam break; 87916620Ssam } 88016620Ssam r = (r + BITSPERBYTE - 1) div BITSPERBYTE; 88116620Ssam break; 88216620Ssam 88318235Slinton /* 88418235Slinton * These can happen in C (unfortunately) for unresolved type references 88518235Slinton * Assume they are pointers. 88618235Slinton */ 88718235Slinton case BADUSE: 88818235Slinton r = sizeof(Address); 88918235Slinton break; 89018235Slinton 8919657Slinton default: 8929657Slinton if (ord(t->class) > ord(TYPEREF)) { 8939657Slinton panic("size: bad class (%d)", ord(t->class)); 8949657Slinton } else { 89518235Slinton fprintf(stderr, "can't compute size of a %s\n", classname(t)); 8969657Slinton } 89716620Ssam r = 0; 89816620Ssam break; 8999657Slinton } 9009657Slinton return r; 9019657Slinton } 9029657Slinton 9039657Slinton /* 90418235Slinton * Return the size associated with a symbol that takes into account 90518235Slinton * reference parameters. This might be better as the normal size function, but 90618235Slinton * too many places already depend on it working the way it does. 90718235Slinton */ 90818235Slinton 90918235Slinton public integer psize (s) 91018235Slinton Symbol s; 91118235Slinton { 91218235Slinton integer r; 91318235Slinton Symbol t; 91418235Slinton 91518235Slinton if (s->class == REF) { 91618235Slinton t = rtype(s->type); 91733337Sdonn if (t->class == OPENARRAY) { 91818235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word); 91918235Slinton } else if (t->class == SUBARRAY) { 92018235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 92118235Slinton } else { 92218235Slinton r = sizeof(Word); 92318235Slinton } 92418235Slinton } else { 92518235Slinton r = size(s); 92618235Slinton } 92718235Slinton return r; 92818235Slinton } 92918235Slinton 93018235Slinton /* 9319657Slinton * Test if a symbol is a parameter. This is true if there 9329657Slinton * is a cycle from s->block to s via chain pointers. 9339657Slinton */ 9349657Slinton 9359657Slinton public Boolean isparam(s) 9369657Slinton Symbol s; 9379657Slinton { 9389657Slinton register Symbol t; 9399657Slinton 9409657Slinton t = s->block; 9419657Slinton while (t != nil and t != s) { 9429657Slinton t = t->chain; 9439657Slinton } 9449657Slinton return (Boolean) (t != nil); 9459657Slinton } 9469657Slinton 9479657Slinton /* 94816620Ssam * Test if a type is an open array parameter type. 9499657Slinton */ 9509657Slinton 95118235Slinton public boolean isopenarray (type) 95218235Slinton Symbol type; 95316620Ssam { 95418235Slinton Symbol t; 95518235Slinton 95618235Slinton t = rtype(type); 95733337Sdonn return (boolean) (t->class == OPENARRAY); 95816620Ssam } 95916620Ssam 96016620Ssam /* 96118235Slinton * Test if a symbol is a var parameter, i.e. has class REF. 96216620Ssam */ 96316620Ssam 9649657Slinton public Boolean isvarparam(s) 9659657Slinton Symbol s; 9669657Slinton { 9679657Slinton return (Boolean) (s->class == REF); 9689657Slinton } 9699657Slinton 9709657Slinton /* 9719657Slinton * Test if a symbol is a variable (actually any addressible quantity 9729657Slinton * with do). 9739657Slinton */ 9749657Slinton 9759657Slinton public Boolean isvariable(s) 97618235Slinton Symbol s; 9779657Slinton { 9789657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 9799657Slinton } 9809657Slinton 9819657Slinton /* 98218235Slinton * Test if a symbol is a constant. 98318235Slinton */ 98418235Slinton 98518235Slinton public Boolean isconst(s) 98618235Slinton Symbol s; 9879657Slinton { 98818235Slinton return (Boolean) (s->class == CONST); 9899657Slinton } 9909657Slinton 9919657Slinton /* 9929657Slinton * Test if a symbol is a module. 9939657Slinton */ 9949657Slinton 9959657Slinton public Boolean ismodule(s) 9969657Slinton register Symbol s; 9979657Slinton { 9989657Slinton return (Boolean) (s->class == MODULE); 9999657Slinton } 10009657Slinton 10019657Slinton /* 100216620Ssam * Mark a procedure or function as internal, meaning that it is called 100316620Ssam * with a different calling sequence. 100416620Ssam */ 100516620Ssam 100616620Ssam public markInternal (s) 100716620Ssam Symbol s; 100816620Ssam { 100916620Ssam s->symvalue.funcv.intern = true; 101016620Ssam } 101116620Ssam 101216620Ssam public boolean isinternal (s) 101316620Ssam Symbol s; 101416620Ssam { 101516620Ssam return s->symvalue.funcv.intern; 101616620Ssam } 101716620Ssam 101816620Ssam /* 101918235Slinton * Decide if a field begins or ends on a bit rather than byte boundary. 102018235Slinton */ 102118235Slinton 102218235Slinton public Boolean isbitfield(s) 102318235Slinton register Symbol s; 102418235Slinton { 102518235Slinton boolean b; 102618235Slinton register integer off, len; 102718235Slinton register Symbol t; 102818235Slinton 102918235Slinton off = s->symvalue.field.offset; 103018235Slinton len = s->symvalue.field.length; 103118235Slinton if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { 103218235Slinton b = true; 103318235Slinton } else { 103418235Slinton t = rtype(s->type); 103518235Slinton b = (Boolean) ( 103618235Slinton (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or 103718235Slinton len != (size(t)*BITSPERBYTE) 103818235Slinton ); 103918235Slinton } 104018235Slinton return b; 104118235Slinton } 104218235Slinton 104318235Slinton private boolean primlang_typematch (t1, t2) 104418235Slinton Symbol t1, t2; 104518235Slinton { 104618235Slinton return (boolean) ( 104718235Slinton (t1 == t2) or 104818235Slinton ( 104918235Slinton t1->class == RANGE and t2->class == RANGE and 105018235Slinton t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 105118235Slinton t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 105218235Slinton ) or ( 105318235Slinton t1->class == PTR and t2->class == RANGE and 105418235Slinton t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower 105518235Slinton ) or ( 105618235Slinton t2->class == PTR and t1->class == RANGE and 105718235Slinton t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower 105818235Slinton ) 105918235Slinton ); 106018235Slinton } 106118235Slinton 106218235Slinton /* 10639657Slinton * Test if two types match. 10649657Slinton * Equivalent names implies a match in any language. 10659657Slinton * 10669657Slinton * Special symbols must be handled with care. 10679657Slinton */ 10689657Slinton 10699657Slinton public Boolean compatible(t1, t2) 10709657Slinton register Symbol t1, t2; 10719657Slinton { 10729657Slinton Boolean b; 107316620Ssam Symbol rt1, rt2; 10749657Slinton 10759657Slinton if (t1 == t2) { 10769657Slinton b = true; 10779657Slinton } else if (t1 == nil or t2 == nil) { 10789657Slinton b = false; 10799657Slinton } else if (t1 == procsym) { 10809657Slinton b = isblock(t2); 10819657Slinton } else if (t2 == procsym) { 10829657Slinton b = isblock(t1); 10839657Slinton } else if (t1->language == nil) { 108416620Ssam if (t2->language == nil) { 108516620Ssam b = false; 108633337Sdonn } else if (t2->language == primlang) { 108733337Sdonn b = (boolean) primlang_typematch(rtype(t1), rtype(t2)); 108816620Ssam } else { 108916620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 109016620Ssam } 109133337Sdonn } else if (t1->language == primlang) { 109233337Sdonn if (t2->language == primlang or t2->language == nil) { 109333337Sdonn b = primlang_typematch(rtype(t1), rtype(t2)); 109433337Sdonn } else { 109533337Sdonn b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 109633337Sdonn } 10979657Slinton } else { 109816620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 10999657Slinton } 11009657Slinton return b; 11019657Slinton } 11029657Slinton 11039657Slinton /* 11049657Slinton * Check for a type of the given name. 11059657Slinton */ 11069657Slinton 11079657Slinton public Boolean istypename(type, name) 11089657Slinton Symbol type; 11099657Slinton String name; 11109657Slinton { 111118235Slinton register Symbol t; 11129657Slinton Boolean b; 11139657Slinton 11149657Slinton t = type; 111518235Slinton if (t == nil) { 111618235Slinton b = false; 111718235Slinton } else { 111818235Slinton b = (Boolean) ( 111918235Slinton t->class == TYPE and streq(ident(t->name), name) 112018235Slinton ); 112118235Slinton } 11229657Slinton return b; 11239657Slinton } 11249657Slinton 11259657Slinton /* 112616620Ssam * Determine if a (value) parameter should actually be passed by address. 112716620Ssam */ 112816620Ssam 112916620Ssam public boolean passaddr (p, exprtype) 113016620Ssam Symbol p, exprtype; 113116620Ssam { 113216620Ssam boolean b; 113316620Ssam Language def; 113416620Ssam 113516620Ssam if (p == nil) { 113616620Ssam def = findlanguage(".c"); 113716620Ssam b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); 113816620Ssam } else if (p->language == nil or p->language == primlang) { 113916620Ssam b = false; 114016620Ssam } else if (isopenarray(p->type)) { 114116620Ssam b = true; 114216620Ssam } else { 114316620Ssam b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); 114416620Ssam } 114516620Ssam return b; 114616620Ssam } 114716620Ssam 114816620Ssam /* 11499657Slinton * Test if the name of a symbol is uniquely defined or not. 11509657Slinton */ 11519657Slinton 11529657Slinton public Boolean isambiguous(s) 11539657Slinton register Symbol s; 11549657Slinton { 11559657Slinton register Symbol t; 11569657Slinton 11579657Slinton find(t, s->name) where t != s endfind(t); 11589657Slinton return (Boolean) (t != nil); 11599657Slinton } 11609657Slinton 11619657Slinton typedef char *Arglist; 11629657Slinton 11639657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 11649657Slinton 11659657Slinton private Symbol mkstring(); 11669657Slinton 11679657Slinton /* 11689657Slinton * Determine the type of a parse tree. 116918235Slinton * 11709657Slinton * Also make some symbol-dependent changes to the tree such as 117118235Slinton * removing indirection for constant or register symbols. 11729657Slinton */ 11739657Slinton 117418235Slinton public assigntypes (p) 11759657Slinton register Node p; 11769657Slinton { 11779657Slinton register Node p1; 11789657Slinton register Symbol s; 11799657Slinton 11809657Slinton switch (p->op) { 11819657Slinton case O_SYM: 118218235Slinton p->nodetype = p->value.sym; 11839657Slinton break; 11849657Slinton 11859657Slinton case O_LCON: 11869657Slinton p->nodetype = t_int; 11879657Slinton break; 11889657Slinton 118918235Slinton case O_CCON: 119018235Slinton p->nodetype = t_char; 119118235Slinton break; 119218235Slinton 11939657Slinton case O_FCON: 11949657Slinton p->nodetype = t_real; 11959657Slinton break; 11969657Slinton 11979657Slinton case O_SCON: 119818235Slinton p->nodetype = mkstring(p->value.scon); 11999657Slinton break; 12009657Slinton 12019657Slinton case O_INDIR: 12029657Slinton p1 = p->value.arg[0]; 120318235Slinton s = rtype(p1->nodetype); 120418235Slinton if (s->class != PTR) { 120518235Slinton beginerrmsg(); 120618235Slinton fprintf(stderr, "\""); 120718235Slinton prtree(stderr, p1); 120818235Slinton fprintf(stderr, "\" is not a pointer"); 120918235Slinton enderrmsg(); 121018235Slinton } 12119657Slinton p->nodetype = rtype(p1->nodetype)->type; 12129657Slinton break; 12139657Slinton 12149657Slinton case O_DOT: 12159657Slinton p->nodetype = p->value.arg[1]->value.sym; 12169657Slinton break; 12179657Slinton 12189657Slinton case O_RVAL: 12199657Slinton p1 = p->value.arg[0]; 12209657Slinton p->nodetype = p1->nodetype; 12219657Slinton if (p1->op == O_SYM) { 122218235Slinton if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) { 122318235Slinton p->op = p1->op; 122418235Slinton p->value.sym = p1->value.sym; 122518235Slinton p->nodetype = p1->nodetype; 122618235Slinton dispose(p1); 12279657Slinton } else if (p1->value.sym->class == CONST) { 122818235Slinton p->op = p1->op; 122918235Slinton p->value = p1->value; 123018235Slinton p->nodetype = p1->nodetype; 123118235Slinton dispose(p1); 12329657Slinton } else if (isreg(p1->value.sym)) { 12339657Slinton p->op = O_SYM; 12349657Slinton p->value.sym = p1->value.sym; 12359657Slinton dispose(p1); 12369657Slinton } 12379657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 12389657Slinton s = p1->value.arg[0]->value.sym; 12399657Slinton if (isreg(s)) { 12409657Slinton p1->op = O_SYM; 12419657Slinton dispose(p1->value.arg[0]); 12429657Slinton p1->value.sym = s; 12439657Slinton p1->nodetype = s; 12449657Slinton } 12459657Slinton } 12469657Slinton break; 12479657Slinton 124818235Slinton case O_COMMA: 124918235Slinton p->nodetype = p->value.arg[0]->nodetype; 125018235Slinton break; 125118235Slinton 125218235Slinton case O_CALLPROC: 12539657Slinton case O_CALL: 12549657Slinton p1 = p->value.arg[0]; 125511171Slinton p->nodetype = rtype(p1->nodetype)->type; 12569657Slinton break; 12579657Slinton 125811171Slinton case O_TYPERENAME: 125911171Slinton p->nodetype = p->value.arg[1]->nodetype; 126011171Slinton break; 126111171Slinton 12629657Slinton case O_ITOF: 12639657Slinton p->nodetype = t_real; 12649657Slinton break; 12659657Slinton 12669657Slinton case O_NEG: 12679657Slinton s = p->value.arg[0]->nodetype; 12689657Slinton if (not compatible(s, t_int)) { 12699657Slinton if (not compatible(s, t_real)) { 12709657Slinton beginerrmsg(); 127116620Ssam fprintf(stderr, "\""); 12729657Slinton prtree(stderr, p->value.arg[0]); 127316620Ssam fprintf(stderr, "\" is improper type"); 12749657Slinton enderrmsg(); 12759657Slinton } else { 12769657Slinton p->op = O_NEGF; 12779657Slinton } 12789657Slinton } 12799657Slinton p->nodetype = s; 12809657Slinton break; 12819657Slinton 12829657Slinton case O_ADD: 12839657Slinton case O_SUB: 12849657Slinton case O_MUL: 128516620Ssam binaryop(p, nil); 128616620Ssam break; 128716620Ssam 12889657Slinton case O_LT: 12899657Slinton case O_LE: 12909657Slinton case O_GT: 12919657Slinton case O_GE: 12929657Slinton case O_EQ: 12939657Slinton case O_NE: 129416620Ssam binaryop(p, t_boolean); 12959657Slinton break; 12969657Slinton 12979657Slinton case O_DIVF: 12989657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 12999657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 13009657Slinton p->nodetype = t_real; 13019657Slinton break; 13029657Slinton 13039657Slinton case O_DIV: 13049657Slinton case O_MOD: 13059657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 13069657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 13079657Slinton p->nodetype = t_int; 13089657Slinton break; 13099657Slinton 13109657Slinton case O_AND: 13119657Slinton case O_OR: 13129657Slinton chkboolean(p->value.arg[0]); 13139657Slinton chkboolean(p->value.arg[1]); 13149657Slinton p->nodetype = t_boolean; 13159657Slinton break; 13169657Slinton 13179657Slinton case O_QLINE: 13189657Slinton p->nodetype = t_int; 13199657Slinton break; 13209657Slinton 13219657Slinton default: 13229657Slinton p->nodetype = nil; 13239657Slinton break; 13249657Slinton } 13259657Slinton } 13269657Slinton 13279657Slinton /* 132816620Ssam * Process a binary arithmetic or relational operator. 132916620Ssam * Convert from integer to real if necessary. 133016620Ssam */ 133116620Ssam 133216620Ssam private binaryop (p, t) 133316620Ssam Node p; 133416620Ssam Symbol t; 133516620Ssam { 133616620Ssam Node p1, p2; 133716620Ssam Boolean t1real, t2real; 133816620Ssam Symbol t1, t2; 133916620Ssam 134016620Ssam p1 = p->value.arg[0]; 134116620Ssam p2 = p->value.arg[1]; 134216620Ssam t1 = rtype(p1->nodetype); 134316620Ssam t2 = rtype(p2->nodetype); 134416620Ssam t1real = compatible(t1, t_real); 134516620Ssam t2real = compatible(t2, t_real); 134616620Ssam if (t1real or t2real) { 134716620Ssam p->op = (Operator) (ord(p->op) + 1); 134816620Ssam if (not t1real) { 134916620Ssam p->value.arg[0] = build(O_ITOF, p1); 135016620Ssam } else if (not t2real) { 135116620Ssam p->value.arg[1] = build(O_ITOF, p2); 135216620Ssam } 135316620Ssam p->nodetype = t_real; 135416620Ssam } else { 135516620Ssam if (size(p1->nodetype) > sizeof(integer)) { 135616620Ssam beginerrmsg(); 135716620Ssam fprintf(stderr, "operation not defined on \""); 135816620Ssam prtree(stderr, p1); 135916620Ssam fprintf(stderr, "\""); 136016620Ssam enderrmsg(); 136116620Ssam } else if (size(p2->nodetype) > sizeof(integer)) { 136216620Ssam beginerrmsg(); 136316620Ssam fprintf(stderr, "operation not defined on \""); 136416620Ssam prtree(stderr, p2); 136516620Ssam fprintf(stderr, "\""); 136616620Ssam enderrmsg(); 136716620Ssam } 136816620Ssam p->nodetype = t_int; 136916620Ssam } 137016620Ssam if (t != nil) { 137116620Ssam p->nodetype = t; 137216620Ssam } 137316620Ssam } 137416620Ssam 137516620Ssam /* 13769657Slinton * Convert a tree to a type via a conversion operator; 13779657Slinton * if this isn't possible generate an error. 13789657Slinton */ 13799657Slinton 13809657Slinton private convert(tp, typeto, op) 13819657Slinton Node *tp; 13829657Slinton Symbol typeto; 13839657Slinton Operator op; 13849657Slinton { 138516620Ssam Node tree; 138616620Ssam Symbol s, t; 13879657Slinton 138816620Ssam tree = *tp; 13899657Slinton s = rtype(tree->nodetype); 139016620Ssam t = rtype(typeto); 139116620Ssam if (compatible(t, t_real) and compatible(s, t_int)) { 139234257Sdonn /* we can convert int => floating but not the reverse */ 13939657Slinton tree = build(op, tree); 139416620Ssam } else if (not compatible(s, t)) { 13959657Slinton beginerrmsg(); 139616620Ssam prtree(stderr, tree); 139734257Sdonn fprintf(stderr, ": illegal type in operation"); 13989657Slinton enderrmsg(); 13999657Slinton } 140016620Ssam *tp = tree; 14019657Slinton } 14029657Slinton 14039657Slinton /* 14049657Slinton * Construct a node for the dot operator. 14059657Slinton * 14069657Slinton * If the left operand is not a record, but rather a procedure 14079657Slinton * or function, then we interpret the "." as referencing an 14089657Slinton * "invisible" variable; i.e. a variable within a dynamically 14099657Slinton * active block but not within the static scope of the current procedure. 14109657Slinton */ 14119657Slinton 14129657Slinton public Node dot(record, fieldname) 14139657Slinton Node record; 14149657Slinton Name fieldname; 14159657Slinton { 141618235Slinton register Node rec, p; 14179657Slinton register Symbol s, t; 14189657Slinton 141918235Slinton rec = record; 142018235Slinton if (isblock(rec->nodetype)) { 14219657Slinton find(s, fieldname) where 142218235Slinton s->block == rec->nodetype and 142318235Slinton s->class != FIELD 14249657Slinton endfind(s); 14259657Slinton if (s == nil) { 14269657Slinton beginerrmsg(); 14279657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 142818235Slinton printname(stderr, rec->nodetype); 14299657Slinton enderrmsg(); 14309657Slinton } 14319657Slinton p = new(Node); 14329657Slinton p->op = O_SYM; 14339657Slinton p->value.sym = s; 143418235Slinton p->nodetype = s; 14359657Slinton } else { 143618235Slinton p = rec; 14379657Slinton t = rtype(p->nodetype); 14389657Slinton if (t->class == PTR) { 14399657Slinton s = findfield(fieldname, t->type); 14409657Slinton } else { 14419657Slinton s = findfield(fieldname, t); 14429657Slinton } 14439657Slinton if (s == nil) { 14449657Slinton beginerrmsg(); 14459657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 144618235Slinton prtree(stderr, rec); 14479657Slinton enderrmsg(); 14489657Slinton } 144918235Slinton if (t->class != PTR or isreg(rec->nodetype)) { 145018235Slinton p = unrval(p); 14519657Slinton } 145218235Slinton p->nodetype = t_addr; 14539657Slinton p = build(O_DOT, p, build(O_SYM, s)); 14549657Slinton } 145518235Slinton return build(O_RVAL, p); 14569657Slinton } 14579657Slinton 14589657Slinton /* 14599657Slinton * Return a tree corresponding to an array reference and do the 14609657Slinton * error checking. 14619657Slinton */ 14629657Slinton 14639657Slinton public Node subscript(a, slist) 14649657Slinton Node a, slist; 14659657Slinton { 146616620Ssam Symbol t; 146718235Slinton Node p; 14689657Slinton 146916620Ssam t = rtype(a->nodetype); 147018235Slinton if (t->language == nil or t->language == primlang) { 147118235Slinton p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); 147216620Ssam } else { 147318235Slinton p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); 147416620Ssam } 147518235Slinton return build(O_RVAL, p); 14769657Slinton } 14779657Slinton 14789657Slinton /* 14799657Slinton * Evaluate a subscript index. 14809657Slinton */ 14819657Slinton 148218235Slinton public int evalindex(s, base, i) 14839657Slinton Symbol s; 148418235Slinton Address base; 14859657Slinton long i; 14869657Slinton { 148716620Ssam Symbol t; 148818235Slinton int r; 14899657Slinton 149016620Ssam t = rtype(s); 149118235Slinton if (t->language == nil or t->language == primlang) { 149218235Slinton r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); 149316620Ssam } else { 149418235Slinton r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); 149516620Ssam } 149618235Slinton return r; 14979657Slinton } 14989657Slinton 14999657Slinton /* 15009657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 15019657Slinton */ 15029657Slinton 15039657Slinton public chkboolean(p) 15049657Slinton register Node p; 15059657Slinton { 15069657Slinton if (p->nodetype != t_boolean) { 15079657Slinton beginerrmsg(); 15089657Slinton fprintf(stderr, "found "); 15099657Slinton prtree(stderr, p); 15109657Slinton fprintf(stderr, ", expected boolean expression"); 15119657Slinton enderrmsg(); 15129657Slinton } 15139657Slinton } 15149657Slinton 15159657Slinton /* 151616620Ssam * Construct a node for the type of a string. 15179657Slinton */ 15189657Slinton 15199657Slinton private Symbol mkstring(str) 15209657Slinton String str; 15219657Slinton { 15229657Slinton register Symbol s; 15239657Slinton 152418235Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil); 152518235Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 152618235Slinton s->chain->language = s->language; 152718235Slinton s->chain->symvalue.rangev.lower = 1; 152818235Slinton s->chain->symvalue.rangev.upper = strlen(str) + 1; 15299657Slinton return s; 15309657Slinton } 15319657Slinton 15329657Slinton /* 15339657Slinton * Free up the space allocated for a string type. 15349657Slinton */ 15359657Slinton 15369657Slinton public unmkstring(s) 15379657Slinton Symbol s; 15389657Slinton { 15399657Slinton dispose(s->chain); 15409657Slinton } 15419657Slinton 15429657Slinton /* 154318235Slinton * Figure out the "current" variable or function being referred to 154418235Slinton * by the name n. 15459657Slinton */ 15469657Slinton 154718235Slinton private boolean stwhich(), dynwhich(); 154818235Slinton 154918235Slinton public Symbol which (n) 15509657Slinton Name n; 15519657Slinton { 155218235Slinton Symbol s; 15539657Slinton 155418235Slinton s = lookup(n); 15559657Slinton if (s == nil) { 155618235Slinton error("\"%s\" is not defined", ident(n)); 155718235Slinton } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { 155818235Slinton printf("[using "); 155918235Slinton printname(stdout, s); 156018235Slinton printf("]\n"); 15619657Slinton } 156218235Slinton return s; 156318235Slinton } 156418235Slinton 156518235Slinton /* 156618235Slinton * Static search. 156718235Slinton */ 156818235Slinton 156918235Slinton private boolean stwhich (var_s) 157018235Slinton Symbol *var_s; 157118235Slinton { 157218235Slinton Name n; /* name of desired symbol */ 157318235Slinton Symbol s; /* iteration variable for symbols with name n */ 157418235Slinton Symbol f; /* iteration variable for blocks containing s */ 157518235Slinton integer count; /* number of levels from s->block to curfunc */ 157618235Slinton Symbol t; /* current best answer for stwhich(n) */ 157718235Slinton integer mincount; /* relative level for current best answer (t) */ 157818235Slinton boolean b; /* return value, true if symbol found */ 157918235Slinton 158018235Slinton s = *var_s; 158118235Slinton n = s->name; 158218235Slinton t = s; 158318235Slinton mincount = 10000; /* force first match to set mincount */ 158418235Slinton do { 158518235Slinton if (s->name == n and s->class != FIELD and s->class != TAG) { 158618235Slinton f = curfunc; 158718235Slinton count = 0; 158818235Slinton while (f != nil and f != s->block) { 158918235Slinton ++count; 159018235Slinton f = f->block; 159118235Slinton } 159218235Slinton if (f != nil and count < mincount) { 159318235Slinton t = s; 159418235Slinton mincount = count; 159518235Slinton b = true; 159618235Slinton } 159718235Slinton } 159818235Slinton s = s->next_sym; 159918235Slinton } while (s != nil); 160018235Slinton if (mincount != 10000) { 160118235Slinton *var_s = t; 160218235Slinton b = true; 16039657Slinton } else { 160418235Slinton b = false; 160518235Slinton } 160618235Slinton return b; 160718235Slinton } 160818235Slinton 160918235Slinton /* 161018235Slinton * Dynamic search. 161118235Slinton */ 161218235Slinton 161318235Slinton private boolean dynwhich (var_s) 161418235Slinton Symbol *var_s; 161518235Slinton { 161618235Slinton Name n; /* name of desired symbol */ 161718235Slinton Symbol s; /* iteration variable for possible symbols */ 161818235Slinton Symbol f; /* iteration variable for active functions */ 161918235Slinton Frame frp; /* frame associated with stack walk */ 162018235Slinton boolean b; /* return value */ 162118235Slinton 162218235Slinton f = curfunc; 162318235Slinton frp = curfuncframe(); 162418235Slinton n = (*var_s)->name; 162518235Slinton b = false; 162618235Slinton if (frp != nil) { 162718235Slinton frp = nextfunc(frp, &f); 162818235Slinton while (frp != nil) { 162918235Slinton s = *var_s; 163018235Slinton while (s != nil and 163118235Slinton ( 163218235Slinton s->name != n or s->block != f or 163318235Slinton s->class == FIELD or s->class == TAG 163418235Slinton ) 163518235Slinton ) { 163618235Slinton s = s->next_sym; 163718235Slinton } 163818235Slinton if (s != nil) { 163918235Slinton *var_s = s; 164018235Slinton b = true; 164118235Slinton break; 164218235Slinton } 164318235Slinton if (f == program) { 164418235Slinton break; 164518235Slinton } 164618235Slinton frp = nextfunc(frp, &f); 16479657Slinton } 16489657Slinton } 164918235Slinton return b; 16509657Slinton } 16519657Slinton 16529657Slinton /* 165318235Slinton * Find the symbol that has the same name and scope as the 16549657Slinton * given symbol but is of the given field. Return nil if there is none. 16559657Slinton */ 16569657Slinton 165718235Slinton public Symbol findfield (fieldname, record) 16589657Slinton Name fieldname; 16599657Slinton Symbol record; 16609657Slinton { 16619657Slinton register Symbol t; 16629657Slinton 16639657Slinton t = rtype(record)->chain; 16649657Slinton while (t != nil and t->name != fieldname) { 16659657Slinton t = t->chain; 16669657Slinton } 16679657Slinton return t; 16689657Slinton } 166912547Scsvaf 167012547Scsvaf public Boolean getbound(s,off,type,valp) 167112547Scsvaf Symbol s; 167212547Scsvaf int off; 167312547Scsvaf Rangetype type; 167412547Scsvaf int *valp; 167512547Scsvaf { 167612547Scsvaf Frame frp; 167712547Scsvaf Address addr; 167812547Scsvaf Symbol cur; 167912547Scsvaf 168012547Scsvaf if (not isactive(s->block)) { 168112547Scsvaf return(false); 168212547Scsvaf } 168312547Scsvaf cur = s->block; 168412547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 168512547Scsvaf cur = cur->block; 168612547Scsvaf } 168712547Scsvaf if(cur == nil) { 168812547Scsvaf cur = whatblock(pc); 168912547Scsvaf } 169012547Scsvaf frp = findframe(cur); 169112547Scsvaf if (frp == nil) { 169212547Scsvaf return(false); 169312547Scsvaf } 169412547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 169512547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 169612547Scsvaf else return(false); 169712547Scsvaf dread(valp,addr,sizeof(long)); 169812547Scsvaf return(true); 169912547Scsvaf } 1700