19657Slinton /* Copyright (c) 1982 Regents of the University of California */ 29657Slinton 3*16620Ssam static char sccsid[] = "@(#)symbols.c 1.10 8/10/83"; 49657Slinton 5*16620Ssam static char rcsid[] = "$Header: symbols.c,v 1.4 84/03/27 10:24:18 linton Exp $"; 6*16620Ssam 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" 319657Slinton 329657Slinton /* 339657Slinton * Symbol classes 349657Slinton */ 359657Slinton 369657Slinton typedef enum { 379657Slinton BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD, 3812547Scsvaf PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 399657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 40*16620Ssam FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF 419657Slinton } Symclass; 429657Slinton 4312547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 4412547Scsvaf 459657Slinton struct Symbol { 469657Slinton Name name; 479657Slinton Language language; 489657Slinton Symclass class : 8; 499657Slinton Integer level : 8; 509657Slinton Symbol type; 519657Slinton Symbol chain; 529657Slinton union { 539657Slinton int offset; /* variable address */ 549657Slinton long iconval; /* integer constant value */ 559657Slinton double fconval; /* floating constant value */ 569657Slinton struct { /* field offset and size (both in bits) */ 579657Slinton int offset; 589657Slinton int length; 599657Slinton } field; 6012547Scsvaf struct { /* common offset and chain; used to relocate */ 6112547Scsvaf int offset; /* vars in global BSS */ 6212547Scsvaf Symbol chain; 6312547Scsvaf } common; 649657Slinton struct { /* range bounds */ 6512547Scsvaf Rangetype lowertype : 16; 6612547Scsvaf Rangetype uppertype : 16; 679657Slinton long lower; 689657Slinton long upper; 699657Slinton } rangev; 7011865Slinton struct { 7111865Slinton int offset : 16; /* offset for of function value */ 72*16620Ssam Boolean src : 1; /* true if there is source line info */ 73*16620Ssam Boolean inline : 1; /* true if no separate act. rec. */ 74*16620Ssam Boolean intern : 1; /* internal calling sequence */ 75*16620Ssam int unused : 13; 7611865Slinton Address beginaddr; /* address of function code */ 779657Slinton } funcv; 789657Slinton struct { /* variant record info */ 799657Slinton int size; 809657Slinton Symbol vtorec; 819657Slinton Symbol vtag; 829657Slinton } varnt; 83*16620Ssam String typeref; /* type defined by "<module>:<type>" */ 84*16620Ssam Symbol extref; /* indirect symbol for external reference */ 859657Slinton } symvalue; 869657Slinton Symbol block; /* symbol containing this symbol */ 879657Slinton Symbol next_sym; /* hash chain */ 889657Slinton }; 899657Slinton 909657Slinton /* 919657Slinton * Basic types. 929657Slinton */ 939657Slinton 949657Slinton Symbol t_boolean; 959657Slinton Symbol t_char; 969657Slinton Symbol t_int; 979657Slinton Symbol t_real; 989657Slinton Symbol t_nil; 99*16620Ssam Symbol t_open; 1009657Slinton 1019657Slinton Symbol program; 1029657Slinton Symbol curfunc; 1039657Slinton 1049657Slinton #define symname(s) ident(s->name) 1059657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 1069657Slinton #define isblock(s) (Boolean) ( \ 1079657Slinton s->class == FUNC or s->class == PROC or \ 1089657Slinton s->class == MODULE or s->class == PROG \ 1099657Slinton ) 110*16620Ssam #define isroutine(s) (Boolean) ( \ 111*16620Ssam s->class == FUNC or s->class == PROC \ 112*16620Ssam ) 1139657Slinton 11411865Slinton #define nosource(f) (not (f)->symvalue.funcv.src) 11514441Slinton #define isinline(f) ((f)->symvalue.funcv.inline) 11611865Slinton 1179657Slinton #include "tree.h" 1189657Slinton 1199657Slinton /* 1209657Slinton * Some macros to make finding a symbol with certain attributes. 1219657Slinton */ 1229657Slinton 1239657Slinton #define find(s, withname) \ 1249657Slinton { \ 1259657Slinton s = lookup(withname); \ 1269657Slinton while (s != nil and not (s->name == (withname) and 1279657Slinton 1289657Slinton #define where /* qualification */ 1299657Slinton 1309657Slinton #define endfind(s) )) { \ 1319657Slinton s = s->next_sym; \ 1329657Slinton } \ 1339657Slinton } 1349657Slinton 1359657Slinton #endif 1369657Slinton 1379657Slinton /* 1389657Slinton * Symbol table structure currently does not support deletions. 1399657Slinton */ 1409657Slinton 1419657Slinton #define HASHTABLESIZE 2003 1429657Slinton 1439657Slinton private Symbol hashtab[HASHTABLESIZE]; 1449657Slinton 1459657Slinton #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 1469657Slinton 1479657Slinton /* 1489657Slinton * Allocate a new symbol. 1499657Slinton */ 1509657Slinton 15111171Slinton #define SYMBLOCKSIZE 100 1529657Slinton 1539657Slinton typedef struct Sympool { 1549657Slinton struct Symbol sym[SYMBLOCKSIZE]; 1559657Slinton struct Sympool *prevpool; 1569657Slinton } *Sympool; 1579657Slinton 1589657Slinton private Sympool sympool = nil; 1599657Slinton private Integer nleft = 0; 1609657Slinton 1619657Slinton public Symbol symbol_alloc() 1629657Slinton { 1639657Slinton register Sympool newpool; 1649657Slinton 1659657Slinton if (nleft <= 0) { 1669657Slinton newpool = new(Sympool); 16711171Slinton bzero(newpool, sizeof(newpool)); 1689657Slinton newpool->prevpool = sympool; 1699657Slinton sympool = newpool; 1709657Slinton nleft = SYMBLOCKSIZE; 1719657Slinton } 1729657Slinton --nleft; 1739657Slinton return &(sympool->sym[nleft]); 1749657Slinton } 1759657Slinton 17612547Scsvaf 17712547Scsvaf public symbol_dump(func) 17812547Scsvaf Symbol func; 17912547Scsvaf { 180*16620Ssam register Symbol s; 181*16620Ssam register Integer i; 18212547Scsvaf 183*16620Ssam printf(" symbols in %s \n",symname(func)); 184*16620Ssam for(i=0; i< HASHTABLESIZE; i++) 185*16620Ssam for(s=hashtab[i]; s != nil; s=s->next_sym) { 186*16620Ssam if (s->block == func) psym(s); 187*16620Ssam } 18812547Scsvaf } 18912547Scsvaf 1909657Slinton /* 1919657Slinton * Free all the symbols currently allocated. 1929657Slinton */ 1939657Slinton public symbol_free() 1949657Slinton { 1959657Slinton Sympool s, t; 1969657Slinton register Integer i; 1979657Slinton 1989657Slinton s = sympool; 1999657Slinton while (s != nil) { 2009657Slinton t = s->prevpool; 2019657Slinton dispose(s); 2029657Slinton s = t; 2039657Slinton } 2049657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 2059657Slinton hashtab[i] = nil; 2069657Slinton } 2079657Slinton sympool = nil; 2089657Slinton nleft = 0; 2099657Slinton } 2109657Slinton 2119657Slinton /* 2129657Slinton * Create a new symbol with the given attributes. 2139657Slinton */ 2149657Slinton 2159657Slinton public Symbol newSymbol(name, blevel, class, type, chain) 2169657Slinton Name name; 2179657Slinton Integer blevel; 2189657Slinton Symclass class; 2199657Slinton Symbol type; 2209657Slinton Symbol chain; 2219657Slinton { 2229657Slinton register Symbol s; 2239657Slinton 2249657Slinton s = symbol_alloc(); 2259657Slinton s->name = name; 2269657Slinton s->level = blevel; 2279657Slinton s->class = class; 2289657Slinton s->type = type; 2299657Slinton s->chain = chain; 2309657Slinton return s; 2319657Slinton } 2329657Slinton 2339657Slinton /* 2349657Slinton * Insert a symbol into the hash table. 2359657Slinton */ 2369657Slinton 2379657Slinton public Symbol insert(name) 2389657Slinton Name name; 2399657Slinton { 2409657Slinton register Symbol s; 2419657Slinton register unsigned int h; 2429657Slinton 2439657Slinton h = hash(name); 2449657Slinton s = symbol_alloc(); 2459657Slinton s->name = name; 2469657Slinton s->next_sym = hashtab[h]; 2479657Slinton hashtab[h] = s; 2489657Slinton return s; 2499657Slinton } 2509657Slinton 2519657Slinton /* 2529657Slinton * Symbol lookup. 2539657Slinton */ 2549657Slinton 2559657Slinton public Symbol lookup(name) 2569657Slinton Name name; 2579657Slinton { 2589657Slinton register Symbol s; 2599657Slinton register unsigned int h; 2609657Slinton 2619657Slinton h = hash(name); 2629657Slinton s = hashtab[h]; 2639657Slinton while (s != nil and s->name != name) { 2649657Slinton s = s->next_sym; 2659657Slinton } 2669657Slinton return s; 2679657Slinton } 2689657Slinton 2699657Slinton /* 270*16620Ssam * Delete a symbol from the symbol table. 271*16620Ssam */ 272*16620Ssam 273*16620Ssam public delete (s) 274*16620Ssam Symbol s; 275*16620Ssam { 276*16620Ssam register Symbol t; 277*16620Ssam register unsigned int h; 278*16620Ssam 279*16620Ssam h = hash(s->name); 280*16620Ssam t = hashtab[h]; 281*16620Ssam if (t == nil) { 282*16620Ssam panic("delete of non-symbol '%s'", symname(s)); 283*16620Ssam } else if (t == s) { 284*16620Ssam hashtab[h] = s->next_sym; 285*16620Ssam } else { 286*16620Ssam while (t->next_sym != s) { 287*16620Ssam t = t->next_sym; 288*16620Ssam if (t == nil) { 289*16620Ssam panic("delete of non-symbol '%s'", symname(s)); 290*16620Ssam } 291*16620Ssam } 292*16620Ssam t->next_sym = s->next_sym; 293*16620Ssam } 294*16620Ssam } 295*16620Ssam 296*16620Ssam /* 2979657Slinton * Dump out all the variables associated with the given 2989657Slinton * procedure, function, or program at the given recursive level. 2999657Slinton * 3009657Slinton * This is quite inefficient. We traverse the entire symbol table 3019657Slinton * each time we're called. The assumption is that this routine 3029657Slinton * won't be called frequently enough to merit improved performance. 3039657Slinton */ 3049657Slinton 3059657Slinton public dumpvars(f, frame) 3069657Slinton Symbol f; 3079657Slinton Frame frame; 3089657Slinton { 3099657Slinton register Integer i; 3109657Slinton register Symbol s; 3119657Slinton 3129657Slinton for (i = 0; i < HASHTABLESIZE; i++) { 3139657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) { 3149657Slinton if (container(s) == f) { 3159657Slinton if (should_print(s)) { 3169657Slinton printv(s, frame); 3179657Slinton putchar('\n'); 3189657Slinton } else if (s->class == MODULE) { 3199657Slinton dumpvars(s, frame); 3209657Slinton } 3219657Slinton } 3229657Slinton } 3239657Slinton } 3249657Slinton } 3259657Slinton 3269657Slinton /* 3279657Slinton * Create a builtin type. 3289657Slinton * Builtin types are circular in that btype->type->type = btype. 3299657Slinton */ 3309657Slinton 3319657Slinton public Symbol maketype(name, lower, upper) 3329657Slinton String name; 3339657Slinton long lower; 3349657Slinton long upper; 3359657Slinton { 3369657Slinton register Symbol s; 3379657Slinton 3389657Slinton s = newSymbol(identname(name, true), 0, TYPE, nil, nil); 339*16620Ssam s->language = primlang; 3409657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil); 341*16620Ssam s->type->language = s->language; 3429657Slinton s->type->symvalue.rangev.lower = lower; 3439657Slinton s->type->symvalue.rangev.upper = upper; 3449657Slinton return s; 3459657Slinton } 3469657Slinton 3479657Slinton /* 3489657Slinton * These functions are now compiled inline. 3499657Slinton * 3509657Slinton * public String symname(s) 3519657Slinton Symbol s; 3529657Slinton { 3539657Slinton checkref(s); 3549657Slinton return ident(s->name); 3559657Slinton } 3569657Slinton 3579657Slinton * 3589657Slinton * public Address codeloc(f) 3599657Slinton Symbol f; 3609657Slinton { 3619657Slinton checkref(f); 3629657Slinton if (not isblock(f)) { 3639657Slinton panic("codeloc: \"%s\" is not a block", ident(f->name)); 3649657Slinton } 3659657Slinton return f->symvalue.funcv.beginaddr; 3669657Slinton } 3679657Slinton * 3689657Slinton */ 3699657Slinton 3709657Slinton /* 3719657Slinton * Reduce type to avoid worrying about type names. 3729657Slinton */ 3739657Slinton 3749657Slinton public Symbol rtype(type) 3759657Slinton Symbol type; 3769657Slinton { 3779657Slinton register Symbol t; 3789657Slinton 3799657Slinton t = type; 3809657Slinton if (t != nil) { 38112547Scsvaf if (t->class == VAR or t->class == FIELD or t->class == REF ) { 3829657Slinton t = t->type; 3839657Slinton } 384*16620Ssam if (t->class == TYPEREF) { 385*16620Ssam resolveRef(t); 386*16620Ssam } 3879657Slinton while (t->class == TYPE or t->class == TAG) { 3889657Slinton t = t->type; 389*16620Ssam if (t->class == TYPEREF) { 390*16620Ssam resolveRef(t); 391*16620Ssam } 3929657Slinton } 3939657Slinton } 3949657Slinton return t; 3959657Slinton } 3969657Slinton 397*16620Ssam /* 398*16620Ssam * Find the end of a module name. Return nil if there is none 399*16620Ssam * in the given string. 400*16620Ssam */ 401*16620Ssam 402*16620Ssam private String findModuleMark (s) 403*16620Ssam String s; 404*16620Ssam { 405*16620Ssam register char *p, *r; 406*16620Ssam register boolean done; 407*16620Ssam 408*16620Ssam p = s; 409*16620Ssam done = false; 410*16620Ssam do { 411*16620Ssam if (*p == ':') { 412*16620Ssam done = true; 413*16620Ssam r = p; 414*16620Ssam } else if (*p == '\0') { 415*16620Ssam done = true; 416*16620Ssam r = nil; 417*16620Ssam } else { 418*16620Ssam ++p; 419*16620Ssam } 420*16620Ssam } while (not done); 421*16620Ssam return r; 422*16620Ssam } 423*16620Ssam 424*16620Ssam /* 425*16620Ssam * Resolve a type reference by modifying to be the appropriate type. 426*16620Ssam * 427*16620Ssam * If the reference has a name, then it refers to an opaque type and 428*16620Ssam * the actual type is directly accessible. Otherwise, we must use 429*16620Ssam * the type reference string, which is of the form "module:{module:}name". 430*16620Ssam */ 431*16620Ssam 432*16620Ssam public resolveRef (t) 433*16620Ssam Symbol t; 434*16620Ssam { 435*16620Ssam register char *p; 436*16620Ssam char *start; 437*16620Ssam Symbol s, m, outer; 438*16620Ssam Name n; 439*16620Ssam 440*16620Ssam if (t->name != nil) { 441*16620Ssam s = t; 442*16620Ssam } else { 443*16620Ssam start = t->symvalue.typeref; 444*16620Ssam outer = program; 445*16620Ssam p = findModuleMark(start); 446*16620Ssam while (p != nil) { 447*16620Ssam *p = '\0'; 448*16620Ssam n = identname(start, true); 449*16620Ssam find(m, n) where m->block == outer endfind(m); 450*16620Ssam if (m == nil) { 451*16620Ssam p = nil; 452*16620Ssam outer = nil; 453*16620Ssam s = nil; 454*16620Ssam } else { 455*16620Ssam outer = m; 456*16620Ssam start = p + 1; 457*16620Ssam p = findModuleMark(start); 458*16620Ssam } 459*16620Ssam } 460*16620Ssam if (outer != nil) { 461*16620Ssam n = identname(start, true); 462*16620Ssam find(s, n) where s->block == outer endfind(s); 463*16620Ssam } 464*16620Ssam } 465*16620Ssam if (s != nil and s->type != nil) { 466*16620Ssam t->name = s->type->name; 467*16620Ssam t->class = s->type->class; 468*16620Ssam t->type = s->type->type; 469*16620Ssam t->chain = s->type->chain; 470*16620Ssam t->symvalue = s->type->symvalue; 471*16620Ssam t->block = s->type->block; 472*16620Ssam } 473*16620Ssam } 474*16620Ssam 4759657Slinton public Integer level(s) 4769657Slinton Symbol s; 4779657Slinton { 4789657Slinton checkref(s); 4799657Slinton return s->level; 4809657Slinton } 4819657Slinton 4829657Slinton public Symbol container(s) 4839657Slinton Symbol s; 4849657Slinton { 4859657Slinton checkref(s); 4869657Slinton return s->block; 4879657Slinton } 4889657Slinton 4899657Slinton /* 4909657Slinton * Return the object address of the given symbol. 4919657Slinton * 4929657Slinton * There are the following possibilities: 4939657Slinton * 4949657Slinton * globals - just take offset 4959657Slinton * locals - take offset from locals base 4969657Slinton * arguments - take offset from argument base 4979657Slinton * register - offset is register number 4989657Slinton */ 4999657Slinton 500*16620Ssam #define isglobal(s) (s->level == 1) 501*16620Ssam #define islocaloff(s) (s->level >= 2 and s->symvalue.offset < 0) 502*16620Ssam #define isparamoff(s) (s->level >= 2 and s->symvalue.offset >= 0) 5039657Slinton #define isreg(s) (s->level < 0) 5049657Slinton 5059657Slinton public Address address(s, frame) 5069657Slinton Symbol s; 5079657Slinton Frame frame; 5089657Slinton { 5099657Slinton register Frame frp; 5109657Slinton register Address addr; 5119657Slinton register Symbol cur; 5129657Slinton 5139657Slinton checkref(s); 5149657Slinton if (not isactive(s->block)) { 5159657Slinton error("\"%s\" is not currently defined", symname(s)); 5169657Slinton } else if (isglobal(s)) { 5179657Slinton addr = s->symvalue.offset; 5189657Slinton } else { 5199657Slinton frp = frame; 5209657Slinton if (frp == nil) { 5219657Slinton cur = s->block; 5229657Slinton while (cur != nil and cur->class == MODULE) { 5239657Slinton cur = cur->block; 5249657Slinton } 5259657Slinton if (cur == nil) { 5269657Slinton cur = whatblock(pc); 5279657Slinton } 5289657Slinton frp = findframe(cur); 5299657Slinton if (frp == nil) { 5309657Slinton panic("unexpected nil frame for \"%s\"", symname(s)); 5319657Slinton } 5329657Slinton } 5339657Slinton if (islocaloff(s)) { 5349657Slinton addr = locals_base(frp) + s->symvalue.offset; 5359657Slinton } else if (isparamoff(s)) { 5369657Slinton addr = args_base(frp) + s->symvalue.offset; 5379657Slinton } else if (isreg(s)) { 5389657Slinton addr = savereg(s->symvalue.offset, frp); 5399657Slinton } else { 5409657Slinton panic("address: bad symbol \"%s\"", symname(s)); 5419657Slinton } 5429657Slinton } 5439657Slinton return addr; 5449657Slinton } 5459657Slinton 5469657Slinton /* 5479657Slinton * Define a symbol used to access register values. 5489657Slinton */ 5499657Slinton 5509657Slinton public defregname(n, r) 5519657Slinton Name n; 5529657Slinton Integer r; 5539657Slinton { 5549657Slinton register Symbol s, t; 5559657Slinton 5569657Slinton s = insert(n); 5579657Slinton t = newSymbol(nil, 0, PTR, t_int, nil); 558*16620Ssam t->language = primlang; 5599657Slinton s->language = t->language; 5609657Slinton s->class = VAR; 5619657Slinton s->level = -3; 5629657Slinton s->type = t; 5639657Slinton s->block = program; 5649657Slinton s->symvalue.offset = r; 5659657Slinton } 5669657Slinton 5679657Slinton /* 5689657Slinton * Resolve an "abstract" type reference. 5699657Slinton * 5709657Slinton * It is possible in C to define a pointer to a type, but never define 5719657Slinton * the type in a particular source file. Here we try to resolve 5729657Slinton * the type definition. This is problematic, it is possible to 5739657Slinton * have multiple, different definitions for the same name type. 5749657Slinton */ 5759657Slinton 5769657Slinton public findtype(s) 5779657Slinton Symbol s; 5789657Slinton { 5799657Slinton register Symbol t, u, prev; 5809657Slinton 5819657Slinton u = s; 5829657Slinton prev = nil; 5839657Slinton while (u != nil and u->class != BADUSE) { 5849657Slinton if (u->name != nil) { 5859657Slinton prev = u; 5869657Slinton } 5879657Slinton u = u->type; 5889657Slinton } 5899657Slinton if (prev == nil) { 5909657Slinton error("couldn't find link to type reference"); 5919657Slinton } 5929657Slinton find(t, prev->name) where 593*16620Ssam t != prev and t->block->class == MODULE and t->class == prev->class and 594*16620Ssam t->type != nil and t->type->type != nil and 595*16620Ssam t->type->type->class != BADUSE 5969657Slinton endfind(t); 5979657Slinton if (t == nil) { 5989657Slinton error("couldn't resolve reference"); 5999657Slinton } else { 6009657Slinton prev->type = t->type; 6019657Slinton } 6029657Slinton } 6039657Slinton 6049657Slinton /* 6059657Slinton * Find the size in bytes of the given type. 6069657Slinton * 6079657Slinton * This is probably the WRONG thing to do. The size should be kept 6089657Slinton * as an attribute in the symbol information as is done for structures 6099657Slinton * and fields. I haven't gotten around to cleaning this up yet. 6109657Slinton */ 6119657Slinton 61212547Scsvaf #define MAXUCHAR 255 61312547Scsvaf #define MAXUSHORT 65535L 6149657Slinton #define MINCHAR -128 6159657Slinton #define MAXCHAR 127 6169657Slinton #define MINSHORT -32768 6179657Slinton #define MAXSHORT 32767 6189657Slinton 619*16620Ssam /* 620*16620Ssam * When necessary, compute the upper bound for an open array (Modula-2 style). 621*16620Ssam */ 622*16620Ssam 623*16620Ssam public chkOpenArray (sym) 6249657Slinton Symbol sym; 6259657Slinton { 626*16620Ssam Symbol t; 627*16620Ssam Address a; 628*16620Ssam integer n; 629*16620Ssam 630*16620Ssam if (sym->class == REF or sym->class == VAR) { 631*16620Ssam t = rtype(sym->type); 632*16620Ssam if (t->class == ARRAY and t->chain == t_open) { 633*16620Ssam a = address(sym, nil); 634*16620Ssam dread(&n, a + sizeof(Word), sizeof(n)); 635*16620Ssam t->chain->type->symvalue.rangev.upper = n - 1; 636*16620Ssam } 637*16620Ssam } 638*16620Ssam } 639*16620Ssam 640*16620Ssam public findbounds (u, lower, upper) 641*16620Ssam Symbol u; 642*16620Ssam long *lower, *upper; 643*16620Ssam { 644*16620Ssam Rangetype lbt, ubt; 645*16620Ssam long lb, ub; 646*16620Ssam 647*16620Ssam if (u->class == RANGE) { 648*16620Ssam lbt = u->symvalue.rangev.lowertype; 649*16620Ssam ubt = u->symvalue.rangev.uppertype; 650*16620Ssam lb = u->symvalue.rangev.lower; 651*16620Ssam ub = u->symvalue.rangev.upper; 652*16620Ssam if (lbt == R_ARG or lbt == R_TEMP) { 653*16620Ssam if (not getbound(u, lb, lbt, lower)) { 654*16620Ssam error("dynamic bounds not currently available"); 655*16620Ssam } 656*16620Ssam } else { 657*16620Ssam *lower = lb; 658*16620Ssam } 659*16620Ssam if (ubt == R_ARG or ubt == R_TEMP) { 660*16620Ssam if (not getbound(u, ub, ubt, upper)) { 661*16620Ssam error("dynamic bounds not currently available"); 662*16620Ssam } 663*16620Ssam } else { 664*16620Ssam *upper = ub; 665*16620Ssam } 666*16620Ssam } else if (u->class == SCAL) { 667*16620Ssam *lower = 0; 668*16620Ssam *upper = u->symvalue.iconval - 1; 669*16620Ssam } else { 670*16620Ssam panic("unexpected array bound type"); 671*16620Ssam } 672*16620Ssam } 673*16620Ssam 674*16620Ssam public integer size(sym) 675*16620Ssam Symbol sym; 676*16620Ssam { 677*16620Ssam register Symbol s, t, u; 678*16620Ssam register integer nel, elsize; 6799657Slinton long lower, upper; 680*16620Ssam integer r, off, len; 6819657Slinton 6829657Slinton t = sym; 6839657Slinton checkref(t); 684*16620Ssam if (t->class == TYPEREF) { 685*16620Ssam resolveRef(t); 686*16620Ssam } 6879657Slinton switch (t->class) { 6889657Slinton case RANGE: 6899657Slinton lower = t->symvalue.rangev.lower; 6909657Slinton upper = t->symvalue.rangev.upper; 691*16620Ssam if (upper == 0 and lower > 0) { 692*16620Ssam /* real */ 6939657Slinton r = lower; 694*16620Ssam } else if (lower > upper) { 695*16620Ssam /* unsigned long */ 696*16620Ssam r = sizeof(long); 69712045Slinton } else if ( 69812547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or 69912547Scsvaf (lower >= 0 and upper <= MAXUCHAR) 70012547Scsvaf ) { 7019657Slinton r = sizeof(char); 70212547Scsvaf } else if ( 70312547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or 70412547Scsvaf (lower >= 0 and upper <= MAXUSHORT) 70512547Scsvaf ) { 7069657Slinton r = sizeof(short); 7079657Slinton } else { 7089657Slinton r = sizeof(long); 7099657Slinton } 7109657Slinton break; 7119657Slinton 7129657Slinton case ARRAY: 7139657Slinton elsize = size(t->type); 7149657Slinton nel = 1; 7159657Slinton for (t = t->chain; t != nil; t = t->chain) { 716*16620Ssam u = rtype(t); 717*16620Ssam findbounds(u, &lower, &upper); 7189657Slinton nel *= (upper-lower+1); 7199657Slinton } 7209657Slinton r = nel*elsize; 7219657Slinton break; 7229657Slinton 72312547Scsvaf case REF: 7249657Slinton case VAR: 7259657Slinton case FVAR: 726*16620Ssam chkOpenArray(t); 7279657Slinton r = size(t->type); 72812127Slinton /* 72912127Slinton * 73012045Slinton if (r < sizeof(Word) and isparam(t)) { 7319657Slinton r = sizeof(Word); 7329657Slinton } 73312547Scsvaf */ 7349657Slinton break; 7359657Slinton 7369657Slinton case CONST: 7379657Slinton r = size(t->type); 7389657Slinton break; 7399657Slinton 7409657Slinton case TYPE: 7419657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) { 7429657Slinton findtype(t); 7439657Slinton } 7449657Slinton r = size(t->type); 7459657Slinton break; 7469657Slinton 7479657Slinton case TAG: 7489657Slinton r = size(t->type); 7499657Slinton break; 7509657Slinton 7519657Slinton case FIELD: 752*16620Ssam off = t->symvalue.field.offset; 753*16620Ssam len = t->symvalue.field.length; 754*16620Ssam r = (off + len + 7) div 8 - (off div 8); 755*16620Ssam /* r = (t->symvalue.field.length + 7) div 8; */ 7569657Slinton break; 7579657Slinton 7589657Slinton case RECORD: 7599657Slinton case VARNT: 7609657Slinton r = t->symvalue.offset; 7619657Slinton if (r == 0 and t->chain != nil) { 7629657Slinton panic("missing size information for record"); 7639657Slinton } 7649657Slinton break; 7659657Slinton 7669657Slinton case PTR: 7679657Slinton case FILET: 7689657Slinton r = sizeof(Word); 7699657Slinton break; 7709657Slinton 7719657Slinton case SCAL: 77212609Slinton r = sizeof(Word); 77312609Slinton /* 77412609Slinton * 7759657Slinton if (t->symvalue.iconval > 255) { 7769657Slinton r = sizeof(short); 7779657Slinton } else { 7789657Slinton r = sizeof(char); 7799657Slinton } 78012609Slinton * 78112609Slinton */ 7829657Slinton break; 7839657Slinton 7849657Slinton case FPROC: 7859657Slinton case FFUNC: 7869657Slinton r = sizeof(Word); 7879657Slinton break; 7889657Slinton 7899657Slinton case PROC: 7909657Slinton case FUNC: 7919657Slinton case MODULE: 7929657Slinton case PROG: 7939657Slinton r = sizeof(Symbol); 7949657Slinton break; 7959657Slinton 796*16620Ssam case SET: 797*16620Ssam u = rtype(t->type); 798*16620Ssam switch (u->class) { 799*16620Ssam case RANGE: 800*16620Ssam r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; 801*16620Ssam break; 802*16620Ssam 803*16620Ssam case SCAL: 804*16620Ssam r = u->symvalue.iconval; 805*16620Ssam break; 806*16620Ssam 807*16620Ssam default: 808*16620Ssam error("expected range for set base type"); 809*16620Ssam break; 810*16620Ssam } 811*16620Ssam r = (r + BITSPERBYTE - 1) div BITSPERBYTE; 812*16620Ssam break; 813*16620Ssam 8149657Slinton default: 8159657Slinton if (ord(t->class) > ord(TYPEREF)) { 8169657Slinton panic("size: bad class (%d)", ord(t->class)); 8179657Slinton } else { 818*16620Ssam fprintf(stderr, "!! size(%s) ??", classname(t)); 8199657Slinton } 820*16620Ssam r = 0; 821*16620Ssam break; 8229657Slinton } 8239657Slinton return r; 8249657Slinton } 8259657Slinton 8269657Slinton /* 8279657Slinton * Test if a symbol is a parameter. This is true if there 8289657Slinton * is a cycle from s->block to s via chain pointers. 8299657Slinton */ 8309657Slinton 8319657Slinton public Boolean isparam(s) 8329657Slinton Symbol s; 8339657Slinton { 8349657Slinton register Symbol t; 8359657Slinton 8369657Slinton t = s->block; 8379657Slinton while (t != nil and t != s) { 8389657Slinton t = t->chain; 8399657Slinton } 8409657Slinton return (Boolean) (t != nil); 8419657Slinton } 8429657Slinton 8439657Slinton /* 844*16620Ssam * Test if a type is an open array parameter type. 8459657Slinton */ 8469657Slinton 847*16620Ssam public Boolean isopenarray (t) 848*16620Ssam Symbol t; 849*16620Ssam { 850*16620Ssam return (Boolean) (t->class == ARRAY and t->chain == t_open); 851*16620Ssam } 852*16620Ssam 853*16620Ssam /* 854*16620Ssam * Test if a symbol is a var parameter, i.e. has class REF but 855*16620Ssam * is not an open array parameter (those are treated special). 856*16620Ssam */ 857*16620Ssam 8589657Slinton public Boolean isvarparam(s) 8599657Slinton Symbol s; 8609657Slinton { 8619657Slinton return (Boolean) (s->class == REF); 8629657Slinton } 8639657Slinton 8649657Slinton /* 8659657Slinton * Test if a symbol is a variable (actually any addressible quantity 8669657Slinton * with do). 8679657Slinton */ 8689657Slinton 8699657Slinton public Boolean isvariable(s) 8709657Slinton register Symbol s; 8719657Slinton { 8729657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 8739657Slinton } 8749657Slinton 8759657Slinton /* 8769657Slinton * Test if a symbol is a block, e.g. function, procedure, or the 8779657Slinton * main program. 8789657Slinton * 8799657Slinton * This function is now expanded inline for efficiency. 8809657Slinton * 8819657Slinton * public Boolean isblock(s) 8829657Slinton register Symbol s; 8839657Slinton { 8849657Slinton return (Boolean) ( 8859657Slinton s->class == FUNC or s->class == PROC or 8869657Slinton s->class == MODULE or s->class == PROG 8879657Slinton ); 8889657Slinton } 8899657Slinton * 8909657Slinton */ 8919657Slinton 8929657Slinton /* 8939657Slinton * Test if a symbol is a module. 8949657Slinton */ 8959657Slinton 8969657Slinton public Boolean ismodule(s) 8979657Slinton register Symbol s; 8989657Slinton { 8999657Slinton return (Boolean) (s->class == MODULE); 9009657Slinton } 9019657Slinton 9029657Slinton /* 9039657Slinton * Test if a symbol is builtin, that is, a predefined type or 9049657Slinton * reserved word. 9059657Slinton */ 9069657Slinton 9079657Slinton public Boolean isbuiltin(s) 9089657Slinton register Symbol s; 9099657Slinton { 9109657Slinton return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); 9119657Slinton } 9129657Slinton 9139657Slinton /* 914*16620Ssam * Mark a procedure or function as internal, meaning that it is called 915*16620Ssam * with a different calling sequence. 916*16620Ssam */ 917*16620Ssam 918*16620Ssam public markInternal (s) 919*16620Ssam Symbol s; 920*16620Ssam { 921*16620Ssam s->symvalue.funcv.intern = true; 922*16620Ssam } 923*16620Ssam 924*16620Ssam public boolean isinternal (s) 925*16620Ssam Symbol s; 926*16620Ssam { 927*16620Ssam return s->symvalue.funcv.intern; 928*16620Ssam } 929*16620Ssam 930*16620Ssam /* 9319657Slinton * Test if two types match. 9329657Slinton * Equivalent names implies a match in any language. 9339657Slinton * 9349657Slinton * Special symbols must be handled with care. 9359657Slinton */ 9369657Slinton 9379657Slinton public Boolean compatible(t1, t2) 9389657Slinton register Symbol t1, t2; 9399657Slinton { 9409657Slinton Boolean b; 941*16620Ssam Symbol rt1, rt2; 9429657Slinton 9439657Slinton if (t1 == t2) { 9449657Slinton b = true; 9459657Slinton } else if (t1 == nil or t2 == nil) { 9469657Slinton b = false; 9479657Slinton } else if (t1 == procsym) { 9489657Slinton b = isblock(t2); 9499657Slinton } else if (t2 == procsym) { 9509657Slinton b = isblock(t1); 951*16620Ssam } else if (t1->language == primlang) { 952*16620Ssam if (t2->language == primlang) { 953*16620Ssam rt1 = rtype(t1); 954*16620Ssam rt2 = rtype(t2); 955*16620Ssam b = (boolean) ( 956*16620Ssam (rt1->type == t_open and rt2->type == t_int) or 957*16620Ssam (rt2->type == t_open and rt1->type == t_int) or 958*16620Ssam rt1 == rt2 959*16620Ssam ); 960*16620Ssam } else { 961*16620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 962*16620Ssam } 963*16620Ssam } else if (t2->language == primlang) { 964*16620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 9659657Slinton } else if (t1->language == nil) { 966*16620Ssam if (t2->language == nil) { 967*16620Ssam b = false; 968*16620Ssam } else { 969*16620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 970*16620Ssam } 97112547Scsvaf } else if (t2->language == nil) { 972*16620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 973*16620Ssam } else if (isbuiltin(t1) or isbuiltin(t1->type)) { 974*16620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 9759657Slinton } else { 976*16620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 9779657Slinton } 9789657Slinton return b; 9799657Slinton } 9809657Slinton 9819657Slinton /* 9829657Slinton * Check for a type of the given name. 9839657Slinton */ 9849657Slinton 9859657Slinton public Boolean istypename(type, name) 9869657Slinton Symbol type; 9879657Slinton String name; 9889657Slinton { 9899657Slinton Symbol t; 9909657Slinton Boolean b; 9919657Slinton 9929657Slinton t = type; 9939657Slinton checkref(t); 9949657Slinton b = (Boolean) ( 995*16620Ssam t->class == TYPE and streq(ident(t->name), name) 9969657Slinton ); 9979657Slinton return b; 9989657Slinton } 9999657Slinton 10009657Slinton /* 1001*16620Ssam * Determine if a (value) parameter should actually be passed by address. 1002*16620Ssam */ 1003*16620Ssam 1004*16620Ssam public boolean passaddr (p, exprtype) 1005*16620Ssam Symbol p, exprtype; 1006*16620Ssam { 1007*16620Ssam boolean b; 1008*16620Ssam Language def; 1009*16620Ssam 1010*16620Ssam if (p == nil) { 1011*16620Ssam def = findlanguage(".c"); 1012*16620Ssam b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); 1013*16620Ssam } else if (p->language == nil or p->language == primlang) { 1014*16620Ssam b = false; 1015*16620Ssam } else if (isopenarray(p->type)) { 1016*16620Ssam b = true; 1017*16620Ssam } else { 1018*16620Ssam b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); 1019*16620Ssam } 1020*16620Ssam return b; 1021*16620Ssam } 1022*16620Ssam 1023*16620Ssam /* 10249657Slinton * Test if the name of a symbol is uniquely defined or not. 10259657Slinton */ 10269657Slinton 10279657Slinton public Boolean isambiguous(s) 10289657Slinton register Symbol s; 10299657Slinton { 10309657Slinton register Symbol t; 10319657Slinton 10329657Slinton find(t, s->name) where t != s endfind(t); 10339657Slinton return (Boolean) (t != nil); 10349657Slinton } 10359657Slinton 10369657Slinton typedef char *Arglist; 10379657Slinton 10389657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 10399657Slinton 10409657Slinton private Symbol mkstring(); 10419657Slinton private Symbol namenode(); 10429657Slinton 10439657Slinton /* 10449657Slinton * Determine the type of a parse tree. 10459657Slinton * Also make some symbol-dependent changes to the tree such as 10469657Slinton * changing removing RVAL nodes for constant symbols. 10479657Slinton */ 10489657Slinton 10499657Slinton public assigntypes(p) 10509657Slinton register Node p; 10519657Slinton { 10529657Slinton register Node p1; 10539657Slinton register Symbol s; 10549657Slinton 10559657Slinton switch (p->op) { 10569657Slinton case O_SYM: 10579657Slinton p->nodetype = namenode(p); 10589657Slinton break; 10599657Slinton 10609657Slinton case O_LCON: 10619657Slinton p->nodetype = t_int; 10629657Slinton break; 10639657Slinton 10649657Slinton case O_FCON: 10659657Slinton p->nodetype = t_real; 10669657Slinton break; 10679657Slinton 10689657Slinton case O_SCON: 10699657Slinton p->value.scon = strdup(p->value.scon); 10709657Slinton s = mkstring(p->value.scon); 10719657Slinton if (s == t_char) { 10729657Slinton p->op = O_LCON; 10739657Slinton p->value.lcon = p->value.scon[0]; 10749657Slinton } 10759657Slinton p->nodetype = s; 10769657Slinton break; 10779657Slinton 10789657Slinton case O_INDIR: 10799657Slinton p1 = p->value.arg[0]; 10809657Slinton chkclass(p1, PTR); 10819657Slinton p->nodetype = rtype(p1->nodetype)->type; 10829657Slinton break; 10839657Slinton 10849657Slinton case O_DOT: 10859657Slinton p->nodetype = p->value.arg[1]->value.sym; 10869657Slinton break; 10879657Slinton 10889657Slinton case O_RVAL: 10899657Slinton p1 = p->value.arg[0]; 10909657Slinton p->nodetype = p1->nodetype; 10919657Slinton if (p1->op == O_SYM) { 10929657Slinton if (p1->nodetype->class == FUNC) { 10939657Slinton p->op = O_CALL; 10949657Slinton p->value.arg[1] = nil; 10959657Slinton } else if (p1->value.sym->class == CONST) { 10969657Slinton if (compatible(p1->value.sym->type, t_real)) { 10979657Slinton p->op = O_FCON; 10989657Slinton p->value.fcon = p1->value.sym->symvalue.fconval; 10999657Slinton p->nodetype = t_real; 11009657Slinton dispose(p1); 11019657Slinton } else { 11029657Slinton p->op = O_LCON; 11039657Slinton p->value.lcon = p1->value.sym->symvalue.iconval; 11049657Slinton p->nodetype = p1->value.sym->type; 11059657Slinton dispose(p1); 11069657Slinton } 11079657Slinton } else if (isreg(p1->value.sym)) { 11089657Slinton p->op = O_SYM; 11099657Slinton p->value.sym = p1->value.sym; 11109657Slinton dispose(p1); 11119657Slinton } 11129657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 11139657Slinton s = p1->value.arg[0]->value.sym; 11149657Slinton if (isreg(s)) { 11159657Slinton p1->op = O_SYM; 11169657Slinton dispose(p1->value.arg[0]); 11179657Slinton p1->value.sym = s; 11189657Slinton p1->nodetype = s; 11199657Slinton } 11209657Slinton } 11219657Slinton break; 11229657Slinton 1123*16620Ssam /* 1124*16620Ssam * Perform a cast if the call is of the form "type(expr)". 1125*16620Ssam */ 11269657Slinton case O_CALL: 11279657Slinton p1 = p->value.arg[0]; 112811171Slinton p->nodetype = rtype(p1->nodetype)->type; 11299657Slinton break; 11309657Slinton 113111171Slinton case O_TYPERENAME: 113211171Slinton p->nodetype = p->value.arg[1]->nodetype; 113311171Slinton break; 113411171Slinton 11359657Slinton case O_ITOF: 11369657Slinton p->nodetype = t_real; 11379657Slinton break; 11389657Slinton 11399657Slinton case O_NEG: 11409657Slinton s = p->value.arg[0]->nodetype; 11419657Slinton if (not compatible(s, t_int)) { 11429657Slinton if (not compatible(s, t_real)) { 11439657Slinton beginerrmsg(); 1144*16620Ssam fprintf(stderr, "\""); 11459657Slinton prtree(stderr, p->value.arg[0]); 1146*16620Ssam fprintf(stderr, "\" is improper type"); 11479657Slinton enderrmsg(); 11489657Slinton } else { 11499657Slinton p->op = O_NEGF; 11509657Slinton } 11519657Slinton } 11529657Slinton p->nodetype = s; 11539657Slinton break; 11549657Slinton 11559657Slinton case O_ADD: 11569657Slinton case O_SUB: 11579657Slinton case O_MUL: 1158*16620Ssam binaryop(p, nil); 1159*16620Ssam break; 1160*16620Ssam 11619657Slinton case O_LT: 11629657Slinton case O_LE: 11639657Slinton case O_GT: 11649657Slinton case O_GE: 11659657Slinton case O_EQ: 11669657Slinton case O_NE: 1167*16620Ssam binaryop(p, t_boolean); 11689657Slinton break; 11699657Slinton 11709657Slinton case O_DIVF: 11719657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF); 11729657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF); 11739657Slinton p->nodetype = t_real; 11749657Slinton break; 11759657Slinton 11769657Slinton case O_DIV: 11779657Slinton case O_MOD: 11789657Slinton convert(&(p->value.arg[0]), t_int, O_NOP); 11799657Slinton convert(&(p->value.arg[1]), t_int, O_NOP); 11809657Slinton p->nodetype = t_int; 11819657Slinton break; 11829657Slinton 11839657Slinton case O_AND: 11849657Slinton case O_OR: 11859657Slinton chkboolean(p->value.arg[0]); 11869657Slinton chkboolean(p->value.arg[1]); 11879657Slinton p->nodetype = t_boolean; 11889657Slinton break; 11899657Slinton 11909657Slinton case O_QLINE: 11919657Slinton p->nodetype = t_int; 11929657Slinton break; 11939657Slinton 11949657Slinton default: 11959657Slinton p->nodetype = nil; 11969657Slinton break; 11979657Slinton } 11989657Slinton } 11999657Slinton 12009657Slinton /* 1201*16620Ssam * Process a binary arithmetic or relational operator. 1202*16620Ssam * Convert from integer to real if necessary. 1203*16620Ssam */ 1204*16620Ssam 1205*16620Ssam private binaryop (p, t) 1206*16620Ssam Node p; 1207*16620Ssam Symbol t; 1208*16620Ssam { 1209*16620Ssam Node p1, p2; 1210*16620Ssam Boolean t1real, t2real; 1211*16620Ssam Symbol t1, t2; 1212*16620Ssam 1213*16620Ssam p1 = p->value.arg[0]; 1214*16620Ssam p2 = p->value.arg[1]; 1215*16620Ssam t1 = rtype(p1->nodetype); 1216*16620Ssam t2 = rtype(p2->nodetype); 1217*16620Ssam t1real = compatible(t1, t_real); 1218*16620Ssam t2real = compatible(t2, t_real); 1219*16620Ssam if (t1real or t2real) { 1220*16620Ssam p->op = (Operator) (ord(p->op) + 1); 1221*16620Ssam if (not t1real) { 1222*16620Ssam p->value.arg[0] = build(O_ITOF, p1); 1223*16620Ssam } else if (not t2real) { 1224*16620Ssam p->value.arg[1] = build(O_ITOF, p2); 1225*16620Ssam } 1226*16620Ssam p->nodetype = t_real; 1227*16620Ssam } else { 1228*16620Ssam if (size(p1->nodetype) > sizeof(integer)) { 1229*16620Ssam beginerrmsg(); 1230*16620Ssam fprintf(stderr, "operation not defined on \""); 1231*16620Ssam prtree(stderr, p1); 1232*16620Ssam fprintf(stderr, "\""); 1233*16620Ssam enderrmsg(); 1234*16620Ssam } else if (size(p2->nodetype) > sizeof(integer)) { 1235*16620Ssam beginerrmsg(); 1236*16620Ssam fprintf(stderr, "operation not defined on \""); 1237*16620Ssam prtree(stderr, p2); 1238*16620Ssam fprintf(stderr, "\""); 1239*16620Ssam enderrmsg(); 1240*16620Ssam } 1241*16620Ssam p->nodetype = t_int; 1242*16620Ssam } 1243*16620Ssam if (t != nil) { 1244*16620Ssam p->nodetype = t; 1245*16620Ssam } 1246*16620Ssam } 1247*16620Ssam 1248*16620Ssam /* 12499657Slinton * Create a node for a name. The symbol for the name has already 12509657Slinton * been chosen, either implicitly with "which" or explicitly from 12519657Slinton * the dot routine. 12529657Slinton */ 12539657Slinton 12549657Slinton private Symbol namenode(p) 12559657Slinton Node p; 12569657Slinton { 12579657Slinton register Symbol r, s; 12589657Slinton register Node np; 12599657Slinton 12609657Slinton s = p->value.sym; 12619657Slinton if (s->class == REF) { 12629657Slinton np = new(Node); 12639657Slinton np->op = p->op; 12649657Slinton np->nodetype = s; 12659657Slinton np->value.sym = s; 12669657Slinton p->op = O_INDIR; 12679657Slinton p->value.arg[0] = np; 12689657Slinton } 12699657Slinton /* 12709657Slinton * Old way 12719657Slinton * 12729657Slinton if (s->class == CONST or s->class == VAR or s->class == FVAR) { 12739657Slinton r = s->type; 12749657Slinton } else { 12759657Slinton r = s; 12769657Slinton } 12779657Slinton * 12789657Slinton */ 12799657Slinton return s; 12809657Slinton } 12819657Slinton 12829657Slinton /* 12839657Slinton * Convert a tree to a type via a conversion operator; 12849657Slinton * if this isn't possible generate an error. 12859657Slinton * 12869657Slinton * Note the tree is call by address, hence the #define below. 12879657Slinton */ 12889657Slinton 12899657Slinton private convert(tp, typeto, op) 12909657Slinton Node *tp; 12919657Slinton Symbol typeto; 12929657Slinton Operator op; 12939657Slinton { 1294*16620Ssam Node tree; 1295*16620Ssam Symbol s, t; 12969657Slinton 1297*16620Ssam tree = *tp; 12989657Slinton s = rtype(tree->nodetype); 1299*16620Ssam t = rtype(typeto); 1300*16620Ssam if (compatible(t, t_real) and compatible(s, t_int)) { 13019657Slinton tree = build(op, tree); 1302*16620Ssam } else if (not compatible(s, t)) { 13039657Slinton beginerrmsg(); 1304*16620Ssam fprintf(stderr, "expected integer or real, found \""); 1305*16620Ssam prtree(stderr, tree); 1306*16620Ssam fprintf(stderr, "\""); 13079657Slinton enderrmsg(); 1308*16620Ssam } else if (op != O_NOP and s != t) { 13099657Slinton tree = build(op, tree); 13109657Slinton } 1311*16620Ssam *tp = tree; 13129657Slinton } 13139657Slinton 13149657Slinton /* 13159657Slinton * Construct a node for the dot operator. 13169657Slinton * 13179657Slinton * If the left operand is not a record, but rather a procedure 13189657Slinton * or function, then we interpret the "." as referencing an 13199657Slinton * "invisible" variable; i.e. a variable within a dynamically 13209657Slinton * active block but not within the static scope of the current procedure. 13219657Slinton */ 13229657Slinton 13239657Slinton public Node dot(record, fieldname) 13249657Slinton Node record; 13259657Slinton Name fieldname; 13269657Slinton { 13279657Slinton register Node p; 13289657Slinton register Symbol s, t; 13299657Slinton 13309657Slinton if (isblock(record->nodetype)) { 13319657Slinton find(s, fieldname) where 13329657Slinton s->block == record->nodetype and 13339657Slinton s->class != FIELD and s->class != TAG 13349657Slinton endfind(s); 13359657Slinton if (s == nil) { 13369657Slinton beginerrmsg(); 13379657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 13389657Slinton printname(stderr, record->nodetype); 13399657Slinton enderrmsg(); 13409657Slinton } 13419657Slinton p = new(Node); 13429657Slinton p->op = O_SYM; 13439657Slinton p->value.sym = s; 13449657Slinton p->nodetype = namenode(p); 13459657Slinton } else { 13469657Slinton p = record; 13479657Slinton t = rtype(p->nodetype); 13489657Slinton if (t->class == PTR) { 13499657Slinton s = findfield(fieldname, t->type); 13509657Slinton } else { 13519657Slinton s = findfield(fieldname, t); 13529657Slinton } 13539657Slinton if (s == nil) { 13549657Slinton beginerrmsg(); 13559657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 13569657Slinton prtree(stderr, record); 13579657Slinton enderrmsg(); 13589657Slinton } 13599657Slinton if (t->class == PTR and not isreg(record->nodetype)) { 13609657Slinton p = build(O_INDIR, record); 13619657Slinton } 13629657Slinton p = build(O_DOT, p, build(O_SYM, s)); 13639657Slinton } 13649657Slinton return p; 13659657Slinton } 13669657Slinton 13679657Slinton /* 13689657Slinton * Return a tree corresponding to an array reference and do the 13699657Slinton * error checking. 13709657Slinton */ 13719657Slinton 13729657Slinton public Node subscript(a, slist) 13739657Slinton Node a, slist; 13749657Slinton { 1375*16620Ssam Symbol t; 13769657Slinton 1377*16620Ssam t = rtype(a->nodetype); 1378*16620Ssam if (t->language == nil) { 137912547Scsvaf error("unknown language"); 1380*16620Ssam } else { 1381*16620Ssam return (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); 1382*16620Ssam } 13839657Slinton } 13849657Slinton 13859657Slinton /* 13869657Slinton * Evaluate a subscript index. 13879657Slinton */ 13889657Slinton 13899657Slinton public int evalindex(s, i) 13909657Slinton Symbol s; 13919657Slinton long i; 13929657Slinton { 1393*16620Ssam Symbol t; 13949657Slinton 1395*16620Ssam t = rtype(s); 1396*16620Ssam if (t->language == nil) { 139712547Scsvaf error("unknown language"); 1398*16620Ssam } else { 1399*16620Ssam return ((*language_op(t->language, L_EVALAREF)) (s, i)); 1400*16620Ssam } 14019657Slinton } 14029657Slinton 14039657Slinton /* 14049657Slinton * Check to see if a tree is boolean-valued, if not it's an error. 14059657Slinton */ 14069657Slinton 14079657Slinton public chkboolean(p) 14089657Slinton register Node p; 14099657Slinton { 14109657Slinton if (p->nodetype != t_boolean) { 14119657Slinton beginerrmsg(); 14129657Slinton fprintf(stderr, "found "); 14139657Slinton prtree(stderr, p); 14149657Slinton fprintf(stderr, ", expected boolean expression"); 14159657Slinton enderrmsg(); 14169657Slinton } 14179657Slinton } 14189657Slinton 14199657Slinton /* 14209657Slinton * Check to make sure the given tree has a type of the given class. 14219657Slinton */ 14229657Slinton 14239657Slinton private chkclass(p, class) 14249657Slinton Node p; 14259657Slinton Symclass class; 14269657Slinton { 14279657Slinton struct Symbol tmpsym; 14289657Slinton 14299657Slinton tmpsym.class = class; 14309657Slinton if (rtype(p->nodetype)->class != class) { 14319657Slinton beginerrmsg(); 14329657Slinton fprintf(stderr, "\""); 14339657Slinton prtree(stderr, p); 14349657Slinton fprintf(stderr, "\" is not a %s", classname(&tmpsym)); 14359657Slinton enderrmsg(); 14369657Slinton } 14379657Slinton } 14389657Slinton 14399657Slinton /* 1440*16620Ssam * Construct a node for the type of a string. 14419657Slinton */ 14429657Slinton 14439657Slinton private Symbol mkstring(str) 14449657Slinton String str; 14459657Slinton { 14469657Slinton register char *p, *q; 14479657Slinton register Symbol s; 1448*16620Ssam integer len; 14499657Slinton 14509657Slinton p = str; 14519657Slinton q = str; 14529657Slinton while (*p != '\0') { 14539657Slinton if (*p == '\\') { 14549657Slinton ++p; 14559657Slinton } 14569657Slinton *q = *p; 14579657Slinton ++p; 14589657Slinton ++q; 14599657Slinton } 14609657Slinton *q = '\0'; 1461*16620Ssam len = p - str; 1462*16620Ssam if (len == 1) { 1463*16620Ssam s = t_char; 1464*16620Ssam } else { 1465*16620Ssam s = newSymbol(nil, 0, ARRAY, t_char, nil); 1466*16620Ssam s->language = primlang; 1467*16620Ssam s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 1468*16620Ssam s->chain->language = s->language; 1469*16620Ssam s->chain->symvalue.rangev.lower = 1; 1470*16620Ssam s->chain->symvalue.rangev.upper = len + 1; 1471*16620Ssam } 14729657Slinton return s; 14739657Slinton } 14749657Slinton 14759657Slinton /* 14769657Slinton * Free up the space allocated for a string type. 14779657Slinton */ 14789657Slinton 14799657Slinton public unmkstring(s) 14809657Slinton Symbol s; 14819657Slinton { 14829657Slinton dispose(s->chain); 14839657Slinton } 14849657Slinton 14859657Slinton /* 14869657Slinton * Figure out the "current" variable or function being referred to, 14879657Slinton * this is either the active one or the most visible from the 14889657Slinton * current scope. 14899657Slinton */ 14909657Slinton 14919657Slinton public Symbol which(n) 14929657Slinton Name n; 14939657Slinton { 14949657Slinton register Symbol s, p, t, f; 14959657Slinton 1496*16620Ssam find(s, n) where s->class != FIELD and s->class != TAG endfind(s); 14979657Slinton if (s == nil) { 14989657Slinton s = lookup(n); 14999657Slinton } 15009657Slinton if (s == nil) { 15019657Slinton error("\"%s\" is not defined", ident(n)); 15029657Slinton } else if (s == program or isbuiltin(s)) { 15039657Slinton t = s; 15049657Slinton } else { 1505*16620Ssam /* 1506*16620Ssam * Old way 1507*16620Ssam * 1508*16620Ssam if (not isactive(program)) { 1509*16620Ssam f = program; 1510*16620Ssam } else { 1511*16620Ssam f = whatblock(pc); 1512*16620Ssam if (f == nil) { 1513*16620Ssam panic("no block for addr 0x%x", pc); 1514*16620Ssam } 1515*16620Ssam } 1516*16620Ssam * 1517*16620Ssam * Now start with curfunc. 1518*16620Ssam */ 15199657Slinton p = curfunc; 15209657Slinton do { 15219657Slinton find(t, n) where 1522*16620Ssam t->block == p and t->class != FIELD and t->class != TAG 15239657Slinton endfind(t); 15249657Slinton p = p->block; 15259657Slinton } while (t == nil and p != nil); 15269657Slinton if (t == nil) { 15279657Slinton t = s; 15289657Slinton } 15299657Slinton } 15309657Slinton return t; 15319657Slinton } 15329657Slinton 15339657Slinton /* 15349657Slinton * Find the symbol which is has the same name and scope as the 15359657Slinton * given symbol but is of the given field. Return nil if there is none. 15369657Slinton */ 15379657Slinton 15389657Slinton public Symbol findfield(fieldname, record) 15399657Slinton Name fieldname; 15409657Slinton Symbol record; 15419657Slinton { 15429657Slinton register Symbol t; 15439657Slinton 15449657Slinton t = rtype(record)->chain; 15459657Slinton while (t != nil and t->name != fieldname) { 15469657Slinton t = t->chain; 15479657Slinton } 15489657Slinton return t; 15499657Slinton } 155012547Scsvaf 155112547Scsvaf public Boolean getbound(s,off,type,valp) 155212547Scsvaf Symbol s; 155312547Scsvaf int off; 155412547Scsvaf Rangetype type; 155512547Scsvaf int *valp; 155612547Scsvaf { 155712547Scsvaf Frame frp; 155812547Scsvaf Address addr; 155912547Scsvaf Symbol cur; 156012547Scsvaf 156112547Scsvaf if (not isactive(s->block)) { 156212547Scsvaf return(false); 156312547Scsvaf } 156412547Scsvaf cur = s->block; 156512547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/ 156612547Scsvaf cur = cur->block; 156712547Scsvaf } 156812547Scsvaf if(cur == nil) { 156912547Scsvaf cur = whatblock(pc); 157012547Scsvaf } 157112547Scsvaf frp = findframe(cur); 157212547Scsvaf if (frp == nil) { 157312547Scsvaf return(false); 157412547Scsvaf } 157512547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off; 157612547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off; 157712547Scsvaf else return(false); 157812547Scsvaf dread(valp,addr,sizeof(long)); 157912547Scsvaf return(true); 158012547Scsvaf } 1581