Beispiel #1
0
        private static void EnterNextRegion <TInstruction>(
            IndexableStack <ScopeInfo <TInstruction> > scopeStack,
            IControlFlowRegion <TInstruction>[] activeRegions)
        {
            var enteredRegion = activeRegions[scopeStack.Count];

            // Add new scope block to the current scope.
            var currentScope = scopeStack.Peek();

            if (enteredRegion is ExceptionHandlerRegion <TInstruction> ehRegion)
            {
                // We entered an exception handler region.
                var ehBlock = new ExceptionHandlerBlock <TInstruction>();
                currentScope.AddBlock(ehBlock);
                scopeStack.Push(new ScopeInfo <TInstruction>(ehRegion, ehBlock));
            }
            else if (enteredRegion.ParentRegion is ExceptionHandlerRegion <TInstruction> parentEhRegion)
            {
                // We entered one of the exception handler sub regions. Figure out which one it is.
                ScopeBlock <TInstruction> enteredBlock;

                if (!(currentScope.Block is ExceptionHandlerBlock <TInstruction> ehBlock))
                {
                    throw new InvalidOperationException("The parent scope is not an exception handler scope.");
                }

                if (parentEhRegion.ProtectedRegion == enteredRegion)
                {
                    // We entered the protected region.
                    enteredBlock = ehBlock.ProtectedBlock;
                }
                else
                {
                    // We entered a handler region.
                    enteredBlock = new ScopeBlock <TInstruction>();
                    ehBlock.HandlerBlocks.Add(enteredBlock);
                }

                // Push the entered scope.
                scopeStack.Push(new ScopeInfo <TInstruction>(parentEhRegion.ProtectedRegion, enteredBlock));
            }
            else
            {
                // Fall back method: just enter a new scope block.
                var scopeBlock = new ScopeBlock <TInstruction>();
                currentScope.AddBlock(scopeBlock);
                scopeStack.Push(new ScopeInfo <TInstruction>(enteredRegion, scopeBlock));
            }
        }
Beispiel #2
0
        private static ScopeBlock <TInstruction> BuildBlocksFromSortedNodes <TInstruction>(
            ControlFlowGraph <TInstruction> cfg,
            IEnumerable <ControlFlowNode <TInstruction> > sorting)
        {
            // We maintain a stack of scope information. Every time we enter a new region, we enter a new scope,
            // and similarly, we leave a scope when we leave a region.

            var rootScope  = new ScopeBlock <TInstruction>();
            var scopeStack = new IndexableStack <ScopeInfo <TInstruction> >();

            scopeStack.Push(new ScopeInfo <TInstruction>(cfg, rootScope));

            // Add the nodes in the order of the sorting.
            foreach (var node in sorting)
            {
                var currentScope = scopeStack.Peek();
                if (node.ParentRegion != currentScope.Region)
                {
                    UpdateScopeStack(scopeStack, node);
                    currentScope = scopeStack.Peek();
                }

                currentScope.AddBlock(node.Contents);
            }

            return(rootScope);
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
        private static void EnterExceptionHandlerRegion <TInstruction>(
            IndexableStack <ScopeInfo <TInstruction> > scopeStack,
            ExceptionHandlerRegion <TInstruction> ehRegion)
        {
            var ehBlock = new ExceptionHandlerBlock <TInstruction>
            {
                Tag = ehRegion.Tag
            };

            scopeStack.Peek().AddBlock(ehBlock);
            scopeStack.Push(new ScopeInfo <TInstruction>(ehRegion, ehBlock));
        }
Beispiel #5
0
        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));
        }
Beispiel #6
0
        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));
        }
Beispiel #7
0
        /// <summary>
        /// Constructs the tree of scopes and basic blocks based on the provided control flow graph.
        /// </summary>
        /// <param name="cfg">The control flow graph.</param>
        /// <returns>The root scope.</returns>
        public ScopeBlock <TInstruction> ConstructBlocks(ControlFlowGraph <TInstruction> cfg)
        {
            // Sort the nodes in topological order, where we ignore cyclic dependencies.
            var sorter = new TopologicalSorter <ControlFlowNode <TInstruction> >(ChildrenLister)
            {
                IgnoreCycles = true
            };

            var sorting = sorter
                          .GetTopologicalSorting(cfg.Entrypoint)
                          .Reverse()
#if DEBUG
                          .ToArray()
#endif
            ;

            // We maintain a stack of scope information. Every time we enter a new region, we enter a new scope,
            // and similarly, we leave a scope when we leave a region.

            var rootScope  = new ScopeBlock <TInstruction>();
            var scopeStack = new IndexableStack <ScopeInfo>();

            scopeStack.Push(new ScopeInfo(cfg, rootScope));

            // Add the nodes in the order of the sorting.
            foreach (var node in sorting)
            {
                var currentScope = scopeStack.Peek();
                if (node.ParentRegion != currentScope.Region)
                {
                    UpdateScopeStack(node, scopeStack);
                    currentScope = scopeStack.Peek();
                }

                currentScope.AddBlock(node.Contents);
            }

            return(rootScope);
        }
Beispiel #8
0
        private void UpdateScopeStack(ControlFlowNode <TInstruction> node, IndexableStack <ScopeInfo> scopeStack)
        {
            var activeRegions = node.GetSituatedRegions()
                                .Reverse()
                                .ToArray();

            int largestPossibleCommonDepth = Math.Min(scopeStack.Count, activeRegions.Length);

            // Figure out common region depth.
            int commonDepth = 1;

            while (commonDepth < largestPossibleCommonDepth)
            {
                if (scopeStack[commonDepth].Region != activeRegions[commonDepth])
                {
                    break;
                }
                commonDepth++;
            }

            // Leave for every left region a scope block.
            while (scopeStack.Count > commonDepth)
            {
                scopeStack.Pop();
            }

            // Enter for every entered region a new block.
            while (scopeStack.Count < activeRegions.Length)
            {
                // Create new scope block.
                var enteredRegion = activeRegions[scopeStack.Count];

                // Add new cope block to the current scope.
                var currentScope = scopeStack.Peek();

                if (enteredRegion is ExceptionHandlerRegion <TInstruction> ehRegion)
                {
                    // We entered an exception handler region.
                    var ehBlock = new ExceptionHandlerBlock <TInstruction>();
                    currentScope.AddBlock(ehBlock);
                    scopeStack.Push(new ScopeInfo(ehRegion, ehBlock));
                }
                else if (enteredRegion.ParentRegion is ExceptionHandlerRegion <TInstruction> parentEhRegion)
                {
                    // We entered one of the exception handler sub regions. Figure out which one it is.
                    var enteredBlock = default(ScopeBlock <TInstruction>);

                    if (!(currentScope.Block is ExceptionHandlerBlock <TInstruction> ehBlock))
                    {
                        throw new InvalidOperationException("The parent scope is not an exception handler scope.");
                    }

                    if (parentEhRegion.ProtectedRegion == enteredRegion)
                    {
                        // We entered the protected region.
                        enteredBlock = ehBlock.ProtectedBlock;
                    }
                    else
                    {
                        // We entered a handler region.
                        enteredBlock = new ScopeBlock <TInstruction>();
                        ehBlock.HandlerBlocks.Add(enteredBlock);
                    }

                    // Push the entered scope.
                    scopeStack.Push(new ScopeInfo(parentEhRegion.ProtectedRegion, enteredBlock));
                }
                else
                {
                    // Fall back method: just enter a new scope block.
                    var scopeBlock = new ScopeBlock <TInstruction>();
                    currentScope.AddBlock(scopeBlock);
                    scopeStack.Push(new ScopeInfo(enteredRegion, scopeBlock));
                }
            }
        }