public void BodyWithSingleInvocation() { var invokerSource = @"var a = 10; Method(a);"; var invokerCfg = CreateControlFlowGraph(invokerSource); var methodSource = @" class Test { private void Method(int x) { } }"; var semanticModel = DocumentFactory.Create().CreateSemanticModel(methodSource); var methodCode = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var methodCfg = ControlFlowGraphFactory.Create(methodCode, "Method", true); var procedureCfgs = new Dictionary <string, ControlFlowGraph> { { "Method", methodCfg } }; var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); Assert.AreEqual(4, callGraph.Edges.Count); Assert.IsTrue(callGraph.Edges.Any(edge => edge.From is FlowInvocation && _IsExpectedTransfer(edge.To, "<root>", "Method", true, false))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedTransfer(edge.From, "<root>", "Method", true, false) && _IsExpectedBoundary(edge.To, "Method", FlowKind.Start))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedBoundary(edge.From, "Method", FlowKind.End) && _IsExpectedTransfer(edge.To, "Method", "<root>", false, true))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedTransfer(edge.From, "Method", "<root>", false, true) && edge.To is FlowInvocation)); Debug.WriteLine(new[] { invokerCfg }.Concat(procedureCfgs.Values).ToDot(callGraph)); }
public void BodyWithoutInvocations() { var invokerSource = @"var a = 10;"; var invokerCfg = CreateControlFlowGraph(invokerSource); var procedureCfgs = new Dictionary <string, ControlFlowGraph>(); var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); Assert.AreEqual(0, callGraph.Edges.Count); }
private bool _HasConflictingArrayAccesses(TLoopStatementSyntax loopStatement, string loopIndex, Code code, VariableAccesses variableAccesses) { var optimized = OptimizationRunner.Optimize(code); code = optimized.Code; variableAccesses = optimized.Changed ? VariableAccesses.Collect(code) : variableAccesses; var cfg = ControlFlowGraphFactory.Create(code, true); var callGraph = CallGraphFactory.Create(cfg, _methods); var calledMethods = callGraph.Methods.Select(methodName => _methods[methodName]).ToImmutableList(); var aliasAnalysis = AliasAnalysis.Analyze(cfg, callGraph, _methods.Values, _GetAliasesAtLoopEntry(loopStatement, variableAccesses)); return(ArrayAccessVerifier.HasConflictingAccesses(loopIndex, cfg, aliasAnalysis, callGraph, calledMethods)); }
public void LoopIndexLostThroughRecursion() { var invokerSource = @"Method(i);"; var invokerCfg = CreateControlFlowGraph(invokerSource); var methodSource = @" class Test { private int Method(int x) { if(x > 0) { return Method(x - 1); } return x; } }"; var semanticModel = DocumentFactory.Create().CreateSemanticModel(methodSource); var methodCode = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var methodCfg = ControlFlowGraphFactory.Create(methodCode, "Method", true); var procedureCfgs = new Dictionary <string, ControlFlowGraph> { { "Method", methodCfg } }; var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); var analysis = LoopDependenceAnalysis.Analyze(invokerCfg, "i", callGraph, procedureCfgs.Values); // Outer body Assert.AreEqual(4, analysis.Entry[invokerCfg.Start].Count); Assert.AreEqual("{i != 0, i@, i|, i+}", GetString(analysis.Entry[invokerCfg.Start])); Assert.AreEqual(10, analysis.Exit[invokerCfg.End].Count); Assert.AreEqual("{$arg_Method_0 != 0, $arg_Method_0@, $arg_Method_0|, $arg_Method_0+, $result_Method@, $result_Method@, i != 0, i@, i|, i+}", GetString(analysis.Exit[invokerCfg.End])); // invoked method Assert.AreEqual(2, analysis.Entry[methodCfg.Start].Count); Assert.AreEqual("{$arg_Method_0@, $arg_Method_0@}", GetString(analysis.Entry[methodCfg.Start])); Debug.WriteLine(GetString(analysis.Exit[methodCfg.End])); Assert.AreEqual(5, analysis.Exit[methodCfg.End].Count); Assert.AreEqual("{$arg_Method_0@, $arg_Method_0@, $result_Method@, $result_Method@, x@}", GetString(analysis.Exit[methodCfg.End])); }
public void LoopIndexAndRegularPassingWithExchangeRemovesInformation() { var invokerSource = @"var a = 0; var b = Recursive(i, a);"; var invokerCfg = CreateControlFlowGraph(invokerSource); var methodSource = @" class Test { private void Recursive(int x, int y) { if(x > y) { Recursive(y, x); } return x; } }"; var semanticModel = DocumentFactory.Create().CreateSemanticModel(methodSource); var methodCode = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var methodCfg = ControlFlowGraphFactory.Create(methodCode, "Recursive", true); var procedureCfgs = new Dictionary <string, ControlFlowGraph> { { "Recursive", methodCfg } }; var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); var analysis = LoopDependenceAnalysis.Analyze(invokerCfg, "i", callGraph, procedureCfgs.Values); // Outer body Assert.AreEqual(4, analysis.Entry[invokerCfg.Start].Count); Assert.AreEqual("{i != 0, i@, i|, i+}", GetString(analysis.Entry[invokerCfg.Start])); Assert.AreEqual(16, analysis.Exit[invokerCfg.End].Count); Assert.AreEqual("{$arg_Recursive_0 != 0, $arg_Recursive_0@, $arg_Recursive_0|, $arg_Recursive_0+, $arg_Recursive_1 = 0, $arg_Recursive_1/, $arg_Recursive_1@, $result_Recursive@, a = 0, a/, a@, b@, i != 0, i@, i|, i+}", GetString(analysis.Exit[invokerCfg.End])); // invoked method Assert.AreEqual(4, analysis.Entry[methodCfg.Start].Count); Assert.AreEqual("{$arg_Recursive_0@, $arg_Recursive_0@, $arg_Recursive_1@, $arg_Recursive_1@}", GetString(analysis.Entry[methodCfg.Start])); Assert.AreEqual(7, analysis.Exit[methodCfg.End].Count); Assert.AreEqual("{$arg_Recursive_0@, $arg_Recursive_0@, $arg_Recursive_1@, $arg_Recursive_1@, $result_Recursive@, x@, y@}", GetString(analysis.Exit[methodCfg.End])); }
public void LoopIndexPassingToSingleArgumentWithReturnValue() { var invokerSource = @"var a = Method(i);"; var invokerCfg = CreateControlFlowGraph(invokerSource); var methodSource = @" class Test { private void Method(int x) { return x; } }"; var semanticModel = DocumentFactory.Create().CreateSemanticModel(methodSource); var methodCode = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var methodCfg = ControlFlowGraphFactory.Create(methodCode, "Method", true); var procedureCfgs = new Dictionary <string, ControlFlowGraph> { { "Method", methodCfg } }; var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); var analysis = LoopDependenceAnalysis.Analyze(invokerCfg, "i", callGraph, procedureCfgs.Values); // Outer body Assert.AreEqual(4, analysis.Entry[invokerCfg.Start].Count); Assert.AreEqual("{i != 0, i@, i|, i+}", GetString(analysis.Entry[invokerCfg.Start])); Assert.AreEqual(16, analysis.Exit[invokerCfg.End].Count); Assert.AreEqual("{$arg_Method_0 != 0, $arg_Method_0@, $arg_Method_0|, $arg_Method_0+, $result_Method != 0, $result_Method@, $result_Method|, $result_Method+, a != 0, a@, a|, a+, i != 0, i@, i|, i+}", GetString(analysis.Exit[invokerCfg.End])); // invoked method Assert.AreEqual(4, analysis.Entry[methodCfg.Start].Count); Assert.AreEqual("{$arg_Method_0 != 0, $arg_Method_0@, $arg_Method_0|, $arg_Method_0+}", GetString(analysis.Entry[methodCfg.Start])); Assert.AreEqual(12, analysis.Exit[methodCfg.End].Count); Assert.AreEqual("{$arg_Method_0 != 0, $arg_Method_0@, $arg_Method_0|, $arg_Method_0+, $result_Method != 0, $result_Method@, $result_Method|, $result_Method+, x != 0, x@, x|, x+}", GetString(analysis.Exit[methodCfg.End])); }
public void NestedRecursion() { var invokerSource = @"var a = 10; Recursive1(a);"; var invokerCfg = CreateControlFlowGraph(invokerSource); var methodSource = @" class Test { private void Recursive1(int x) { Recursive2(x); } private void Recursive2(int x) { if(x > 0) { Recursive1(x - 1); } } }"; var semanticModel = DocumentFactory.Create().CreateSemanticModel(methodSource); var recursive1Code = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Where(declaration => declaration.Identifier.Text.Equals("Recursive1")) .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var recursive2Code = semanticModel.SyntaxTree.GetRoot().DescendantNodes() .OfType <MethodDeclarationSyntax>() .Where(declaration => declaration.Identifier.Text.Equals("Recursive2")) .Select(declaration => CodeFactory.CreateMethod(declaration, semanticModel)) .Single(); var recursive1Cfg = ControlFlowGraphFactory.Create(recursive1Code, "Recursive1", true); var recursive2Cfg = ControlFlowGraphFactory.Create(recursive2Code, "Recursive2", true); var procedureCfgs = new Dictionary <string, ControlFlowGraph> { { "Recursive1", recursive1Cfg }, { "Recursive2", recursive2Cfg } }; var callGraph = CallGraphFactory.Create(invokerCfg, procedureCfgs); Assert.AreEqual(12, callGraph.Edges.Count); // Initial call Assert.IsTrue(callGraph.Edges.Any(edge => edge.From is FlowInvocation && _IsExpectedTransfer(edge.To, "<root>", "Recursive1", true, false))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedTransfer(edge.From, "<root>", "Recursive1", true, false) && _IsExpectedBoundary(edge.To, "Recursive1", FlowKind.Start))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedBoundary(edge.From, "Recursive1", FlowKind.End) && _IsExpectedTransfer(edge.To, "Recursive1", "<root>", false, true))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedTransfer(edge.From, "Recursive1", "<root>", false, true) && edge.To is FlowInvocation)); // Recursive 1 call Assert.IsTrue(callGraph.Edges.Any(edge => edge.From is FlowInvocation && _IsExpectedTransfer(edge.To, "Recursive1", "Recursive2", true, false))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedTransfer(edge.From, "Recursive1", "Recursive2", true, false) && _IsExpectedBoundary(edge.To, "Recursive2", FlowKind.Start))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedBoundary(edge.From, "Recursive2", FlowKind.End) && _IsExpectedTransfer(edge.To, "Recursive2", "Recursive1", false, true))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedTransfer(edge.From, "Recursive2", "Recursive1", false, true) && edge.To is FlowInvocation)); // Recursive 2 call Assert.IsTrue(callGraph.Edges.Any(edge => edge.From is FlowInvocation && _IsExpectedTransfer(edge.To, "Recursive2", "Recursive1", true, false))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedTransfer(edge.From, "Recursive2", "Recursive1", true, false) && _IsExpectedBoundary(edge.To, "Recursive1", FlowKind.Start))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedBoundary(edge.From, "Recursive1", FlowKind.End) && _IsExpectedTransfer(edge.To, "Recursive1", "Recursive2", false, true))); Assert.IsTrue(callGraph.Edges.Any(edge => _IsExpectedTransfer(edge.From, "Recursive1", "Recursive2", false, true) && edge.To is FlowInvocation)); Debug.WriteLine(new[] { invokerCfg }.Concat(procedureCfgs.Values).ToDot(callGraph)); }