public static Int64Value Add(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) return new Int64Value(a.value + b.value); if (ReferenceEquals(a, b)) return new Int64Value(a.value << 1, (a.validMask << 1) | 1); return createUnknown(); }
public static Bool3 compareGt(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) return a.value > b.value ? Bool3.True : Bool3.False; if (a.hasValue(long.MinValue)) return Bool3.False; // min > x => false if (b.hasValue(long.MaxValue)) return Bool3.False; // x > max => false return Bool3.Unknown; }
public static Bool3 CompareFalse(Int64Value a) { if (a.AllBitsValid()) return a.Value == 0 ? Bool3.True : Bool3.False; if (((ulong)a.Value & a.ValidMask) != 0) return Bool3.False; return Bool3.Unknown; }
public static Int32Value Ceq(Int64Value a, Int64Value b) { return(Create(CompareEq(a, b))); }
public static Int32Value Clt_Un(Int64Value a, Int64Value b) { return create(compareLt_Un(a, b)); }
public static Int64Value Mul(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) return new Int64Value(a.value * b.value); if (a.isZero() || b.isZero()) return new Int64Value(0); if (a.hasValue(1)) return b; if (b.hasValue(1)) return a; return createUnknown(); }
public static Int64Value Shr(Int64Value a, Int32Value b) { if (b.hasUnknownBits()) return createUnknown(); if (b.value == 0) return a; if (b.value < 0 || b.value >= sizeof(long) * 8) return createUnknown(); int shift = b.value; ulong validMask = a.validMask >> shift; if (a.isBitValid(sizeof(long) * 8 - 1)) validMask |= (ulong.MaxValue << (sizeof(long) * 8 - shift)); return new Int64Value(a.value >> shift, validMask); }
public static Int64Value Conv_Ovf_U8_Un(Int64Value a) { return(a); }
public static Int64Value Not(Int64Value a) { return(new Int64Value(~a.Value, a.ValidMask)); }
public static Int32Value Conv_I1(Int64Value a) => Conv_I1((int)a.Value, (uint)a.ValidMask);
public static Int64Value Conv_I8(Int64Value a) { return(a); }
public static Int64Value Conv_Ovf_U8(Int32Value a) { if (!IsBitValid(a.ValidMask, 31) || a.Value < 0) return Int64Value.CreateUnknown(); return new Int64Value(a.Value, (ulong)a.ValidMask | (Int64Value.NO_UNKNOWN_BITS << 32)); }
public static Int32Value Conv_I4(Int64Value a) => new Int32Value((int)a.Value, (uint)a.ValidMask);
public static Int32Value Cgt(Int64Value a, Int64Value b) { return(Create(CompareGt(a, b))); }
public static Bool3 compareLt_Un(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) return (ulong)a.value < (ulong)b.value ? Bool3.True : Bool3.False; if (a.hasValue(ulong.MaxValue)) return Bool3.False; // max < x => false if (b.hasValue(ulong.MinValue)) return Bool3.False; // x < min => false return Bool3.Unknown; }
public static Int32Value Cgt_Un(Int64Value a, Int64Value b) { return(Int32Value.Create(CompareGt_Un(a, b))); }
public static Int64Value Conv_U8(Int64Value a) { return a; }
public static Int32Value Clt(Int64Value a, Int64Value b) { return(Int32Value.Create(CompareLt(a, b))); }
public static Int64Value Not(Int64Value a) { return new Int64Value(~a.value, a.validMask); }
public static Int64Value Conv_Ovf_U8_Un(Int64Value a) => a;
public static Int64Value Sub(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) return new Int64Value(a.value - b.value); if (ReferenceEquals(a, b)) return new Int64Value(0); return createUnknown(); }
public static Int64Value Not(Int64Value a) => new Int64Value(~a.Value, a.ValidMask);
public static Int32Value Ceq(Int64Value a, Int64Value b) { return create(compareEq(a, b)); }
public static Int32Value Ceq(Int64Value a, Int64Value b) => Int32Value.Create(CompareEq(a, b));
public static Int32Value Conv_I2(Int64Value a) { return Conv_I2((int)a.Value, (uint)a.ValidMask); }
public static Int32Value Cgt(Int64Value a, Int64Value b) => Int32Value.Create(CompareGt(a, b));
public static Bool3 CompareLt(Int64Value a, Int64Value b) { if (a.AllBitsValid() && b.AllBitsValid()) return a.Value < b.Value ? Bool3.True : Bool3.False; if (a.HasValue(long.MaxValue)) return Bool3.False; // max < x => false if (b.HasValue(long.MinValue)) return Bool3.False; // x < min => false return Bool3.Unknown; }
public static Int32Value Clt_Un(Int64Value a, Int64Value b) => Int32Value.Create(CompareLt_Un(a, b));
public static Bool3 compareGe(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) return a.value >= b.value ? Bool3.True : Bool3.False; if (a.hasValue(long.MaxValue)) return Bool3.True; // max >= x => true if (b.hasValue(long.MinValue)) return Bool3.True; // x >= min => true return Bool3.Unknown; }
public static Int64Value Conv_I8(Int64Value a) => a;
public static Bool3 compareLe_Un(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) return (ulong)a.value <= (ulong)b.value ? Bool3.True : Bool3.False; if (a.hasValue(ulong.MinValue)) return Bool3.True; // min <= x => true if (b.hasValue(ulong.MaxValue)) return Bool3.True; // x <= max => true return Bool3.Unknown; }
Value truncateValue(Value value, TypeSig type) { if (type == null) { return(value); } if (protectedStackValues.ContainsKey(value)) { return(value); } switch (type.ElementType) { case ElementType.Boolean: if (value.isInt32()) { return(((Int32Value)value).toBoolean()); } return(Int32Value.createUnknownBool()); case ElementType.I1: if (value.isInt32()) { return(((Int32Value)value).toInt8()); } return(Int32Value.createUnknown()); case ElementType.U1: if (value.isInt32()) { return(((Int32Value)value).toUInt8()); } return(Int32Value.createUnknownUInt8()); case ElementType.I2: if (value.isInt32()) { return(((Int32Value)value).toInt16()); } return(Int32Value.createUnknown()); case ElementType.U2: if (value.isInt32()) { return(((Int32Value)value).toUInt16()); } return(Int32Value.createUnknownUInt16()); case ElementType.I4: case ElementType.U4: if (value.isInt32()) { return(value); } return(Int32Value.createUnknown()); case ElementType.I8: case ElementType.U8: if (value.isInt64()) { return(value); } return(Int64Value.createUnknown()); case ElementType.R4: if (value.isReal8()) { return(new Real8Value((float)((Real8Value)value).value)); } return(new UnknownValue()); case ElementType.R8: if (value.isReal8()) { return(value); } return(new UnknownValue()); } return(value); }
public static Bool3 compareTrue(Int64Value a) { if (a.allBitsValid()) return a.value != 0 ? Bool3.True : Bool3.False; if (((ulong)a.value & a.validMask) != 0) return Bool3.True; return Bool3.Unknown; }
public void emulate(Instruction instr) { switch (instr.OpCode.Code) { case Code.Starg: case Code.Starg_S: emulate_Starg((Parameter)instr.Operand); break; case Code.Stloc: case Code.Stloc_S: emulate_Stloc((Local)instr.Operand); break; case Code.Stloc_0: emulate_Stloc(0); break; case Code.Stloc_1: emulate_Stloc(1); break; case Code.Stloc_2: emulate_Stloc(2); break; case Code.Stloc_3: emulate_Stloc(3); break; case Code.Ldarg: case Code.Ldarg_S: valueStack.push(getArg((Parameter)instr.Operand)); break; case Code.Ldarg_0: valueStack.push(getArg(0)); break; case Code.Ldarg_1: valueStack.push(getArg(1)); break; case Code.Ldarg_2: valueStack.push(getArg(2)); break; case Code.Ldarg_3: valueStack.push(getArg(3)); break; case Code.Ldloc: case Code.Ldloc_S: valueStack.push(getLocal((Local)instr.Operand)); break; case Code.Ldloc_0: valueStack.push(getLocal(0)); break; case Code.Ldloc_1: valueStack.push(getLocal(1)); break; case Code.Ldloc_2: valueStack.push(getLocal(2)); break; case Code.Ldloc_3: valueStack.push(getLocal(3)); break; case Code.Ldarga: case Code.Ldarga_S: emulate_Ldarga((Parameter)instr.Operand); break; case Code.Ldloca: case Code.Ldloca_S: emulate_Ldloca((Local)instr.Operand); break; case Code.Dup: valueStack.copyTop(); break; case Code.Ldc_I4: valueStack.push(new Int32Value((int)instr.Operand)); break; case Code.Ldc_I4_S: valueStack.push(new Int32Value((sbyte)instr.Operand)); break; case Code.Ldc_I8: valueStack.push(new Int64Value((long)instr.Operand)); break; case Code.Ldc_R4: valueStack.push(new Real8Value((float)instr.Operand)); break; case Code.Ldc_R8: valueStack.push(new Real8Value((double)instr.Operand)); break; case Code.Ldc_I4_0: valueStack.push(Int32Value.zero); break; case Code.Ldc_I4_1: valueStack.push(Int32Value.one); break; case Code.Ldc_I4_2: valueStack.push(new Int32Value(2)); break; case Code.Ldc_I4_3: valueStack.push(new Int32Value(3)); break; case Code.Ldc_I4_4: valueStack.push(new Int32Value(4)); break; case Code.Ldc_I4_5: valueStack.push(new Int32Value(5)); break; case Code.Ldc_I4_6: valueStack.push(new Int32Value(6)); break; case Code.Ldc_I4_7: valueStack.push(new Int32Value(7)); break; case Code.Ldc_I4_8: valueStack.push(new Int32Value(8)); break; case Code.Ldc_I4_M1: valueStack.push(new Int32Value(-1)); break; case Code.Ldnull: valueStack.push(NullValue.Instance); break; case Code.Ldstr: valueStack.push(new StringValue((string)instr.Operand)); break; case Code.Box: valueStack.push(new BoxedValue(valueStack.pop())); break; case Code.Conv_U1: emulate_Conv_U1(instr); break; case Code.Conv_U2: emulate_Conv_U2(instr); break; case Code.Conv_U4: emulate_Conv_U4(instr); break; case Code.Conv_U8: emulate_Conv_U8(instr); break; case Code.Conv_I1: emulate_Conv_I1(instr); break; case Code.Conv_I2: emulate_Conv_I2(instr); break; case Code.Conv_I4: emulate_Conv_I4(instr); break; case Code.Conv_I8: emulate_Conv_I8(instr); break; case Code.Add: emulate_Add(instr); break; case Code.Sub: emulate_Sub(instr); break; case Code.Mul: emulate_Mul(instr); break; case Code.Div: emulate_Div(instr); break; case Code.Div_Un: emulate_Div_Un(instr); break; case Code.Rem: emulate_Rem(instr); break; case Code.Rem_Un: emulate_Rem_Un(instr); break; case Code.Neg: emulate_Neg(instr); break; case Code.And: emulate_And(instr); break; case Code.Or: emulate_Or(instr); break; case Code.Xor: emulate_Xor(instr); break; case Code.Not: emulate_Not(instr); break; case Code.Shl: emulate_Shl(instr); break; case Code.Shr: emulate_Shr(instr); break; case Code.Shr_Un: emulate_Shr_Un(instr); break; case Code.Ceq: emulate_Ceq(instr); break; case Code.Cgt: emulate_Cgt(instr); break; case Code.Cgt_Un: emulate_Cgt_Un(instr); break; case Code.Clt: emulate_Clt(instr); break; case Code.Clt_Un: emulate_Clt_Un(instr); break; case Code.Unbox_Any: emulate_Unbox_Any(instr); break; case Code.Call: emulate_Call(instr); break; case Code.Callvirt: emulate_Callvirt(instr); break; case Code.Castclass: emulate_Castclass(instr); break; case Code.Isinst: emulate_Isinst(instr); break; case Code.Add_Ovf: emulateIntOps2(); break; case Code.Add_Ovf_Un: emulateIntOps2(); break; case Code.Sub_Ovf: emulateIntOps2(); break; case Code.Sub_Ovf_Un: emulateIntOps2(); break; case Code.Mul_Ovf: emulateIntOps2(); break; case Code.Mul_Ovf_Un: emulateIntOps2(); break; case Code.Conv_Ovf_I1: case Code.Conv_Ovf_I1_Un: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Conv_Ovf_I2: case Code.Conv_Ovf_I2_Un: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Conv_Ovf_I4: case Code.Conv_Ovf_I4_Un: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Conv_Ovf_I8: case Code.Conv_Ovf_I8_Un: valueStack.pop(); valueStack.push(Int64Value.createUnknown()); break; case Code.Conv_Ovf_U1: case Code.Conv_Ovf_U1_Un: valueStack.pop(); valueStack.push(Int32Value.createUnknownUInt8()); break; case Code.Conv_Ovf_U2: case Code.Conv_Ovf_U2_Un: valueStack.pop(); valueStack.push(Int32Value.createUnknownUInt16()); break; case Code.Conv_Ovf_U4: case Code.Conv_Ovf_U4_Un: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Conv_Ovf_U8: case Code.Conv_Ovf_U8_Un: valueStack.pop(); valueStack.push(Int64Value.createUnknown()); break; case Code.Ldelem_I1: valueStack.pop(2); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldelem_I2: valueStack.pop(2); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldelem_I4: valueStack.pop(2); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldelem_I8: valueStack.pop(2); valueStack.push(Int64Value.createUnknown()); break; case Code.Ldelem_U1: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt8()); break; case Code.Ldelem_U2: valueStack.pop(2); valueStack.push(Int32Value.createUnknownUInt16()); break; case Code.Ldelem_U4: valueStack.pop(2); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldelem: valueStack.pop(2); valueStack.push(getUnknownValue(instr.Operand as ITypeDefOrRef)); break; case Code.Ldind_I1: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldind_I2: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldind_I4: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldind_I8: valueStack.pop(); valueStack.push(Int64Value.createUnknown()); break; case Code.Ldind_U1: valueStack.pop(); valueStack.push(Int32Value.createUnknownUInt8()); break; case Code.Ldind_U2: valueStack.pop(); valueStack.push(Int32Value.createUnknownUInt16()); break; case Code.Ldind_U4: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Ldlen: valueStack.pop(); valueStack.push(Int32Value.createUnknown()); break; case Code.Sizeof: valueStack.push(Int32Value.createUnknown()); break; case Code.Ldfld: emulate_Ldfld(instr); break; case Code.Ldsfld: emulate_Ldsfld(instr); break; case Code.Ldftn: valueStack.push(new ObjectValue(instr.Operand)); break; case Code.Ldsflda: valueStack.push(new ObjectValue(instr.Operand)); break; case Code.Ldtoken: valueStack.push(new ObjectValue(instr.Operand)); break; case Code.Ldvirtftn: valueStack.pop(); valueStack.push(new ObjectValue()); break; case Code.Ldflda: valueStack.pop(); valueStack.push(new ObjectValue()); break; case Code.Unbox: case Code.Conv_R_Un: case Code.Conv_R4: case Code.Conv_R8: case Code.Arglist: case Code.Beq: case Code.Beq_S: case Code.Bge: case Code.Bge_S: case Code.Bge_Un: case Code.Bge_Un_S: case Code.Bgt: case Code.Bgt_S: case Code.Bgt_Un: case Code.Bgt_Un_S: case Code.Ble: case Code.Ble_S: case Code.Ble_Un: case Code.Ble_Un_S: case Code.Blt: case Code.Blt_S: case Code.Blt_Un: case Code.Blt_Un_S: case Code.Bne_Un: case Code.Bne_Un_S: case Code.Brfalse: case Code.Brfalse_S: case Code.Brtrue: case Code.Brtrue_S: case Code.Br: case Code.Br_S: case Code.Break: case Code.Calli: case Code.Ckfinite: case Code.Constrained: case Code.Conv_I: case Code.Conv_Ovf_I: case Code.Conv_Ovf_I_Un: case Code.Conv_Ovf_U: case Code.Conv_Ovf_U_Un: case Code.Conv_U: case Code.Cpblk: case Code.Cpobj: case Code.Endfilter: case Code.Endfinally: case Code.Initblk: case Code.Initobj: case Code.Jmp: case Code.Ldelema: case Code.Ldelem_I: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldind_I: case Code.Ldind_R4: case Code.Ldind_R8: case Code.Ldind_Ref: case Code.Ldobj: case Code.Leave: case Code.Leave_S: case Code.Localloc: case Code.Mkrefany: case Code.Newarr: case Code.Newobj: case Code.Nop: case Code.Pop: case Code.Readonly: case Code.Refanytype: case Code.Refanyval: case Code.Ret: case Code.Rethrow: case Code.Stelem: case Code.Stelem_I: case Code.Stelem_I1: case Code.Stelem_I2: case Code.Stelem_I4: case Code.Stelem_I8: case Code.Stelem_R4: case Code.Stelem_R8: case Code.Stelem_Ref: case Code.Stfld: case Code.Stind_I: case Code.Stind_I1: case Code.Stind_I2: case Code.Stind_I4: case Code.Stind_I8: case Code.Stind_R4: case Code.Stind_R8: case Code.Stind_Ref: case Code.Stobj: case Code.Stsfld: case Code.Switch: case Code.Tailcall: case Code.Throw: case Code.Unaligned: case Code.Volatile: default: updateStack(instr); break; } }
public static Int64Value Div(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) { try { return new Int64Value(a.value / b.value); } catch (ArithmeticException) { return createUnknown(); } } if (ReferenceEquals(a, b) && a.isNonZero()) return new Int64Value(1); if (b.hasValue(1)) return a; return createUnknown(); }
public static Int32Value Conv_U2(Int64Value a) { return(Conv_U2((int)a.Value, (uint)a.ValidMask)); }
public static Int64Value Neg(Int64Value a) { if (a.allBitsValid()) return new Int64Value(-a.value); return createUnknown(); }
public static Int32Value Conv_I4(Int64Value a) { return(new Int32Value((int)a.Value, (uint)a.ValidMask)); }
public static Int64Value Rem_Un(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) { try { return new Int64Value((long)((ulong)a.value % (ulong)b.value)); } catch (ArithmeticException) { return createUnknown(); } } if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1)) return new Int64Value(0); return createUnknown(); }
public static Int64Value Conv_Ovf_I8(Real8Value a) => Int64Value.CreateUnknown();
public static Int64Value Shr_Un(Int64Value a, Int32Value b) { if (b.hasUnknownBits()) return createUnknown(); if (b.value == 0) return a; if (b.value < 0 || b.value >= sizeof(long) * 8) return createUnknown(); int shift = b.value; ulong validMask = (a.validMask >> shift) | (ulong.MaxValue << (sizeof(long) * 8 - shift)); return new Int64Value((long)((ulong)a.value >> shift), validMask); }
public static Int32Value Cgt_Un(Int64Value a, Int64Value b) { return Create(CompareGt_Un(a, b)); }
public static Int64Value Xor(Int64Value a, Int64Value b) { if (ReferenceEquals(a, b)) return new Int64Value(0); long av = a.value, bv = b.value; ulong am = a.validMask, bm = b.validMask; return new Int64Value(av ^ bv, am & bm); }
public static Int32Value Clt(Int64Value a, Int64Value b) { return Create(CompareLt(a, b)); }
public static Int64Value And(Int64Value a, Int64Value b) { long av = a.value, bv = b.value; ulong am = a.validMask, bm = b.validMask; return new Int64Value(av & bv, (am & bm) | (((ulong)av & am) ^ am) | (((ulong)bv & bm) ^ bm)); }
public static Bool3 CompareGt_Un(Int64Value a, Int64Value b) { if (a.AllBitsValid() && b.AllBitsValid()) return (ulong)a.Value > (ulong)b.Value ? Bool3.True : Bool3.False; if (a.HasValue(ulong.MinValue)) return Bool3.False; // min > x => false if (b.HasValue(ulong.MaxValue)) return Bool3.False; // x > max => false return Bool3.Unknown; }
public static Int32Value Cgt(Int64Value a, Int64Value b) { return create(compareGt(a, b)); }
public static Bool3 CompareGe_Un(Int64Value a, Int64Value b) { if (a.AllBitsValid() && b.AllBitsValid()) return (ulong)a.Value >= (ulong)b.Value ? Bool3.True : Bool3.False; if (a.HasValue(ulong.MaxValue)) return Bool3.True; // max >= x => true if (b.HasValue(ulong.MinValue)) return Bool3.True; // x >= min => true return Bool3.Unknown; }
public static Bool3 compareEq(Int64Value a, Int64Value b) { if (a.allBitsValid() && b.allBitsValid()) return a.value == b.value ? Bool3.True : Bool3.False; if (ReferenceEquals(a, b)) return Bool3.True; if (((ulong)a.value & a.validMask & b.validMask) != ((ulong)b.value & a.validMask & b.validMask)) return Bool3.False; return Bool3.Unknown; }
public static Bool3 CompareLe(Int64Value a, Int64Value b) { if (a.AllBitsValid() && b.AllBitsValid()) return a.Value <= b.Value ? Bool3.True : Bool3.False; if (a.HasValue(long.MinValue)) return Bool3.True; // min <= x => true if (b.HasValue(long.MaxValue)) return Bool3.True; // x <= max => true return Bool3.Unknown; }
public static Int32Value Conv_I4(Int64Value a) { return new Int32Value((int)a.Value, (uint)a.ValidMask); }
public static Int32Value Clt_Un(Int64Value a, Int64Value b) { return(create(compareLt_Un(a, b))); }