public void SplittingNodeShouldPreserveParentRegion() { var graph = new ControlFlowGraph <int>(IntArchitecture.Instance); var n1 = new ControlFlowNode <int>(0, 0, 2, 3, 4); var n2 = new ControlFlowNode <int>(5, 5, 6, 7, 8); var region = new ExceptionHandlerRegion <int>(); graph.Regions.Add(region); var handler = new HandlerRegion <int>(); region.Handlers.Add(handler); graph.Nodes.AddRange(new[] { n1, n2 }); region.ProtectedRegion.Nodes.Add(n1); handler.Contents.Nodes.Add(n2); n1.ConnectWith(n2, ControlFlowEdgeType.Abnormal); graph.Entrypoint = n1; var(first, second) = n1.SplitAtIndex(2); Assert.Equal(first.ParentRegion, second.ParentRegion); Assert.Equal(first.ParentRegion, region.ProtectedRegion); Assert.Equal(2, region.ProtectedRegion.Nodes.Count); }
public void ExceptionHandler() { var cfg = new ControlFlowGraph <int>(IntArchitecture.Instance); for (int i = 0; i < 7; i++) { cfg.Nodes.Add(new ControlFlowNode <int>(i)); } cfg.Entrypoint = cfg.Nodes[0]; cfg.Nodes[0].ConnectWith(cfg.Nodes[1]); cfg.Nodes[1].ConnectWith(cfg.Nodes[2], ControlFlowEdgeType.Conditional); cfg.Nodes[1].ConnectWith(cfg.Nodes[3], ControlFlowEdgeType.FallThrough); cfg.Nodes[2].ConnectWith(cfg.Nodes[4], ControlFlowEdgeType.Unconditional); cfg.Nodes[3].ConnectWith(cfg.Nodes[4], ControlFlowEdgeType.FallThrough); cfg.Nodes[4].ConnectWith(cfg.Nodes[6], ControlFlowEdgeType.Unconditional); cfg.Nodes[5].ConnectWith(cfg.Nodes[6], ControlFlowEdgeType.Unconditional); var ehRegion = new ExceptionHandlerRegion <int>(); cfg.Regions.Add(ehRegion); ehRegion.ProtectedRegion.Entrypoint = cfg.Nodes[1]; ehRegion.ProtectedRegion.Nodes.AddRange(new[] { cfg.Nodes[1], cfg.Nodes[2], cfg.Nodes[3], cfg.Nodes[4], }); var handler = new HandlerRegion <int>(); ehRegion.Handlers.Add(handler); handler.Contents.Nodes.Add(cfg.Nodes[5]); handler.Contents.Entrypoint = cfg.Nodes[5]; var tree = DominatorTree <int> .FromGraph(cfg); Assert.True(tree.Dominates(cfg.Nodes[1], cfg.Nodes[6])); Assert.False(tree.Dominates(cfg.Nodes[4], cfg.Nodes[6])); Assert.False(tree.Dominates(cfg.Nodes[5], cfg.Nodes[6])); }
private static void EnterHandlerSubRegion <TInstruction>( IndexableStack <ScopeInfo <TInstruction> > scopeStack, HandlerRegion <TInstruction> parentRegion, IControlFlowRegion <TInstruction> enteredRegion) { IBlock <TInstruction> enteredBlock; IControlFlowRegion <TInstruction> enteredSubRegion; if (!(scopeStack.Peek().Block is HandlerBlock <TInstruction> handlerBlock)) { throw new InvalidOperationException("The parent scope is not a handler scope."); } if (parentRegion.Prologue == enteredRegion) { // We entered the prologue. handlerBlock.Prologue = new ScopeBlock <TInstruction>(); enteredBlock = handlerBlock.Prologue; enteredSubRegion = parentRegion.Prologue; } else if (parentRegion.Contents == enteredRegion) { // We entered the contents. enteredBlock = handlerBlock.Contents; enteredSubRegion = parentRegion.Contents; } else if (parentRegion.Epilogue == enteredRegion) { // We entered the epilogue. handlerBlock.Epilogue = new ScopeBlock <TInstruction>(); enteredBlock = handlerBlock.Epilogue; enteredSubRegion = parentRegion.Epilogue; } else { // Exhaustive search, this should never happen. throw new InvalidOperationException( "Entered subregion of handler doesn't belong to any of its regions."); } // Push the entered scope. scopeStack.Push(new ScopeInfo <TInstruction>(enteredSubRegion, enteredBlock)); }
private HandlerRegion <Statement <TInstruction> > TransformHandlerRegion(HandlerRegion <TInstruction> handlerRegion) { var result = new HandlerRegion <Statement <TInstruction> >(); if (handlerRegion.Prologue != null) { result.Prologue = (ScopeRegion <Statement <TInstruction> >)TransformRegion(handlerRegion.Prologue); } if (handlerRegion.Epilogue != null) { result.Epilogue = (ScopeRegion <Statement <TInstruction> >)TransformRegion(handlerRegion.Epilogue); } // Contents is read-only, so instead we just transform all sub regions and add it to the // existing protected region. TransformSubRegions(handlerRegion.Contents, result.Contents); _regionsMapping[handlerRegion.Contents] = result.Contents; return(result); }
private static Dictionary <AddressRange, ScopeRegion <TInstruction> > CreateEHRegions <TInstruction>( ControlFlowGraph <TInstruction> cfg, IReadOnlyList <ExceptionHandlerRange> sortedRanges) { var result = new Dictionary <AddressRange, ScopeRegion <TInstruction> >(); var ehRegions = new Dictionary <AddressRange, ExceptionHandlerRegion <TInstruction> >(); for (int i = 0; i < sortedRanges.Count; i++) { var currentEHRange = sortedRanges[i]; // We want to merge exception handlers that have the exact same protected region. // This allows for exception handler constructs that have multiple handler blocks. // Check if we have already created the EH region in an earlier iteration: if (!ehRegions.TryGetValue(currentEHRange.ProtectedRange, out var ehRegion)) { // If not, create and register a new EH region for the protected range. ehRegion = new ExceptionHandlerRegion <TInstruction>(); ehRegions.Add(currentEHRange.ProtectedRange, ehRegion); result.Add(currentEHRange.ProtectedRange, ehRegion.ProtectedRegion); // We need to add the EH region to a parent region. This can either be the CFG itself, or a // sub region that was previously added. var parentRegion = FindParentRegion(result, sortedRanges, i); if (parentRegion is null) { cfg.Regions.Add(ehRegion); } else { parentRegion.Regions.Add(ehRegion); } } // Create and add new handler region from the range. var handlerRegion = new HandlerRegion <TInstruction>(); handlerRegion.Tag = currentEHRange.UserData; ehRegion.Handlers.Add(handlerRegion); result.Add(currentEHRange.HandlerRange, handlerRegion.Contents); // Do we need to add a prologue block? if (currentEHRange.PrologueRange != AddressRange.NilRange) { handlerRegion.Prologue = new ScopeRegion <TInstruction>(); ehRegions.Add(currentEHRange.PrologueRange, ehRegion); result.Add(currentEHRange.PrologueRange, handlerRegion.Prologue); } // Do we need to add an epilogue block? if (currentEHRange.EpilogueRange != AddressRange.NilRange) { handlerRegion.Epilogue = new ScopeRegion <TInstruction>(); ehRegions.Add(currentEHRange.EpilogueRange, ehRegion); result.Add(currentEHRange.EpilogueRange, handlerRegion.Epilogue); } } return(result); }