/// <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); }
/// <summary> /// Analize the MoveNext method /// </summary> /// <param name="cfg"></param> /// <param name="pointsToAnalyzer"></param> /// <param name="protectedNodes"></param> /// <returns></returns> DependencyPTGDomain AnalyzeScopeMethod(ControlFlowGraph cfg, SimplePointsToAnalysis pointsToAnalyzer, IEnumerable <ProtectedRowNode> protectedNodes) { var nodeEntry = cfg.Entry.Successors.First(); var nodeExit = cfg.Exit; nodeExit.Successors.Add(nodeEntry); nodeEntry.Predecessors.Add(nodeExit); var rangeAnalysis = new RangeAnalysis(cfg, this.processToAnalyze.MoveNextMethod); var ranges = rangeAnalysis.Analyze(); var exitRange = ranges[cfg.Exit.Id]; var dependencyAnalysis = new IteratorDependencyAnalysis(this.processToAnalyze, this.processToAnalyze.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; var result = resultDepAnalysis[node.Id].Output; if (!this.OutputColumns.Any()) { var thisVariable = result.PTG.Roots.Where(v => v.Name == "this").Single(); var currentTraceables = this.GetTraceablesFromYieldReturn(result).OfType <TraceableTable>(); if (currentTraceables.Any(t => t.TableKind == ProtectedRowKind.Input)) { var inputSchema = processToAnalyze.InputSchema; dependencyAnalysis.CopyRow(result, thisVariable, inputSchema, inputTable, outputTable); } } return(result); }
/// 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) { callInfo.CallerState.Dependencies.IsTop = true; AnalysisStats.AddAnalysisReason(new AnalysisReason(callInfo.Caller, callInfo.Instruction, String.Format(CultureInfo.InvariantCulture, "Reach maximum call depth {0}", callInfo.Callee.Name))); 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); //Console.WriteLine("Analyzing Method {0} Stack: {1}", new string(' ',stackDepth*2) + callInfo.Callee.ToString(), 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); SimplePointsToAnalysis calleePTA = new SimplePointsToAnalysis(calleeCFG, callInfo.Callee, calleePTG); IDictionary <IVariable, IExpression> equalities = new Dictionary <IVariable, IExpression>(); calleeCFG.PropagateExpressions(equalities); // 2) Bind Parameters of the dependency analysis VariableRangeDomain boundVariablesRanges; var calleeDomain = BindCallerCallee(callInfo, out boundVariablesRanges); var rangesAnalysis = new RangeAnalysis(calleeCFG, callInfo.Callee, boundVariablesRanges); // 4) Now we perform the analyses rangesAnalysis.Analyze(); calleeDomain.PTG = calleePTG; var dependencyAnalysis = new IteratorDependencyAnalysis(processToAnalyze, 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, rangesAnalysis); // 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) { InputColumns = dependencyAnalysis.InputColumns, OutputColumns = dependencyAnalysis.OutputColumns }); //return new InterProceduralReturnInfo(exitResult, bindPtg); }