private static string DetermineRegionPrefix(IControlFlowRegion <TInstruction> region) { string prefix = null; switch (region) { case BasicControlFlowRegion <TInstruction> basicRegion: if (basicRegion.ParentRegion is ExceptionHandlerRegion <TInstruction> parentEh) { if (parentEh.ProtectedRegion == basicRegion) { prefix = "cluster_protected"; } else if (parentEh.HandlerRegions.Contains(basicRegion)) { prefix = "cluster_handler"; } } prefix ??= "cluster_block"; break; case ExceptionHandlerRegion <TInstruction> _: prefix = "cluster_eh"; break; default: prefix = "cluster_region"; break; } return(prefix); }
private static void EnterGenericRegion <TInstruction>(IndexableStack <ScopeInfo <TInstruction> > scopeStack, IControlFlowRegion <TInstruction> enteredRegion) { var scopeBlock = new ScopeBlock <TInstruction>(); scopeStack.Peek().AddBlock(scopeBlock); scopeStack.Push(new ScopeInfo <TInstruction>(enteredRegion, scopeBlock)); }
private (DotEntityStyle Style, string Label) GetSubGraphStyle(IControlFlowRegion <TInstruction> region) { switch (region) { case ScopeRegion <TInstruction> basicRegion: return(GetScopeStyle(basicRegion)); case ExceptionHandlerRegion <TInstruction> _: return(ExceptionHandlerStyle, ExceptionHandlerLabel); case HandlerRegion <TInstruction> _: return(HandlerStyle, HandlerLabel); } return(DefaultStyle, string.Empty); }
private static string DetermineRegionPrefix(IControlFlowRegion <TInstruction> region) { switch (region) { case ScopeRegion <TInstruction> scopeRegion: return(GetScopeRegionPrefix(scopeRegion)); case ExceptionHandlerRegion <TInstruction> _: return("cluster_eh"); case HandlerRegion <TInstruction> _: return("cluster_handler"); default: return("cluster_region"); } }
private static void EnterExceptionHandlerSubRegion <TInstruction>( IndexableStack <ScopeInfo <TInstruction> > scopeStack, ExceptionHandlerRegion <TInstruction> parentRegion, IControlFlowRegion <TInstruction> enteredRegion) { IBlock <TInstruction> enteredBlock; IControlFlowRegion <TInstruction> enteredSubRegion; if (!(scopeStack.Peek().Block is ExceptionHandlerBlock <TInstruction> ehBlock)) { throw new InvalidOperationException("The parent scope is not an exception handler scope."); } // Did we enter the protected region, or one of the handler regions? if (parentRegion.ProtectedRegion == enteredRegion) { // We entered the protected region. enteredBlock = ehBlock.ProtectedBlock; enteredSubRegion = parentRegion.ProtectedRegion; } else { // We entered a handler region. var handlerRegion = parentRegion.Handlers.First(r => r == enteredRegion); var handlerBlock = new HandlerBlock <TInstruction> { Tag = handlerRegion.Tag }; enteredBlock = handlerBlock; enteredSubRegion = handlerRegion; ehBlock.Handlers.Add(handlerBlock); } // Sanity check: If the entered subregion's parent is the exception handler region but the region // isn't a protected, prologue, epilogue nor one of the handler regions, that would mean that // something went *seriously* wrong. if (enteredSubRegion is null) { throw new InvalidOperationException( "Entered subregion of exception handler doesn't belong to any of its regions!?"); } // Push the entered scope. scopeStack.Push(new ScopeInfo <TInstruction>(enteredSubRegion, enteredBlock)); }
private ControlFlowRegion <Statement <TInstruction> > TransformRegion(IControlFlowRegion <TInstruction> region) { switch (region) { case BasicControlFlowRegion <TInstruction> basicRegion: // Create new basic region. var newBasicRegion = new BasicControlFlowRegion <Statement <TInstruction> >(); TransformSubRegions(basicRegion, newBasicRegion); // Register basic region pair. _context.RegionsMapping[basicRegion] = newBasicRegion; return(newBasicRegion); case ExceptionHandlerRegion <TInstruction> ehRegion: var newEhRegion = new ExceptionHandlerRegion <Statement <TInstruction> >(); // ProtectedRegion is read-only, so instead we just transform all sub regions and add it to the // existing protected region. TransformSubRegions(ehRegion.ProtectedRegion, newEhRegion.ProtectedRegion); _context.RegionsMapping[ehRegion.ProtectedRegion] = newEhRegion.ProtectedRegion; // Add handler regions. foreach (var subRegion in ehRegion.HandlerRegions) { newEhRegion.HandlerRegions.Add(TransformRegion(subRegion)); } return(newEhRegion); default: throw new ArgumentOutOfRangeException(nameof(region)); } void TransformSubRegions( BasicControlFlowRegion <TInstruction> originalRegion, BasicControlFlowRegion <Statement <TInstruction> > newRegion) { foreach (var subRegion in originalRegion.Regions) { newRegion.Regions.Add(TransformRegion(subRegion)); } } }
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)); }
/// <summary> /// Obtains the parent exception handler region that this region resides in (if any). /// </summary> /// <returns> /// The parent exception handler region, or <c>null</c> if the region is not part of any exception handler. /// </returns> public static ExceptionHandlerRegion <TInstruction> GetParentExceptionHandler <TInstruction>(this IControlFlowRegion <TInstruction> self) { var region = self.ParentRegion; while (region is {})
/// <summary> /// Creates a new instance of the <see cref="RegionCollection{TInstruction}"/> class. /// </summary> /// <param name="owner">The owner of the sub regions.</param> public RegionCollection(IControlFlowRegion <TInstruction> owner) { _owner = owner ?? throw new ArgumentNullException(nameof(owner)); }
public ScopeInfo(IControlFlowRegion <TInstruction> region, IBlock <TInstruction> block) { Region = region ?? throw new ArgumentNullException(nameof(region)); Block = block ?? throw new ArgumentNullException(nameof(block)); }
/// <summary> /// Obtains the parent region of a specific type that this region resides in (if any). /// </summary> /// <returns> /// The parent region, or <c>null</c> if the region is not part of any region of type <typeparamref name="TRegion"/>. /// </returns> private static TRegion GetParentRegion <TInstruction, TRegion>(IControlFlowRegion <TInstruction> self) where TRegion : class, IControlFlowRegion <TInstruction> { var region = self.ParentRegion; while (region is {})
/// <summary> /// Obtains the parent handler region that this region resides in (if any). /// </summary> /// <returns> /// The parent exception handler region, or <c>null</c> if the region is not part of any exception handler. /// </returns> public static HandlerRegion <TInstruction> GetParentHandler <TInstruction>(this IControlFlowRegion <TInstruction> self) => GetParentRegion <TInstruction, HandlerRegion <TInstruction> >(self);