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