/// <summary> /// Analize the MoveNext method /// </summary> /// <param name="cfg"></param> /// <param name="pointsToAnalyzer"></param> /// <param name="protectedNodes"></param> /// <returns></returns> DependencyPTGDomain AnalyzeScopeMethod(ControlFlowGraph cfg, IteratorPointsToAnalysis pointsToAnalyzer, IEnumerable <ProtectedRowNode> protectedNodes) { // Before I did Points-to analysis beforehand the dependnecy analysis. Now I compute then together ////var iteratorAnalysis = new IteratorStateAnalysis(cfg, ptgs, this.equalities); ////var result = iteratorAnalysis.Analyze(); //// var dependencyAnalysis = new IteratorDependencyAnalysis(this.moveNextMethod, cfg, ptgs, this.specialFields , this.equalities); //var nodeEntry = cfg.Entry.Successors.First(); //var nodeExit = cfg.NormalExit; //nodeExit.NormalSuccessors.Add(nodeEntry); //nodeEntry.Predecessors.Add(nodeExit); var rangeAnalysis = new RangeAnalysis(cfg); var ranges = rangeAnalysis.Analyze(); var exitRange = ranges[cfg.Exit.Id]; var dependencyAnalysis = new IteratorDependencyAnalysis(this.moveNextMethod, cfg, pointsToAnalyzer, protectedNodes, this.equalities, this.interprocManager, rangeAnalysis); var resultDepAnalysis = dependencyAnalysis.Analyze(); //dependencyAnalysis.SetPreviousResult(resultDepAnalysis); //resultDepAnalysis = dependencyAnalysis.Analyze(); var node = cfg.Exit; System.Console.Out.WriteLine("At {0}\nBefore {1}\nAfter {2}\n", node.Id, resultDepAnalysis[node.Id].Input, resultDepAnalysis[node.Id].Output); this.InputColumns = dependencyAnalysis.InputColumns; this.OutputColumns = dependencyAnalysis.OutputColumns; return(resultDepAnalysis[node.Id].Output); }
public DependencyPTGDomain AnalyzeMoveNextMethod() { // 1) Analyze the entry method that creates, populates and return the clousure var cfgEntry = entryMethod.DoAnalysisPhases(host); var pointsToEntry = new IteratorPointsToAnalysis(cfgEntry, this.entryMethod); // , this.specialFields); var entryResult = pointsToEntry.Analyze(); var ptgOfEntry = entryResult[cfgEntry.Exit.Id].Output; // 2) Call the GetEnumerator that may create a new clousure and polulate it var myGetEnumResult = new LocalVariable("$_temp_it") { Type = getEnumMethod.ReturnType }; ptgOfEntry.Add(myGetEnumResult); var ptgAfterEnum = this.interprocManager.PTAInterProcAnalysis(ptgOfEntry, new List <IVariable> { pointsToEntry.ReturnVariable }, myGetEnumResult, this.getEnumMethod); // These are the nodes that we want to protect/analyze var protectedNodes = ptgOfEntry.Nodes.OfType <ParameterNode>() .Where(n => IsScopeType(n.Type)).Select(n => new ProtectedRowNode(n, ProtectedRowNode.GetKind(n.Type))); // I no longer need this. //var specialFields = cfgEntry.ForwardOrder[1].Instructions.OfType<StoreInstruction>() // .Where(st => st.Result is InstanceFieldAccess).Select(st => new KeyValuePair<string,IVariable>((st.Result as InstanceFieldAccess).FieldName,st.Operand) ); //this.specialFields = specialFields.ToDictionary(item => item.Key, item => item.Value); // 3) I bing the current PTG with the parameters of MoveNext method on the clousure // Well... Inlining is broken we we added the Exceptional control graph. Let's avoid it //var cfg = this.moveNextMethod.DoAnalysisPhases(host, this.GetMethodsToInline()); var cfg = this.interprocManager.GetCFG(this.moveNextMethod); PropagateExpressions(cfg, this.equalities); // In general, the variable to bind is going to be pointsToEntry.ReturnVariable which is aliased with "$_temp_it" (myGetEnumResult) SimplePointsToGraph calleePTG = InterproceduralManager.PTABindCallerCallee(ptgAfterEnum, new List <IVariable> { myGetEnumResult }, this.moveNextMethod); this.pointsToAnalyzer = new IteratorPointsToAnalysis(cfg, this.moveNextMethod, calleePTG); //this.pta= this.interprocManager.PTABindAndRunInterProcAnalysis(ptgAfterEnum, new List<IVariable> { myGetEnumResult }, this.moveNextMethod, cfg); //var pointsTo = new IteratorPointsToAnalysis(cfg, this.moveNextMethod, this.specialFields); //this.ptAnalysisResult = pointsTo.Analyze(); // var pointsTo = new IteratorPointsToAnalysis(cfg, this.moveNextMethod, this.specialFields, ptgOfEntry); // Now I analyze the Movenext method with the proper initialization var result = this.AnalyzeScopeMethod(cfg, pointsToAnalyzer, protectedNodes); return(result); }
public IteratorPointsToAnalysis PTABindAndRunInterProcAnalysis(SimplePointsToGraph ptg, IList <IVariable> arguments, MethodDefinition resolvedCallee, ControlFlowGraph calleeCFG) { var bindPtg = PTABindCallerCallee(ptg, arguments, resolvedCallee); // Compute PT analysis for callee var pta = new IteratorPointsToAnalysis(calleeCFG, resolvedCallee, bindPtg); pta.Analyze(); return(pta); }
/// This does the interprocedural analysis. /// It (currently) does NOT support recursive method invocations /// </summary> /// <param name="instruction"></param> /// <param name="resolvedCallee"></param> /// <param name="calleeCFG"></param> public SimplePointsToGraph PTAInterProcAnalysis(SimplePointsToGraph ptg, IList <IVariable> arguments, IVariable result, MethodDefinition resolvedCallee) { if (resolvedCallee.Body.Instructions.Any()) { ControlFlowGraph calleeCFG = this.GetCFG(resolvedCallee); //DGMLSerializer.Serialize(calleeCFG); stackDepth++; IteratorPointsToAnalysis pta = this.PTABindAndRunInterProcAnalysis(ptg, arguments, resolvedCallee, calleeCFG); stackDepth--; return(PTABindCaleeCalleer(result, calleeCFG, pta)); } return(ptg); }
private SimplePointsToGraph PTABindCaleeCalleer(IVariable result, ControlFlowGraph calleeCFG, IteratorPointsToAnalysis pta) { var exitPTG = pta.Result[calleeCFG.Exit.Id].Output; if (result != null) { exitPTG.RestoreFrame(pta.ReturnVariable, result); } else { exitPTG.RestoreFrame(); } return(exitPTG); }
/// This does the interprocedural analysis. /// It (currently) does NOT support recursive method invocations /// </summary> /// <param name="instruction"></param> /// <param name="resolvedCallee"></param> /// <param name="calleeCFG"></param> private InterProceduralReturnInfo InterproceduralAnalysis(InterProceduralCallInfo callInfo, ControlFlowGraph calleeCFG) { if (stackDepth > InterproceduralManager.MaxStackDepth) { return(new InterProceduralReturnInfo(callInfo.CallerState)); } stackDepth++; // I currently do not support recursive calls // Will add support for this in the near future if (callStack.Contains(callInfo.Callee)) { callInfo.CallerState.Dependencies.IsTop = true; AnalysisStats.AddAnalysisReason(new AnalysisReason(callInfo.Caller, callInfo.Instruction, String.Format(CultureInfo.InvariantCulture, "Recursive call to {0}", callInfo.Callee.Name))); return(new InterProceduralReturnInfo(callInfo.CallerState)); } this.callStack.Push(callInfo.Callee); System.Console.WriteLine("Analyzing Method {0} Stack: {1}", new string(' ', stackDepth * 2) + callInfo.Callee.ToSignatureString(), stackDepth); // 1) Bind PTG and create a Poinst-to Analysis for the callee. In pta.Result[node.Exit] is the PTG at exit of the callee var calleePTG = PTABindCallerCallee(callInfo.CallerPTG, callInfo.CallArguments, callInfo.Callee); IteratorPointsToAnalysis calleePTA = new IteratorPointsToAnalysis(calleeCFG, callInfo.Callee, calleePTG); IDictionary <IVariable, IExpression> equalities = new Dictionary <IVariable, IExpression>(); SongTaoDependencyAnalysis.PropagateExpressions(calleeCFG, equalities); var rangesAnalysis = new RangeAnalysis(calleeCFG); rangesAnalysis.Analyze(); // 2) Bind Parameters of the dependency analysis and run var calleeDomain = BindCallerCallee(callInfo); calleeDomain.PTG = calleePTG; var dependencyAnalysis = new IteratorDependencyAnalysis(callInfo.Callee, calleeCFG, calleePTA, callInfo.ProtectedNodes, equalities, this, rangesAnalysis, calleeDomain, callInfo.ScopeData); // If we already did the dataflow analysis for this method we recover the dataflow state // This should be adapted (or removed) if we want the analysis to be context sensitive //if (dataflowCache.ContainsKey(callInfo.Callee)) //{ // var previosResult = dataflowCache[callInfo.Callee]; // //DataFlowAnalysisResult<DependencyPTGDomain>[] resultsCopy = new DataFlowAnalysisResult<DependencyPTGDomain>[previosResult.Length]; // //for(int i=0; i< previosResult.Length; i++) // //{ // // resultsCopy[i] = new DataFlowAnalysisResult<DependencyPTGDomain>(); // // resultsCopy[i].Input = previosResult[i].Input!=null? previosResult[i].Input.Clone(): null; // // resultsCopy[i].Output = previosResult[i].Output!=null? previosResult[i].Output.Clone(): null; // //} // //dependencyAnalysis.SetPreviousResult(resultsCopy); // dependencyAnalysis.SetPreviousResult(previosResult); //} dependencyAnalysis.Analyze(); this.dataflowCache[callInfo.Callee] = dependencyAnalysis.Result; stackDepth--; this.callStack.Pop(); // 3) Bind callee with caller // Should I need the PTG of caller and callee? //var exitCalleePTG = calleePTA.Result[calleeCFG.Exit.Id].Output; var exitCalleePTG = dependencyAnalysis.Result[calleeCFG.Exit.Id].Output.PTG; var exitResult = BindCalleeCaller(callInfo, calleeCFG, dependencyAnalysis); // Recover the frame of the original Ptg and bind ptg results //PointsToGraph bindPtg = PTABindCaleeCalleer(callInfo.CallLHS, calleeCFG, calleePTA); var bindPtg = PTABindCaleeCalleer(callInfo.CallLHS, calleeCFG, exitCalleePTG, calleePTA.ReturnVariable); exitResult.PTG = bindPtg; return(new InterProceduralReturnInfo(exitResult)); //return new InterProceduralReturnInfo(exitResult, bindPtg); }