case is_eq_exact: {
Insn.LSS insn = (Insn.LSS) insn_;
checkArg(current, insn.src1);
checkArg(current, insn.src2);
Type t1 = getType(current, insn.src1);
Type t2 = getType(current, insn.src2);
if (!t1.equals(t2)) {
//TODO: for reg-vs-reg, we should really use the GLB.
DestinationOperand reg;
if ((reg = insn.src1.testDestination()) != null) {
current = setType(current, reg, t2);
}
if ((reg = insn.src2.testDestination()) != null) {
current = setType(current, reg, t1);
}
}
return current;
}
case bs_start_match2: {
Insn.LDIID insn = (Insn.LDIID) insn_;
checkArg(current, insn.dest);
return setType(current, insn.dest5, EMATCHSTATE_TYPE);
}
case bs_get_integer2: {
Insn.LDISIID insn = (Insn.LDISIID) insn_;
if (!EMATCHSTATE_TYPE.equals(getType(current, insn.dest))) {
throw new Error("matching without a state");
}
Int bits = insn.src4.testInt();
int unit = insn.i5;
int flags = insn.i6;
if (unit == 1 && flags == 0 && bits != null && (bits.value*unit) <= 32 ) {
return setType(current, insn.dest7, ESMALL_TYPE);
}
/* DISABLED because it triggers a get_test_bif()-related bug
if (insn.i5 <= 32) {
return setType(current, insn.dest7, Type.INT_TYPE);
}
*/
return setType(current, insn.dest7, EINTEGER_TYPE);
}
case bs_get_binary2: {
Insn.LDISIID insn = (Insn.LDISIID) insn_;
if (!EMATCHSTATE_TYPE.equals(getType(current, insn.dest))) {
throw new Error("matching without a state");
}
return setType(current, insn.dest7, EBINARY_TYPE);
}
case bs_get_float2: {
Insn.LDISIID insn = (Insn.LDISIID) insn_;
if (!EMATCHSTATE_TYPE.equals(getType(current, insn.dest))) {
throw new Error("matching without a state");
}
return setType(current, insn.dest7, Type.DOUBLE_TYPE);
}
case bs_test_tail2:
case bs_test_unit:
case bs_skip_bits2:
case bs_match_string:
case bs_skip_utf8:
case bs_skip_utf16:
case bs_skip_utf32: {
// These bit string matchers don't modify registers.
Insn.LD insn = (Insn.LD) insn_;
if (!EMATCHSTATE_TYPE.equals(getType(current, insn.dest))) {
throw new Error("matching without a state");
}
return current;
}
case bs_get_utf8:
case bs_get_utf16:
case bs_get_utf32: {
// These bit string matchers don't modify registers.
Insn.LDIID insn = (Insn.LDIID) insn_;
if (!EMATCHSTATE_TYPE.equals(getType(current, insn.dest))) {
throw new Error("matching without a state");
}
return setType(current, insn.dest5, ESMALL_TYPE);
}
case is_integer:
{
Insn.LD insn = (Insn.LD) insn_;
checkArg(current, insn.dest);
if (getType(current, insn.dest) == Type.INT_TYPE
|| getType(current, insn.dest).equals(ESMALL_TYPE) ) {
return setType(current, insn.dest, ESMALL_TYPE);
}
}
default: { // All type tests:
Insn.LD insn = (Insn.LD) insn_;
checkArg(current, insn.dest);
switch (opcode) {
case test_arity: {
int arity = ((Insn.LDI)insn).i;
return setType(current, insn.dest, getTupleType(arity));
}
case is_function2: {
Insn.LDS insn2 = (Insn.LDS) insn;
checkArg(current, insn2.src);
// TODO: Use more specific type when arity is known?
return setType(current, insn.dest, EFUN_TYPE);
}
default: {
if (insn instanceof Insn.LD) {
Type test_type = type_tested_for((Insn.LD)insn);
if (test_type != null)
return setType(current, insn.dest, test_type);
}
throw new Error("unhandled test: " + insn_.toSymbolic());
}