コード例 #1
0
        private void Layout(ScopeBlock methodBlock)
        {
            var lastProtectedBlocks = new List <ScopeBlock>();
            int index = 0;

            _basicBlocks = new List <BasicBlock>();

            foreach (var block in methodBlock.Enumerate <Block>())
            {
                if (block is BasicBlock basicBlock)
                {
                    basicBlock.Contexts.Set(this, new BlockContext(index, basicBlock.BranchOpcode, lastProtectedBlocks));
                    _basicBlocks.Add(basicBlock);
                    lastProtectedBlocks.Clear();
                    index++;
                }
                else if (block.Type == BlockType.Protected)
                {
                    lastProtectedBlocks.Add((ScopeBlock)block);
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Sorts all blocks in <paramref name="methodBlock"/>
        /// NOTICE: Do NOT use it to remove unsed blocks! Please call <see cref="BlockCleaner.RemoveUnusedBlocks(ScopeBlock)"/> first!
        /// </summary>
        /// <param name="methodBlock"></param>
        public static void Sort(ScopeBlock methodBlock)
        {
            if (methodBlock is null)
            {
                throw new ArgumentNullException(nameof(methodBlock));
            }
            if (methodBlock.Type != BlockType.Method)
            {
                throw new ArgumentException($"{nameof(methodBlock)} is not a method block");
            }

            object contextKey = new object();

            foreach (var basicBlock in methodBlock.Enumerate <BasicBlock>())
            {
                if (basicBlock.Successors.Count == 0)
                {
                    basicBlock.Contexts.Set(contextKey, BlockContext.Empty);
                    continue;
                }

                var block = (Block)basicBlock;
                // block is jump source (jump from)
                bool added;

                /*
                 * There are three situations and they appear in order
                 * 1. Jump out of scope
                 * 2. Add target(s) successfully (only appear once)
                 * 3. Self-loop
                 * When we add target(s) successfully, we should break do-while loop.
                 */
                do
                {
                    if (!block.Contexts.TryGet <BlockContext>(contextKey, out var context))
                    {
                        context = block.Contexts.Set(contextKey, new BlockContext());
                    }
                    var targets = context.Targets;
                    var scope   = block.Scope;

                    added = AddTarget(targets, scope, basicBlock.FallThroughNoThrow);
                    // target is jump destination (jump to)
                    if (added)
                    {
                        // If fall through is added successfully, then we can try adding other targets
                        AddTarget(targets, scope, basicBlock.CondTargetNoThrow);
                        var switchTargets = basicBlock.SwitchTargetsNoThrow;
                        if (!(switchTargets is null))
                        {
                            foreach (var switchTarget in switchTargets)
                            {
                                AddTarget(targets, scope, switchTarget);
                            }
                        }
                    }
                    else
                    {
                        block = block.Scope.Scope;
                        // Gets upper protected block as jump source, not its child blocks (try, catch, ...)
                    }
                } while (!added && block.Type != BlockType.Method);