aboutsummaryrefslogtreecommitdiffhomepage
path: root/irdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'irdump.c')
-rw-r--r--irdump.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/irdump.c b/irdump.c
new file mode 100644
index 0000000..b7fbcc0
--- /dev/null
+++ b/irdump.c
@@ -0,0 +1,124 @@
+#include "common.h"
+#include "ir.h"
+
+extern struct xcon conht[];
+extern vec_of(struct ircall) calls;
+
+static const char *clsname[] = {
+ "?", "i4", "i8", "iP", "f4", "f8"
+};
+
+static void
+prityp(union irtype typ)
+{
+ if (!typ.isagg)
+ efmt(clsname[typ.cls]);
+ else {
+ const struct typedata *td = &typedata[typ.dat];
+ const char *tag = td->t == TYSTRUCT ? "struct" : "union";
+ if (ttypenames[td->id])
+ efmt("%s.%s.%d", tag, ttypenames[td->id], td->id);
+ else
+ efmt("%s.%d", tag, td->id);
+ }
+}
+
+static void
+dumpref(union irref ref)
+{
+ struct xcon *con;
+ struct ircall *call;
+ switch (ref.t) {
+ case RTMP: efmt("%%%d", ref.idx); break;
+ case RARG: efmt("%%arg%d", ref.idx); break;
+ case RICON: efmt("%d", ref.i); break;
+ case RXCON:
+ con = &conht[ref.idx];
+ if (con->issym) efmt("$%s", con->sym);
+ else switch (con->cls) {
+ case KI4: efmt("%d", con->i4); break;
+ case KI8: efmt("%ld", con->i8); break;
+ case KIP: efmt("%'x", con->i8); break;
+ case KF4: efmt("%f", con->fs); break;
+ case KF8: efmt("%f", con->fd); break;
+ default: assert(0);
+ }
+ break;
+ case RCALL:
+ call = &calls.p[ref.idx];
+ for (int i = 0; i < call->narg; ++i) {
+ if (call->vararg == i) {
+ if (i > 0) efmt(", ");
+ efmt("..., ");
+ }
+ prityp(call->typs[i]);
+ efmt(" ");
+ dumpref(call->args[i]);
+ }
+ break;
+ default: assert(!"ref");
+ }
+}
+
+extern struct instr instr[];
+static const char *opname[] = {
+ "???",
+#define _(o,...) #o,
+#include "op.def"
+#undef _
+};
+static const uchar opnarg[] = {
+ 0,
+#define _(o,n) n,
+#include "op.def"
+#undef _
+};
+
+static void
+dumpinst(const struct instr *ins)
+{
+ int i;
+ efmt(" ");
+ if (ins->cls)
+ efmt("%s %%%d = ", clsname[ins->cls], ins - instr);
+ efmt("%s ", opname[ins->op]);
+ for (i = 0; i < opnarg[ins->op]; ++i) {
+ if (i) efmt(", ");
+ dumpref((&ins->l)[i]);
+ }
+ efmt("\n");
+}
+
+static void
+dumpblk(struct block *blk)
+{
+ static const char *jnames[] = { 0, "b", "b", "ret", "rets" };
+ static const uchar jnarg[] = { 0, 0, 1, 0, 1 };
+ efmt(" .L%d:\n", blk->id);
+ for (int i = 0; i < blk->ins.n; ++i) {
+ dumpinst(&instr[blk->ins.p[i]]);
+ }
+ efmt(" %s ", jnames[blk->jmp.t]);
+ if (jnarg[blk->jmp.t]) {
+ dumpref(blk->jmp.arg);
+ if (blk->s1) efmt(", ");
+ }
+ if (blk->s1 && blk->s2) efmt(".L%d, .L%d", blk->s1->id, blk->s2->id);
+ else if (blk->s1) efmt(".L%d", blk->s1->id);
+ efmt("\n");
+}
+
+void
+irdump(struct function *fn, const char *fname)
+{
+ struct block *blk;
+
+ efmt("function %s : %ty\n", fname, fn->fnty);
+ blk = fn->entry;
+ do {
+ dumpblk(blk);
+ blk = blk->lnext;
+ } while (blk != fn->entry);
+}
+
+/* vim:set ts=3 sw=3 expandtab: */