public static bool TryGet(CSharpSyntaxNode node, SemanticModel semanticModel, out IControlFlowGraph cfg)
        {
            cfg = null;
            try
            {
                if (node != null)
                {
                    cfg = Create(node, semanticModel);
                }
                else
                {
                    return false;
                }
            }
            catch (Exception exc) when (exc is InvalidOperationException ||
                                        exc is ArgumentException ||
                                        exc is NotSupportedException)
            {
                // These are expected
            }
            catch (Exception exc) when (exc is NotImplementedException)
            {
                Debug.Fail(exc.ToString());
            }

            return cfg != null;
        }
示例#2
0
        protected AbstractExplodedGraph(IControlFlowGraph cfg, ISymbol declaration, SemanticModel semanticModel, AbstractLiveVariableAnalysis lva)
        {
            this.cfg         = cfg;
            this.declaration = declaration;
            this.lva         = lva;

            SemanticModel = semanticModel;

            this.declarationParameters      = declaration.GetParameters();
            this.nonInDeclarationParameters = this.declarationParameters.Where(p => p.RefKind != RefKind.None);
        }
示例#3
0
        public static string ToDot(this IControlFlowGraph graph)
        {
            var sb = new StringBuilder();

            sb.AppendLine("digraph {");
            sb.AppendLine("  node [fontsize = \"12\"];");
            sb.AppendLine("  edge [fontsize = \"8\"];");

            // Add root node
            var root = graph.Vertices.Single(a => a.Type == BasicBlockType.Entry);

            sb.AppendLine($"  {ID(root.ID)} [label=\"entry\" shape=circle rank=min];");
示例#4
0
        /// <summary>
        /// Removed error/continue edges which we know cannot happen due to type info
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="types"></param>
        /// <returns></returns>
        public static IControlFlowGraph TypeDrivenEdgeTrimming(this IControlFlowGraph graph, ITypeAssignments types)
        {
            return(graph.Trim(edge => {
                // Find last statement in previous block
                var stmt = edge.Start.Statements.LastOrDefault();
                var tass = stmt as TypedAssignment;
                var err = stmt as ErrorStatement;

                // If type is unassigned we can't make a judgement
                if (tass?.Type == Execution.Type.Unassigned)
                {
                    return true;
                }

                if (edge.Type == EdgeType.RuntimeError)
                {
                    // If it's an error statement keep it
                    if (err != null)
                    {
                        return true;
                    }

                    // If there is no statement at all then it can't be an error
                    if (tass == null)
                    {
                        return false;
                    }

                    // Only keep edge if type has an error
                    return tass.Type.HasFlag(Execution.Type.Error);
                }
                else
                {
                    // If it's an error statement remove it
                    if (err != null)
                    {
                        return false;
                    }

                    // If there is no typed assignment we can't judge
                    if (tass == null)
                    {
                        return true;
                    }

                    return tass.Type != Execution.Type.Error;
                }
            }));
        }
示例#5
0
 [NotNull] private static IControlFlowGraph RemoveTypeAssignments([NotNull] this IControlFlowGraph graph)
 {
     return(graph.Modify((a, b) => {
         foreach (var stmt in a.Statements)
         {
             if (stmt is TypedAssignment tass)
             {
                 b.Add(new Assignment(tass.Left, tass.Right));
             }
             else
             {
                 b.Add(stmt);
             }
         }
     }));
 }
示例#6
0
        /// <summary>
        /// Find variables which are guaranteed to be `0` or `1`
        /// </summary>
        /// <param name="cfg"></param>
        /// <param name="ssa"></param>
        /// <param name="types"></param>
        /// <returns></returns>
        [NotNull] public static ISet <VariableName> FindBooleanVariables([NotNull] this IControlFlowGraph cfg, ISingleStaticAssignmentTable ssa, ITypeAssignments types)
        {
            var booleans = new HashSet <VariableName>();

            // Keep finding more constants until no more are found
            var count = -1;

            while (count != booleans.Count)
            {
                count = booleans.Count;
                cfg.VisitBlocks(() => new FindBooleanVariables(booleans, ssa, types));
            }

            var result = new HashSet <VariableName>(booleans.Where(n => !n.IsExternal));

            return(result);
        }
示例#7
0
        private static HashSet <IControlFlowEdge> GetEdges(IControlFlowGraph graph)
        {
            var edges = new HashSet <IControlFlowEdge>(new EdgeEqualityComparer());

            foreach (var element in graph.AllElements)
            {
                foreach (var edge in element.Exits)
                {
                    edges.Add(edge);
                }
                foreach (var edge in element.Entries)
                {
                    edges.Add(edge);
                }
            }
            return(FudgeGraph(graph, edges));
        }
示例#8
0
        public static IReadOnlyCollection <VariableName> FindUnreadAssignments(this IControlFlowGraph cfg)
        {
            var assigned = new FindAssignedVariables();
            var read     = new FindReadVariables();

            foreach (var bb in cfg.Vertices)
            {
                assigned.Visit(bb);
                read.Visit(bb);
            }

            var result = new HashSet <VariableName>(assigned.Names.Where(n => !n.IsExternal));

            result.ExceptWith(read.Names);

            return(result);
        }
示例#9
0
        /// <summary>
        /// Replace expressions which result in a constant with the result
        /// </summary>
        /// <param name="cfg"></param>
        /// <param name="ssa"></param>
        /// <returns></returns>
        [NotNull] public static IControlFlowGraph FoldConstants([NotNull] this IControlFlowGraph cfg, ISingleStaticAssignmentTable ssa)
        {
            // Keep finding and replacing constants until nothing is found
            cfg = cfg.Fixpoint(c => {
                // Find variables which are assigned a value which is not tainted by external reads
                var constants = c.FindConstants(ssa);

                // Replace reads of a constant variable with the expression assigned to that variable
                c = c.VisitBlocks(() => new ReplaceConstantSubexpressions(constants));

                return(c);
            });

            // Replace constant subexpressions with their value
            cfg = cfg.VisitBlocks(() => new ConstantFoldingVisitor(true));

            return(cfg);
        }
示例#10
0
        /// <summary>
        /// Copy graph and modify vertices
        /// </summary>
        /// <param name="input"></param>
        /// <param name="copy"></param>
        /// <returns></returns>
        [NotNull] public static IMutableControlFlowGraph Modify([NotNull] this IControlFlowGraph input, [NotNull] Action <IBasicBlock, IMutableBasicBlock> copy)
        {
            var cfg = new ControlFlowGraph();

            // Copy vertices (but leave empty)
            var replacementVertices = input.CloneVertices(cfg, __ => true, (___, ____) => { });

            // Copy edges
            var _ = input.CloneEdges(cfg, replacementVertices, __ => true);

            // Apply clone function to vertices
            foreach (var(key, value) in replacementVertices)
            {
                copy(key, value);
            }

            return(cfg);
        }
示例#11
0
        [NotNull] public static IMutableControlFlowGraph Modify([NotNull] this IControlFlowGraph input, [NotNull] Action <IEdge, Action <IBasicBlock, IBasicBlock, EdgeType> > copy)
        {
            var cfg = new ControlFlowGraph();

            // Copy vertices
            var replacementVertices = input.CloneVertices(cfg, __ => true);

            // Copy edges
            foreach (var edge in input.Edges)
            {
                copy(edge, (s, e, t) => {
                    var ss = replacementVertices[s];
                    var ee = replacementVertices[e];
                    cfg.CreateEdge(ss, ee, t);
                });
            }

            return(cfg);
        }
示例#12
0
        private static HashSet <IControlFlowEdge> FudgeGraph(IControlFlowGraph graph, HashSet <IControlFlowEdge> edges)
        {
            // The C# graph treats the unary negation operator `!` as a conditional. It's not,
            // but having it so means that the CC can be way higher than it should be.
            var dodgyEdges = new HashSet <IControlFlowEdge>(new EdgeEqualityComparer());

            // Look at all of the non-leaf elements (the graph is a tree as well as a graph.
            // The tree represents the structure of the code, with the control flow graph
            // running through it)
            foreach (var element in graph.AllElements.Where(e => e.Children.Count != 0))
            {
                var unaryOperatorExpression = element.SourceElement as IUnaryOperatorExpression;
                if (unaryOperatorExpression != null && unaryOperatorExpression.UnaryOperatorType == UnaryOperatorType.EXCL)
                {
                    // The unary operator shouldn't have 2 exits. It's not a conditional. If it does,
                    // remove one of the edges, and it's path, from the collected edges.
                    if (element.Exits.Count == 2)
                    {
                        var edge = element.Exits[0];
                        do
                        {
                            dodgyEdges.Add(edge);

                            // Get the source of the exit edge. This is the node in the control flow graph,
                            // not the element in the program structure tree.
                            var source = edge.Source;
                            edge = null;

                            // Walk back to the control flow graph node that represents the exit of the
                            // dodgy condition, so keep going until we have an element with 2 exits.
                            if (source.Entries.Count == 1 && source.Exits.Count == 1)
                            {
                                edge = source.Entries[0];
                            }
                        } while (edge != null);
                    }
                }
            }

            edges.ExceptWith(dodgyEdges);
            return(edges);
        }
示例#13
0
        private static void CheckInfiniteJumpLoop(BlockSyntax body, IControlFlowGraph cfg, string declarationType,
                                                  SyntaxNodeAnalysisContext analysisContext)
        {
            if (body == null)
            {
                return;
            }

            var reachableFromBlock = cfg.Blocks.Except(new[] { cfg.ExitBlock }).ToDictionary(
                b => b,
                b => b.AllSuccessorBlocks);

            var alreadyProcessed = new HashSet <Block>();

            foreach (var reachable in reachableFromBlock)
            {
                if (!reachable.Key.AllPredecessorBlocks.Contains(cfg.EntryBlock) ||
                    alreadyProcessed.Contains(reachable.Key) ||
                    reachable.Value.Contains(cfg.ExitBlock))
                {
                    continue;
                }

                alreadyProcessed.UnionWith(reachable.Value);
                alreadyProcessed.Add(reachable.Key);

                var reportOnOptions = reachable.Value.OfType <JumpBlock>()
                                      .Where(jb => jb.JumpNode is GotoStatementSyntax)
                                      .ToList();

                if (!reportOnOptions.Any())
                {
                    continue;
                }

                // Calculate stable report location:
                var lastJumpLocation = reportOnOptions.Max(b => b.JumpNode.SpanStart);
                var reportOn         = reportOnOptions.First(b => b.JumpNode.SpanStart == lastJumpLocation);

                analysisContext.ReportDiagnosticWhenActive(Diagnostic.Create(rule, reportOn.JumpNode.GetLocation(), declarationType));
            }
        }
示例#14
0
            public LiveVariableAnalysisContext(string methodBody, string localFunctionName = null)
            {
                var              method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, methodBody), "Main", out var semanticModel);
                IMethodSymbol    symbol;
                CSharpSyntaxNode body;

                if (localFunctionName == null)
                {
                    symbol = semanticModel.GetDeclaredSymbol(method);
                    body   = method.Body;
                }
                else
                {
                    var function = (LocalFunctionStatementSyntaxWrapper)method.DescendantNodes().Single(x => x.Kind() == SyntaxKindEx.LocalFunctionStatement && ((LocalFunctionStatementSyntaxWrapper)x).Identifier.Text == localFunctionName);
                    symbol = semanticModel.GetDeclaredSymbol(function) as IMethodSymbol;
                    body   = (CSharpSyntaxNode)function.Body ?? function.ExpressionBody;
                }
                this.CFG = CSharpControlFlowGraph.Create(body, semanticModel);
                this.LVA = CSharpLiveVariableAnalysis.Analyze(this.CFG, symbol, semanticModel);
            }
示例#15
0
        /// <summary>
        /// Merge together basic blocks on the same line connected only by a continue edge
        /// </summary>
        /// <param name="cfg"></param>
        /// <returns></returns>
        public static IControlFlowGraph MergeAdjacentBasicBlocks(this IControlFlowGraph cfg)
        {
            // This keeps looping until it finds no work to do
            while (true)
            {
                // Find all candidates for merging
                var candidates = (from vertex in cfg.Vertices
                                  where vertex.Type == BasicBlockType.Basic
                                  where vertex.Outgoing.Count() == 1
                                  let outgoing = vertex.Outgoing.Single()
                                                 where outgoing.Type == EdgeType.Continue
                                                 where outgoing.End.LineNumber == vertex.LineNumber
                                                 where outgoing.End.Type == BasicBlockType.Basic
                                                 where outgoing.End.Incoming.Count() == 1
                                                 select(vertex, outgoing.End));

                // Select a single candidate pair (A -> B), if there is no work then exit now
                var work = candidates.FirstOrDefault();
                if (work == default)
                {
                    return(cfg);
                }

                // Move all the items from the A into B, leaving A empty
                cfg = cfg.Modify((a, b) => {
                    if (a.ID == work.End.ID)
                    {
                        work.vertex.CopyTo(b);
                        a.CopyTo(b);
                    }
                    else if (a.ID != work.vertex.ID)
                    {
                        a.CopyTo(b);
                    }
                });

                // Remove all empty blocks
                cfg = cfg.RemoveEmptyBlocks();
            }
        }
示例#16
0
        public ExplodedGraph(IControlFlowGraph cfg, ISymbol declaration, SemanticModel semanticModel, Common.LiveVariableAnalysis lva)
        {
            this.cfg           = cfg;
            this.semanticModel = semanticModel;
            this.declaration   = declaration;
            this.lva           = lva;

            var methodSymbol = declaration as IMethodSymbol;

            if (methodSymbol != null)
            {
                declarationParameters = methodSymbol.Parameters;
            }

            var propertySymbol = declaration as IPropertySymbol;

            if (propertySymbol != null)
            {
                declarationParameters = propertySymbol.Parameters;
            }

            nonInDeclarationParameters = declarationParameters.Where(p => p.RefKind != RefKind.None);
        }
示例#17
0
        private static IReadOnlyDictionary <IEdge, IEdge> CloneEdges(
            [NotNull] this IControlFlowGraph input,
            IMutableControlFlowGraph output,
            IReadOnlyDictionary <IBasicBlock, IMutableBasicBlock> vertexReplacements,
            [NotNull] Func <IEdge, bool> keep)
        {
            var replacements = new Dictionary <IEdge, IEdge>();

            foreach (var edge in input.Edges)
            {
                if (!keep(edge))
                {
                    continue;
                }

                replacements.Add(
                    edge,
                    output.CreateEdge(vertexReplacements[edge.Start], vertexReplacements[edge.End], edge.Type)
                    );
            }

            return(replacements);
        }
示例#18
0
        [NotNull] public static IControlFlowGraph StaticSingleAssignment([NotNull] this IControlFlowGraph graph, [NotNull] out ISingleStaticAssignmentTable ssa)
        {
            var ssaMut = new SingleStaticAssignmentTable();

            ssa = ssaMut;

            var finalNamesInBlock = new Dictionary <IBasicBlock, IReadOnlyDictionary <VariableName, VariableName> >();

            // Replace every variable assignment with a new name, keep track of the last name in each block
            var output = graph.Modify((a, b) => {
                var finalNames       = new Dictionary <VariableName, VariableName>();
                finalNamesInBlock[b] = finalNames;

                foreach (var stmt in a.Statements)
                {
                    if (stmt is Assignment ass && !ass.Left.IsExternal)
                    {
                        var sname = ssaMut.Assign(ass.Left);
                        b.Add(new Assignment(sname, ass.Right));

                        // Store the final name assigned to this var in this block
                        finalNames[ass.Left] = sname;
                    }
示例#19
0
        /// <summary>
        /// Remove blocks that cannot be reached from the entry node
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        public static IControlFlowGraph RemoveUnreachableBlocks(this IControlFlowGraph graph)
        {
            var reachable = new HashSet <IBasicBlock>();
            var queue     = new Queue <IBasicBlock>();

            void Mark(IBasicBlock block)
            {
                if (reachable.Add(block))
                {
                    foreach (var edge in block.Outgoing)
                    {
                        queue.Enqueue(edge.End);
                    }
                }
            }

            queue.Enqueue(graph.Vertices.Single(v => v.Type == BasicBlockType.Entry));
            while (queue.Count > 0)
            {
                Mark(queue.Dequeue());
            }

            return(graph.Trim(reachable.Contains));
        }
 private LiveVariableAnalysis(IControlFlowGraph controlFlowGraph, ISymbol declaration, SemanticModel semanticModel)
     : base(controlFlowGraph)
 {
     this.declaration = declaration;
     this.semanticModel = semanticModel;
 }
        private static void VerifyBasicCfgProperties(IControlFlowGraph cfg)
        {
            cfg.Should().NotBeNull();
            cfg.EntryBlock.Should().NotBeNull();
            cfg.ExitBlock.Should().NotBeNull();

            cfg.ExitBlock.SuccessorBlocks.Should().BeEmpty();
            cfg.ExitBlock.Instructions.Should().BeEmpty();
        }
 private static void VerifyEmptyCfg(IControlFlowGraph cfg)
 {
     VerifyCfg(cfg, 1);
 }
        private static void VerifyCfg(IControlFlowGraph cfg, int numberOfBlocks)
        {
            VerifyBasicCfgProperties(cfg);

            cfg.Blocks.Should().HaveCount(numberOfBlocks);

            if (numberOfBlocks > 1)
            {
                cfg.EntryBlock.Should().NotBeSameAs(cfg.ExitBlock);
                cfg.Blocks.Should().ContainInOrder(new[] { cfg.EntryBlock, cfg.ExitBlock });
            }
            else
            {
                cfg.EntryBlock.Should().BeSameAs(cfg.ExitBlock);
                cfg.Blocks.Should().Contain(cfg.EntryBlock);
            }
        }
示例#24
0
        private static void CheckInfiniteJumpLoop(BlockSyntax body, IControlFlowGraph cfg, string declarationType,
            SyntaxNodeAnalysisContext analysisContext)
        {
            if (body == null)
            {
                return;
            }

            var reachableFromBlock = cfg.Blocks.Except(new[] { cfg.ExitBlock }).ToDictionary(
                b => b,
                b => b.AllSuccessorBlocks);

            var alreadyProcessed = new HashSet<Block>();

            foreach (var reachable in reachableFromBlock)
            {
                if (!reachable.Key.AllPredecessorBlocks.Contains(cfg.EntryBlock) ||
                    alreadyProcessed.Contains(reachable.Key) ||
                    reachable.Value.Contains(cfg.ExitBlock))
                {
                    continue;
                }

                alreadyProcessed.UnionWith(reachable.Value);
                alreadyProcessed.Add(reachable.Key);

                var reportOnOptions = reachable.Value.OfType<JumpBlock>()
                    .Where(jb => jb.JumpNode is GotoStatementSyntax)
                    .ToList();

                if (!reportOnOptions.Any())
                {
                    continue;
                }

                // Calculate stable report location:
                var lastJumpLocation = reportOnOptions.Max(b => b.JumpNode.SpanStart);
                var reportOn = reportOnOptions.First(b => b.JumpNode.SpanStart == lastJumpLocation);

                analysisContext.ReportDiagnostic(Diagnostic.Create(Rule, reportOn.JumpNode.GetLocation(), declarationType));
            }
        }
示例#25
0
 protected CfgRecursionSearcher(IControlFlowGraph cfg, ISymbol declaringSymbol, SemanticModel semanticModel, Action reportIssue)
     : base(cfg)
 {
     this.declaringSymbol = declaringSymbol;
     this.semanticModel = semanticModel;
     this.reportIssue = reportIssue;
 }
 protected CfgAllPathValidator(IControlFlowGraph cfg)
 {
     this.cfg = cfg;
 }
 protected CfgAllPathValidator(IControlFlowGraph cfg)
 {
     this.cfg = cfg;
 }
        private static void VerifyJumpWithExpression(IControlFlowGraph cfg, SyntaxKind kind)
        {
            VerifyCfg(cfg, 4);
            var branchBlock = cfg.EntryBlock as BinaryBranchBlock;
            var blocks = cfg.Blocks.ToList();
            var trueBlock = blocks[1] as JumpBlock;
            var falseBlock = blocks[2];
            var exitBlock = cfg.ExitBlock;

            branchBlock.SuccessorBlocks.Should().OnlyContainInOrder(trueBlock, falseBlock);
            trueBlock.SuccessorBlocks.Should().OnlyContain(exitBlock);
            trueBlock.JumpNode.Kind().Should().Be(kind);

            trueBlock.Instructions.FirstOrDefault(n => n.IsKind(SyntaxKind.IdentifierName) && n.ToString() == "ii").Should().NotBeNull();

            exitBlock.PredecessorBlocks.Should().OnlyContain(trueBlock, falseBlock);
        }
示例#29
0
 [NotNull] public static IControlFlowGraph FlowTypingAssignment(
     [NotNull] this IControlFlowGraph graph,
     [NotNull] ISingleStaticAssignmentTable ssa, // We require the SSA object because SSA must be done before flow typing
     [NotNull] out ITypeAssignments types,
     [NotNull] params (VariableName, Execution.Type)[] hints)
示例#30
0
 /// <summary>
 /// Add edges to the graph
 /// </summary>
 /// <param name="input"></param>
 /// <param name="create"></param>
 /// <returns></returns>
 [NotNull] public static IMutableControlFlowGraph Add([NotNull] this IControlFlowGraph input, [NotNull] IEnumerable <(Guid, Guid, EdgeType)> create)
        private static void VerifySimpleJumpBlock(IControlFlowGraph cfg, SyntaxKind kind)
        {
            VerifyCfg(cfg, 3);
            var jumpBlock = cfg.EntryBlock as JumpBlock;
            var bodyBlock = cfg.Blocks.ToList()[1];
            var exitBlock = cfg.ExitBlock;

            jumpBlock.SuccessorBlocks.Should().OnlyContain(bodyBlock);
            bodyBlock.SuccessorBlocks.Should().OnlyContain(exitBlock);

            jumpBlock.JumpNode.Kind().Should().Be(kind);
        }
 internal LiveVariableAnalysis(IControlFlowGraph controlFlowGraph)
 {
     this.controlFlowGraph = controlFlowGraph;
     this.reversedBlocks = controlFlowGraph.Blocks.Reverse().ToList();
 }
示例#33
0
        [NotNull] public static IReadOnlyDictionary <VariableName, BaseExpression> FindConstants([NotNull] this IControlFlowGraph cfg, ISingleStaticAssignmentTable ssa)
        {
            var constants = new Dictionary <VariableName, BaseExpression>();
            var count     = -1;

            // Keep finding more constants until no more are found
            while (count != constants.Count)
            {
                count = constants.Count;
                cfg.VisitBlocks(() => new FindConstantVariables(constants, ssa));
            }

            return(constants);
        }
 public static Common.LiveVariableAnalysis Analyze(IControlFlowGraph controlFlowGraph, ISymbol declaration, SemanticModel semanticModel)
 {
     var lva = new LiveVariableAnalysis(controlFlowGraph, declaration, semanticModel);
     lva.PerformAnalysis();
     return lva;
 }
示例#35
0
        public static bool TryGet(CSharpSyntaxNode node, SemanticModel semanticModel, out IControlFlowGraph cfg)
        {
            cfg = null;
            try
            {
                if (node != null)
                {
                    cfg = Create(node, semanticModel);
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception exc) when(exc is InvalidOperationException ||
                                       exc is ArgumentException ||
                                       exc is NotSupportedException)
            {
                // These are expected
            }
            catch (Exception exc) when(exc is NotImplementedException)
            {
                Debug.Fail(exc.ToString());
            }

            return(cfg != null);
        }
        private static void VerifyJumpWithNoExpression(IControlFlowGraph cfg, SyntaxKind kind)
        {
            VerifyCfg(cfg, 4);
            var branchBlock = cfg.EntryBlock as BinaryBranchBlock;
            var blocks = cfg.Blocks.ToList();
            var trueBlock = blocks[1] as JumpBlock;
            var falseBlock = blocks[2];
            var exitBlock = cfg.ExitBlock;

            branchBlock.SuccessorBlocks.Should().OnlyContainInOrder(trueBlock, falseBlock);
            trueBlock.SuccessorBlocks.Should().OnlyContain(exitBlock);
            trueBlock.JumpNode.Kind().Should().Be(kind);

            exitBlock.PredecessorBlocks.Should().OnlyContain(trueBlock, falseBlock);
        }
示例#37
0
 public static void Serialize(string methodName, IControlFlowGraph cfg, TextWriter writer)
 {
     new CfgWalker(new DotWriter(writer)).Visit(methodName, cfg);
 }
示例#38
0
 public static IControlFlowGraph RecomposeModify(this IControlFlowGraph cfg)
 {
     return(cfg.VisitBlocks(() => new RecomposeModifyIR()));
 }
        public UCFG Build(SemanticModel semanticModel, SyntaxNode syntaxNode, IMethodSymbol methodSymbol, IControlFlowGraph cfg)
        {
            var ucfg = new UCFG
            {
                MethodId = GetMethodId(methodSymbol),
                Location = GetLocation(syntaxNode),
            };

            ucfg.BasicBlocks.AddRange(cfg.Blocks.Select(b => CreateBasicBlock(b, semanticModel)));
            ucfg.Parameters.AddRange(methodSymbol.GetParameters().Select(p => p.Name));

            if (syntaxNode is BaseMethodDeclarationSyntax methodDeclaration &&
                EntryPointRecognizer.IsEntryPoint(methodSymbol))
            {
                var entryPointBlock = CreateEntryPointBlock(semanticModel, methodDeclaration, methodSymbol, blockId.Get(cfg.EntryBlock));
                ucfg.BasicBlocks.Add(entryPointBlock);
                ucfg.Entries.Add(entryPointBlock.Id);
            }
        private static void VerifyForStatementEmpty(IControlFlowGraph cfg)
        {
            VerifyCfg(cfg, 4);
            var initializerBlock = cfg.EntryBlock as ForInitializerBlock;
            var blocks = cfg.Blocks.ToList();
            var branchBlock = blocks[1] as BinaryBranchBlock;
            var loopBodyBlock = cfg.Blocks
                .First(b => b.Instructions.Any(n => n.ToString() == "x = 10"));
            var exitBlock = cfg.ExitBlock;

            initializerBlock.SuccessorBlock.ShouldBeEquivalentTo(branchBlock);

            branchBlock.SuccessorBlocks.Should().OnlyContainInOrder(loopBodyBlock, exitBlock);
            branchBlock.BranchingNode.Kind().Should().Be(SyntaxKind.ForStatement);

            loopBodyBlock.SuccessorBlocks.Should().OnlyContain(branchBlock);
            branchBlock.PredecessorBlocks.Should().OnlyContain(loopBodyBlock, initializerBlock);
            exitBlock.PredecessorBlocks.Should().OnlyContain(branchBlock);
        }
示例#41
0
            public RecursionAnalysisContext(IControlFlowGraph controlFlowGraph, ISymbol analyzedSymbol, Location issueLocation,
                SyntaxNodeAnalysisContext analysisContext)
            {
                ControlFlowGraph = controlFlowGraph;
                AnalyzedSymbol = analyzedSymbol;
                IssueLocation = issueLocation;
                AnalysisContext = analysisContext;

                SemanticModel = analysisContext.SemanticModel;
            }
示例#42
0
 /// <summary>
 /// Replace inc/dec operations on numbers with a+=1 and a-=1
 /// </summary>
 /// <param name="cfg"></param>
 /// <param name="types"></param>
 /// <returns></returns>
 public static IControlFlowGraph SimplifyModificationExpressions(this IControlFlowGraph cfg, ITypeAssignments types)
 {
     return(cfg.VisitBlocks(() => new SimplifyModify(types)));
 }
示例#43
0
 private LiveVariableAnalysis(IControlFlowGraph controlFlowGraph, ISymbol declaration, SemanticModel semanticModel)
     : base(controlFlowGraph)
 {
     this.declaration   = declaration;
     this.semanticModel = semanticModel;
 }
        private static void VerifyForStatement(IControlFlowGraph cfg)
        {
            VerifyCfg(cfg, 5);
            var initBlock = cfg.EntryBlock;
            var blocks = cfg.Blocks.ToList();
            var branchBlock = blocks[1] as BinaryBranchBlock;
            var incrementorBlock = blocks[3];
            var loopBodyBlock = blocks[2];
            var exitBlock = cfg.ExitBlock;

            initBlock.SuccessorBlocks.Should().OnlyContain(branchBlock);

            branchBlock.SuccessorBlocks.Should().OnlyContainInOrder(loopBodyBlock, exitBlock);
            branchBlock.BranchingNode.Kind().Should().Be(SyntaxKind.ForStatement);

            loopBodyBlock.SuccessorBlocks.Should().OnlyContain(incrementorBlock);
            incrementorBlock.SuccessorBlocks.Should().OnlyContain(branchBlock);
            branchBlock.PredecessorBlocks.Should().OnlyContain(initBlock, incrementorBlock);
            exitBlock.PredecessorBlocks.Should().OnlyContain(branchBlock);
        }
        private static void VerifyMinimalCfg(IControlFlowGraph cfg)
        {
            VerifyCfg(cfg, 2);

            cfg.EntryBlock.SuccessorBlocks.Should().OnlyContain(cfg.ExitBlock);
        }
示例#46
0
 internal LiveVariableAnalysis(IControlFlowGraph controlFlowGraph)
 {
     this.controlFlowGraph = controlFlowGraph;
     this.reversedBlocks   = controlFlowGraph.Blocks.Reverse().ToList();
 }
 public MemberInitializerRedundancyChecker(IControlFlowGraph cfg, ISymbol memberToCheck, SemanticModel semanticModel)
     : base(cfg)
 {
     this.memberToCheck = memberToCheck;
     this.semanticModel = semanticModel;
 }
示例#48
0
 public PopTreeGraph(IControlFlowGraph cfg)
 {
     _cfg = cfg;
 }