// ldarg.0 this // ldc.i4.0 // stfld System.Int32 Smokey.Tests.UseDefaultInitTest/BadCase1::m_int public void VisitStore(StoreField store) { if (m_needsCheck && m_offset < 0) { long?value = m_info.Tracker.GetStack(store.Index, 0); LoadConstantFloat flt = m_info.Instructions[store.Index - 1] as LoadConstantFloat; if ((value.HasValue && value.Value == 0) || (flt != null && flt.Value == 0.0)) { Log.DebugLine(this, "found zero value at index {0}", store.Index - 1); int index = m_info.Tracker.GetStackIndex(store.Index, 1); if (index >= 0) { LoadArg load = m_info.Instructions[index] as LoadArg; if (load != null) { Log.DebugLine(this, "found load at index {0}", index); } if (load != null && load.Arg == 0) { m_offset = store.Untyped.Offset; Log.DebugLine(this, "found zero field store at {0:X2}", m_offset); } } } } }
public void VisitBinary(BinaryOp op) { if (m_offset < 0 && (op.Untyped.OpCode.Code == Code.Div || op.Untyped.OpCode.Code == Code.Div_Un)) { do { LoadConstantFloat load1 = m_info.Instructions[op.Index - 1] as LoadConstantFloat; if (load1 != null) { if (load1.Value == 0.0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero constant denominator at {0:X2}", m_offset); } break; } LoadLocal load2 = m_info.Instructions[op.Index - 1] as LoadLocal; if (load2 != null) { if (DoIsFloatType(load2.Type)) { State state = m_info.Tracker.State(op.Index - 1); long? value = state.Locals[load2.Variable]; if (value.HasValue && value.Value == 0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero local denominator at {0:X2}", m_offset); } } break; } LoadArg load3 = m_info.Instructions[op.Index - 1] as LoadArg; if (load3 != null) { if (DoIsFloatType(load3.Type)) { State state2 = m_info.Tracker.State(op.Index - 1); long? value2 = state2.Arguments[m_info.Method.HasThis ? load3.Arg : load3.Arg - 1]; if (value2.HasValue && value2.Value == 0) { m_offset = op.Untyped.Offset; Log.DebugLine(this, "zero arg denominator at {0:X2}", m_offset); } } break; } }while (false); } }
private bool DoIsBad(int index) { bool bad = false; if (index >= 0) { LoadConstantFloat load = m_info.Instructions[index] as LoadConstantFloat; if (load != null) { bad = Double.IsNaN(load.Value); } } return(bad); }
private bool DoIsFloat(int index) { TypedInstruction instruction = m_info.Instructions[index]; TypeReference type = null; do { LoadArg arg = instruction as LoadArg; if (arg != null && arg.Arg >= 1) { type = m_info.Method.Parameters[arg.Arg - 1].ParameterType; break; } LoadLocal local = instruction as LoadLocal; if (local != null) { type = m_info.Method.Body.Variables[local.Variable].VariableType; break; } LoadField field = instruction as LoadField; if (field != null) { type = field.Field.FieldType; break; } LoadStaticField sfield = instruction as LoadStaticField; if (sfield != null) { type = sfield.Field.FieldType; break; } LoadConstantFloat cf = instruction as LoadConstantFloat; if (cf != null) { return(cf.Value != double.PositiveInfinity && cf.Value != double.NegativeInfinity); } BinaryOp binary = instruction as BinaryOp; if (binary != null) { int j = m_info.Tracker.GetStackIndex(instruction.Index, 0); int k = m_info.Tracker.GetStackIndex(instruction.Index, 1); if (j >= 0 && k >= 0) { if (DoIsFloat(j) && DoIsFloat(k)) { return(true); } } } if (instruction.Untyped.OpCode.Code == Code.Conv_R4 || instruction.Untyped.OpCode.Code == Code.Conv_R8 || instruction.Untyped.OpCode.Code == Code.Conv_R_Un) { return(true); } Call call = instruction as Call; if (call != null) { type = call.Target.ReturnType.ReturnType; break; } }while (false); return(type != null && (type.FullName == "System.Single" || type.FullName == "System.Double")); }
private void DoStackPushes(List <StackEntry> stack, int index, List <StackEntry> oldStack) { long?value; TypedInstruction instruction = m_instructions[index]; switch (instruction.Untyped.OpCode.Code) { case Code.Add: case Code.Sub: case Code.Mul: case Code.Div: case Code.Div_Un: case Code.Rem: case Code.Rem_Un: case Code.And: case Code.Or: case Code.Xor: case Code.Shl: case Code.Shr: case Code.Shr_Un: case Code.Neg: case Code.Not: case Code.Add_Ovf: case Code.Add_Ovf_Un: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Sub_Ovf: case Code.Sub_Ovf_Un: stack.Add(new StackEntry(null, index)); // could compute these, but we don't care too much about integer values atm break; case Code.Arglist: // push non-null case Code.Box: case Code.Ldarga: case Code.Ldarga_S: case Code.Ldelema: case Code.Ldflda: case Code.Ldftn: case Code.Ldind_Ref: case Code.Ldloca: case Code.Ldloca_S: case Code.Ldobj: case Code.Ldsflda: case Code.Ldstr: case Code.Ldtoken: case Code.Ldvirtftn: case Code.Localloc: case Code.Mkrefany: case Code.Newarr: case Code.Newobj: case Code.Refanytype: case Code.Refanyval: case Code.Unbox: case Code.Unbox_Any: stack.Add(new StackEntry(1, index)); break; case Code.Call: case Code.Calli: case Code.Callvirt: Call call = instruction as Call; if (call.Target.ReturnType.ReturnType.ToString() != "System.Void") { stack.Add(new StackEntry(null, index)); } break; case Code.Castclass: value = oldStack.Back().Value; if (value.HasValue && value.Value == 0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(1, index)); } break; case Code.Ceq: // push indeterminate case Code.Cgt: case Code.Cgt_Un: case Code.Clt: case Code.Clt_Un: case Code.Ckfinite: case Code.Conv_I1: case Code.Conv_I2: case Code.Conv_I4: case Code.Conv_I8: case Code.Conv_U4: case Code.Conv_U8: case Code.Conv_R4: case Code.Conv_R8: case Code.Conv_U2: case Code.Conv_U1: case Code.Conv_I: case Code.Conv_R_Un: case Code.Conv_U: case Code.Ldelem_I1: case Code.Ldelem_U1: case Code.Ldelem_I2: case Code.Ldelem_U2: case Code.Ldelem_I4: case Code.Ldelem_U4: case Code.Ldelem_I8: case Code.Ldelem_I: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldelem_Any: case Code.Ldind_I1: case Code.Ldind_U1: case Code.Ldind_I2: case Code.Ldind_U2: case Code.Ldind_I4: case Code.Ldind_U4: case Code.Ldind_I8: case Code.Ldind_I: case Code.Ldind_R4: case Code.Ldind_R8: case Code.Ldfld: case Code.Ldsfld: case Code.Ldlen: case Code.Sizeof: stack.Add(new StackEntry(null, index)); break; case Code.Conv_Ovf_I1: // push previous value case Code.Conv_Ovf_U1: case Code.Conv_Ovf_I2: case Code.Conv_Ovf_U2: case Code.Conv_Ovf_I4: case Code.Conv_Ovf_U4: case Code.Conv_Ovf_I8: case Code.Conv_Ovf_U8: case Code.Conv_Ovf_I: case Code.Conv_Ovf_U: case Code.Conv_Ovf_I1_Un: case Code.Conv_Ovf_I2_Un: case Code.Conv_Ovf_I4_Un: case Code.Conv_Ovf_I8_Un: case Code.Conv_Ovf_U1_Un: case Code.Conv_Ovf_U2_Un: case Code.Conv_Ovf_U4_Un: case Code.Conv_Ovf_U8_Un: case Code.Conv_Ovf_I_Un: case Code.Conv_Ovf_U_Un: value = oldStack.Back().Value; stack.Add(new StackEntry(value, index)); break; case Code.Dup: value = oldStack.Back().Value; stack.Add(new StackEntry(value, index)); stack.Add(new StackEntry(value, index)); break; case Code.Isinst: value = oldStack.Back().Value; if (value.HasValue && value.Value == 0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(null, index)); } break; case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: case Code.Ldarg: case Code.Ldarg_S: LoadArg arg = instruction as LoadArg; value = m_state.Arguments[arg.Arg]; stack.Add(new StackEntry(value, index)); break; case Code.Ldc_I4_M1: case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_S: case Code.Ldc_I4: case Code.Ldc_I8: LoadConstantInt constant = instruction as LoadConstantInt; stack.Add(new StackEntry(constant.Value, index)); break; case Code.Ldc_R4: case Code.Ldc_R8: LoadConstantFloat constant2 = instruction as LoadConstantFloat; if (constant2.Value == 0.0) { stack.Add(new StackEntry(0, index)); } else { stack.Add(new StackEntry(null, index)); } break; case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: case Code.Ldloc: case Code.Ldloc_S: LoadLocal local = instruction as LoadLocal; value = m_state.Locals[local.Variable]; stack.Add(new StackEntry(value, index)); break; case Code.Ldnull: // push null stack.Add(new StackEntry(0, index)); break; default: DBC.Assert(instruction.Untyped.OpCode.StackBehaviourPush == StackBehaviour.Push0, "Expected {0} to push nothing", instruction.Untyped.OpCode); break; } }