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)); } }
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; }