/// <summary> /// Unions this state range with (other intersect (minVal to maxVal)) /// </summary> public void UnionWith(StateRange other, int minVal, int maxVal) { foreach (Interval v in other.data) { int start = Math.Max(v.Start, minVal); int end = Math.Min(v.End, maxVal); if (start <= end) data.Add(new Interval(start, end)); } }
internal Dictionary<MethodDef, Interval> finallyMethodToStateInterval; // used only for IteratorDispose /// <summary> /// Initializes the state range logic: /// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue) /// </summary> public StateRangeAnalysis(ILNode entryPoint, StateRangeAnalysisMode mode, FieldDef stateField) { this.mode = mode; this.stateField = stateField; if (mode == StateRangeAnalysisMode.IteratorDispose) { finallyMethodToStateInterval = new Dictionary<MethodDef, Interval>(); } ranges = new DefaultDictionary<ILNode, StateRange>(n => new StateRange()); ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue); evalContext = new SymbolicEvaluationContext(stateField); }
internal Dictionary <MethodDefinition, StateRange> finallyMethodToStateRange; // used only for IteratorDispose /// <summary> /// Initializes the state range logic: /// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue) /// </summary> public StateRangeAnalysis(ILNode entryPoint, StateRangeAnalysisMode mode, FieldDefinition stateField, ILVariable cachedStateVar = null) { this.mode = mode; this.stateField = stateField; if (mode == StateRangeAnalysisMode.IteratorDispose) { finallyMethodToStateRange = new Dictionary <MethodDefinition, StateRange>(); } ranges = new DefaultDictionary <ILNode, StateRange>(n => new StateRange()); ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue); evalContext = new SymbolicEvaluationContext(stateField); if (cachedStateVar != null) { evalContext.AddStateVariable(cachedStateVar); } }
public void UnionWith(StateRange other) { data.AddRange(other.data); }
public int AssignStateRanges(List <ILNode> body, int bodyLength) { if (bodyLength == 0) { return(0); } for (int i = 0; i < bodyLength; i++) { StateRange nodeRange = ranges[body[i]]; nodeRange.Simplify(); ILLabel label = body[i] as ILLabel; if (label != null) { ranges[body[i + 1]].UnionWith(nodeRange); continue; } ILTryCatchBlock tryFinally = body[i] as ILTryCatchBlock; if (tryFinally != null) { if (mode == StateRangeAnalysisMode.IteratorDispose) { if (tryFinally.CatchBlocks.Count != 0 || tryFinally.FaultBlock != null || tryFinally.FinallyBlock == null) { throw new SymbolicAnalysisFailedException(); } ranges[tryFinally.TryBlock].UnionWith(nodeRange); if (tryFinally.TryBlock.Body.Count != 0) { ranges[tryFinally.TryBlock.Body[0]].UnionWith(nodeRange); AssignStateRanges(tryFinally.TryBlock.Body, tryFinally.TryBlock.Body.Count); } continue; } else if (mode == StateRangeAnalysisMode.AsyncMoveNext) { return(i); } else { throw new SymbolicAnalysisFailedException(); } } ILExpression expr = body[i] as ILExpression; if (expr == null) { throw new SymbolicAnalysisFailedException(); } switch (expr.Code) { case ILCode.Switch: { SymbolicValue val = evalContext.Eval(expr.Arguments[0]); if (val.Type != SymbolicValueType.State) { goto default; } ILLabel[] targetLabels = (ILLabel[])expr.Operand; for (int j = 0; j < targetLabels.Length; j++) { int state = j - val.Constant; ranges[targetLabels[j]].UnionWith(nodeRange, state, state); } StateRange nextRange = ranges[body[i + 1]]; nextRange.UnionWith(nodeRange, int.MinValue, -1 - val.Constant); nextRange.UnionWith(nodeRange, targetLabels.Length - val.Constant, int.MaxValue); break; } case ILCode.Br: case ILCode.Leave: ranges[(ILLabel)expr.Operand].UnionWith(nodeRange); break; case ILCode.Brtrue: { SymbolicValue val = evalContext.Eval(expr.Arguments[0]); if (val.Type == SymbolicValueType.StateEquals) { ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant); StateRange nextRange = ranges[body[i + 1]]; nextRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1); nextRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue); break; } else if (val.Type == SymbolicValueType.StateInEquals) { ranges[body[i + 1]].UnionWith(nodeRange, val.Constant, val.Constant); StateRange targetRange = ranges[(ILLabel)expr.Operand]; targetRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1); targetRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue); break; } else { goto default; } } case ILCode.Nop: ranges[body[i + 1]].UnionWith(nodeRange); break; case ILCode.Ret: break; case ILCode.Stloc: { SymbolicValue val = evalContext.Eval(expr.Arguments[0]); if (val.Type == SymbolicValueType.State && val.Constant == 0) { evalContext.AddStateVariable((ILVariable)expr.Operand); goto case ILCode.Nop; } else { goto default; } } case ILCode.Call: // in some cases (e.g. foreach over array) the C# compiler produces a finally method outside of try-finally blocks if (mode == StateRangeAnalysisMode.IteratorDispose) { MethodDefinition mdef = (expr.Operand as MethodReference).ResolveWithinSameModule(); if (mdef == null || finallyMethodToStateInterval.ContainsKey(mdef)) { throw new SymbolicAnalysisFailedException(); } finallyMethodToStateInterval.Add(mdef, nodeRange.ToEnclosingInterval()); break; } else { goto default; } default: if (mode == StateRangeAnalysisMode.IteratorDispose) { throw new SymbolicAnalysisFailedException(); } else { return(i); } } } return(bodyLength); }
/// <summary> /// Initializes the state range logic: /// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue) /// </summary> void InitStateRanges(ILNode entryPoint) { ranges = new DefaultDictionary <ILNode, StateRange>(n => new StateRange()); ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue); rangeAnalysisStateVariable = null; }