private AbstractStackState <VariabilityInfo> UpdateStackState(ILInstruction ili, VariabilityInfo newVar, AbstractStackState <VariabilityInfo> cur) { MethodFacts myFacts = FactUniverse.Instance.GetFacts(Method); foreach (LocalMutation lm in myFacts.GetLocalMutations(ili.Index)) { IModifiesStackState mss = lm as IModifiesStackState; if (mss != null) { cur = mss.ModifyStackState(cur, newVar, VariabilityInfo.MergeDefs); } } return(cur); }
/// <summary> /// Executes the analysis. /// </summary> public virtual void Run() { Contract.Requires(!AnalysisDone); Contract.Ensures(AnalysisDone); MethodFacts myFacts = FactUniverse.Instance.GetFacts(Method); CFG = myFacts.CFG; _stackStates = new AbstractStackState <TElem> [CFG.Instructions.Count]; AbstractStackState <TElem> initial = CreateInitialStackState(); Queue <Tuple <AbstractStackState <TElem>, ILInstruction> > q = new Queue <Tuple <AbstractStackState <TElem>, ILInstruction> >(); q.Enqueue(Tuple.Create(initial, CFG.Instructions[0])); int marshal = CFG.Instructions.Count - 1; while (q.Count > 0) { Tuple <AbstractStackState <TElem>, ILInstruction> cur = q.Dequeue(); AbstractStackState <TElem> preState = cur.Item1; ILInstruction ili = cur.Item2; AbstractStackState <TElem> nextState = Propagate(ili, preState); ILInstruction[] succs = CFG.GetSuccessorsOf(ili); if (_stackStates[ili.Index] == null) { _stackStates[ili.Index] = nextState; } else { bool changed = Merge(_stackStates[ili.Index], nextState, out _stackStates[ili.Index]); if (!changed) { continue; } } foreach (ILInstruction nextILI in succs) { if (nextILI.Index < marshal) // skip pseudo ret at the end { q.Enqueue(Tuple.Create(_stackStates[ili.Index], nextILI)); } } } AnalysisDone = true; }
private AbstractStackState <VariabilityInfo> HandleCall(ILInstruction ili, AbstractStackState <VariabilityInfo> pre, bool isCalli) { MethodBase callee = (MethodBase)ili.Operand; bool hasThis = callee.CallingConvention.HasFlag(CallingConventions.HasThis); EVariability callVar = EVariability.Constant; ParameterInfo[] args = callee.GetParameters(); MethodFacts myFacts = FactUniverse.Instance.GetFacts(Method); MethodFacts calleeFacts = FactUniverse.Instance.GetFacts(callee); AbstractStackState <VariabilityInfo> next = pre; if (hasThis) { callVar = VariabilityOperations.Stronger(callVar, pre[0].Variability); next = pre.Pop(); } for (int i = 0; i < args.Length; i++) { callVar = VariabilityOperations.Stronger(callVar, next[0].Variability); next = next.Pop(); } if (!calleeFacts.IsSideEffectFree) { callVar = EVariability.ExternVariable; } if (calleeFacts.IsStaticEvaluation) { callVar = EVariability.Constant; } if (isCalli) { next = pre.Pop(); } VariabilityInfo callVarI = VariabilityInfo.CreateBySingleDef(callVar, ili.Index); next = UpdateStackState(ili, callVarI, next); Type returnType; if (callee.IsFunction(out returnType)) { next = next.Push(callVarI); } return(next.UniqueSuccessor()); }
private AbstractStackState <VariabilityInfo> HandleLdArg(ILInstruction ili, int narg, AbstractStackState <VariabilityInfo> pre) { MethodFacts myFacts = FactUniverse.Instance.GetFacts(Method); EVariability varia; if (Method.CallingConvention.HasFlag(CallingConventions.HasThis)) { if (narg == 0) { varia = EVariability.Constant; } else { varia = _callPattern.Pattern[narg - 1]; } } else { varia = _callPattern.Pattern[narg]; } return(pre.Push(VariabilityInfo.CreateBySingleDef(varia, ili.Index)).UniqueSuccessor()); }