public void ExplodedGraph_BothBranchesVisited_NonCondition() { string testInput = "var str = this?.ToString();"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var countConditionEvaluated = 0; explodedGraph.ConditionEvaluated += (sender, args) => { countConditionEvaluated++; }; var visitedBlocks = new HashSet <Block>(); explodedGraph.InstructionProcessed += (sender, args) => { visitedBlocks.Add(args.ProgramPoint.Block); }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(cfg.Blocks.Count() - 1 /* Exit block */, visitedBlocks.Count); Assert.AreEqual(0, countConditionEvaluated); }
public static ControlFlowGraph LiveVariableDeleteDeadCode(ControlFlowGraph cfg) { var newInstructions = new List <Instruction>(); var activeVariable = new LiveVariableAnalysis(); var resActiveVariable = activeVariable.Execute(cfg); foreach (var x in cfg.GetCurrentBasicBlocks().Take(cfg.GetCurrentBasicBlocks().Count - 1).Skip(1)) { var instructionsTemp = x.GetInstructions(); if (resActiveVariable.ContainsKey(x)) { var InOutTemp = resActiveVariable[x]; foreach (var i in instructionsTemp) { if (!InOutTemp.Out.Contains(i.Result) && i.Operation == "assign" && i.Argument1 != i.Result) { if (i.Label != "") { newInstructions.Add(new Instruction(i.Label, "noop", "", "", "")); } } else { newInstructions.Add(i); } } } } return(new ControlFlowGraph(newInstructions)); }
public void LiveVariableTest() { var program = @" var a,b,c,i; for i = 1,b { input (a); c = c + a; print(c); if c < b c = c + 1; else { b = b - 1; print(b); print(c); } } print (c+a+b);"; var graph = GenCFG(program); var algorithm = new LiveVariableAnalysis(); algorithm.Execute(graph); var iterationsFast = algorithm.Iterations; algorithm.Execute(graph, false); var iterationsSlow = algorithm.Iterations; Assert.LessOrEqual(iterationsFast, iterationsSlow); }
public void ExplodedGraph_LoopExploration() { string testInput = "var i = 0; while (i < 1) { i = i + 1; }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var exceeded = 0; explodedGraph.ProgramPointVisitCountExceedLimit += (sender, args) => { exceeded++; args.ProgramPoint.Block.Instructions.Where(i => i.ToString() == "i < 1").Should().NotBeEmpty(); }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, exceeded); }
private void ProcessIdentifier(SyntaxNode instruction, HashSet <SyntaxNode> assignmentLhs, HashSet <ISymbol> liveOut) { var identifier = (IdentifierNameSyntax)instruction; var symbol = context.SemanticModel.GetSymbolInfo(identifier).Symbol; if (!IsSymbolRelevant(symbol)) { return; } if (!identifier.GetSelfOrTopParenthesizedExpression().IsInNameofCall(context.SemanticModel) && LiveVariableAnalysis.IsLocalScoped(symbol, declaration)) { if (LiveVariableAnalysis.IsOutArgument(identifier)) { liveOut.Remove(symbol); } else { if (!assignmentLhs.Contains(identifier)) { liveOut.Add(symbol); } } } }
public static (bool wasChanged, List <Instruction> instructions) LiveVariableDeleteDeadCode(List <Instruction> instructions) { var wasChanged = false; var newInstructions = new List <Instruction>(); var divResult = BasicBlockLeader.DivideLeaderToLeader(newInstructions); var cfg = new ControlFlowGraph(divResult); var activeVariable = new LiveVariableAnalysis(); var resActiveVariable = activeVariable.Execute(cfg); newInstructions = instructions.GetRange(0, instructions.Count - 1); foreach (var x in resActiveVariable) { foreach (var y in x.Value.Out) { if (instructions[instructions.Count - 1].Result != y && instructions[instructions.Count - 1].Operation == "assign" && instructions[instructions.Count - 1].Argument1 != y) { wasChanged = true; } else { return(wasChanged, newInstructions); } } } newInstructions.Add(instructions[instructions.Count - 1]); return(wasChanged, newInstructions); }
public void ReachingDefinitionsTest() { var program = @" var i, m, j, n, a, u1, u2, u3, k; 1: i = m - 1; 2: j = n; 3: a = u1; for k = 0, 1 { i = i + 1; j = j - 1; if i < j a = u2; i = u3; }"; var graph = GenCFG(program); var algorithm = new LiveVariableAnalysis(); algorithm.Execute(graph); var iterationsFast = algorithm.Iterations; algorithm.Execute(graph, false); var iterationsSlow = algorithm.Iterations; Assert.LessOrEqual(iterationsFast, iterationsSlow); }
public void ExplodedGraph_SequentialInput_Max() { var inputBuilder = new StringBuilder(); for (int i = 0; i < ExplodedGraph.MaxStepCount / 2 + 1; i++) { inputBuilder.AppendLine($"var x{i} = true;"); } string testInput = inputBuilder.ToString(); SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var maxStepCountReached = false; explodedGraph.MaxStepCountReached += (sender, args) => { maxStepCountReached = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; explodedGraph.Walk(); Assert.IsFalse(explorationEnded); Assert.IsTrue(maxStepCountReached); Assert.AreEqual(0, numberOfExitBlockReached); }
public static (bool wasChanged, IReadOnlyList <Instruction> instructions) LiveVariableDeleteDeadCode(IReadOnlyList <Instruction> instructions) { var wasChanged = false; var newInstructions = new List <Instruction>(); var divResult = BasicBlockLeader.DivideLeaderToLeader(instructions); var cfg = new ControlFlowGraph(divResult); var activeVariable = new LiveVariableAnalysis(); var resActiveVariable = activeVariable.Execute(cfg); foreach (var x in divResult) { var instructionsTemp = x.GetInstructions(); if (resActiveVariable.ContainsKey(x)) { var InOutTemp = resActiveVariable[x]; foreach (var i in instructionsTemp) { if (!InOutTemp.Out.Contains(i.Result) && i.Operation == "assign" && i.Argument1 != i.Result) { wasChanged = true; if (i.Label != "") { newInstructions.Add(new Instruction(i.Label, "noop", "", "", "")); } } else { newInstructions.Add(i); } } } } return(wasChanged, newInstructions); }
public void ExplodedGraph_SingleBranchVisited_If() { string testInput = "var a = false; bool b; if (a) { b = true; } else { b = false; } a = b;"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfLastInstructionVisits = 0; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = false") { Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False); } if (args.Instruction.ToString() == "b = true") { Assert.Fail("We should never get into this branch"); } if (args.Instruction.ToString() == "b = false") { Assert.IsTrue(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False); Assert.IsNull(args.ProgramState.GetSymbolValue(aSymbol), "a is dead, so there should be no associated value to it."); } if (args.Instruction.ToString() == "a = b") { numberOfLastInstructionVisits++; } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(10, numberOfProcessedInstructions); Assert.AreEqual(1, numberOfExitBlockReached); Assert.AreEqual(1, numberOfLastInstructionVisits); }
public void ExplodedGraph_SequentialInput() { string testInput = "var a = true; var b = false; b = !b; a = (b);"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = true") { Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True); } if (args.Instruction.ToString() == "b = false") { Assert.IsTrue(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False); } if (args.Instruction.ToString() == "b = !b") { Assert.IsFalse(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False); Assert.IsFalse(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.True); } if (args.Instruction.ToString() == "a = (b)") { Assert.AreEqual( args.ProgramState.GetSymbolValue(bSymbol), args.ProgramState.GetSymbolValue(aSymbol)); } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(11, numberOfProcessedInstructions); Assert.AreEqual(1, numberOfExitBlockReached); }
private static void ReportOnAssignment(AssignmentExpressionSyntax assignment, ExpressionSyntax left, ISymbol symbol, ISymbol declaration, HashSet <SyntaxNode> assignmentLhs, HashSet <ISymbol> outState, SyntaxNodeAnalysisContext context) { if (LiveVariableAnalysis.IsLocalScoped(symbol, declaration) && !outState.Contains(symbol)) { var location = GetFirstLineLocationFromToken(assignment.OperatorToken, assignment.Right); context.ReportDiagnostic(Diagnostic.Create(rule, location, symbol.Name)); } assignmentLhs.Add(left); }
private List <(HashSet <string> IN, HashSet <string> OUT)> Execute(List <Instruction> TAC) { var cfg = GenCFG(TAC); var liveAct = new LiveVariableAnalysis(); liveAct.ExecuteInternal(cfg); var listAct = liveAct.dictInOut .Select(x => x.Value) .Select(y => (y.IN as HashSet <string>, y.OUT as HashSet <string>)); return(listAct.ToList()); }
private List <(HashSet <string> IN, HashSet <string> OUT)> Execute(List <Instruction> TAC) { var blocks = BasicBlockLeader.DivideLeaderToLeader(TAC); var cfg = new ControlFlowGraph(blocks); var liveAct = new LiveVariableAnalysis(); liveAct.ExecuteInternal(cfg); var listAct = liveAct.dictInOut .Select(x => x.Value) .Select(y => (y.IN as HashSet <string>, y.OUT as HashSet <string>)); return(listAct.ToList()); }
private static void CheckForDeadStores(CSharpSyntaxNode node, ISymbol declaration, SyntaxNodeAnalysisContext context) { IControlFlowGraph cfg; if (!ControlFlowGraph.TryGet(node, context.SemanticModel, out cfg)) { return; } var lva = LiveVariableAnalysis.Analyze(cfg, declaration, context.SemanticModel); foreach (var block in cfg.Blocks) { CheckCfgBlockForDeadStores(block, lva.GetLiveOut(block), lva.CapturedVariables, node, declaration, context); } }
public void ExplodedGraph_AllBranchesVisited() { string testInput = "int i = 1; switch (i) { case 1: default: cw1(); break; case 2: cw2(); break; }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfCw1InstructionVisits = 0; var numberOfCw2InstructionVisits = 0; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "cw1()") { numberOfCw1InstructionVisits++; } if (args.Instruction.ToString() == "cw2()") { numberOfCw2InstructionVisits++; } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, numberOfExitBlockReached); Assert.AreEqual(1, numberOfCw1InstructionVisits); Assert.AreEqual(1, numberOfCw2InstructionVisits); }
public void ExplodedGraph_SingleBranchVisited_And() { string testInput = "var a = false; if (a && !a) { a = true; }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = !true") { Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False); // Roslyn is clever !true has const value. } if (args.Instruction.ToString() == "!a") { Assert.Fail("We should never get into this branch"); } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, numberOfExitBlockReached); }
private void ProcessPostfixExpression(SyntaxNode instruction, HashSet <ISymbol> liveOut) { var postfixExpression = (PostfixUnaryExpressionSyntax)instruction; var operand = postfixExpression.Operand.RemoveParentheses(); if (operand.IsKind(SyntaxKind.IdentifierName)) { var symbol = context.SemanticModel.GetSymbolInfo(operand).Symbol; if (!IsSymbolRelevant(symbol)) { return; } if (LiveVariableAnalysis.IsLocalScoped(symbol, declaration) && !liveOut.Contains(symbol)) { context.ReportDiagnostic(Diagnostic.Create(rule, postfixExpression.GetLocation(), symbol.Name)); } } }
public void ExplodedGraph_NonLocalSymbolBranching() { string testInput = "if (field) { cw(); }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var fieldSymbol = semanticModel.GetSymbolInfo( method.DescendantNodes().OfType <IdentifierNameSyntax>().First(d => d.Identifier.ToString() == "field")).Symbol; Assert.IsNotNull(fieldSymbol); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "field") { Assert.IsNull(args.ProgramState.GetSymbolValue(fieldSymbol)); } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, numberOfExitBlockReached); }
private static void ReportOnDeadParametersAtEntry(BaseMethodDeclarationSyntax declaration, IMethodSymbol methodSymbol, IImmutableList <IParameterSymbol> noReportOnParameters, SyntaxNodeAnalysisContext context) { if (!declaration.IsKind(SyntaxKind.MethodDeclaration) || declaration.Body == null) { return; } var excludedParameters = noReportOnParameters; if (methodSymbol.IsExtensionMethod) { excludedParameters = excludedParameters.Add(methodSymbol.Parameters.First()); } excludedParameters = excludedParameters.AddRange(methodSymbol.Parameters.Where(p => p.RefKind != RefKind.None)); var candidateParameters = methodSymbol.Parameters.Except(excludedParameters); if (!candidateParameters.Any()) { return; } IControlFlowGraph cfg; if (!ControlFlowGraph.TryGet(declaration.Body, context.SemanticModel, out cfg)) { return; } var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, context.SemanticModel); var liveParameters = lva.GetLiveIn(cfg.EntryBlock).OfType <IParameterSymbol>(); ReportOnUnusedParameters(declaration, candidateParameters.Except(liveParameters).Except(lva.CapturedVariables), MessageDead, context, isRemovable: false); }
public void LiveVariableIterativeTest() { var program = @" var a,b,c; input (b); a = b + 1; if a < c c = b - a; else c = b + a; print (c);" ; var cfg = GenCFG(program); var resActiveVariable = new LiveVariableAnalysis().Execute(cfg); var actual = cfg.GetCurrentBasicBlocks() .Select(z => resActiveVariable[z]) .Select(p => ((IEnumerable <string>)p.In, (IEnumerable <string>)p.Out)) .ToList(); var expected = new List <(IEnumerable <string>, IEnumerable <string>)>() { (new HashSet <string>() { "c" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "c" }, new HashSet <string>() { "a", "b" }), (new HashSet <string>() { "a", "b" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "a", "b" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "c" }, new HashSet <string>() { }), (new HashSet <string>() { }, new HashSet <string>() { }) }; AssertSet(expected, actual); }
public void LiveVariableIterativeTest() { var TAC = GenTAC(@" var a,b,c; input (b); a = b + 1; if a < c c = b - a; else c = b + a; print (c);" ); var cfg = new ControlFlowGraph(BasicBlockLeader.DivideLeaderToLeader(TAC)); var activeVariable = new LiveVariableAnalysis(); var resActiveVariable = activeVariable.Execute(cfg); var In = new HashSet <string>(); var Out = new HashSet <string>(); var actual = new List <(HashSet <string> IN, HashSet <string> OUT)>(); foreach (var x in cfg.GetCurrentBasicBlocks().Select(z => resActiveVariable[z])) { foreach (var y in x.In) { In.Add(y); } foreach (var y in x.Out) { Out.Add(y); } actual.Add((new HashSet <string>(In), new HashSet <string>(Out))); In.Clear(); Out.Clear(); } var expected = new List <(HashSet <string> IN, HashSet <string> OUT)>() { (new HashSet <string>() { "c" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "c" }, new HashSet <string>() { "a", "b" }), (new HashSet <string>() { "a", "b" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "a", "b" }, new HashSet <string>() { "c" }), (new HashSet <string>() { "c" }, new HashSet <string>() { }), (new HashSet <string>() { }, new HashSet <string>() { }) }; AssertSet(expected, actual); }
public void ExplodedGraph_NonDecisionMakingAssignments() { string testInput = "var a = true; a |= false; var b = 42; b++; ++b;"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); SymbolicValue sv = null; var numberOfProcessedInstructions = 0; var branchesVisited = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = true") { branchesVisited++; Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True); } if (args.Instruction.ToString() == "a |= false") { branchesVisited++; Assert.IsNotNull(args.ProgramState.GetSymbolValue(aSymbol)); Assert.IsFalse(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False); Assert.IsFalse(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True); } if (args.Instruction.ToString() == "b = 42") { branchesVisited++; sv = args.ProgramState.GetSymbolValue(bSymbol); Assert.IsNotNull(sv); } if (args.Instruction.ToString() == "b++") { branchesVisited++; var svNew = args.ProgramState.GetSymbolValue(bSymbol); Assert.IsNotNull(svNew); Assert.AreNotEqual(sv, svNew); } if (args.Instruction.ToString() == "++b") { branchesVisited++; var svNew = args.ProgramState.GetSymbolValue(bSymbol); Assert.IsNotNull(svNew); Assert.AreNotEqual(sv, svNew); } }; explodedGraph.Walk(); Assert.AreEqual(11, numberOfProcessedInstructions); Assert.AreEqual(5, branchesVisited); }
public static Common.LiveVariableAnalysis Analyze(IControlFlowGraph controlFlowGraph, ISymbol declaration, SemanticModel semanticModel) { var lva = new LiveVariableAnalysis(controlFlowGraph, declaration, semanticModel); lva.PerformAnalysis(); return lva; }
public void ExplodedGraph_BothBranchesVisited() { string testInput = "var a = false; bool b; if (inParameter) { b = inParameter; } else { b = !inParameter; } a = b;"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var parameters = method.DescendantNodes().OfType <ParameterSyntax>(); var inParameterSymbol = semanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "inParameter")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfLastInstructionVisits = 0; var numberOfProcessedInstructions = 0; var visitedBlocks = new HashSet <Block>(); var branchesVisited = 0; explodedGraph.InstructionProcessed += (sender, args) => { visitedBlocks.Add(args.ProgramPoint.Block); numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = false") { branchesVisited++; Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False); // Roslyn is clever !true has const value. } if (args.Instruction.ToString() == "b = inParameter") { branchesVisited++; Assert.IsTrue(bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState)); Assert.IsTrue(inParameterSymbol.HasConstraint(BoolConstraint.True, args.ProgramState)); } if (args.Instruction.ToString() == "b = !inParameter") { branchesVisited++; // b has value, but not true or false Assert.IsNotNull(args.ProgramState.GetSymbolValue(bSymbol)); Assert.IsFalse(bSymbol.HasConstraint(BoolConstraint.False, args.ProgramState)); Assert.IsFalse(bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState)); Assert.IsTrue(inParameterSymbol.HasConstraint(BoolConstraint.False, args.ProgramState)); } if (args.Instruction.ToString() == "a = b") { branchesVisited++; Assert.IsNull(args.ProgramState.GetSymbolValue(inParameterSymbol)); // not out/ref parameter and LVA says dead numberOfLastInstructionVisits++; } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(4 + 1, branchesVisited); Assert.AreEqual(1, numberOfExitBlockReached, "All variables are dead at the ExitBlock, so whenever we get there, the ExplodedGraph nodes should be the same, " + "and thus should be processed only once."); Assert.AreEqual(2, numberOfLastInstructionVisits); Assert.AreEqual(cfg.Blocks.Count() - 1 /* Exit block */, visitedBlocks.Count); }
public static void Main() { var FileName = @"../../a.txt"; try { var Text = File.ReadAllText(FileName); var scanner = new Scanner(); scanner.SetSource(Text, 0); var parser = new Parser(scanner); var b = parser.Parse(); if (!b) { Console.WriteLine("Error"); } else { Console.WriteLine("Syntax tree built"); var fillParents = new FillParentsVisitor(); parser.root.Visit(fillParents); var pp = new PrettyPrintVisitor(); parser.root.Visit(pp); Console.WriteLine(pp.Text); ASTOptimizer.Optimize(parser); Console.WriteLine("\n\nAfter AST optimizations"); pp = new PrettyPrintVisitor(); parser.root.Visit(pp); Console.WriteLine(pp.Text); Console.WriteLine("\n\nThree address code"); var threeAddrCodeVisitor = new ThreeAddrGenVisitor(); parser.root.Visit(threeAddrCodeVisitor); var threeAddressCode = threeAddrCodeVisitor.Instructions; foreach (var instruction in threeAddressCode) { Console.WriteLine(instruction); } Console.WriteLine("\n\nOptimized three address code"); var optResult = ThreeAddressCodeOptimizer.OptimizeAll(threeAddressCode); foreach (var x in optResult) { Console.WriteLine(x); } Console.WriteLine("\n\nDivided three address code"); var divResult = BasicBlockLeader.DivideLeaderToLeader(optResult); foreach (var x in divResult) { foreach (var y in x.GetInstructions()) { Console.WriteLine(y); } Console.WriteLine("--------------"); } var cfg = new ControlFlowGraph(divResult); Console.WriteLine("\n\n Edge Classification"); Console.WriteLine("----------"); foreach (var pair in cfg.ClassifiedEdges) { Console.WriteLine(pair); } Console.WriteLine("----------"); foreach (var block in cfg.GetCurrentBasicBlocks()) { Console.WriteLine($"{cfg.VertexOf(block)} {block.GetInstructions().First()}"); var children = cfg.GetChildrenBasicBlocks(cfg.VertexOf(block)); var childrenStr = string.Join(" | ", children.Select(v => v.block.GetInstructions().First().ToString())); Console.WriteLine($" children: {childrenStr}"); var parents = cfg.GetParentsBasicBlocks(cfg.VertexOf(block)); var parentsStr = string.Join(" | ", parents.Select(v => v.block.GetInstructions().First().ToString())); Console.WriteLine($" parents: {parentsStr}"); } /// /// LiveVariableAnalysisAlgorithm /// Console.WriteLine("------------"); Console.WriteLine(); var activeVariable = new LiveVariableAnalysis(); var resActiveVariable = activeVariable.Execute(cfg); foreach (var x in resActiveVariable) { foreach (var y in x.Value.In) { Console.WriteLine("In " + y); } Console.WriteLine(); foreach (var y in x.Value.Out) { Console.WriteLine("Out " + y); } } Console.WriteLine(); Console.WriteLine(); Console.WriteLine("NatLoop"); var natLoops = NaturalLoop.GetAllNaturalLoops(cfg); foreach (var x in natLoops) { if (x.Count == 0) { continue; } //Console.WriteLine("Loop"); for (var i = 0; i < x.Count; i++) { Console.WriteLine("NumberBlock:" + i); foreach (var xfrom in x[i].GetInstructions()) { Console.WriteLine(xfrom.ToString()); } } Console.WriteLine(); Console.WriteLine("-------------"); } Console.WriteLine(" \nDone"); } } catch (FileNotFoundException) { Console.WriteLine("File {0} not found", FileName); } catch (LexException e) { Console.WriteLine("Lex Error. " + e.Message); } catch (SyntaxException e) { Console.WriteLine("Syntax Error. " + e.Message); } Console.ReadLine(); }