121625Sdist /*
238105Sbostic * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic * All rights reserved.
438105Sbostic *
542687Sbostic * %sccs.include.redist.c%
621625Sdist */
79657Slinton
821625Sdist #ifndef lint
9*46994Sbostic static char sccsid[] = "@(#)symbols.c 5.9 (Berkeley) 03/05/91";
1038105Sbostic #endif /* not lint */
119657Slinton
129657Slinton /*
139657Slinton * Symbol management.
149657Slinton */
159657Slinton
169657Slinton #include "defs.h"
179657Slinton #include "symbols.h"
189657Slinton #include "languages.h"
199657Slinton #include "printsym.h"
209657Slinton #include "tree.h"
219657Slinton #include "operators.h"
229657Slinton #include "eval.h"
239657Slinton #include "mappings.h"
249657Slinton #include "events.h"
259657Slinton #include "process.h"
269657Slinton #include "runtime.h"
279657Slinton #include "machine.h"
289657Slinton #include "names.h"
299657Slinton
309657Slinton #ifndef public
319657Slinton typedef struct Symbol *Symbol;
329657Slinton
339657Slinton #include "machine.h"
349657Slinton #include "names.h"
359657Slinton #include "languages.h"
3618235Slinton #include "tree.h"
379657Slinton
389657Slinton /*
399657Slinton * Symbol classes
409657Slinton */
419657Slinton
429657Slinton typedef enum {
4333337Sdonn BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY,
4433337Sdonn PTRFILE, RECORD, FIELD,
4512547Scsvaf PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
469657Slinton LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
4716620Ssam FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF
489657Slinton } Symclass;
499657Slinton
5012547Scsvaf typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
5112547Scsvaf
5233337Sdonn #define INREG 0
5333337Sdonn #define STK 1
5433337Sdonn #define EXT 2
5533337Sdonn
5640260Sdonn typedef unsigned int Storage;
5733337Sdonn
589657Slinton struct Symbol {
599657Slinton Name name;
609657Slinton Language language;
6133337Sdonn Symclass class : 8;
6233337Sdonn Storage storage : 2;
6333337Sdonn unsigned int level : 6; /* for variables stored on stack only */
649657Slinton Symbol type;
659657Slinton Symbol chain;
669657Slinton union {
6718235Slinton Node constval; /* value of constant symbol */
689657Slinton int offset; /* variable address */
699657Slinton long iconval; /* integer constant value */
709657Slinton double fconval; /* floating constant value */
7118235Slinton int ndims; /* no. of dimensions for dynamic/sub-arrays */
729657Slinton struct { /* field offset and size (both in bits) */
739657Slinton int offset;
749657Slinton int length;
759657Slinton } field;
7612547Scsvaf struct { /* common offset and chain; used to relocate */
7712547Scsvaf int offset; /* vars in global BSS */
7812547Scsvaf Symbol chain;
7912547Scsvaf } common;
809657Slinton struct { /* range bounds */
8112547Scsvaf Rangetype lowertype : 16;
8212547Scsvaf Rangetype uppertype : 16;
839657Slinton long lower;
849657Slinton long upper;
859657Slinton } rangev;
8611865Slinton struct {
8711865Slinton int offset : 16; /* offset for of function value */
8816620Ssam Boolean src : 1; /* true if there is source line info */
89*46994Sbostic Boolean inlne : 1; /* true if no separate act. rec. */
9016620Ssam Boolean intern : 1; /* internal calling sequence */
9116620Ssam int unused : 13;
9211865Slinton Address beginaddr; /* address of function code */
939657Slinton } funcv;
949657Slinton struct { /* variant record info */
959657Slinton int size;
969657Slinton Symbol vtorec;
979657Slinton Symbol vtag;
989657Slinton } varnt;
9916620Ssam String typeref; /* type defined by "<module>:<type>" */
10016620Ssam Symbol extref; /* indirect symbol for external reference */
1019657Slinton } symvalue;
1029657Slinton Symbol block; /* symbol containing this symbol */
1039657Slinton Symbol next_sym; /* hash chain */
1049657Slinton };
1059657Slinton
1069657Slinton /*
1079657Slinton * Basic types.
1089657Slinton */
1099657Slinton
1109657Slinton Symbol t_boolean;
1119657Slinton Symbol t_char;
1129657Slinton Symbol t_int;
1139657Slinton Symbol t_real;
1149657Slinton Symbol t_nil;
11518235Slinton Symbol t_addr;
1169657Slinton
1179657Slinton Symbol program;
1189657Slinton Symbol curfunc;
1199657Slinton
12018235Slinton boolean showaggrs;
12118235Slinton
1229657Slinton #define symname(s) ident(s->name)
1239657Slinton #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
1249657Slinton #define isblock(s) (Boolean) ( \
1259657Slinton s->class == FUNC or s->class == PROC or \
1269657Slinton s->class == MODULE or s->class == PROG \
1279657Slinton )
12816620Ssam #define isroutine(s) (Boolean) ( \
12916620Ssam s->class == FUNC or s->class == PROC \
13016620Ssam )
1319657Slinton
13211865Slinton #define nosource(f) (not (f)->symvalue.funcv.src)
133*46994Sbostic #define isinline(f) ((f)->symvalue.funcv.inlne)
13411865Slinton
13533337Sdonn #define isreg(s) (s->storage == INREG)
13624554Smckusick
1379657Slinton #include "tree.h"
1389657Slinton
1399657Slinton /*
1409657Slinton * Some macros to make finding a symbol with certain attributes.
1419657Slinton */
1429657Slinton
1439657Slinton #define find(s, withname) \
1449657Slinton { \
1459657Slinton s = lookup(withname); \
1469657Slinton while (s != nil and not (s->name == (withname) and
1479657Slinton
1489657Slinton #define where /* qualification */
1499657Slinton
1509657Slinton #define endfind(s) )) { \
1519657Slinton s = s->next_sym; \
1529657Slinton } \
1539657Slinton }
1549657Slinton
1559657Slinton #endif
1569657Slinton
1579657Slinton /*
1589657Slinton * Symbol table structure currently does not support deletions.
15933337Sdonn * Hash table size is a power of two to make hashing faster.
16033337Sdonn * Using a non-prime is ok since we aren't doing rehashing.
1619657Slinton */
1629657Slinton
16333337Sdonn #define HASHTABLESIZE 8192
1649657Slinton
1659657Slinton private Symbol hashtab[HASHTABLESIZE];
1669657Slinton
16733337Sdonn #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1))
1689657Slinton
1699657Slinton /*
1709657Slinton * Allocate a new symbol.
1719657Slinton */
1729657Slinton
17333337Sdonn #define SYMBLOCKSIZE 1000
1749657Slinton
1759657Slinton typedef struct Sympool {
1769657Slinton struct Symbol sym[SYMBLOCKSIZE];
1779657Slinton struct Sympool *prevpool;
1789657Slinton } *Sympool;
1799657Slinton
1809657Slinton private Sympool sympool = nil;
1819657Slinton private Integer nleft = 0;
1829657Slinton
symbol_alloc()1839657Slinton public Symbol symbol_alloc()
1849657Slinton {
1859657Slinton register Sympool newpool;
1869657Slinton
1879657Slinton if (nleft <= 0) {
1889657Slinton newpool = new(Sympool);
18933337Sdonn bzero(newpool, sizeof(*newpool));
1909657Slinton newpool->prevpool = sympool;
1919657Slinton sympool = newpool;
1929657Slinton nleft = SYMBLOCKSIZE;
1939657Slinton }
1949657Slinton --nleft;
1959657Slinton return &(sympool->sym[nleft]);
1969657Slinton }
1979657Slinton
symbol_dump(func)19818235Slinton public symbol_dump (func)
19912547Scsvaf Symbol func;
20012547Scsvaf {
20118235Slinton register Symbol s;
20218235Slinton register integer i;
20312547Scsvaf
20418235Slinton printf(" symbols in %s \n",symname(func));
20518235Slinton for (i = 0; i < HASHTABLESIZE; i++) {
20618235Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) {
20718235Slinton if (s->block == func) {
20818235Slinton psym(s);
20918235Slinton }
21018235Slinton }
21118235Slinton }
21212547Scsvaf }
21312547Scsvaf
2149657Slinton /*
2159657Slinton * Free all the symbols currently allocated.
2169657Slinton */
21718235Slinton
symbol_free()2189657Slinton public symbol_free()
2199657Slinton {
2209657Slinton Sympool s, t;
2219657Slinton register Integer i;
2229657Slinton
2239657Slinton s = sympool;
2249657Slinton while (s != nil) {
2259657Slinton t = s->prevpool;
2269657Slinton dispose(s);
2279657Slinton s = t;
2289657Slinton }
2299657Slinton for (i = 0; i < HASHTABLESIZE; i++) {
2309657Slinton hashtab[i] = nil;
2319657Slinton }
2329657Slinton sympool = nil;
2339657Slinton nleft = 0;
2349657Slinton }
2359657Slinton
2369657Slinton /*
2379657Slinton * Create a new symbol with the given attributes.
2389657Slinton */
2399657Slinton
newSymbol(name,blevel,class,type,chain)2409657Slinton public Symbol newSymbol(name, blevel, class, type, chain)
2419657Slinton Name name;
2429657Slinton Integer blevel;
2439657Slinton Symclass class;
2449657Slinton Symbol type;
2459657Slinton Symbol chain;
2469657Slinton {
2479657Slinton register Symbol s;
2489657Slinton
2499657Slinton s = symbol_alloc();
2509657Slinton s->name = name;
25118235Slinton s->language = primlang;
25233337Sdonn s->storage = EXT;
2539657Slinton s->level = blevel;
2549657Slinton s->class = class;
2559657Slinton s->type = type;
2569657Slinton s->chain = chain;
2579657Slinton return s;
2589657Slinton }
2599657Slinton
2609657Slinton /*
2619657Slinton * Insert a symbol into the hash table.
2629657Slinton */
2639657Slinton
insert(name)2649657Slinton public Symbol insert(name)
2659657Slinton Name name;
2669657Slinton {
2679657Slinton register Symbol s;
2689657Slinton register unsigned int h;
2699657Slinton
2709657Slinton h = hash(name);
2719657Slinton s = symbol_alloc();
2729657Slinton s->name = name;
2739657Slinton s->next_sym = hashtab[h];
2749657Slinton hashtab[h] = s;
2759657Slinton return s;
2769657Slinton }
2779657Slinton
2789657Slinton /*
2799657Slinton * Symbol lookup.
2809657Slinton */
2819657Slinton
lookup(name)2829657Slinton public Symbol lookup(name)
2839657Slinton Name name;
2849657Slinton {
2859657Slinton register Symbol s;
2869657Slinton register unsigned int h;
2879657Slinton
2889657Slinton h = hash(name);
2899657Slinton s = hashtab[h];
2909657Slinton while (s != nil and s->name != name) {
2919657Slinton s = s->next_sym;
2929657Slinton }
2939657Slinton return s;
2949657Slinton }
2959657Slinton
2969657Slinton /*
29716620Ssam * Delete a symbol from the symbol table.
29816620Ssam */
29916620Ssam
delete(s)30016620Ssam public delete (s)
30116620Ssam Symbol s;
30216620Ssam {
30316620Ssam register Symbol t;
30416620Ssam register unsigned int h;
30516620Ssam
30616620Ssam h = hash(s->name);
30716620Ssam t = hashtab[h];
30816620Ssam if (t == nil) {
30916620Ssam panic("delete of non-symbol '%s'", symname(s));
31016620Ssam } else if (t == s) {
31116620Ssam hashtab[h] = s->next_sym;
31216620Ssam } else {
31316620Ssam while (t->next_sym != s) {
31416620Ssam t = t->next_sym;
31516620Ssam if (t == nil) {
31616620Ssam panic("delete of non-symbol '%s'", symname(s));
31716620Ssam }
31816620Ssam }
31916620Ssam t->next_sym = s->next_sym;
32016620Ssam }
32116620Ssam }
32216620Ssam
32316620Ssam /*
3249657Slinton * Dump out all the variables associated with the given
32518235Slinton * procedure, function, or program associated with the given stack frame.
3269657Slinton *
3279657Slinton * This is quite inefficient. We traverse the entire symbol table
3289657Slinton * each time we're called. The assumption is that this routine
3299657Slinton * won't be called frequently enough to merit improved performance.
3309657Slinton */
3319657Slinton
dumpvars(f,frame)3329657Slinton public dumpvars(f, frame)
3339657Slinton Symbol f;
3349657Slinton Frame frame;
3359657Slinton {
3369657Slinton register Integer i;
3379657Slinton register Symbol s;
3389657Slinton
3399657Slinton for (i = 0; i < HASHTABLESIZE; i++) {
3409657Slinton for (s = hashtab[i]; s != nil; s = s->next_sym) {
3419657Slinton if (container(s) == f) {
3429657Slinton if (should_print(s)) {
3439657Slinton printv(s, frame);
3449657Slinton putchar('\n');
3459657Slinton } else if (s->class == MODULE) {
3469657Slinton dumpvars(s, frame);
3479657Slinton }
3489657Slinton }
3499657Slinton }
3509657Slinton }
3519657Slinton }
3529657Slinton
3539657Slinton /*
3549657Slinton * Create a builtin type.
3559657Slinton * Builtin types are circular in that btype->type->type = btype.
3569657Slinton */
3579657Slinton
maketype(name,lower,upper)35818235Slinton private Symbol maketype(name, lower, upper)
3599657Slinton String name;
3609657Slinton long lower;
3619657Slinton long upper;
3629657Slinton {
3639657Slinton register Symbol s;
36418235Slinton Name n;
3659657Slinton
36618235Slinton if (name == nil) {
36718235Slinton n = nil;
36818235Slinton } else {
36918235Slinton n = identname(name, true);
37018235Slinton }
37118235Slinton s = insert(n);
37216620Ssam s->language = primlang;
37318235Slinton s->level = 0;
37418235Slinton s->class = TYPE;
37518235Slinton s->type = nil;
37618235Slinton s->chain = nil;
3779657Slinton s->type = newSymbol(nil, 0, RANGE, s, nil);
3789657Slinton s->type->symvalue.rangev.lower = lower;
3799657Slinton s->type->symvalue.rangev.upper = upper;
3809657Slinton return s;
3819657Slinton }
3829657Slinton
3839657Slinton /*
38418235Slinton * Create the builtin symbols.
38518235Slinton */
38618235Slinton
symbols_init()38718235Slinton public symbols_init ()
3889657Slinton {
38918235Slinton Symbol s;
3909657Slinton
39118235Slinton t_boolean = maketype("$boolean", 0L, 1L);
39218235Slinton t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
39318235Slinton t_char = maketype("$char", 0L, 255L);
39418235Slinton t_real = maketype("$real", 8L, 0L);
39518235Slinton t_nil = maketype("$nil", 0L, 0L);
39618235Slinton t_addr = insert(identname("$address", true));
39718235Slinton t_addr->language = primlang;
39818235Slinton t_addr->level = 0;
39918235Slinton t_addr->class = TYPE;
40018235Slinton t_addr->type = newSymbol(nil, 1, PTR, t_int, nil);
40118235Slinton s = insert(identname("true", true));
40218235Slinton s->class = CONST;
40318235Slinton s->type = t_boolean;
40418235Slinton s->symvalue.constval = build(O_LCON, 1L);
40518235Slinton s->symvalue.constval->nodetype = t_boolean;
40618235Slinton s = insert(identname("false", true));
40718235Slinton s->class = CONST;
40818235Slinton s->type = t_boolean;
40918235Slinton s->symvalue.constval = build(O_LCON, 0L);
41018235Slinton s->symvalue.constval->nodetype = t_boolean;
4119657Slinton }
4129657Slinton
4139657Slinton /*
4149657Slinton * Reduce type to avoid worrying about type names.
4159657Slinton */
4169657Slinton
rtype(type)4179657Slinton public Symbol rtype(type)
4189657Slinton Symbol type;
4199657Slinton {
4209657Slinton register Symbol t;
4219657Slinton
4229657Slinton t = type;
4239657Slinton if (t != nil) {
42418235Slinton if (t->class == VAR or t->class == CONST or
42518235Slinton t->class == FIELD or t->class == REF
42618235Slinton ) {
4279657Slinton t = t->type;
4289657Slinton }
42916620Ssam if (t->class == TYPEREF) {
43016620Ssam resolveRef(t);
43116620Ssam }
4329657Slinton while (t->class == TYPE or t->class == TAG) {
4339657Slinton t = t->type;
43416620Ssam if (t->class == TYPEREF) {
43516620Ssam resolveRef(t);
43616620Ssam }
4379657Slinton }
4389657Slinton }
4399657Slinton return t;
4409657Slinton }
4419657Slinton
44216620Ssam /*
44316620Ssam * Find the end of a module name. Return nil if there is none
44416620Ssam * in the given string.
44516620Ssam */
44616620Ssam
findModuleMark(s)44716620Ssam private String findModuleMark (s)
44816620Ssam String s;
44916620Ssam {
45016620Ssam register char *p, *r;
45116620Ssam register boolean done;
45216620Ssam
45316620Ssam p = s;
45416620Ssam done = false;
45516620Ssam do {
45616620Ssam if (*p == ':') {
45716620Ssam done = true;
45816620Ssam r = p;
45916620Ssam } else if (*p == '\0') {
46016620Ssam done = true;
46116620Ssam r = nil;
46216620Ssam } else {
46316620Ssam ++p;
46416620Ssam }
46516620Ssam } while (not done);
46616620Ssam return r;
46716620Ssam }
46816620Ssam
46916620Ssam /*
47016620Ssam * Resolve a type reference by modifying to be the appropriate type.
47116620Ssam *
47216620Ssam * If the reference has a name, then it refers to an opaque type and
47316620Ssam * the actual type is directly accessible. Otherwise, we must use
47416620Ssam * the type reference string, which is of the form "module:{module:}name".
47516620Ssam */
47616620Ssam
resolveRef(t)47716620Ssam public resolveRef (t)
47816620Ssam Symbol t;
47916620Ssam {
48016620Ssam register char *p;
48116620Ssam char *start;
48216620Ssam Symbol s, m, outer;
48316620Ssam Name n;
48416620Ssam
48516620Ssam if (t->name != nil) {
48616620Ssam s = t;
48716620Ssam } else {
48816620Ssam start = t->symvalue.typeref;
48916620Ssam outer = program;
49016620Ssam p = findModuleMark(start);
49116620Ssam while (p != nil) {
49216620Ssam *p = '\0';
49316620Ssam n = identname(start, true);
49416620Ssam find(m, n) where m->block == outer endfind(m);
49516620Ssam if (m == nil) {
49616620Ssam p = nil;
49716620Ssam outer = nil;
49816620Ssam s = nil;
49916620Ssam } else {
50016620Ssam outer = m;
50116620Ssam start = p + 1;
50216620Ssam p = findModuleMark(start);
50316620Ssam }
50416620Ssam }
50516620Ssam if (outer != nil) {
50616620Ssam n = identname(start, true);
50716620Ssam find(s, n) where s->block == outer endfind(s);
50816620Ssam }
50916620Ssam }
51016620Ssam if (s != nil and s->type != nil) {
51116620Ssam t->name = s->type->name;
51216620Ssam t->class = s->type->class;
51316620Ssam t->type = s->type->type;
51416620Ssam t->chain = s->type->chain;
51516620Ssam t->symvalue = s->type->symvalue;
51616620Ssam t->block = s->type->block;
51716620Ssam }
51816620Ssam }
51916620Ssam
regnum(s)52018235Slinton public integer regnum (s)
5219657Slinton Symbol s;
5229657Slinton {
52318235Slinton integer r;
52418235Slinton
5259657Slinton checkref(s);
52633337Sdonn if (s->storage == INREG) {
52718235Slinton r = s->symvalue.offset;
52818235Slinton } else {
52918235Slinton r = -1;
53018235Slinton }
53118235Slinton return r;
5329657Slinton }
5339657Slinton
container(s)5349657Slinton public Symbol container(s)
5359657Slinton Symbol s;
5369657Slinton {
5379657Slinton checkref(s);
5389657Slinton return s->block;
5399657Slinton }
5409657Slinton
constval(s)54118235Slinton public Node constval(s)
54218235Slinton Symbol s;
54318235Slinton {
54418235Slinton checkref(s);
54518235Slinton if (s->class != CONST) {
54618235Slinton error("[internal error: constval(non-CONST)]");
54718235Slinton }
54818235Slinton return s->symvalue.constval;
54918235Slinton }
55018235Slinton
5519657Slinton /*
5529657Slinton * Return the object address of the given symbol.
5539657Slinton *
5549657Slinton * There are the following possibilities:
5559657Slinton *
5569657Slinton * globals - just take offset
5579657Slinton * locals - take offset from locals base
5589657Slinton * arguments - take offset from argument base
5599657Slinton * register - offset is register number
5609657Slinton */
5619657Slinton
56233337Sdonn #define isglobal(s) (s->storage == EXT)
56333337Sdonn #define islocaloff(s) (s->storage == STK and s->symvalue.offset < 0)
56433337Sdonn #define isparamoff(s) (s->storage == STK and s->symvalue.offset >= 0)
5659657Slinton
address(s,frame)56618235Slinton public Address address (s, frame)
5679657Slinton Symbol s;
5689657Slinton Frame frame;
5699657Slinton {
5709657Slinton register Frame frp;
5719657Slinton register Address addr;
5729657Slinton register Symbol cur;
5739657Slinton
5749657Slinton checkref(s);
5759657Slinton if (not isactive(s->block)) {
5769657Slinton error("\"%s\" is not currently defined", symname(s));
5779657Slinton } else if (isglobal(s)) {
5789657Slinton addr = s->symvalue.offset;
5799657Slinton } else {
5809657Slinton frp = frame;
5819657Slinton if (frp == nil) {
5829657Slinton cur = s->block;
5839657Slinton while (cur != nil and cur->class == MODULE) {
5849657Slinton cur = cur->block;
5859657Slinton }
5869657Slinton if (cur == nil) {
58718235Slinton frp = nil;
58818235Slinton } else {
58918235Slinton frp = findframe(cur);
59018235Slinton if (frp == nil) {
59118235Slinton error("[internal error: unexpected nil frame for \"%s\"]",
59218235Slinton symname(s)
59318235Slinton );
59418235Slinton }
5959657Slinton }
5969657Slinton }
5979657Slinton if (islocaloff(s)) {
5989657Slinton addr = locals_base(frp) + s->symvalue.offset;
5999657Slinton } else if (isparamoff(s)) {
6009657Slinton addr = args_base(frp) + s->symvalue.offset;
6019657Slinton } else if (isreg(s)) {
6029657Slinton addr = savereg(s->symvalue.offset, frp);
6039657Slinton } else {
6049657Slinton panic("address: bad symbol \"%s\"", symname(s));
6059657Slinton }
6069657Slinton }
6079657Slinton return addr;
6089657Slinton }
6099657Slinton
6109657Slinton /*
6119657Slinton * Define a symbol used to access register values.
6129657Slinton */
6139657Slinton
defregname(n,r)61418235Slinton public defregname (n, r)
6159657Slinton Name n;
61618235Slinton integer r;
6179657Slinton {
61818235Slinton Symbol s;
6199657Slinton
6209657Slinton s = insert(n);
62118235Slinton s->language = t_addr->language;
6229657Slinton s->class = VAR;
62333337Sdonn s->storage = INREG;
62433337Sdonn s->level = 3;
62518235Slinton s->type = t_addr;
6269657Slinton s->symvalue.offset = r;
6279657Slinton }
6289657Slinton
6299657Slinton /*
6309657Slinton * Resolve an "abstract" type reference.
6319657Slinton *
6329657Slinton * It is possible in C to define a pointer to a type, but never define
6339657Slinton * the type in a particular source file. Here we try to resolve
6349657Slinton * the type definition. This is problematic, it is possible to
6359657Slinton * have multiple, different definitions for the same name type.
6369657Slinton */
6379657Slinton
findtype(s)6389657Slinton public findtype(s)
6399657Slinton Symbol s;
6409657Slinton {
6419657Slinton register Symbol t, u, prev;
6429657Slinton
6439657Slinton u = s;
6449657Slinton prev = nil;
6459657Slinton while (u != nil and u->class != BADUSE) {
6469657Slinton if (u->name != nil) {
6479657Slinton prev = u;
6489657Slinton }
6499657Slinton u = u->type;
6509657Slinton }
6519657Slinton if (prev == nil) {
6529657Slinton error("couldn't find link to type reference");
6539657Slinton }
65418235Slinton t = lookup(prev->name);
65518235Slinton while (t != nil and
65618235Slinton not (
65718235Slinton t != prev and t->name == prev->name and
65818235Slinton t->block->class == MODULE and t->class == prev->class and
65918235Slinton t->type != nil and t->type->type != nil and
66018235Slinton t->type->type->class != BADUSE
66118235Slinton )
66218235Slinton ) {
66318235Slinton t = t->next_sym;
66418235Slinton }
6659657Slinton if (t == nil) {
6669657Slinton error("couldn't resolve reference");
6679657Slinton } else {
6689657Slinton prev->type = t->type;
6699657Slinton }
6709657Slinton }
6719657Slinton
6729657Slinton /*
6739657Slinton * Find the size in bytes of the given type.
6749657Slinton *
6759657Slinton * This is probably the WRONG thing to do. The size should be kept
6769657Slinton * as an attribute in the symbol information as is done for structures
6779657Slinton * and fields. I haven't gotten around to cleaning this up yet.
6789657Slinton */
6799657Slinton
68012547Scsvaf #define MAXUCHAR 255
68112547Scsvaf #define MAXUSHORT 65535L
6829657Slinton #define MINCHAR -128
6839657Slinton #define MAXCHAR 127
6849657Slinton #define MINSHORT -32768
6859657Slinton #define MAXSHORT 32767
6869657Slinton
findbounds(u,lower,upper)68716620Ssam public findbounds (u, lower, upper)
68816620Ssam Symbol u;
68916620Ssam long *lower, *upper;
69016620Ssam {
69116620Ssam Rangetype lbt, ubt;
69216620Ssam long lb, ub;
69316620Ssam
69416620Ssam if (u->class == RANGE) {
69516620Ssam lbt = u->symvalue.rangev.lowertype;
69616620Ssam ubt = u->symvalue.rangev.uppertype;
69716620Ssam lb = u->symvalue.rangev.lower;
69816620Ssam ub = u->symvalue.rangev.upper;
69916620Ssam if (lbt == R_ARG or lbt == R_TEMP) {
70016620Ssam if (not getbound(u, lb, lbt, lower)) {
70116620Ssam error("dynamic bounds not currently available");
70216620Ssam }
70316620Ssam } else {
70416620Ssam *lower = lb;
70516620Ssam }
70616620Ssam if (ubt == R_ARG or ubt == R_TEMP) {
70716620Ssam if (not getbound(u, ub, ubt, upper)) {
70816620Ssam error("dynamic bounds not currently available");
70916620Ssam }
71016620Ssam } else {
71116620Ssam *upper = ub;
71216620Ssam }
71316620Ssam } else if (u->class == SCAL) {
71416620Ssam *lower = 0;
71516620Ssam *upper = u->symvalue.iconval - 1;
71616620Ssam } else {
71718235Slinton error("[internal error: unexpected array bound type]");
71816620Ssam }
71916620Ssam }
72016620Ssam
size(sym)72116620Ssam public integer size(sym)
72216620Ssam Symbol sym;
72316620Ssam {
72416620Ssam register Symbol s, t, u;
72516620Ssam register integer nel, elsize;
7269657Slinton long lower, upper;
72716620Ssam integer r, off, len;
7289657Slinton
7299657Slinton t = sym;
7309657Slinton checkref(t);
73116620Ssam if (t->class == TYPEREF) {
73216620Ssam resolveRef(t);
73316620Ssam }
7349657Slinton switch (t->class) {
7359657Slinton case RANGE:
7369657Slinton lower = t->symvalue.rangev.lower;
7379657Slinton upper = t->symvalue.rangev.upper;
73816620Ssam if (upper == 0 and lower > 0) {
73916620Ssam /* real */
7409657Slinton r = lower;
74116620Ssam } else if (lower > upper) {
74216620Ssam /* unsigned long */
74316620Ssam r = sizeof(long);
74412045Slinton } else if (
74512547Scsvaf (lower >= MINCHAR and upper <= MAXCHAR) or
74612547Scsvaf (lower >= 0 and upper <= MAXUCHAR)
74712547Scsvaf ) {
7489657Slinton r = sizeof(char);
74912547Scsvaf } else if (
75012547Scsvaf (lower >= MINSHORT and upper <= MAXSHORT) or
75112547Scsvaf (lower >= 0 and upper <= MAXUSHORT)
75212547Scsvaf ) {
7539657Slinton r = sizeof(short);
7549657Slinton } else {
7559657Slinton r = sizeof(long);
7569657Slinton }
7579657Slinton break;
7589657Slinton
7599657Slinton case ARRAY:
7609657Slinton elsize = size(t->type);
7619657Slinton nel = 1;
7629657Slinton for (t = t->chain; t != nil; t = t->chain) {
76316620Ssam u = rtype(t);
76416620Ssam findbounds(u, &lower, &upper);
7659657Slinton nel *= (upper-lower+1);
7669657Slinton }
7679657Slinton r = nel*elsize;
7689657Slinton break;
7699657Slinton
77033337Sdonn case OPENARRAY:
77118235Slinton case DYNARRAY:
77218235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word);
77318235Slinton break;
77418235Slinton
77518235Slinton case SUBARRAY:
77618235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
77718235Slinton break;
77818235Slinton
77912547Scsvaf case REF:
7809657Slinton case VAR:
7819657Slinton r = size(t->type);
78212127Slinton /*
78312127Slinton *
78412045Slinton if (r < sizeof(Word) and isparam(t)) {
7859657Slinton r = sizeof(Word);
7869657Slinton }
78712547Scsvaf */
7889657Slinton break;
7899657Slinton
79018235Slinton case FVAR:
7919657Slinton case CONST:
79218235Slinton case TAG:
7939657Slinton r = size(t->type);
7949657Slinton break;
7959657Slinton
7969657Slinton case TYPE:
79733337Sdonn /*
79833337Sdonn * This causes problems on the IRIS because of the compiler bug
79933337Sdonn * with stab offsets for parameters. Not sure it's really
80033337Sdonn * necessary anyway.
80133337Sdonn */
80233337Sdonn # ifndef IRIS
8039657Slinton if (t->type->class == PTR and t->type->type->class == BADUSE) {
8049657Slinton findtype(t);
8059657Slinton }
80633337Sdonn # endif
8079657Slinton r = size(t->type);
8089657Slinton break;
8099657Slinton
8109657Slinton case FIELD:
81116620Ssam off = t->symvalue.field.offset;
81216620Ssam len = t->symvalue.field.length;
81316620Ssam r = (off + len + 7) div 8 - (off div 8);
8149657Slinton break;
8159657Slinton
8169657Slinton case RECORD:
8179657Slinton case VARNT:
8189657Slinton r = t->symvalue.offset;
8199657Slinton if (r == 0 and t->chain != nil) {
8209657Slinton panic("missing size information for record");
8219657Slinton }
8229657Slinton break;
8239657Slinton
8249657Slinton case PTR:
82518235Slinton case TYPEREF:
8269657Slinton case FILET:
8279657Slinton r = sizeof(Word);
8289657Slinton break;
8299657Slinton
8309657Slinton case SCAL:
83112609Slinton r = sizeof(Word);
83212609Slinton /*
83312609Slinton *
8349657Slinton if (t->symvalue.iconval > 255) {
8359657Slinton r = sizeof(short);
8369657Slinton } else {
8379657Slinton r = sizeof(char);
8389657Slinton }
83912609Slinton *
84012609Slinton */
8419657Slinton break;
8429657Slinton
8439657Slinton case FPROC:
8449657Slinton case FFUNC:
8459657Slinton r = sizeof(Word);
8469657Slinton break;
8479657Slinton
8489657Slinton case PROC:
8499657Slinton case FUNC:
8509657Slinton case MODULE:
8519657Slinton case PROG:
8529657Slinton r = sizeof(Symbol);
8539657Slinton break;
8549657Slinton
85516620Ssam case SET:
85616620Ssam u = rtype(t->type);
85716620Ssam switch (u->class) {
85816620Ssam case RANGE:
85916620Ssam r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
86016620Ssam break;
86116620Ssam
86216620Ssam case SCAL:
86316620Ssam r = u->symvalue.iconval;
86416620Ssam break;
86516620Ssam
86616620Ssam default:
86716620Ssam error("expected range for set base type");
86816620Ssam break;
86916620Ssam }
87016620Ssam r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
87116620Ssam break;
87216620Ssam
87318235Slinton /*
87418235Slinton * These can happen in C (unfortunately) for unresolved type references
87518235Slinton * Assume they are pointers.
87618235Slinton */
87718235Slinton case BADUSE:
87818235Slinton r = sizeof(Address);
87918235Slinton break;
88018235Slinton
8819657Slinton default:
8829657Slinton if (ord(t->class) > ord(TYPEREF)) {
8839657Slinton panic("size: bad class (%d)", ord(t->class));
8849657Slinton } else {
88518235Slinton fprintf(stderr, "can't compute size of a %s\n", classname(t));
8869657Slinton }
88716620Ssam r = 0;
88816620Ssam break;
8899657Slinton }
8909657Slinton return r;
8919657Slinton }
8929657Slinton
8939657Slinton /*
89418235Slinton * Return the size associated with a symbol that takes into account
89518235Slinton * reference parameters. This might be better as the normal size function, but
89618235Slinton * too many places already depend on it working the way it does.
89718235Slinton */
89818235Slinton
psize(s)89918235Slinton public integer psize (s)
90018235Slinton Symbol s;
90118235Slinton {
90218235Slinton integer r;
90318235Slinton Symbol t;
90418235Slinton
90518235Slinton if (s->class == REF) {
90618235Slinton t = rtype(s->type);
90733337Sdonn if (t->class == OPENARRAY) {
90818235Slinton r = (t->symvalue.ndims + 1) * sizeof(Word);
90918235Slinton } else if (t->class == SUBARRAY) {
91018235Slinton r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
91118235Slinton } else {
91218235Slinton r = sizeof(Word);
91318235Slinton }
91418235Slinton } else {
91518235Slinton r = size(s);
91618235Slinton }
91718235Slinton return r;
91818235Slinton }
91918235Slinton
92018235Slinton /*
9219657Slinton * Test if a symbol is a parameter. This is true if there
9229657Slinton * is a cycle from s->block to s via chain pointers.
9239657Slinton */
9249657Slinton
isparam(s)9259657Slinton public Boolean isparam(s)
9269657Slinton Symbol s;
9279657Slinton {
9289657Slinton register Symbol t;
9299657Slinton
9309657Slinton t = s->block;
9319657Slinton while (t != nil and t != s) {
9329657Slinton t = t->chain;
9339657Slinton }
9349657Slinton return (Boolean) (t != nil);
9359657Slinton }
9369657Slinton
9379657Slinton /*
93816620Ssam * Test if a type is an open array parameter type.
9399657Slinton */
9409657Slinton
isopenarray(type)94118235Slinton public boolean isopenarray (type)
94218235Slinton Symbol type;
94316620Ssam {
94418235Slinton Symbol t;
94518235Slinton
94618235Slinton t = rtype(type);
94733337Sdonn return (boolean) (t->class == OPENARRAY);
94816620Ssam }
94916620Ssam
95016620Ssam /*
95118235Slinton * Test if a symbol is a var parameter, i.e. has class REF.
95216620Ssam */
95316620Ssam
isvarparam(s)9549657Slinton public Boolean isvarparam(s)
9559657Slinton Symbol s;
9569657Slinton {
9579657Slinton return (Boolean) (s->class == REF);
9589657Slinton }
9599657Slinton
9609657Slinton /*
9619657Slinton * Test if a symbol is a variable (actually any addressible quantity
9629657Slinton * with do).
9639657Slinton */
9649657Slinton
isvariable(s)9659657Slinton public Boolean isvariable(s)
96618235Slinton Symbol s;
9679657Slinton {
9689657Slinton return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
9699657Slinton }
9709657Slinton
9719657Slinton /*
97218235Slinton * Test if a symbol is a constant.
97318235Slinton */
97418235Slinton
isconst(s)97518235Slinton public Boolean isconst(s)
97618235Slinton Symbol s;
9779657Slinton {
97818235Slinton return (Boolean) (s->class == CONST);
9799657Slinton }
9809657Slinton
9819657Slinton /*
9829657Slinton * Test if a symbol is a module.
9839657Slinton */
9849657Slinton
ismodule(s)9859657Slinton public Boolean ismodule(s)
9869657Slinton register Symbol s;
9879657Slinton {
9889657Slinton return (Boolean) (s->class == MODULE);
9899657Slinton }
9909657Slinton
9919657Slinton /*
99216620Ssam * Mark a procedure or function as internal, meaning that it is called
99316620Ssam * with a different calling sequence.
99416620Ssam */
99516620Ssam
markInternal(s)99616620Ssam public markInternal (s)
99716620Ssam Symbol s;
99816620Ssam {
99916620Ssam s->symvalue.funcv.intern = true;
100016620Ssam }
100116620Ssam
isinternal(s)100216620Ssam public boolean isinternal (s)
100316620Ssam Symbol s;
100416620Ssam {
100516620Ssam return s->symvalue.funcv.intern;
100616620Ssam }
100716620Ssam
100816620Ssam /*
100918235Slinton * Decide if a field begins or ends on a bit rather than byte boundary.
101018235Slinton */
101118235Slinton
isbitfield(s)101218235Slinton public Boolean isbitfield(s)
101318235Slinton register Symbol s;
101418235Slinton {
101518235Slinton boolean b;
101618235Slinton register integer off, len;
101718235Slinton register Symbol t;
101818235Slinton
101918235Slinton off = s->symvalue.field.offset;
102018235Slinton len = s->symvalue.field.length;
102118235Slinton if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
102218235Slinton b = true;
102318235Slinton } else {
102418235Slinton t = rtype(s->type);
102518235Slinton b = (Boolean) (
102618235Slinton (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or
102718235Slinton len != (size(t)*BITSPERBYTE)
102818235Slinton );
102918235Slinton }
103018235Slinton return b;
103118235Slinton }
103218235Slinton
primlang_typematch(t1,t2)103318235Slinton private boolean primlang_typematch (t1, t2)
103418235Slinton Symbol t1, t2;
103518235Slinton {
103618235Slinton return (boolean) (
103718235Slinton (t1 == t2) or
103818235Slinton (
103918235Slinton t1->class == RANGE and t2->class == RANGE and
104018235Slinton t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
104118235Slinton t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
104218235Slinton ) or (
104318235Slinton t1->class == PTR and t2->class == RANGE and
104418235Slinton t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower
104518235Slinton ) or (
104618235Slinton t2->class == PTR and t1->class == RANGE and
104718235Slinton t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower
104818235Slinton )
104918235Slinton );
105018235Slinton }
105118235Slinton
105218235Slinton /*
10539657Slinton * Test if two types match.
10549657Slinton * Equivalent names implies a match in any language.
10559657Slinton *
10569657Slinton * Special symbols must be handled with care.
10579657Slinton */
10589657Slinton
compatible(t1,t2)10599657Slinton public Boolean compatible(t1, t2)
10609657Slinton register Symbol t1, t2;
10619657Slinton {
10629657Slinton Boolean b;
106316620Ssam Symbol rt1, rt2;
10649657Slinton
10659657Slinton if (t1 == t2) {
10669657Slinton b = true;
10679657Slinton } else if (t1 == nil or t2 == nil) {
10689657Slinton b = false;
10699657Slinton } else if (t1 == procsym) {
10709657Slinton b = isblock(t2);
10719657Slinton } else if (t2 == procsym) {
10729657Slinton b = isblock(t1);
10739657Slinton } else if (t1->language == nil) {
107416620Ssam if (t2->language == nil) {
107516620Ssam b = false;
107633337Sdonn } else if (t2->language == primlang) {
107733337Sdonn b = (boolean) primlang_typematch(rtype(t1), rtype(t2));
107816620Ssam } else {
107916620Ssam b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
108016620Ssam }
108133337Sdonn } else if (t1->language == primlang) {
108233337Sdonn if (t2->language == primlang or t2->language == nil) {
108333337Sdonn b = primlang_typematch(rtype(t1), rtype(t2));
108433337Sdonn } else {
108533337Sdonn b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
108633337Sdonn }
10879657Slinton } else {
108816620Ssam b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
10899657Slinton }
10909657Slinton return b;
10919657Slinton }
10929657Slinton
10939657Slinton /*
10949657Slinton * Check for a type of the given name.
10959657Slinton */
10969657Slinton
istypename(type,name)10979657Slinton public Boolean istypename(type, name)
10989657Slinton Symbol type;
10999657Slinton String name;
11009657Slinton {
110118235Slinton register Symbol t;
11029657Slinton Boolean b;
11039657Slinton
11049657Slinton t = type;
110518235Slinton if (t == nil) {
110618235Slinton b = false;
110718235Slinton } else {
110818235Slinton b = (Boolean) (
110918235Slinton t->class == TYPE and streq(ident(t->name), name)
111018235Slinton );
111118235Slinton }
11129657Slinton return b;
11139657Slinton }
11149657Slinton
11159657Slinton /*
111616620Ssam * Determine if a (value) parameter should actually be passed by address.
111716620Ssam */
111816620Ssam
passaddr(p,exprtype)111916620Ssam public boolean passaddr (p, exprtype)
112016620Ssam Symbol p, exprtype;
112116620Ssam {
112216620Ssam boolean b;
112316620Ssam Language def;
112416620Ssam
112516620Ssam if (p == nil) {
112616620Ssam def = findlanguage(".c");
112716620Ssam b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
112816620Ssam } else if (p->language == nil or p->language == primlang) {
112916620Ssam b = false;
113016620Ssam } else if (isopenarray(p->type)) {
113116620Ssam b = true;
113216620Ssam } else {
113316620Ssam b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
113416620Ssam }
113516620Ssam return b;
113616620Ssam }
113716620Ssam
113816620Ssam /*
11399657Slinton * Test if the name of a symbol is uniquely defined or not.
11409657Slinton */
11419657Slinton
isambiguous(s)11429657Slinton public Boolean isambiguous(s)
11439657Slinton register Symbol s;
11449657Slinton {
11459657Slinton register Symbol t;
11469657Slinton
11479657Slinton find(t, s->name) where t != s endfind(t);
11489657Slinton return (Boolean) (t != nil);
11499657Slinton }
11509657Slinton
11519657Slinton typedef char *Arglist;
11529657Slinton
11539657Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1]
11549657Slinton
11559657Slinton private Symbol mkstring();
11569657Slinton
11579657Slinton /*
11589657Slinton * Determine the type of a parse tree.
115918235Slinton *
11609657Slinton * Also make some symbol-dependent changes to the tree such as
116118235Slinton * removing indirection for constant or register symbols.
11629657Slinton */
11639657Slinton
assigntypes(p)116418235Slinton public assigntypes (p)
11659657Slinton register Node p;
11669657Slinton {
11679657Slinton register Node p1;
11689657Slinton register Symbol s;
11699657Slinton
11709657Slinton switch (p->op) {
11719657Slinton case O_SYM:
117218235Slinton p->nodetype = p->value.sym;
11739657Slinton break;
11749657Slinton
11759657Slinton case O_LCON:
11769657Slinton p->nodetype = t_int;
11779657Slinton break;
11789657Slinton
117918235Slinton case O_CCON:
118018235Slinton p->nodetype = t_char;
118118235Slinton break;
118218235Slinton
11839657Slinton case O_FCON:
11849657Slinton p->nodetype = t_real;
11859657Slinton break;
11869657Slinton
11879657Slinton case O_SCON:
118818235Slinton p->nodetype = mkstring(p->value.scon);
11899657Slinton break;
11909657Slinton
11919657Slinton case O_INDIR:
11929657Slinton p1 = p->value.arg[0];
119318235Slinton s = rtype(p1->nodetype);
119418235Slinton if (s->class != PTR) {
119518235Slinton beginerrmsg();
119618235Slinton fprintf(stderr, "\"");
119718235Slinton prtree(stderr, p1);
119818235Slinton fprintf(stderr, "\" is not a pointer");
119918235Slinton enderrmsg();
120018235Slinton }
12019657Slinton p->nodetype = rtype(p1->nodetype)->type;
12029657Slinton break;
12039657Slinton
12049657Slinton case O_DOT:
12059657Slinton p->nodetype = p->value.arg[1]->value.sym;
12069657Slinton break;
12079657Slinton
12089657Slinton case O_RVAL:
12099657Slinton p1 = p->value.arg[0];
12109657Slinton p->nodetype = p1->nodetype;
12119657Slinton if (p1->op == O_SYM) {
121218235Slinton if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) {
121318235Slinton p->op = p1->op;
121418235Slinton p->value.sym = p1->value.sym;
121518235Slinton p->nodetype = p1->nodetype;
121618235Slinton dispose(p1);
12179657Slinton } else if (p1->value.sym->class == CONST) {
121818235Slinton p->op = p1->op;
121918235Slinton p->value = p1->value;
122018235Slinton p->nodetype = p1->nodetype;
122118235Slinton dispose(p1);
12229657Slinton } else if (isreg(p1->value.sym)) {
12239657Slinton p->op = O_SYM;
12249657Slinton p->value.sym = p1->value.sym;
12259657Slinton dispose(p1);
12269657Slinton }
12279657Slinton } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
12289657Slinton s = p1->value.arg[0]->value.sym;
12299657Slinton if (isreg(s)) {
12309657Slinton p1->op = O_SYM;
12319657Slinton dispose(p1->value.arg[0]);
12329657Slinton p1->value.sym = s;
12339657Slinton p1->nodetype = s;
12349657Slinton }
12359657Slinton }
12369657Slinton break;
12379657Slinton
123818235Slinton case O_COMMA:
123918235Slinton p->nodetype = p->value.arg[0]->nodetype;
124018235Slinton break;
124118235Slinton
124218235Slinton case O_CALLPROC:
12439657Slinton case O_CALL:
12449657Slinton p1 = p->value.arg[0];
124511171Slinton p->nodetype = rtype(p1->nodetype)->type;
12469657Slinton break;
12479657Slinton
124811171Slinton case O_TYPERENAME:
124911171Slinton p->nodetype = p->value.arg[1]->nodetype;
125011171Slinton break;
125111171Slinton
12529657Slinton case O_ITOF:
12539657Slinton p->nodetype = t_real;
12549657Slinton break;
12559657Slinton
12569657Slinton case O_NEG:
12579657Slinton s = p->value.arg[0]->nodetype;
12589657Slinton if (not compatible(s, t_int)) {
12599657Slinton if (not compatible(s, t_real)) {
12609657Slinton beginerrmsg();
126116620Ssam fprintf(stderr, "\"");
12629657Slinton prtree(stderr, p->value.arg[0]);
126316620Ssam fprintf(stderr, "\" is improper type");
12649657Slinton enderrmsg();
12659657Slinton } else {
12669657Slinton p->op = O_NEGF;
12679657Slinton }
12689657Slinton }
12699657Slinton p->nodetype = s;
12709657Slinton break;
12719657Slinton
12729657Slinton case O_ADD:
12739657Slinton case O_SUB:
12749657Slinton case O_MUL:
127516620Ssam binaryop(p, nil);
127616620Ssam break;
127716620Ssam
12789657Slinton case O_LT:
12799657Slinton case O_LE:
12809657Slinton case O_GT:
12819657Slinton case O_GE:
12829657Slinton case O_EQ:
12839657Slinton case O_NE:
128416620Ssam binaryop(p, t_boolean);
12859657Slinton break;
12869657Slinton
12879657Slinton case O_DIVF:
12889657Slinton convert(&(p->value.arg[0]), t_real, O_ITOF);
12899657Slinton convert(&(p->value.arg[1]), t_real, O_ITOF);
12909657Slinton p->nodetype = t_real;
12919657Slinton break;
12929657Slinton
12939657Slinton case O_DIV:
12949657Slinton case O_MOD:
12959657Slinton convert(&(p->value.arg[0]), t_int, O_NOP);
12969657Slinton convert(&(p->value.arg[1]), t_int, O_NOP);
12979657Slinton p->nodetype = t_int;
12989657Slinton break;
12999657Slinton
13009657Slinton case O_AND:
13019657Slinton case O_OR:
13029657Slinton chkboolean(p->value.arg[0]);
13039657Slinton chkboolean(p->value.arg[1]);
13049657Slinton p->nodetype = t_boolean;
13059657Slinton break;
13069657Slinton
13079657Slinton case O_QLINE:
13089657Slinton p->nodetype = t_int;
13099657Slinton break;
13109657Slinton
13119657Slinton default:
13129657Slinton p->nodetype = nil;
13139657Slinton break;
13149657Slinton }
13159657Slinton }
13169657Slinton
13179657Slinton /*
131816620Ssam * Process a binary arithmetic or relational operator.
131916620Ssam * Convert from integer to real if necessary.
132016620Ssam */
132116620Ssam
binaryop(p,t)132216620Ssam private binaryop (p, t)
132316620Ssam Node p;
132416620Ssam Symbol t;
132516620Ssam {
132616620Ssam Node p1, p2;
132716620Ssam Boolean t1real, t2real;
132816620Ssam Symbol t1, t2;
132916620Ssam
133016620Ssam p1 = p->value.arg[0];
133116620Ssam p2 = p->value.arg[1];
133216620Ssam t1 = rtype(p1->nodetype);
133316620Ssam t2 = rtype(p2->nodetype);
133416620Ssam t1real = compatible(t1, t_real);
133516620Ssam t2real = compatible(t2, t_real);
133616620Ssam if (t1real or t2real) {
133716620Ssam p->op = (Operator) (ord(p->op) + 1);
133816620Ssam if (not t1real) {
133916620Ssam p->value.arg[0] = build(O_ITOF, p1);
134016620Ssam } else if (not t2real) {
134116620Ssam p->value.arg[1] = build(O_ITOF, p2);
134216620Ssam }
134316620Ssam p->nodetype = t_real;
134416620Ssam } else {
134516620Ssam if (size(p1->nodetype) > sizeof(integer)) {
134616620Ssam beginerrmsg();
134716620Ssam fprintf(stderr, "operation not defined on \"");
134816620Ssam prtree(stderr, p1);
134916620Ssam fprintf(stderr, "\"");
135016620Ssam enderrmsg();
135116620Ssam } else if (size(p2->nodetype) > sizeof(integer)) {
135216620Ssam beginerrmsg();
135316620Ssam fprintf(stderr, "operation not defined on \"");
135416620Ssam prtree(stderr, p2);
135516620Ssam fprintf(stderr, "\"");
135616620Ssam enderrmsg();
135716620Ssam }
135816620Ssam p->nodetype = t_int;
135916620Ssam }
136016620Ssam if (t != nil) {
136116620Ssam p->nodetype = t;
136216620Ssam }
136316620Ssam }
136416620Ssam
136516620Ssam /*
13669657Slinton * Convert a tree to a type via a conversion operator;
13679657Slinton * if this isn't possible generate an error.
13689657Slinton */
13699657Slinton
convert(tp,typeto,op)13709657Slinton private convert(tp, typeto, op)
13719657Slinton Node *tp;
13729657Slinton Symbol typeto;
13739657Slinton Operator op;
13749657Slinton {
137516620Ssam Node tree;
137616620Ssam Symbol s, t;
13779657Slinton
137816620Ssam tree = *tp;
13799657Slinton s = rtype(tree->nodetype);
138016620Ssam t = rtype(typeto);
138116620Ssam if (compatible(t, t_real) and compatible(s, t_int)) {
138234257Sdonn /* we can convert int => floating but not the reverse */
13839657Slinton tree = build(op, tree);
138416620Ssam } else if (not compatible(s, t)) {
13859657Slinton beginerrmsg();
138616620Ssam prtree(stderr, tree);
138734257Sdonn fprintf(stderr, ": illegal type in operation");
13889657Slinton enderrmsg();
13899657Slinton }
139016620Ssam *tp = tree;
13919657Slinton }
13929657Slinton
13939657Slinton /*
13949657Slinton * Construct a node for the dot operator.
13959657Slinton *
13969657Slinton * If the left operand is not a record, but rather a procedure
13979657Slinton * or function, then we interpret the "." as referencing an
13989657Slinton * "invisible" variable; i.e. a variable within a dynamically
13999657Slinton * active block but not within the static scope of the current procedure.
14009657Slinton */
14019657Slinton
dot(record,fieldname)14029657Slinton public Node dot(record, fieldname)
14039657Slinton Node record;
14049657Slinton Name fieldname;
14059657Slinton {
140618235Slinton register Node rec, p;
14079657Slinton register Symbol s, t;
14089657Slinton
140918235Slinton rec = record;
141018235Slinton if (isblock(rec->nodetype)) {
14119657Slinton find(s, fieldname) where
141218235Slinton s->block == rec->nodetype and
141318235Slinton s->class != FIELD
14149657Slinton endfind(s);
14159657Slinton if (s == nil) {
14169657Slinton beginerrmsg();
14179657Slinton fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
141818235Slinton printname(stderr, rec->nodetype);
14199657Slinton enderrmsg();
14209657Slinton }
14219657Slinton p = new(Node);
14229657Slinton p->op = O_SYM;
14239657Slinton p->value.sym = s;
142418235Slinton p->nodetype = s;
14259657Slinton } else {
142618235Slinton p = rec;
14279657Slinton t = rtype(p->nodetype);
14289657Slinton if (t->class == PTR) {
14299657Slinton s = findfield(fieldname, t->type);
14309657Slinton } else {
14319657Slinton s = findfield(fieldname, t);
14329657Slinton }
14339657Slinton if (s == nil) {
14349657Slinton beginerrmsg();
14359657Slinton fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
143618235Slinton prtree(stderr, rec);
14379657Slinton enderrmsg();
14389657Slinton }
143918235Slinton if (t->class != PTR or isreg(rec->nodetype)) {
144018235Slinton p = unrval(p);
14419657Slinton }
144218235Slinton p->nodetype = t_addr;
14439657Slinton p = build(O_DOT, p, build(O_SYM, s));
14449657Slinton }
144518235Slinton return build(O_RVAL, p);
14469657Slinton }
14479657Slinton
14489657Slinton /*
14499657Slinton * Return a tree corresponding to an array reference and do the
14509657Slinton * error checking.
14519657Slinton */
14529657Slinton
subscript(a,slist)14539657Slinton public Node subscript(a, slist)
14549657Slinton Node a, slist;
14559657Slinton {
145616620Ssam Symbol t;
145718235Slinton Node p;
14589657Slinton
145916620Ssam t = rtype(a->nodetype);
146018235Slinton if (t->language == nil or t->language == primlang) {
146118235Slinton p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
146216620Ssam } else {
146318235Slinton p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
146416620Ssam }
146518235Slinton return build(O_RVAL, p);
14669657Slinton }
14679657Slinton
14689657Slinton /*
14699657Slinton * Evaluate a subscript index.
14709657Slinton */
14719657Slinton
evalindex(s,base,i)147218235Slinton public int evalindex(s, base, i)
14739657Slinton Symbol s;
147418235Slinton Address base;
14759657Slinton long i;
14769657Slinton {
147716620Ssam Symbol t;
147818235Slinton int r;
14799657Slinton
148016620Ssam t = rtype(s);
148118235Slinton if (t->language == nil or t->language == primlang) {
148218235Slinton r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
148316620Ssam } else {
148418235Slinton r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
148516620Ssam }
148618235Slinton return r;
14879657Slinton }
14889657Slinton
14899657Slinton /*
14909657Slinton * Check to see if a tree is boolean-valued, if not it's an error.
14919657Slinton */
14929657Slinton
chkboolean(p)14939657Slinton public chkboolean(p)
14949657Slinton register Node p;
14959657Slinton {
14969657Slinton if (p->nodetype != t_boolean) {
14979657Slinton beginerrmsg();
14989657Slinton fprintf(stderr, "found ");
14999657Slinton prtree(stderr, p);
15009657Slinton fprintf(stderr, ", expected boolean expression");
15019657Slinton enderrmsg();
15029657Slinton }
15039657Slinton }
15049657Slinton
15059657Slinton /*
150616620Ssam * Construct a node for the type of a string.
15079657Slinton */
15089657Slinton
mkstring(str)15099657Slinton private Symbol mkstring(str)
15109657Slinton String str;
15119657Slinton {
15129657Slinton register Symbol s;
15139657Slinton
151418235Slinton s = newSymbol(nil, 0, ARRAY, t_char, nil);
151518235Slinton s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
151618235Slinton s->chain->language = s->language;
151718235Slinton s->chain->symvalue.rangev.lower = 1;
151818235Slinton s->chain->symvalue.rangev.upper = strlen(str) + 1;
15199657Slinton return s;
15209657Slinton }
15219657Slinton
15229657Slinton /*
15239657Slinton * Free up the space allocated for a string type.
15249657Slinton */
15259657Slinton
unmkstring(s)15269657Slinton public unmkstring(s)
15279657Slinton Symbol s;
15289657Slinton {
15299657Slinton dispose(s->chain);
15309657Slinton }
15319657Slinton
15329657Slinton /*
153318235Slinton * Figure out the "current" variable or function being referred to
153418235Slinton * by the name n.
15359657Slinton */
15369657Slinton
153718235Slinton private boolean stwhich(), dynwhich();
153818235Slinton
which(n)153918235Slinton public Symbol which (n)
15409657Slinton Name n;
15419657Slinton {
154218235Slinton Symbol s;
15439657Slinton
154418235Slinton s = lookup(n);
15459657Slinton if (s == nil) {
154618235Slinton error("\"%s\" is not defined", ident(n));
154718235Slinton } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
154818235Slinton printf("[using ");
154918235Slinton printname(stdout, s);
155018235Slinton printf("]\n");
15519657Slinton }
155218235Slinton return s;
155318235Slinton }
155418235Slinton
155518235Slinton /*
155618235Slinton * Static search.
155718235Slinton */
155818235Slinton
stwhich(var_s)155918235Slinton private boolean stwhich (var_s)
156018235Slinton Symbol *var_s;
156118235Slinton {
156218235Slinton Name n; /* name of desired symbol */
156318235Slinton Symbol s; /* iteration variable for symbols with name n */
156418235Slinton Symbol f; /* iteration variable for blocks containing s */
156518235Slinton integer count; /* number of levels from s->block to curfunc */
156618235Slinton Symbol t; /* current best answer for stwhich(n) */
156718235Slinton integer mincount; /* relative level for current best answer (t) */
156818235Slinton boolean b; /* return value, true if symbol found */
156918235Slinton
157018235Slinton s = *var_s;
157118235Slinton n = s->name;
157218235Slinton t = s;
157318235Slinton mincount = 10000; /* force first match to set mincount */
157418235Slinton do {
157518235Slinton if (s->name == n and s->class != FIELD and s->class != TAG) {
157618235Slinton f = curfunc;
157718235Slinton count = 0;
157818235Slinton while (f != nil and f != s->block) {
157918235Slinton ++count;
158018235Slinton f = f->block;
158118235Slinton }
158218235Slinton if (f != nil and count < mincount) {
158318235Slinton t = s;
158418235Slinton mincount = count;
158518235Slinton b = true;
158618235Slinton }
158718235Slinton }
158818235Slinton s = s->next_sym;
158918235Slinton } while (s != nil);
159018235Slinton if (mincount != 10000) {
159118235Slinton *var_s = t;
159218235Slinton b = true;
15939657Slinton } else {
159418235Slinton b = false;
159518235Slinton }
159618235Slinton return b;
159718235Slinton }
159818235Slinton
159918235Slinton /*
160018235Slinton * Dynamic search.
160118235Slinton */
160218235Slinton
dynwhich(var_s)160318235Slinton private boolean dynwhich (var_s)
160418235Slinton Symbol *var_s;
160518235Slinton {
160618235Slinton Name n; /* name of desired symbol */
160718235Slinton Symbol s; /* iteration variable for possible symbols */
160818235Slinton Symbol f; /* iteration variable for active functions */
160918235Slinton Frame frp; /* frame associated with stack walk */
161018235Slinton boolean b; /* return value */
161118235Slinton
161218235Slinton f = curfunc;
161318235Slinton frp = curfuncframe();
161418235Slinton n = (*var_s)->name;
161518235Slinton b = false;
161618235Slinton if (frp != nil) {
161718235Slinton frp = nextfunc(frp, &f);
161818235Slinton while (frp != nil) {
161918235Slinton s = *var_s;
162018235Slinton while (s != nil and
162118235Slinton (
162218235Slinton s->name != n or s->block != f or
162318235Slinton s->class == FIELD or s->class == TAG
162418235Slinton )
162518235Slinton ) {
162618235Slinton s = s->next_sym;
162718235Slinton }
162818235Slinton if (s != nil) {
162918235Slinton *var_s = s;
163018235Slinton b = true;
163118235Slinton break;
163218235Slinton }
163318235Slinton if (f == program) {
163418235Slinton break;
163518235Slinton }
163618235Slinton frp = nextfunc(frp, &f);
16379657Slinton }
16389657Slinton }
163918235Slinton return b;
16409657Slinton }
16419657Slinton
16429657Slinton /*
164318235Slinton * Find the symbol that has the same name and scope as the
16449657Slinton * given symbol but is of the given field. Return nil if there is none.
16459657Slinton */
16469657Slinton
findfield(fieldname,record)164718235Slinton public Symbol findfield (fieldname, record)
16489657Slinton Name fieldname;
16499657Slinton Symbol record;
16509657Slinton {
16519657Slinton register Symbol t;
16529657Slinton
16539657Slinton t = rtype(record)->chain;
16549657Slinton while (t != nil and t->name != fieldname) {
16559657Slinton t = t->chain;
16569657Slinton }
16579657Slinton return t;
16589657Slinton }
165912547Scsvaf
getbound(s,off,type,valp)166012547Scsvaf public Boolean getbound(s,off,type,valp)
166112547Scsvaf Symbol s;
166212547Scsvaf int off;
166312547Scsvaf Rangetype type;
166412547Scsvaf int *valp;
166512547Scsvaf {
166612547Scsvaf Frame frp;
166712547Scsvaf Address addr;
166812547Scsvaf Symbol cur;
166912547Scsvaf
167012547Scsvaf if (not isactive(s->block)) {
167112547Scsvaf return(false);
167212547Scsvaf }
167312547Scsvaf cur = s->block;
167412547Scsvaf while (cur != nil and cur->class == MODULE) { /* WHY*/
167512547Scsvaf cur = cur->block;
167612547Scsvaf }
167712547Scsvaf if(cur == nil) {
167812547Scsvaf cur = whatblock(pc);
167912547Scsvaf }
168012547Scsvaf frp = findframe(cur);
168112547Scsvaf if (frp == nil) {
168212547Scsvaf return(false);
168312547Scsvaf }
168412547Scsvaf if(type == R_TEMP) addr = locals_base(frp) + off;
168512547Scsvaf else if (type == R_ARG) addr = args_base(frp) + off;
168612547Scsvaf else return(false);
168712547Scsvaf dread(valp,addr,sizeof(long));
168812547Scsvaf return(true);
168912547Scsvaf }
1690