aboutsummaryrefslogtreecommitdiff
path: root/src/irdump.cff
blob: 4147c8acd36e32b5e38c87b74a753ece2fc08c73 (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
import "ir.hff";
import "common.hff";

fn dump(fmt *const u8, ...) void {
   let ap va_list #?;
   ap->start(fmt);
   for let c = *fmt; c != 0; c = *++fmt {
      if c != '%' {
         fputc(c, stderr);
         continue;
      }
      switch (c = *++fmt) {
      case '%';
         fputc('%', stderr);
      case 'd';
         efmt("%d", ap->arg(int));         
      case 'a';
         let arg = ap->arg(IRArg);
         switch arg {
         case Val val;
            switch val.u {
            case IImm i;
               efmt("%I", i);
            case FImm f;
               efmt("%f", f);
            case SImm s;
               efmt("%S", s);
            case BImm b;
               efmt("%s", b ? "#t" : "#f");
            case Null;
               efmt("#null");
            case Tmp t;
               efmt("%%%d", t);
            }
         case Ty ty; efmt("%t", ty);
         case Fn decl; efmt("%s", decl.name);
         case else assert(#f, "arg? %d", arg.#tag);
         }
      case 't';
         efmt("%t", ap->arg(*Type));
      case else
         assert(#f, "bad fmt %c", c);
      }
   }
   ap->end();
}

extern fn irdump(a *IRInst) void {
   if a == #null { return; }

   dump("         ");
   #'dump do {
      defmacro exprinst(tag, nam, n) [
         if a.t == (tag) {
            dump("%%%d(%t) = " ## nam ## " ", a.args[0].Val.u.Tmp, a.args[0].Val.ty);
            for let $i = 1; $i < (n); ++$i {
               dump("%a", a.args[$i]);
               if $i < (n) - 1 {
                  dump(", ");
               }
            }
            dump("\n");
            break #'dump;
         }
      ]
      defmacro stmtinst(tag, nam, n) [
         if a.t == (tag) {
            dump(nam##" ");
            for let $i = 0; $i < (n); ++$i {
               dump("%a", a.args[$i]);
               if $i < (n) - 1 {
                  dump(", ");
               }
            }
            dump("\n");
            break #'dump;
         }
      ]

      exprinst(:neg,   "neg", 2)
      exprinst(:compl, "compl", 2)
      exprinst(:fneg,  "fneg", 2)
      exprinst(:add,   "add", 3);
      exprinst(:sub,   "sub", 3);
      exprinst(:mul,   "mul", 3);
      exprinst(:div,   "div", 3);
      exprinst(:mod,   "mod", 3);
      exprinst(:band,  "band", 3);
      exprinst(:bor,   "bor", 3);
      exprinst(:xor,   "xor", 3);
      exprinst(:lsl,   "lsl", 3);
      exprinst(:lsr,   "lsr", 3);
      exprinst(:asr,   "asr", 3);
      exprinst(:fadd,  "fadd", 3);
      exprinst(:fsub,  "fsub", 3);
      exprinst(:fmul,  "fmul", 3);
      exprinst(:fdiv,  "fdiv", 3);
      if a.t == :call {
         let fnty = a.args[1].Fn.u.Fn.ty.u.Fn;
         dump("%%%d(%t) = call %a, ", a.args[0].Val.u.Tmp, a.args[0].Val.ty, a.args[1]);
         let n = a.call_nargs;
         for let i = 0; i < n; ++i {
            dump("%a(%t)", a.args[i + 2],
                 i < fnty.params.#len ? fnty.params[i] : a.args[i + 2].Val.ty);
            if i < n - 1 {
               dump(", ");
            }
         }
         dump("\n");
         break #'dump;
      }

      stmtinst(:ret0, "ret", 0);

      assert(#f, "inst? %d\n", a.t);
   } while #f;

   irdump(a.next);
}