📄 symbols.c
字号:
frp = findframe(cur); if (frp == nil) { panic("unexpected nil frame for \"%s\"", symname(s)); } } if (islocaloff(s)) { addr = locals_base(frp) + s->symvalue.offset; } else if (isparamoff(s)) { addr = args_base(frp) + s->symvalue.offset; } else if (isreg(s)) { addr = savereg(s->symvalue.offset, frp); } else { panic("address: bad symbol \"%s\"", symname(s)); } } return addr;}/* * Define a symbol used to access register values. */public defregname(n, r)Name n;Integer r;{ register Symbol s, t; s = insert(n); t = newSymbol(nil, 0, PTR, t_int, nil); t->language = primlang; s->language = t->language; s->class = VAR; s->level = -3; s->type = t; s->block = program; s->symvalue.offset = r;}/* * Resolve an "abstract" type reference. * * It is possible in C to define a pointer to a type, but never define * the type in a particular source file. Here we try to resolve * the type definition. This is problematic, it is possible to * have multiple, different definitions for the same name type. */public findtype(s)Symbol s;{ register Symbol t, u, prev; u = s; prev = nil; while (u != nil and u->class != BADUSE) { if (u->name != nil) { prev = u; } u = u->type; } if (prev == nil) { error("couldn't find link to type reference"); } find(t, prev->name) where t != prev and t->block->class == MODULE and t->class == prev->class and t->type != nil and t->type->type != nil and t->type->type->class != BADUSE endfind(t); if (t == nil) { error("couldn't resolve reference"); } else { prev->type = t->type; }}/* * Find the size in bytes of the given type. * * This is probably the WRONG thing to do. The size should be kept * as an attribute in the symbol information as is done for structures * and fields. I haven't gotten around to cleaning this up yet. */#define MAXUCHAR 255#define MAXUSHORT 65535L#define MINCHAR -128#define MAXCHAR 127#define MINSHORT -32768#define MAXSHORT 32767/* * When necessary, compute the upper bound for an open array (Modula-2 style). */public chkOpenArray (sym)Symbol sym;{ Symbol t; Address a; integer n; if (sym->class == REF or sym->class == VAR) { t = rtype(sym->type); if (t->class == ARRAY and t->chain == t_open) { a = address(sym, nil); dread(&n, a + sizeof(Word), sizeof(n)); t->chain->type->symvalue.rangev.upper = n - 1; } }}public findbounds (u, lower, upper)Symbol u;long *lower, *upper;{ Rangetype lbt, ubt; long lb, ub; if (u->class == RANGE) { lbt = u->symvalue.rangev.lowertype; ubt = u->symvalue.rangev.uppertype; lb = u->symvalue.rangev.lower; ub = u->symvalue.rangev.upper; if (lbt == R_ARG or lbt == R_TEMP) { if (not getbound(u, lb, lbt, lower)) { error("dynamic bounds not currently available"); } } else { *lower = lb; } if (ubt == R_ARG or ubt == R_TEMP) { if (not getbound(u, ub, ubt, upper)) { error("dynamic bounds not currently available"); } } else { *upper = ub; } } else if (u->class == SCAL) { *lower = 0; *upper = u->symvalue.iconval - 1; } else { panic("unexpected array bound type"); }}public integer size(sym)Symbol sym;{ register Symbol s, t, u; register integer nel, elsize; long lower, upper; integer r, off, len; t = sym; checkref(t); if (t->class == TYPEREF) { resolveRef(t); } switch (t->class) { case RANGE: lower = t->symvalue.rangev.lower; upper = t->symvalue.rangev.upper; if (upper == 0 and lower > 0) { /* real */ r = lower; } else if (lower > upper) { /* unsigned long */ r = sizeof(long); } else if ( (lower >= MINCHAR and upper <= MAXCHAR) or (lower >= 0 and upper <= MAXUCHAR) ) { r = sizeof(char); } else if ( (lower >= MINSHORT and upper <= MAXSHORT) or (lower >= 0 and upper <= MAXUSHORT) ) { r = sizeof(short); } else { r = sizeof(long); } break; case ARRAY: elsize = size(t->type); nel = 1; for (t = t->chain; t != nil; t = t->chain) { u = rtype(t); findbounds(u, &lower, &upper); nel *= (upper-lower+1); } r = nel*elsize; break; case REF: case VAR: case FVAR: chkOpenArray(t); r = size(t->type); /* * if (r < sizeof(Word) and isparam(t)) { r = sizeof(Word); } */ break; case CONST: r = size(t->type); break; case TYPE: if (t->type->class == PTR and t->type->type->class == BADUSE) { findtype(t); } r = size(t->type); break; case TAG: r = size(t->type); break; case FIELD: off = t->symvalue.field.offset; len = t->symvalue.field.length; r = (off + len + 7) div 8 - (off div 8); /* r = (t->symvalue.field.length + 7) div 8; */ break; case RECORD: case VARNT: r = t->symvalue.offset; if (r == 0 and t->chain != nil) { panic("missing size information for record"); } break; case PTR: case FILET: r = sizeof(Word); break; case SCAL: r = sizeof(Word); /* * if (t->symvalue.iconval > 255) { r = sizeof(short); } else { r = sizeof(char); } * */ break; case FPROC: case FFUNC: r = sizeof(Word); break; case PROC: case FUNC: case MODULE: case PROG: r = sizeof(Symbol); break; case SET: u = rtype(t->type); switch (u->class) { case RANGE: r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; break; case SCAL: r = u->symvalue.iconval; break; default: error("expected range for set base type"); break; } r = (r + BITSPERBYTE - 1) div BITSPERBYTE; break; default: if (ord(t->class) > ord(TYPEREF)) { panic("size: bad class (%d)", ord(t->class)); } else { fprintf(stderr, "!! size(%s) ??", classname(t)); } r = 0; break; } return r;}/* * Test if a symbol is a parameter. This is true if there * is a cycle from s->block to s via chain pointers. */public Boolean isparam(s)Symbol s;{ register Symbol t; t = s->block; while (t != nil and t != s) { t = t->chain; } return (Boolean) (t != nil);}/* * Test if a type is an open array parameter type. */public Boolean isopenarray (t)Symbol t;{ return (Boolean) (t->class == ARRAY and t->chain == t_open);}/* * Test if a symbol is a var parameter, i.e. has class REF but * is not an open array parameter (those are treated special). */public Boolean isvarparam(s)Symbol s;{ return (Boolean) (s->class == REF);}/* * Test if a symbol is a variable (actually any addressible quantity * with do). */public Boolean isvariable(s)register Symbol s;{ return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);}/* * Test if a symbol is a block, e.g. function, procedure, or the * main program. * * This function is now expanded inline for efficiency. * * public Boolean isblock(s)register Symbol s;{ return (Boolean) ( s->class == FUNC or s->class == PROC or s->class == MODULE or s->class == PROG );} * *//* * Test if a symbol is a module. */public Boolean ismodule(s)register Symbol s;{ return (Boolean) (s->class == MODULE);}/* * Test if a symbol is builtin, that is, a predefined type or * reserved word. */public Boolean isbuiltin(s)register Symbol s;{ return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR);}/* * Mark a procedure or function as internal, meaning that it is called * with a different calling sequence. */public markInternal (s)Symbol s;{ s->symvalue.funcv.intern = true;}public boolean isinternal (s)Symbol s;{ return s->symvalue.funcv.intern;}/* * Test if two types match. * Equivalent names implies a match in any language. * * Special symbols must be handled with care. */public Boolean compatible(t1, t2)register Symbol t1, t2;{ Boolean b; Symbol rt1, rt2; if (t1 == t2) { b = true; } else if (t1 == nil or t2 == nil) { b = false; } else if (t1 == procsym) { b = isblock(t2); } else if (t2 == procsym) { b = isblock(t1); } else if (t1->language == primlang) { if (t2->language == primlang) { rt1 = rtype(t1); rt2 = rtype(t2); b = (boolean) ( (rt1->type == t_open and rt2->type == t_int) or (rt2->type == t_open and rt1->type == t_int) or rt1 == rt2 ); } else { b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); } } else if (t2->language == primlang) { b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); } else if (t1->language == nil) { if (t2->language == nil) { b = false; } else { b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); } } else if (t2->language == nil) { b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); } else if (isbuiltin(t1) or isbuiltin(t1->type)) { b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); } else { b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); } return b;}/* * Check for a type of the given name. */public Boolean istypename(type, name)Symbol type;String name;{ Symbol t; Boolean b; t = type; checkref(t); b = (Boolean) ( t->class == TYPE and streq(ident(t->name), name) ); return b;}/* * Determine if a (value) parameter should actually be passed by address. */public boolean passaddr (p, exprtype)Symbol p, exprtype;{ boolean b; Language def; if (p == nil) { def = findlanguage(".c"); b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); } else if (p->language == nil or p->language == primlang) { b = false; } else if (isopenarray(p->type)) { b = true; } else { b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); } return b;}/* * Test if the name of a symbol is uniquely defined or not. */public Boolean isambiguous(s)register Symbol s;{ register Symbol t; find(t, s->name) where t != s endfind(t); return (Boolean) (t != nil);}typedef char *Arglist;#define nextarg(type) ((type *) (ap += sizeof(type)))[-1]private Symbol mkstring();private Symbol namenode();/* * Determine the type of a parse tree. * Also make some symbol-dependent changes to the tree such as * changing removing RVAL nodes for constant symbols. */public assigntypes(p)register Node p;{ register Node p1; register Symbol s; switch (p->op) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -