diff options
| author | 2022-08-03 20:24:47 +0200 | |
|---|---|---|
| committer | 2022-08-03 20:24:47 +0200 | |
| commit | 1625c50f0c0e4b1c7ba01a5df5713efaf6dce606 (patch) | |
| tree | bc5f24811413749b776964c1bbdec13a46dd9768 /bootstrap/dump.c | |
initial
Diffstat (limited to 'bootstrap/dump.c')
| -rw-r--r-- | bootstrap/dump.c | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/bootstrap/dump.c b/bootstrap/dump.c new file mode 100644 index 0000000..e4f35c9 --- /dev/null +++ b/bootstrap/dump.c @@ -0,0 +1,384 @@ +#include "all.h" +#include <stdarg.h> + +static void pri(const char *fmt, ...); + +static void +pritype(const struct type *ty) { + assert(ty); + if (ty->konst) + pri("const "); + switch (ty->t) { + case TYvoid: + pri("void"); + break; + case TYbool: + pri("bool"); + break; + case TYint: + pri("%c%z", ty->int_signed ? 'i' : 'u', + 8 * ty->size); + break; + case TYfloat: + pri("f%z", 8 * ty->size); + break; + case TYptr: + pri("*%t", ty->child); + break; + case TYarr: + assert(ty->length >= 0); + pri("[%U]%t", ty->length, ty->child); + break; + case TYslice: + pri("[#]%t", ty->child); + break; + case TYfn: + pri("fn("); + for (int i = 0; i < ty->fn.params.n; ++i) { + pri("_ %t", ty->fn.params.d[i]); + pri(", "); + } + if (ty->fn.variadic) + pri("..."); + pri(") %t", ty->fn.retty); + } +} + +static void dumpexpr(const struct expr *expr); + +static void +pristring(const char *s, u64 n) { + extern int isprint(int); + pri("\""); + for (int i = 0; i < n; ++i) { + if (isprint(s[i])) + pri("%c", s[i]); + else + fprintf(stderr, "\\%.3o", s[i]); + } + pri("\""); +} + + +const char * +tokt2str(int t) { + static char buf[128]; + + if (t == TKintlit) { + return "integer literal"; + } else if (t == TKident) { + return "identifier"; + } else if (t == TKstrlit) { + return "string literal"; + } else if (t == TKchrlit) { + return "character literal"; + } else if (t == TKeof) { + return "end of file"; + } else if (t < NUM_KEYWORDS) { + snprintf(buf, sizeof buf - 1, "`%s'", keyword2str[t]); + } else if (t > 0xFF) { + unsigned m = bswap32(t); + int i = 0; + strcpy(buf, "`"); + while (m) { + if (m & 0xFF) + buf[i++] = m; + m >>= 8; + } + strcpy(buf, "'"); + } else { + snprintf(buf, sizeof buf - 1, "`%c'", t); + } + return buf; +} + +const char * +tok2str(struct tok tok) { + static char buf[512]; + + if (tok.t == TKintlit) { + snprintf(buf, sizeof buf - 1, "`%llu'", (unsigned long long)tok.ilit.i); + } else if (tok.t == TKident) { + snprintf(buf, sizeof buf - 1, "`%s'", tok.str); + } else if (tok.t == TKgensym) { + snprintf(buf, sizeof buf - 1, "`$%s'", tok.str); + } else if (tok.t == TKstrlit) { + snprintf(buf, sizeof buf - 1, "\"%s\"", tok.str); + } else if (tok.t == TKchrlit) { + u64 t = bswap64(tok.ilit.i); + int i = 1; + strcpy(buf, "'"); + while (t) { + if (t & 0xFF) + buf[i++] = t; + t >>= 8; + } + buf[i] = '\0'; + strcat(buf, "'"); + } else if (tok.t == TKeof) { + return "<eof>"; + } else if (tok.t < NUM_KEYWORDS) { + snprintf(buf, sizeof buf - 1, "`%s'", keyword2str[tok.t]); + } else if (tok.t > 0xFF) { + unsigned t = bswap32(tok.t); + int i = 1; + strcpy(buf, "`"); + while (t) { + if (t & 0xFF) + buf[i++] = t; + t >>= 8; + } + buf[i] = '\0'; + strcat(buf, "'"); + } else { + snprintf(buf, sizeof buf - 1, "`%c'", tok.t); + } + return buf; +} + +void +pritoktree(struct toktree toks) { + fprintf(stderr, "[ "); + for (int i = 0; i < toks.n; ++i) { + fprintf(stderr, "%s ", tok2str(toks.d[i])); + } + fprintf(stderr, "]"); +} + + +void +pri(const char *fmt, ...) { + va_list ap; + unsigned ch; + const char *S; + int ws; + + va_start(ap, fmt); + for (char c; (c = *fmt++);) { + if (c != '%') { + fputc(c, stderr); + continue; + } + switch ((c = *fmt++)) { + case '%': + fputc(c, stderr); + break; + case 'c': + ch = bswap32(va_arg(ap, int)); + while (ch) { + fputc(ch, stderr); + ch >>= 8; + } + break; + case 'd': + fprintf(stderr, "%d", va_arg(ap, int)); + break; + case 'U': + fprintf(stderr, "%llu", (unsigned long long)va_arg(ap, u64)); + break; + case 'z': + fprintf(stderr, "%zu", va_arg(ap, size_t)); + break; + case 'f': + fprintf(stderr, "%f", va_arg(ap, double)); + break; + case 's': + fprintf(stderr, "%s", va_arg(ap, const char *)); + break; + case 'w': + ws = va_arg(ap, int); + for (int i = 0; i < ws; ++i) + fprintf(stderr, " "); + break; + case 'S': + S = va_arg(ap, const char *); + pristring(S, va_arg(ap, u64)); + break; + case 't': + pritype(va_arg(ap, const struct type *)); + break; + case 'e': + dumpexpr(va_arg(ap, const struct expr *)); + break; + default: + fprintf(stderr, "pri(): bad fmt '%%%c'\n", c); + abort(); + break; + } + } + va_end(ap); +} + +static void dumpexpr(const struct expr *expr) { + switch (expr->t) { + case Eintlit: + pri("%U_%t", expr->i, expr->ty); + break; + case Eflolit: + pri("%f%s", expr->f, expr->ty->size == 4 ? "f" : ""); + break; + case Estrlit: + pri("%S", expr->strlit.d, expr->strlit.n); + break; + case Eboolit: + pri("#%c", expr->i ? 't' : 'f'); + break; + case Enullit: + pri("#null"); + break; + case Ename: + pri("%s", expr->ref->name); + break; + case Ebinop: + pri("(%e %c %e)", expr->binop.lhs, expr->binop.op, expr->binop.rhs); + break; + case Eprefix: + pri("%c(%e)", expr->unop.op, expr->unop.child); + break; + case Epostfix: + pri("(%e)%c", expr->unop.child, expr->unop.op); + break; + case Econd: + pri("(%e) ? (%e) : (%e)", expr->cond.test, expr->cond.t, expr->cond.f); + break; + case Ecall: + pri("%e(", expr->call.callee); + for (int i = 0; i < expr->call.args.n; ++i) { + pri("%e", &expr->call.args.d[i]); + if (i < expr->call.args.n - 1) + pri(", "); + } + pri(")"); + break; + case Eindex: + pri("%e[%e]", expr->index.lhs, expr->index.rhs); + break; + default: + assert(0 && "exprbad"); + } +} + +static void dumpdecl(const struct decl *decl, int ws); +static void dumpstmt(const struct stmt *stmt, int ws); + +static void +dumpblock(const struct blockstmt *block, int ws) { + pri("%w{\n", ws -1); + for (int i = 0; i < block->stmts.n; ++i) + dumpstmt(&block->stmts.d[i], ws + 1); + pri("%w}\n", ws - 1); +} + +static void +dumpstmt(const struct stmt *stmt, int ws) { + switch (stmt->t) { + case Sblock: + dumpblock(&stmt->block, ws); + break; + case Sdecl: + dumpdecl(&stmt->decl, ws); + break; + case Sexpr: + pri("%w%e\n", ws, &stmt->expr); + break; + case Sifelse: + pri("%wif (%e)\n", ws, &stmt->ifelse.test); + dumpblock(&stmt->ifelse.t, ws + 1); + if (stmt->ifelse.f) { + pri("%welse\n", ws); + dumpstmt(stmt->ifelse.f, ws + 1); + } + break; + case Swhile: + pri("%wwhile %e\n", ws, &stmt->loop.test); + dumpblock(&stmt->loop.body, ws + 1); + break; + case Sfor: + pri("%wfor \n", ws); + if (stmt->loop.ini) + dumpstmt(stmt->loop.ini, ws + 1); + pri("%w; %e; ", ws + 1, &stmt->loop.test); + if (stmt->loop.next) + pri("%e", stmt->loop.next); + pri("\n"); + dumpblock(&stmt->loop.body, ws + 1); + break; + case Siswitch: + pri("%wswitch %e {\n", ws, &stmt->iswitch.test); + for (int i = 0; i < stmt->iswitch.cs.n; ++i) { + struct iswitchcase *c = &stmt->iswitch.cs.d[i]; + pri("%wcase ", ws); + for (int j = 0; j < c->es.n; ++j) + pri("%e, ", &c->es.d[j]); + pri("do\n"); + dumpblock(&c->t, ws + 1); + } + if (stmt->iswitch.f) { + pri("%wcase else\n", ws); + dumpblock(stmt->iswitch.f, ws + 1); + } + pri("%w}\n", ws); + break; + case Sreturn: + if (stmt->retex) + pri("%wreturn %e;\n", ws, stmt->retex); + else + pri("%wreturn;\n", ws); + break; + } +} + +static void +dumpdecl(const struct decl *decl, int ws) { + pri("%w", ws); + pri("decl %s ", decl->name); + switch (decl->t) { + case Dtype: + pri("<type> %t\n", decl->ty); + break; + case Dvar: + pri("<var> %t", decl->var.ty); + if (decl->var.ini) + pri(" = %e", decl->var.ini); + pri("\n"); + break; + case Dfn: + pri("<%sfn> (", decl->externp ? "extern " : ""); + for (int i = 0; i < decl->fn.params.n; ++i) + pri("%s %t, ", decl->fn.params.d[i].name, decl->fn.params.d[i].ty); + if (decl->fn.variadic) + pri("..."); + pri(") %t", decl->fn.retty); + if (decl->fn.body) { + pri("\n"); + dumpstmt(decl->fn.body, ws + 1); + } else { + pri(" <...>\n"); + } + break; + case Dmacro: + pri("<macro> {\n"); + for (int i = 0; i < decl->macro.cs.n; ++i) { + struct macrocase c = decl->macro.cs.d[i]; + pri("("); + for (int j = 0; j < c.params.n; ++j) { + if (j == c.params.n - 1 && c.variadic) + pri("..."); + pri("%s", c.params.d[j]); + if (j < c.params.n - 1) + pri(", "); + } + pri(") "); + pritoktree(c.body); + pri("\n"); + } + pri("}\n"); + break; + } +} + +void +dumptransunit(const struct transunit *tu) { + for (int i = 0; i < tu->decls.n; ++i) + dumpdecl(&tu->decls.d[i], 0); +} |