aboutsummaryrefslogtreecommitdiffhomepage
path: root/irdump.c
blob: b7fbcc04c57c6eee713e26326bc0acbf2b1ecd9e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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: */