/// <summary> /// Generates the finally block. /// </summary> /// <remarks> /// Since the condition block and the dispose invocation block should have a common successor, a new EmptyBlockLogicalConstruct /// is added to the logical tree. /// </remarks> /// <returns></returns> private BlockLogicalConstruct GenerateFinallyBlock() { CFGBlockLogicalConstruct finallySuccessor = ProcessFinallyNode(finallyEntryBlock, disposeCallBlock); finallySuccessor.RemoveFromPredecessors(conditionBlock); conditionBlock.RemoveFromSuccessors(finallySuccessor); EmptyBlockLogicalConstruct emptyCommonNode = new EmptyBlockLogicalConstruct(++logicalContext.MaxBlockIndex); emptyCommonNode.AddToPredecessors(disposeCallBlock); emptyCommonNode.AddToPredecessors(conditionBlock); disposeCallBlock.AddToSuccessors(emptyCommonNode); conditionBlock.AddToSuccessors(emptyCommonNode); emptyCommonNode.Parent = finallyEntryBlock.Parent; emptyCommonNode.Parent.Children.Add(emptyCommonNode); for (int i = 0; i < conditionBlock.TheBlock.Successors.Length; i++) { if (conditionBlock.TheBlock.Successors[i] == finallySuccessor.TheBlock) { conditionBlock.TheBlock.Successors[i] = null; } } finallyBlocks.Add(emptyCommonNode); return(new BlockLogicalConstruct(finallyEntryBlock, finallyBlocks)); }
/// <summary> /// Redirect the predecessors and successors of the finally block. /// </summary> /// <remarks> /// Check if the finallyBlockEntry is only reachable by nodes in the try block. /// Make the successor of the finallyBlockEnd successor to all of the predecessors of the finallyBlockEntry. /// This will detach the finally block from the subgraph, which is a desired result since every normal finally block is not reachable from any where /// (the CLR takes care of executing the code in the finally block). /// </remarks> /// <param name="finallyBlockEntry"></param> /// <param name="finallyBlockEnd"></param> /// <returns>The successor of the finally block.</returns> private CFGBlockLogicalConstruct ProcessFinallyNode(CFGBlockLogicalConstruct finallyBlockEntry, CFGBlockLogicalConstruct finallyBlockEnd) { foreach (ILogicalConstruct predecessor in finallyBlockEntry.SameParentPredecessors) { if (!newTryBody.Contains(predecessor)) { throw new Exception("Invalid entry to the finally block"); } } CFGBlockLogicalConstruct finallySuccessor; using (IEnumerator <CFGBlockLogicalConstruct> enumerator = finallyBlockEnd.CFGSuccessors.GetEnumerator()) { enumerator.MoveNext(); finallySuccessor = enumerator.Current; if (enumerator.MoveNext()) { throw new Exception("Invalid count of successors"); } } HashSet <CFGBlockLogicalConstruct> finallyCFGPredecessors = new HashSet <CFGBlockLogicalConstruct>(finallyBlockEntry.CFGPredecessors); foreach (CFGBlockLogicalConstruct cfgPredecessor in finallyCFGPredecessors) { if (cfgPredecessor.TheBlock != finallyBlockEntry.TheBlock && cfgPredecessor.TheBlock.Successors.Length > 1) { ProcessMultiWayCFGPredecessor(finallyBlockEntry, cfgPredecessor.TheBlock, finallySuccessor.TheBlock); } LogicalConstructBase currenConstruct = cfgPredecessor; while (currenConstruct != finallyBlockEntry.Parent) { currenConstruct.RemoveFromSuccessors(finallyBlockEntry); currenConstruct.AddToSuccessors(finallySuccessor); currenConstruct = currenConstruct.Parent as LogicalConstructBase; } finallySuccessor.AddToPredecessors(cfgPredecessor); finallyBlockEntry.RemoveFromPredecessors(cfgPredecessor); } finallySuccessor.RemoveFromPredecessors(finallyBlockEnd); finallyBlockEnd.RemoveFromSuccessors(finallySuccessor); return(finallySuccessor); }
private CFGBlockLogicalConstruct ProcessFinallyNode(CFGBlockLogicalConstruct finallyBlockEntry, CFGBlockLogicalConstruct finallyBlockEnd) { V_1 = finallyBlockEntry.get_SameParentPredecessors().GetEnumerator(); try { while (V_1.MoveNext()) { V_2 = (ILogicalConstruct)V_1.get_Current(); if (this.newTryBody.Contains(V_2)) { continue; } throw new Exception("Invalid entry to the finally block"); } } finally { ((IDisposable)V_1).Dispose(); } V_3 = finallyBlockEnd.get_CFGSuccessors().GetEnumerator(); try { dummyVar0 = V_3.MoveNext(); V_0 = V_3.get_Current(); if (V_3.MoveNext()) { throw new Exception("Invalid count of successors"); } } finally { if (V_3 != null) { V_3.Dispose(); } } V_4 = (new HashSet <CFGBlockLogicalConstruct>(finallyBlockEntry.get_CFGPredecessors())).GetEnumerator(); try { while (V_4.MoveNext()) { V_5 = V_4.get_Current(); if (InstructionBlock.op_Inequality(V_5.get_TheBlock(), finallyBlockEntry.get_TheBlock()) && (int)V_5.get_TheBlock().get_Successors().Length > 1) { this.ProcessMultiWayCFGPredecessor(finallyBlockEntry, V_5.get_TheBlock(), V_0.get_TheBlock()); } V_6 = V_5; while (V_6 != finallyBlockEntry.get_Parent()) { dummyVar1 = V_6.RemoveFromSuccessors(finallyBlockEntry); V_6.AddToSuccessors(V_0); V_6 = V_6.get_Parent() as LogicalConstructBase; } V_0.AddToPredecessors(V_5); dummyVar2 = finallyBlockEntry.RemoveFromPredecessors(V_5); } } finally { ((IDisposable)V_4).Dispose(); } dummyVar3 = V_0.RemoveFromPredecessors(finallyBlockEnd); dummyVar4 = finallyBlockEnd.RemoveFromSuccessors(V_0); return(V_0); }