diff options
Diffstat (limited to 'src/tools/lcc/src/symbolic.c')
-rw-r--r-- | src/tools/lcc/src/symbolic.c | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/src/tools/lcc/src/symbolic.c b/src/tools/lcc/src/symbolic.c new file mode 100644 index 0000000..affa67a --- /dev/null +++ b/src/tools/lcc/src/symbolic.c @@ -0,0 +1,494 @@ +#include <time.h> +#include <ctype.h> +#include "c.h" + +#define I(f) s_##f + +static Node *tail; +static int off, maxoff, uid = 0, verbose = 0, html = 0; + +static const char *yyBEGIN(const char *tag) { + if (html) + print("<%s>", tag); + return tag; +} + +static void yyEND(const char *tag) { + if (html) + print("</%s>", tag); + if (isupper(*tag)) + print("\n"); +} + +#define BEGIN(tag) do { const char *yytag=yyBEGIN(#tag); +#define END yyEND(yytag); } while (0) +#define ITEM BEGIN(li) +#define START BEGIN(LI) +#define ANCHOR(attr,code) do { const char *yytag="a"; if (html) { printf("<a " #attr "=\""); code; print("\">"); } +#define NEWLINE print(html ? "<br>\n" : "\n") + +static void emitCoord(Coordinate src) { + if (src.file && *src.file) { + ANCHOR(href,print("%s", src.file)); print("%s", src.file); END; + print(":"); + } + print("%d.%d", src.y, src.x); +} + +static void emitString(int len, const char *s) { + for ( ; len-- > 0; s++) + if (*s == '&' && html) + print("&"); + else if (*s == '<' && html) + print("<"); + else if (*s == '>' && html) + print("<"); + else if (*s == '"' || *s == '\\') + print("\\%c", *s); + else if (*s >= ' ' && *s < 0177) + print("%c", *s); + else + print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7); +} + +static void emitSymRef(Symbol p) { + (*IR->defsymbol)(p); + ANCHOR(href,print("#%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END; +} + +static void emitSymbol(Symbol p) { + (*IR->defsymbol)(p); + ANCHOR(name,print("%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END; + BEGIN(ul); +#define xx(field,code) ITEM; if (!html) print(" "); print(#field "="); code; END + if (verbose && (src.y || src.x)) + xx(src,emitCoord(p->src)); + xx(type,print("%t", p->type)); + xx(sclass,print("%k", p->sclass)); + switch (p->scope) { + case CONSTANTS: xx(scope,print("CONSTANTS")); break; + case LABELS: xx(scope,print("LABELS")); break; + case GLOBAL: xx(scope,print("GLOBAL")); break; + case PARAM: xx(scope,print("PARAM")); break; + case LOCAL: xx(scope,print("LOCAL")); break; + default: + if (p->scope > LOCAL) + xx(scope,print("LOCAL+%d", p->scope-LOCAL)); + else + xx(scope,print("%d", p->scope)); + } + if (p->scope >= PARAM && p->sclass != STATIC) + xx(offset,print("%d", p->x.offset)); + xx(ref,print("%f", p->ref)); + if (p->temporary && p->u.t.cse) + xx(u.t.cse,print("%p", p->u.t.cse)); + END; +#undef xx +} + +/* address - initialize q for addressing expression p+n */ +static void I(address)(Symbol q, Symbol p, long n) { + q->name = stringf("%s%s%D", p->name, n > 0 ? "+" : "", n); + (*IR->defsymbol)(q); + START; print("address "); emitSymbol(q); END; +} + +/* blockbeg - start a block */ +static void I(blockbeg)(Env *e) { + e->offset = off; + START; print("blockbeg off=%d", off); END; +} + +/* blockend - start a block */ +static void I(blockend)(Env *e) { + if (off > maxoff) + maxoff = off; + START; print("blockend off=%d", off); END; + off = e->offset; +} + +/* defaddress - initialize an address */ +static void I(defaddress)(Symbol p){ + START; print("defaddress "); emitSymRef(p); END; +} + +/* defconst - define a constant */ +static void I(defconst)(int suffix, int size, Value v) { + START; + print("defconst "); + switch (suffix) { + case I: + print("int.%d ", size); + BEGIN(code); + if (size > sizeof (int)) + print("%D", v.i); + else + print("%d", (int)v.i); + END; + break; + case U: + print("unsigned.%d ", size); + BEGIN(code); + if (size > sizeof (unsigned)) + print("%U", v.u); + else + print("%u", (unsigned)v.u); + END; + break; + case P: print("void*.%d ", size); BEGIN(code); print("%p", v.p); END; break; + case F: print("float.%d ", size); BEGIN(code); print("%g", (double)v.d); END; break; + default: assert(0); + } + END; +} + +/* defstring - emit a string constant */ +static void I(defstring)(int len, char *s) { + START; print("defstring "); + BEGIN(code); print("\""); emitString(len, s); print("\""); END; + END; +} + +/* defsymbol - define a symbol: initialize p->x */ +static void I(defsymbol)(Symbol p) { + if (p->x.name == NULL) + p->x.name = stringd(++uid); +} + +/* emit - emit the dags on list p */ +static void I(emit)(Node p){ + ITEM; + if (!html) + print(" "); + for (; p; p = p->x.next) { + if (p->op == LABEL+V) { + assert(p->syms[0]); + ANCHOR(name,print("%s", p->syms[0]->x.name)); + BEGIN(code); print("%s", p->syms[0]->name); END; + END; + print(":"); + } else { + int i; + if (p->x.listed) { + BEGIN(strong); print("%d", p->x.inst); END; print("'"); + print(" %s", opname(p->op)); + } else + print("%d. %s", p->x.inst, opname(p->op)); + if (p->count > 1) + print(" count=%d", p->count); + for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++) + print(" #%d", p->kids[i]->x.inst); + if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type) + print(" {%t}", p->syms[0]->type); + else + for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) { + print(" "); + if (p->syms[i]->scope == CONSTANTS) + print(p->syms[i]->name); + else + emitSymRef(p->syms[i]); + } + } + NEWLINE; + } + END; +} + +/* export - announce p as exported */ +static void I(export)(Symbol p) { + START; print("export "); emitSymRef(p); END; +} + +/* function - generate code for a function */ +static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { + int i; + + (*IR->defsymbol)(f); + off = 0; + for (i = 0; caller[i] && callee[i]; i++) { + off = roundup(off, caller[i]->type->align); + caller[i]->x.offset = callee[i]->x.offset = off; + off += caller[i]->type->size; + } + if (!html) { + print("function "); + emitSymbol(f); + print(" ncalls=%d\n", ncalls); + for (i = 0; caller[i]; i++) + START; print("caller "); emitSymbol(caller[i]); END; + for (i = 0; callee[i]; i++) + START; print("callee "); emitSymbol(callee[i]); END; + } else { + START; + print("function"); + BEGIN(UL); +#define xx(field,code) ITEM; print(#field "="); code; END + xx(f,emitSymbol(f)); + xx(ncalls,print("%d", ncalls)); + if (caller[0]) { + ITEM; print("caller"); BEGIN(OL); + for (i = 0; caller[i]; i++) + ITEM; emitSymbol(caller[i]); END; + END; END; + ITEM; print("callee"); BEGIN(OL); + for (i = 0; callee[i]; i++) + ITEM; emitSymbol(callee[i]); END; + END; END; + } else { + xx(caller,BEGIN(em); print("empty"); END); + xx(callee,BEGIN(em); print("empty"); END); + } + END; + END; + } + maxoff = off = 0; + gencode(caller, callee); + if (html) + START; print("emitcode"); BEGIN(ul); emitcode(); END; END; + else + emitcode(); + START; print("maxoff=%d", maxoff); END; +#undef xx +} + +/* visit - generate code for *p */ +static int visit(Node p, int n) { + if (p && p->x.inst == 0) { + p->x.inst = ++n; + n = visit(p->kids[0], n); + n = visit(p->kids[1], n); + *tail = p; + tail = &p->x.next; + } + return n; +} + +/* gen0 - generate code for the dags on list p */ +static Node I(gen)(Node p) { + int n; + Node nodelist; + + tail = &nodelist; + for (n = 0; p; p = p->link) { + switch (generic(p->op)) { /* check for valid forest */ + case CALL: + assert(IR->wants_dag || p->count == 0); + break; + case ARG: + case ASGN: case JUMP: case LABEL: case RET: + case EQ: case GE: case GT: case LE: case LT: case NE: + assert(p->count == 0); + break; + case INDIR: + assert(IR->wants_dag && p->count > 0); + break; + default: + assert(0); + } + check(p); + p->x.listed = 1; + n = visit(p, n); + } + *tail = 0; + return nodelist; +} + +/* global - announce a global */ +static void I(global)(Symbol p) { + START; print("global "); emitSymbol(p); END; +} + +/* import - import a symbol */ +static void I(import)(Symbol p) { + START; print("import "); emitSymRef(p); END; +} + +/* local - local variable */ +static void I(local)(Symbol p) { + if (p->temporary) + p->name = stringf("t%s", p->name); + (*IR->defsymbol)(p); + off = roundup(off, p->type->align); + p->x.offset = off; + off += p->type->size; + START; print(p->temporary ? "temporary " : "local "); emitSymbol(p); END; +} + +/* progbeg - beginning of program */ +static void I(progbeg)(int argc, char *argv[]) { + int i; + + for (i = 1; i < argc; i++) + if (strcmp(argv[i], "-v") == 0) + verbose++; + else if (strcmp(argv[i], "-html") == 0) + html++; + if (html) { + print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"); + print("<html>"); + BEGIN(head); + if (firstfile && *firstfile) + BEGIN(title); emitString(strlen(firstfile), firstfile); END; + print("<link rev=made href=\"mailto:drh@microsoft.com\">\n"); + END; + print("<body>\n"); + if (firstfile && *firstfile) + BEGIN(h1); emitString(strlen(firstfile), firstfile); END; + BEGIN(P); BEGIN(em); + print("Links lead from uses of identifiers and labels to their definitions."); + END; END; + print("<ul>\n"); + START; + print("progbeg"); + BEGIN(ol); + for (i = 1; i < argc; i++) { + ITEM; + BEGIN(code); print("\""); emitString(strlen(argv[i]), argv[i]); print("\""); END; + END; + } + END; + END; + } +} + +/* progend - end of program */ +static void I(progend)(void) { + START; print("progend"); END; + if (html) { + time_t t; + print("</ul>\n"); + time(&t); + print("<hr><address>%s</address>\n", ctime(&t)); + print("</body></html>\n"); + } +} + +/* segment - switch to segment s */ +static void I(segment)(int s) { + START; print("segment %s", &"text\0bss\0.data\0lit\0.sym\0."[5*s-5]); END; +} + +/* space - initialize n bytes of space */ +static void I(space)(int n) { + START; print("space %d", n); END; +} + +static void I(stabblock)(int brace, int lev, Symbol *p) {} + +/* stabend - finalize stab output */ +static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) { + int i; + + if (p) + emitSymRef(p); + print("\n"); + if (cpp && sp) + for (i = 0; cpp[i] && sp[i]; i++) { + print("%w.%d: ", cpp[i], cpp[i]->x); + emitSymRef(sp[i]); + print("\n"); + } +} + +static void I(stabfend)(Symbol p, int lineno) {} +static void I(stabinit)(char *file, int argc, char *argv[]) {} + +/* stabline - emit line number information for source coordinate *cp */ +static void I(stabline)(Coordinate *cp) { + if (cp->file) + print("%s:", cp->file); + print("%d.%d:\n", cp->y, cp->x); +} + +static void I(stabsym)(Symbol p) {} +static void I(stabtype)(Symbol p) {} + +Interface symbolicIR = { + {1, 1, 0}, /* char */ + {2, 2, 0}, /* short */ + {4, 4, 0}, /* int */ + {4, 4, 0}, /* long */ + {4, 4, 0}, /* long long */ + {4, 4, 1}, /* float */ + {8, 8, 1}, /* double */ + {8, 8, 1}, /* long double */ + {4, 4, 0}, /* T* */ + {0, 4, 0}, /* struct */ + 0, /* little_endian */ + 0, /* mulops_calls */ + 0, /* wants_callb */ + 1, /* wants_argb */ + 1, /* left_to_right */ + 1, /* wants_dag */ + 0, /* unsigned_char */ + I(address), + I(blockbeg), + I(blockend), + I(defaddress), + I(defconst), + I(defstring), + I(defsymbol), + I(emit), + I(export), + I(function), + I(gen), + I(global), + I(import), + I(local), + I(progbeg), + I(progend), + I(segment), + I(space), + I(stabblock), + I(stabend), + I(stabfend), + I(stabinit), + I(stabline), + I(stabsym), + I(stabtype) +}; + +Interface symbolic64IR = { + {1, 1, 0}, /* char */ + {2, 2, 0}, /* short */ + {4, 4, 0}, /* int */ + {8, 8, 0}, /* long */ + {8, 8, 0}, /* long long */ + {4, 4, 1}, /* float */ + {8, 8, 1}, /* double */ + {8, 8, 1}, /* long double */ + {8, 8, 0}, /* T* */ + {0, 1, 0}, /* struct */ + 1, /* little_endian */ + 0, /* mulops_calls */ + 0, /* wants_callb */ + 1, /* wants_argb */ + 1, /* left_to_right */ + 1, /* wants_dag */ + 0, /* unsigned_char */ + I(address), + I(blockbeg), + I(blockend), + I(defaddress), + I(defconst), + I(defstring), + I(defsymbol), + I(emit), + I(export), + I(function), + I(gen), + I(global), + I(import), + I(local), + I(progbeg), + I(progend), + I(segment), + I(space), + I(stabblock), + I(stabend), + I(stabfend), + I(stabinit), + I(stabline), + I(stabsym), + I(stabtype) +}; |