public void CreateBlocks(BlockContainer mainContainer, List <ILInstruction> instructions, BitArray incomingBranches, CancellationToken cancellationToken) { CreateContainerStructure(); mainContainer.ILRange = new Interval(0, body.CodeSize); currentContainer = mainContainer; foreach (var inst in instructions) { cancellationToken.ThrowIfCancellationRequested(); int start = inst.ILRange.Start; if (currentBlock == null || (incomingBranches[start] && !IsStackAdjustment(inst))) { // Finish up the previous block FinalizeCurrentBlock(start, fallthrough: true); // Leave nested containers if necessary while (start >= currentContainer.ILRange.End) { currentContainer = containerStack.Pop(); } // Enter a handler if necessary BlockContainer handlerContainer; if (handlerContainers.TryGetValue(start, out handlerContainer)) { containerStack.Push(currentContainer); currentContainer = handlerContainer; currentBlock = handlerContainer.EntryPoint; } else { // Create the new block currentBlock = new Block(); currentContainer.Blocks.Add(currentBlock); } currentBlock.ILRange = new Interval(start, start); } while (nextTry != null && start == nextTry.TryBlock.ILRange.Start) { currentBlock.Instructions.Add(nextTry); containerStack.Push(currentContainer); currentContainer = (BlockContainer)nextTry.TryBlock; currentBlock = new Block(); currentContainer.Blocks.Add(currentBlock); currentBlock.ILRange = new Interval(start, start); nextTry = tryInstructionList.ElementAtOrDefault(++currentTryIndex); } currentBlock.Instructions.Add(inst); if (inst.HasFlag(InstructionFlags.EndPointUnreachable)) { FinalizeCurrentBlock(inst.ILRange.End, fallthrough: false); } else if (!CreateExtendedBlocks && inst.HasFlag(InstructionFlags.MayBranch)) { FinalizeCurrentBlock(inst.ILRange.End, fallthrough: true); } } FinalizeCurrentBlock(body.CodeSize, fallthrough: false); containerStack.Clear(); ConnectBranches(mainContainer, cancellationToken); }
public void CreateBlocks(BlockContainer mainContainer, List <ILInstruction> instructions, BitArray incomingBranches, CancellationToken cancellationToken) { CreateContainerStructure(); mainContainer.ILRange = new Interval(0, body.GetCodeSize()); currentContainer = mainContainer; if (instructions.Count == 0) { currentContainer.Blocks.Add(new Block { Instructions = { new InvalidBranch("Empty body found. Decompiled assembly might be a reference assembly.") } }); return; } foreach (var inst in instructions) { cancellationToken.ThrowIfCancellationRequested(); int start = inst.ILRange.Start; if (currentBlock == null || (incomingBranches[start] && !IsStackAdjustment(inst))) { // Finish up the previous block FinalizeCurrentBlock(start, fallthrough: true); // Leave nested containers if necessary while (start >= currentContainer.ILRange.End) { currentContainer = containerStack.Pop(); currentBlock = currentContainer.Blocks.Last(); // this container is skipped (i.e. the loop will execute again) // set ILRange to the last instruction offset inside the block. if (start >= currentContainer.ILRange.End) { Debug.Assert(currentBlock.ILRange.IsEmpty); currentBlock.ILRange = new Interval(currentBlock.ILRange.Start, start); } } // Enter a handler if necessary BlockContainer handlerContainer; if (handlerContainers.TryGetValue(start, out handlerContainer)) { containerStack.Push(currentContainer); currentContainer = handlerContainer; currentBlock = handlerContainer.EntryPoint; } else { FinalizeCurrentBlock(start, fallthrough: false); // Create the new block currentBlock = new Block(); currentContainer.Blocks.Add(currentBlock); } currentBlock.ILRange = new Interval(start, start); } while (nextTry != null && start == nextTry.TryBlock.ILRange.Start) { currentBlock.Instructions.Add(nextTry); containerStack.Push(currentContainer); currentContainer = (BlockContainer)nextTry.TryBlock; currentBlock = new Block(); currentContainer.Blocks.Add(currentBlock); currentBlock.ILRange = new Interval(start, start); nextTry = tryInstructionList.ElementAtOrDefault(++currentTryIndex); } currentBlock.Instructions.Add(inst); if (inst.HasFlag(InstructionFlags.EndPointUnreachable)) { FinalizeCurrentBlock(inst.ILRange.End, fallthrough: false); } else if (!CreateExtendedBlocks && inst.HasFlag(InstructionFlags.MayBranch)) { FinalizeCurrentBlock(inst.ILRange.End, fallthrough: true); } } FinalizeCurrentBlock(mainContainer.ILRange.End, fallthrough: false); // Finish up all containers while (containerStack.Count > 0) { currentContainer = containerStack.Pop(); currentBlock = currentContainer.Blocks.Last(); FinalizeCurrentBlock(mainContainer.ILRange.End, fallthrough: false); } ConnectBranches(mainContainer, cancellationToken); }