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);
}
|