📄 symbols.c
字号:
/*#@(#)symbols.c 4.1 Ultrix 7/17/90*//* Copyright (c) 1982 Regents of the University of California */static char sccsid[] = "@(#)symbols.c 1.10 8/10/83";static char rcsid[] = "$Header: symbols.c,v 1.4 84/03/27 10:24:18 linton Exp $";/* * Symbol management. */#include "defs.h"#include "symbols.h"#include "languages.h"#include "printsym.h"#include "tree.h"#include "operators.h"#include "eval.h"#include "mappings.h"#include "events.h"#include "process.h"#include "runtime.h"#include "machine.h"#include "names.h"#ifndef publictypedef struct Symbol *Symbol;#include "machine.h"#include "names.h"#include "languages.h"/* * Symbol classes */typedef enum { BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD, PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF} Symclass;typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; struct Symbol { Name name; Language language; Symclass class : 8; Integer level : 8; Symbol type; Symbol chain; union { int offset; /* variable address */ long iconval; /* integer constant value */ double fconval; /* floating constant value */ struct { /* field offset and size (both in bits) */ int offset; int length; } field; struct { /* common offset and chain; used to relocate */ int offset; /* vars in global BSS */ Symbol chain; } common; struct { /* range bounds */ Rangetype lowertype : 16; Rangetype uppertype : 16; long lower; long upper; } rangev; struct { int offset : 16; /* offset for of function value */ Boolean src : 1; /* true if there is source line info */ Boolean inline : 1; /* true if no separate act. rec. */ Boolean intern : 1; /* internal calling sequence */ int unused : 13; Address beginaddr; /* address of function code */ } funcv; struct { /* variant record info */ int size; Symbol vtorec; Symbol vtag; } varnt; String typeref; /* type defined by "<module>:<type>" */ Symbol extref; /* indirect symbol for external reference */ } symvalue; Symbol block; /* symbol containing this symbol */ Symbol next_sym; /* hash chain */};/* * Basic types. */Symbol t_boolean;Symbol t_char;Symbol t_int;Symbol t_real;Symbol t_nil;Symbol t_open;Symbol program;Symbol curfunc;#define symname(s) ident(s->name)#define codeloc(f) ((f)->symvalue.funcv.beginaddr)#define isblock(s) (Boolean) ( \ s->class == FUNC or s->class == PROC or \ s->class == MODULE or s->class == PROG \)#define isroutine(s) (Boolean) ( \ s->class == FUNC or s->class == PROC \)#define nosource(f) (not (f)->symvalue.funcv.src)#define isinline(f) ((f)->symvalue.funcv.inline)#include "tree.h"/* * Some macros to make finding a symbol with certain attributes. */#define find(s, withname) \{ \ s = lookup(withname); \ while (s != nil and not (s->name == (withname) and#define where /* qualification */#define endfind(s) )) { \ s = s->next_sym; \ } \}#endif/* * Symbol table structure currently does not support deletions. */#define HASHTABLESIZE 2003private Symbol hashtab[HASHTABLESIZE];#define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE)/* * Allocate a new symbol. */#define SYMBLOCKSIZE 100typedef struct Sympool { struct Symbol sym[SYMBLOCKSIZE]; struct Sympool *prevpool;} *Sympool;private Sympool sympool = nil;private Integer nleft = 0;public Symbol symbol_alloc(){ register Sympool newpool; if (nleft <= 0) { newpool = new(Sympool); bzero(newpool, sizeof(newpool)); newpool->prevpool = sympool; sympool = newpool; nleft = SYMBLOCKSIZE; } --nleft; return &(sympool->sym[nleft]);}public symbol_dump(func)Symbol func;{ register Symbol s; register Integer i; printf(" symbols in %s \n",symname(func)); for(i=0; i< HASHTABLESIZE; i++) for(s=hashtab[i]; s != nil; s=s->next_sym) { if (s->block == func) psym(s); }}/* * Free all the symbols currently allocated. */public symbol_free(){ Sympool s, t; register Integer i; s = sympool; while (s != nil) { t = s->prevpool; dispose(s); s = t; } for (i = 0; i < HASHTABLESIZE; i++) { hashtab[i] = nil; } sympool = nil; nleft = 0;}/* * Create a new symbol with the given attributes. */public Symbol newSymbol(name, blevel, class, type, chain)Name name;Integer blevel;Symclass class;Symbol type;Symbol chain;{ register Symbol s; s = symbol_alloc(); s->name = name; s->level = blevel; s->class = class; s->type = type; s->chain = chain; return s;}/* * Insert a symbol into the hash table. */public Symbol insert(name)Name name;{ register Symbol s; register unsigned int h; h = hash(name); s = symbol_alloc(); s->name = name; s->next_sym = hashtab[h]; hashtab[h] = s; return s;}/* * Symbol lookup. */public Symbol lookup(name)Name name;{ register Symbol s; register unsigned int h; h = hash(name); s = hashtab[h]; while (s != nil and s->name != name) { s = s->next_sym; } return s;}/* * Delete a symbol from the symbol table. */public delete (s)Symbol s;{ register Symbol t; register unsigned int h; h = hash(s->name); t = hashtab[h]; if (t == nil) { panic("delete of non-symbol '%s'", symname(s)); } else if (t == s) { hashtab[h] = s->next_sym; } else { while (t->next_sym != s) { t = t->next_sym; if (t == nil) { panic("delete of non-symbol '%s'", symname(s)); } } t->next_sym = s->next_sym; }}/* * Dump out all the variables associated with the given * procedure, function, or program at the given recursive level. * * This is quite inefficient. We traverse the entire symbol table * each time we're called. The assumption is that this routine * won't be called frequently enough to merit improved performance. */public dumpvars(f, frame)Symbol f;Frame frame;{ register Integer i; register Symbol s; for (i = 0; i < HASHTABLESIZE; i++) { for (s = hashtab[i]; s != nil; s = s->next_sym) { if (container(s) == f) { if (should_print(s)) { printv(s, frame); putchar('\n'); } else if (s->class == MODULE) { dumpvars(s, frame); } } } }}/* * Create a builtin type. * Builtin types are circular in that btype->type->type = btype. */public Symbol maketype(name, lower, upper)String name;long lower;long upper;{ register Symbol s; s = newSymbol(identname(name, true), 0, TYPE, nil, nil); s->language = primlang; s->type = newSymbol(nil, 0, RANGE, s, nil); s->type->language = s->language; s->type->symvalue.rangev.lower = lower; s->type->symvalue.rangev.upper = upper; return s;}/* * These functions are now compiled inline. * * public String symname(s)Symbol s;{ checkref(s); return ident(s->name);} * * public Address codeloc(f)Symbol f;{ checkref(f); if (not isblock(f)) { panic("codeloc: \"%s\" is not a block", ident(f->name)); } return f->symvalue.funcv.beginaddr;} * *//* * Reduce type to avoid worrying about type names. */public Symbol rtype(type)Symbol type;{ register Symbol t; t = type; if (t != nil) { if (t->class == VAR or t->class == FIELD or t->class == REF ) { t = t->type; } if (t->class == TYPEREF) { resolveRef(t); } while (t->class == TYPE or t->class == TAG) { t = t->type; if (t->class == TYPEREF) { resolveRef(t); } } } return t;}/* * Find the end of a module name. Return nil if there is none * in the given string. */private String findModuleMark (s)String s;{ register char *p, *r; register boolean done; p = s; done = false; do { if (*p == ':') { done = true; r = p; } else if (*p == '\0') { done = true; r = nil; } else { ++p; } } while (not done); return r;}/* * Resolve a type reference by modifying to be the appropriate type. * * If the reference has a name, then it refers to an opaque type and * the actual type is directly accessible. Otherwise, we must use * the type reference string, which is of the form "module:{module:}name". */public resolveRef (t)Symbol t;{ register char *p; char *start; Symbol s, m, outer; Name n; if (t->name != nil) { s = t; } else { start = t->symvalue.typeref; outer = program; p = findModuleMark(start); while (p != nil) { *p = '\0'; n = identname(start, true); find(m, n) where m->block == outer endfind(m); if (m == nil) { p = nil; outer = nil; s = nil; } else { outer = m; start = p + 1; p = findModuleMark(start); } } if (outer != nil) { n = identname(start, true); find(s, n) where s->block == outer endfind(s); } } if (s != nil and s->type != nil) { t->name = s->type->name; t->class = s->type->class; t->type = s->type->type; t->chain = s->type->chain; t->symvalue = s->type->symvalue; t->block = s->type->block; }}public Integer level(s)Symbol s;{ checkref(s); return s->level;}public Symbol container(s)Symbol s;{ checkref(s); return s->block;}/* * Return the object address of the given symbol. * * There are the following possibilities: * * globals - just take offset * locals - take offset from locals base * arguments - take offset from argument base * register - offset is register number */#define isglobal(s) (s->level == 1)#define islocaloff(s) (s->level >= 2 and s->symvalue.offset < 0)#define isparamoff(s) (s->level >= 2 and s->symvalue.offset >= 0)#define isreg(s) (s->level < 0)public Address address(s, frame)Symbol s;Frame frame;{ register Frame frp; register Address addr; register Symbol cur; checkref(s); if (not isactive(s->block)) { error("\"%s\" is not currently defined", symname(s)); } else if (isglobal(s)) { addr = s->symvalue.offset; } else { frp = frame; if (frp == nil) { cur = s->block; while (cur != nil and cur->class == MODULE) { cur = cur->block; } if (cur == nil) { cur = whatblock(pc); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -