Arg tuple_reg = null;
vis.visitBegin(exh);
for (int insn_idx = 0; insn_idx < insns.size(); insn_idx++) {
Insn insn_ = insns.get(insn_idx);
BeamOpcode opcode = insn_.opcode();
TypeMap type_map = this.map[insn_idx];
switch (opcode) {
case func_info: {
Insn.AAI insn = (Insn.AAI)insn_;
// log.finer("go: " + insn);
vis.visitInsn(opcode, insn.getExtFun());
break;
}
case fnegate: {
Insn.LSD insn = (Insn.LSD)insn_;
EAtom name = opcode.symbol;
int failLabel = decode_labelref(insn.label, type_map.exh);
Arg[] in = new Arg[] {src_arg(insn_idx, insn.src)};
Type[] inTypes = new Type[] {in[0].type};
Arg out = dest_arg(insn_idx, insn.dest);
BuiltInFunction bif = BIFUtil.getMethod("erlang", name.getName(), inTypes,
failLabel != 0, true);
vis.visitInsn(opcode, failLabel, in, out, bif);
break;
}
case fconv:
case fmove:
case move: {
Insn.SD insn = (Insn.SD)insn_;
Arg src = src_arg(insn_idx, insn.src);
Arg dest = dest_arg(insn_idx, insn.dest);
if (insns.size() > insn_idx+1) {
Insn next_insn = insns.get(insn_idx+1);
if (next_insn.opcode() == BeamOpcode.K_return) {
vis.visitInsn(BeamOpcode.K_return, src);
insn_idx += 1;
break;
}
}
if (dest.kind != Kind.F) {
if (src.kind == Kind.F) {
dest = new Arg(dest, EDOUBLE_TYPE);
} else {
dest = new Arg(dest, src.type);
}
} else {
// arg2.kind == F
}
vis.visitInsn(opcode, src, dest);
break;
}
case put_string: {
Insn.ByD insn = (Insn.ByD)insn_;
Arg src = src_arg(insn_idx, insn.bin);
Arg dest = dest_arg(insn_idx, insn.dest);
// Arg arg1 = decode_arg(insn_idx, insn.elm(3));
// Arg arg2 = decode_out_arg(insn_idx, insn.elm(4));
dest = new Arg(dest, ESEQ_TYPE);
vis.visitInsn(BeamOpcode.move, src, dest);
break;
}
case fadd:
case fsub:
case fmul:
case fdiv:
{
Insn.LSSD insn = (Insn.LSSD)insn_;
EAtom name = opcode.symbol;
int failLabel = decode_labelref(insn.label, type_map.exh);
Arg[] in = new Arg[] {src_arg(insn_idx, insn.src1),
src_arg(insn_idx, insn.src2)};
Type[] inTypes = new Type[] {in[0].type,
in[1].type};
Arg out = dest_arg(insn_idx, insn.dest);
BuiltInFunction bif = BIFUtil.getMethod("erlang", name.getName(), inTypes,
failLabel != 0, true);
vis.visitInsn(opcode, failLabel, in, out, bif);
break;
}
case bif0:
case bif1:
case bif2:
{
Insn.Bif insn = (Insn.Bif)insn_;
EAtom name = insn.ext_fun.fun;
int failLabel = decode_labelref(insn.label, type_map.exh);
SourceOperand[] srcs = insn.args;
Arg[] in = src_args(insn_idx, srcs);
Arg out = dest_arg(insn_idx, insn.dest);
BuiltInFunction bif = BIFUtil.getMethod("erlang", name.getName(),
parmTypes(type_map, srcs),
failLabel != 0, true);
vis.visitInsn(opcode, failLabel, in, out, bif);
break;
}
case gc_bif1:
case gc_bif2:
case gc_bif3:
{
Insn.GcBif insn = (Insn.GcBif)insn_;
EAtom name = insn.ext_fun.fun;
int failLabel = decode_labelref(insn.label, type_map.exh);
SourceOperand[] srcs = insn.args;
Arg[] in = src_args(insn_idx, srcs);
Arg out = dest_arg(insn_idx, insn.dest);
// special case for X+1, 1+X, X-1.
Int lop = null, rop = null;
if (srcs.length==2
&& (((name==am_plus || name == am_minus) && (rop=srcs[1].testInt()) != null && rop.equals(1))
|| (name==am_plus && (lop=srcs[0].testInt()) != null && lop.equals(1))))
{
if (name == am_plus) {
Arg src = (lop == null) ? in[0] : in[1];
vis.visitIncrement(src, out);
break;
} else if (name == am_minus) {
Arg src = in[0];
vis.visitDecrement(src, out);
break;
}
}
BuiltInFunction bif = BIFUtil.getMethod("erlang", name.getName(),
parmTypes(type_map, srcs),
failLabel != 0, true);
vis.visitInsn(opcode, failLabel, in, out, bif);
break;
}
case is_tuple: {
if (insn_idx+1 < insns.size()) {
Insn next_insn = insns.get(insn_idx+1);
if (next_insn.opcode() == BeamOpcode.test_arity) {
int this_fail = decode_labelref(((Insn.L)insn_).label, this.map[insn_idx].exh);
int next_fail = decode_labelref(((Insn.L)next_insn).label, this.map[insn_idx+1].exh);
if (this_fail == next_fail) {