aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/dump.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-03 20:24:47 +0200
committerlemon <lsof@mailbox.org>2022-08-03 20:24:47 +0200
commit1625c50f0c0e4b1c7ba01a5df5713efaf6dce606 (patch)
treebc5f24811413749b776964c1bbdec13a46dd9768 /bootstrap/dump.c
initial
Diffstat (limited to 'bootstrap/dump.c')
-rw-r--r--bootstrap/dump.c384
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);
+}