internal override void ReplaceSuccessors(Dictionary<Block, Block> replacementMapping) { if (replacementMapping.ContainsKey(SuccessorBlock)) { SuccessorBlock = replacementMapping[SuccessorBlock]; } }
internal SimpleBlock(Block successor) { if (successor == null) { throw new ArgumentNullException(nameof(successor)); } SuccessorBlock = successor; }
internal override void ReplaceSuccessors(Dictionary<Block, Block> replacementMapping) { base.ReplaceSuccessors(replacementMapping); if (WouldBeSuccessor != null && replacementMapping.ContainsKey(WouldBeSuccessor)) { WouldBeSuccessor = replacementMapping[WouldBeSuccessor]; } }
internal ForeachCollectionProducerBlock(ForEachStatementSyntax foreachNode, Block successor) : base(successor) { if (foreachNode == null) { throw new ArgumentNullException(nameof(foreachNode)); } ForeachNode = foreachNode; }
internal ForInitializerBlock(ForStatementSyntax forNode, Block successor) : base(successor) { if (forNode == null) { throw new ArgumentNullException(nameof(forNode)); } ForNode = forNode; }
internal JumpBlock(SyntaxNode jumpNode, Block successor, Block wouldBeSuccessor) : base(successor) { if (jumpNode == null) { throw new ArgumentNullException(nameof(jumpNode)); } JumpNode = jumpNode; WouldBeSuccessor = wouldBeSuccessor; }
internal BinaryBranchBlock(SyntaxNode branchingNode, Block trueSuccessor, Block falseSuccessor) : base(branchingNode, trueSuccessor, falseSuccessor) { if (trueSuccessor == null) { throw new ArgumentNullException(nameof(trueSuccessor)); } if (falseSuccessor == null) { throw new ArgumentNullException(nameof(falseSuccessor)); } }
protected override void ProcessBlock(Block block, out HashSet<ISymbol> assignedInBlock, out HashSet<ISymbol> usedBeforeAssigned) { assignedInBlock = new HashSet<ISymbol>(); // Kill (The set of variables that are assigned a value.) usedBeforeAssigned = new HashSet<ISymbol>(); // Gen (The set of variables that are used before any assignment.) var assignmentLhs = new HashSet<SyntaxNode>(); foreach (var instruction in block.Instructions.Reverse()) { switch (instruction.Kind()) { case SyntaxKind.IdentifierName: ProcessIdentifier(instruction, assignedInBlock, usedBeforeAssigned, assignmentLhs); break; case SyntaxKind.SimpleAssignmentExpression: ProcessSimpleAssignment(instruction, assignedInBlock, usedBeforeAssigned, assignmentLhs); break; case SyntaxKind.VariableDeclarator: ProcessVariableDeclarator(instruction, assignedInBlock, usedBeforeAssigned); break; case SyntaxKind.AnonymousMethodExpression: case SyntaxKind.ParenthesizedLambdaExpression: case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.QueryExpression: CollectAllCapturedLocal(instruction); break; default: break; } } if (block.Instructions.Any()) { return; } // Variable declaration in a foreach statement is not a VariableDeclarator, so handling it separately: var foreachBlock = block as BinaryBranchBlock; if (foreachBlock != null && foreachBlock.BranchingNode.IsKind(SyntaxKind.ForEachStatement)) { var foreachNode = (ForEachStatementSyntax)foreachBlock.BranchingNode; ProcessVariableInForeach(foreachNode, assignedInBlock, usedBeforeAssigned); } }
private bool AreAllSuccessorsValid(Block block) { alreadyVisitedBlocks.Add(block); if (block.SuccessorBlocks.Contains(cfg.ExitBlock) || !block.SuccessorBlocks.Except(alreadyVisitedBlocks).Any()) { return false; } return block.SuccessorBlocks .Except(alreadyVisitedBlocks) .All(b => IsBlockValidWithSuccessors(b)); }
private static ISet<Block> GetAll(Block initial, Func<Block, IEnumerable<Block>> getNexts) { var toProcess = new Queue<Block>(); var alreadyProcesses = new HashSet<Block>(); getNexts(initial).ToList().ForEach(b => toProcess.Enqueue(b)); while (toProcess.Count != 0) { var current = toProcess.Dequeue(); if (alreadyProcesses.Contains(current)) { continue; } alreadyProcesses.Add(current); getNexts(current).ToList().ForEach(b => toProcess.Enqueue(b)); } return alreadyProcesses.ToImmutableHashSet(); }
private void VerifyInstructions(Block block, int fromIndex, params string[] instructions) { block.Instructions.Count.Should().BeGreaterOrEqualTo(fromIndex + instructions.Length); for (int i = 0; i < instructions.Length; i++) { block.Instructions[fromIndex + i].ToString().Should().BeEquivalentTo(instructions[i]); } }
protected override bool IsBlockValid(Block block) { return BlockHasReferenceToDeclaringSymbol(block); }
protected abstract bool BlockHasReferenceToDeclaringSymbol(Block block);
protected override bool BlockHasReferenceToDeclaringSymbol(Block block) { return block.Instructions.Any(i => { var invocation = i as InvocationExpressionSyntax; if (invocation == null) { return false; } return IsInstructionOnThisAndMatchesDeclaringSymbol(invocation.Expression); }); }
protected override bool BlockHasReferenceToDeclaringSymbol(Block block) { return block.Instructions.Any(i => TypesForReference.Contains(i.GetType()) && MatchesAccessor(i) && IsInstructionOnThisAndMatchesDeclaringSymbol(i)); }
private void VerifyNoInstruction(Block block) { VerifyAllInstructions(block, new string[0]); }
protected virtual bool IsBlockInvalid(Block block) { return false; }
protected abstract void ProcessBlock(Block block, out HashSet<ISymbol> assignedInBlock, out HashSet<ISymbol> usedInBlock);
private bool IsBlockValidWithSuccessors(Block block) { return !IsBlockInvalid(block) && (IsBlockValid(block) || AreAllSuccessorsValid(block)); }
public IReadOnlyList<ISymbol> GetLiveIn(Block block) { return liveInStates[block].Except(capturedVariables).ToImmutableArray(); }
internal BinaryBranchingSimpleBlock(SyntaxNode branchingInstruction, Block trueAndFalseSuccessor) : base(trueAndFalseSuccessor) { BranchingInstruction = branchingInstruction; }
private void VerifyAllInstructions(Block block, params string[] instructions) { block.Instructions.Count.ShouldBeEquivalentTo(instructions.Count()); VerifyInstructions(block, 0, instructions); }
private static void CheckCfgBlockForDeadStores(Block block, IEnumerable<ISymbol> blockOutState, IEnumerable<ISymbol> excludedLocals, CSharpSyntaxNode node, ISymbol declaration, SyntaxNodeAnalysisContext context) { var lva = new InBlockLivenessAnalysis(block, blockOutState, excludedLocals, node, declaration, context); lva.Analyze(); }
public InBlockLivenessAnalysis(Block block, IEnumerable<ISymbol> blockOutState, IEnumerable<ISymbol> excludedLocals, CSharpSyntaxNode node, ISymbol declaration, SyntaxNodeAnalysisContext context) { this.block = block; this.blockOutState = blockOutState; this.node = node; this.declaration = declaration; this.context = context; this.excludedLocals = excludedLocals; }