Пример #1
0
        private Block CreateBlock(ProtectedRegionSpan regionSpan)
        {
            switch (regionSpan.Type)
            {
            case RegionKind.Try:
                return(new TryBlock(regionSpan.From, regionSpan.To));

            //case RegionKind.CatchWrapper:
            //    return BlockKind.CatchWrapper;
            case RegionKind.Catch:
                return(new CatchBlock(regionSpan.CatchType, regionSpan.From, regionSpan.To));

            case RegionKind.Finally:
                return(new FinallyBlock(regionSpan.From, regionSpan.To));

            case RegionKind.Fault:
                return(new FaultBlock(regionSpan.From, regionSpan.To));

            default:
                return(new Block(BlockKind.Normal, regionSpan.From, regionSpan.To));
            }
        }
Пример #2
0
        public void Run(CilMethod method)
        {
            var regions = GetRegions(method);

            var spans = regions
                        .SelectMany(r => r.GetSpans())
                        .OrderBy(s => s.From)
                        .ThenByDescending(s => s.To);

            var regionQueue = new Queue <ProtectedRegionSpan>(spans);

            ProtectedRegionSpan awaitedRegion = null;
            ProtectedRegionSpan currentRegion = null;

            var regionStack = new Stack <ProtectedRegionSpan>();

            if (regionQueue.Any())
            {
                awaitedRegion = regionQueue.Dequeue();
            }

            var block = new Block(BlockKind.Normal, 0, 0);

            block.Ast.Add(new JumpLabel(0, false));

            var rootBlock = block;

            var blockStack = new Stack <Block>();

            foreach (var op in method.OpTree)
            {
                while (currentRegion != null && false == currentRegion.Contains(op))
                {
                    // we are no longer in currentRegion, let's wrap it up!

                    var parentBlock = blockStack.Pop();

                    parentBlock.Ast.Add(block);

                    block         = parentBlock;
                    currentRegion = regionStack.Pop();
                }

                if (op.IsLabel)
                {
                    block.Ast.Add(new JumpLabel(op.Position, true));
                }

                while (awaitedRegion != null && awaitedRegion.Contains(op))
                {
                    // we've entered awaitedRegion

                    blockStack.Push(block);

                    block = CreateBlock(awaitedRegion);

                    block.Ast.Add(new JumpLabel(op.Position, false));

                    regionStack.Push(currentRegion);
                    currentRegion = awaitedRegion;

                    if (regionQueue.Any())
                    {
                        awaitedRegion = regionQueue.Dequeue();
                    }
                    else
                    {
                        awaitedRegion = null;
                    }
                }

                block.Ast.Add(op);
                block.To = op.Position;
            }

            if (blockStack.Any())
            {
                var parentBlock = blockStack.Pop();
                parentBlock.Ast.Add(block);
            }

            method.Block = rootBlock;
        }