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);
        }
示例#3
0
            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));
        }