From c1fca21e8a3e1b890e20f914a0b0bf3e442d00dc Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 16 Feb 2019 20:35:07 +0100 Subject: [PATCH] Make ILRange field private - introduce public API for IL range manipulation. --- .../CSharp/ExpressionBuilder.cs | 8 +- .../CSharp/SequencePointBuilder.cs | 4 +- .../ICSharpCode.Decompiler.csproj | 1 + ICSharpCode.Decompiler/IL/BlockBuilder.cs | 66 ++++++++------- .../IL/ControlFlow/AsyncAwaitDecompiler.cs | 11 +-- .../IL/ControlFlow/AwaitInCatchTransform.cs | 6 +- .../IL/ControlFlow/ConditionDetection.cs | 27 +++--- .../ControlFlow/ControlFlowSimplification.cs | 18 ++-- .../IL/ControlFlow/DetectPinnedRegions.cs | 19 ++--- .../IL/ControlFlow/ExitPoints.cs | 4 +- .../IL/ControlFlow/LoopDetection.cs | 16 ++-- .../IL/ControlFlow/SwitchDetection.cs | 4 +- .../IL/ControlFlow/YieldReturnDecompiler.cs | 38 ++++----- .../IL/ILInstructionExtensions.cs | 22 +++++ ICSharpCode.Decompiler/IL/ILReader.cs | 23 +++--- ICSharpCode.Decompiler/IL/Instructions.cs | 82 +++++++++---------- ICSharpCode.Decompiler/IL/Instructions.tt | 2 +- .../Instructions/BinaryNumericInstruction.cs | 2 +- .../IL/Instructions/Block.cs | 6 +- .../IL/Instructions/BlockContainer.cs | 6 +- .../IL/Instructions/Branch.cs | 6 +- .../IL/Instructions/CallIndirect.cs | 6 +- .../IL/Instructions/CallInstruction.cs | 2 +- .../IL/Instructions/Comp.cs | 7 +- .../CompoundAssignmentInstruction.cs | 8 +- .../IL/Instructions/Conv.cs | 2 +- .../IL/Instructions/DynamicInstructions.cs | 24 +++--- .../IL/Instructions/ExpressionTreeCast.cs | 2 +- .../IL/Instructions/ILFunction.cs | 4 +- .../IL/Instructions/ILInstruction.cs | 42 ++++++++-- .../IL/Instructions/IfInstruction.cs | 2 +- .../IL/Instructions/LdLen.cs | 2 +- .../IL/Instructions/Leave.cs | 2 +- .../IL/Instructions/LockInstruction.cs | 2 +- .../IL/Instructions/MemoryInstructions.cs | 8 +- .../Instructions/NullCoalescingInstruction.cs | 2 +- .../IL/Instructions/SimpleInstruction.cs | 8 +- .../IL/Instructions/StringToInt.cs | 2 +- .../IL/Instructions/SwitchInstruction.cs | 6 +- .../IL/Instructions/TryInstruction.cs | 18 ++-- .../IL/Instructions/UnaryInstruction.cs | 2 +- .../IL/Instructions/UsingInstruction.cs | 2 +- .../IL/PointerArithmeticOffset.cs | 4 +- .../IL/Transforms/CombineExitsTransform.cs | 8 +- .../IL/Transforms/CopyPropagation.cs | 4 +- .../IL/Transforms/DelegateConstruction.cs | 24 +++--- .../Transforms/EarlyExpressionTransforms.cs | 6 +- .../IL/Transforms/ExpressionTransforms.cs | 34 ++++---- .../IL/Transforms/HighLevelLoopTransform.cs | 6 +- .../IL/Transforms/ILInlining.cs | 12 +-- .../IL/Transforms/LockTransform.cs | 8 +- .../IL/Transforms/NullPropagationTransform.cs | 29 ++++--- .../IL/Transforms/NullableLiftingTransform.cs | 81 +++++++----------- .../IL/Transforms/ReduceNestingTransform.cs | 6 +- .../Transforms/SwitchOnNullableTransform.cs | 4 +- .../IL/Transforms/SwitchOnStringTransform.cs | 22 ++--- .../IL/Transforms/TransformAssignment.cs | 2 +- .../IL/Transforms/TransformExpressionTrees.cs | 4 +- .../Transforms/UserDefinedLogicTransform.cs | 15 ++-- .../IL/Transforms/UsingTransform.cs | 2 +- 60 files changed, 404 insertions(+), 391 deletions(-) create mode 100644 ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 2ca023b03..2bd7f9ec8 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -2917,8 +2917,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitInvalidBranch(InvalidBranch inst, TranslationContext context) { string message = "Error"; - if (inst.ILRange.Start != 0) { - message += $" near IL_{inst.ILRange.Start:x4}"; + if (inst.StartILOffset != 0) { + message += $" near IL_{inst.StartILOffset:x4}"; } if (!string.IsNullOrEmpty(inst.Message)) { message += ": " + inst.Message; @@ -2929,8 +2929,8 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitInvalidExpression(InvalidExpression inst, TranslationContext context) { string message = "Error"; - if (inst.ILRange.Start != 0) { - message += $" near IL_{inst.ILRange.Start:x4}"; + if (inst.StartILOffset != 0) { + message += $" near IL_{inst.StartILOffset:x4}"; } if (!string.IsNullOrEmpty(inst.Message)) { message += ": " + inst.Message; diff --git a/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs b/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs index de4eaf51f..849e0eee9 100644 --- a/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs @@ -256,7 +256,7 @@ namespace ICSharpCode.Decompiler.CSharp } // Add the IL range associated with this instruction to the current sequence point. if (HasUsableILRange(inst) && current.Intervals != null) { - current.Intervals.Add(inst.ILRange); + current.Intervals.AddRange(inst.ILRanges); var function = inst.Parent.Ancestors.OfType().FirstOrDefault(); Debug.Assert(current.Function == null || current.Function == function); current.Function = function; @@ -275,7 +275,7 @@ namespace ICSharpCode.Decompiler.CSharp internal static bool HasUsableILRange(ILInstruction inst) { - if (inst.ILRange.IsEmpty) + if (inst.HasILRange) return false; return !(inst is BlockContainer || inst is Block); } diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 08bb6424b..e524c203f 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -267,6 +267,7 @@ + diff --git a/ICSharpCode.Decompiler/IL/BlockBuilder.cs b/ICSharpCode.Decompiler/IL/BlockBuilder.cs index a45781a63..49edd9ef0 100644 --- a/ICSharpCode.Decompiler/IL/BlockBuilder.cs +++ b/ICSharpCode.Decompiler/IL/BlockBuilder.cs @@ -56,26 +56,26 @@ namespace ICSharpCode.Decompiler.IL foreach (var eh in body.ExceptionRegions) { var tryRange = new Interval(eh.TryOffset, eh.TryOffset + eh.TryLength); var handlerBlock = new BlockContainer(); - handlerBlock.ILRange = new Interval(eh.HandlerOffset, eh.HandlerOffset + eh.HandlerLength); + handlerBlock.AddILRange(new Interval(eh.HandlerOffset, eh.HandlerOffset + eh.HandlerLength)); handlerBlock.Blocks.Add(new Block()); - handlerContainers.Add(handlerBlock.ILRange.Start, handlerBlock); + handlerContainers.Add(handlerBlock.StartILOffset, handlerBlock); if (eh.Kind == ExceptionRegionKind.Fault || eh.Kind == ExceptionRegionKind.Finally) { var tryBlock = new BlockContainer(); - tryBlock.ILRange = tryRange; + tryBlock.AddILRange(tryRange); if (eh.Kind == ExceptionRegionKind.Finally) - tryInstructionList.Add(new TryFinally(tryBlock, handlerBlock) { ILRange = tryRange }); + tryInstructionList.Add(new TryFinally(tryBlock, handlerBlock).WithILRange(tryRange)); else - tryInstructionList.Add(new TryFault(tryBlock, handlerBlock) { ILRange = tryRange }); + tryInstructionList.Add(new TryFault(tryBlock, handlerBlock).WithILRange(tryRange)); continue; } // - var tryCatch = tryCatchList.FirstOrDefault(tc => tc.TryBlock.ILRange == tryRange); + var tryCatch = tryCatchList.FirstOrDefault(tc => tc.TryBlock.ILRanges.SingleOrDefault() == tryRange); if (tryCatch == null) { var tryBlock = new BlockContainer(); - tryBlock.ILRange = tryRange; + tryBlock.AddILRange(tryRange); tryCatch = new TryCatch(tryBlock); - tryCatch.ILRange = tryRange; + tryCatch.AddILRange(tryRange); tryCatchList.Add(tryCatch); tryInstructionList.Add(tryCatch); } @@ -83,22 +83,22 @@ namespace ICSharpCode.Decompiler.IL ILInstruction filter; if (eh.Kind == System.Reflection.Metadata.ExceptionRegionKind.Filter) { var filterBlock = new BlockContainer(expectedResultType: StackType.I4); - filterBlock.ILRange = new Interval(eh.FilterOffset, eh.HandlerOffset); + filterBlock.AddILRange(new Interval(eh.FilterOffset, eh.HandlerOffset)); filterBlock.Blocks.Add(new Block()); - handlerContainers.Add(filterBlock.ILRange.Start, filterBlock); + handlerContainers.Add(filterBlock.StartILOffset, filterBlock); filter = filterBlock; } else { filter = new LdcI4(1); } var handler = new TryCatchHandler(filter, handlerBlock, variableByExceptionHandler[eh]); - handler.AddILRange(filter.ILRange); - handler.AddILRange(handlerBlock.ILRange); + handler.AddILRange(filter); + handler.AddILRange(handlerBlock); tryCatch.Handlers.Add(handler); - tryCatch.AddILRange(handler.ILRange); + tryCatch.AddILRange(handler); } if (tryInstructionList.Count > 0) { - tryInstructionList = tryInstructionList.OrderBy(tc => tc.TryBlock.ILRange.Start).ThenByDescending(tc => tc.TryBlock.ILRange.End).ToList(); + tryInstructionList = tryInstructionList.OrderBy(tc => tc.TryBlock.StartILOffset).ThenByDescending(tc => tc.TryBlock.EndILOffset).ToList(); nextTry = tryInstructionList[0]; } } @@ -113,7 +113,7 @@ namespace ICSharpCode.Decompiler.IL public void CreateBlocks(BlockContainer mainContainer, List instructions, BitArray incomingBranches, CancellationToken cancellationToken) { CreateContainerStructure(); - mainContainer.ILRange = new Interval(0, body.GetCodeSize()); + mainContainer.SetILRange(new Interval(0, body.GetCodeSize())); currentContainer = mainContainer; if (instructions.Count == 0) { currentContainer.Blocks.Add(new Block { @@ -126,19 +126,19 @@ namespace ICSharpCode.Decompiler.IL foreach (var inst in instructions) { cancellationToken.ThrowIfCancellationRequested(); - int start = inst.ILRange.Start; + int start = inst.StartILOffset; 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) { + while (start >= currentContainer.EndILOffset) { 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); + if (start >= currentContainer.EndILOffset) { + Debug.Assert(currentBlock.HasILRange); + currentBlock.AddILRange(new Interval(currentBlock.StartILOffset, start)); } } // Enter a handler if necessary @@ -153,30 +153,30 @@ namespace ICSharpCode.Decompiler.IL currentBlock = new Block(); currentContainer.Blocks.Add(currentBlock); } - currentBlock.ILRange = new Interval(start, start); + currentBlock.SetILRange(new Interval(start, start)); } - while (nextTry != null && start == nextTry.TryBlock.ILRange.Start) { + while (nextTry != null && start == nextTry.TryBlock.StartILOffset) { currentBlock.Instructions.Add(nextTry); containerStack.Push(currentContainer); currentContainer = (BlockContainer)nextTry.TryBlock; currentBlock = new Block(); currentContainer.Blocks.Add(currentBlock); - currentBlock.ILRange = new Interval(start, start); + currentBlock.SetILRange(new Interval(start, start)); nextTry = tryInstructionList.ElementAtOrDefault(++currentTryIndex); } currentBlock.Instructions.Add(inst); if (inst.HasFlag(InstructionFlags.EndPointUnreachable)) - FinalizeCurrentBlock(inst.ILRange.End, fallthrough: false); + FinalizeCurrentBlock(inst.EndILOffset, fallthrough: false); else if (!CreateExtendedBlocks && inst.HasFlag(InstructionFlags.MayBranch)) - FinalizeCurrentBlock(inst.ILRange.End, fallthrough: true); + FinalizeCurrentBlock(inst.EndILOffset, fallthrough: true); } - FinalizeCurrentBlock(mainContainer.ILRange.End, fallthrough: false); + FinalizeCurrentBlock(mainContainer.EndILOffset, fallthrough: false); // Finish up all containers while (containerStack.Count > 0) { currentContainer = containerStack.Pop(); currentBlock = currentContainer.Blocks.Last(); - FinalizeCurrentBlock(mainContainer.ILRange.End, fallthrough: false); + FinalizeCurrentBlock(mainContainer.EndILOffset, fallthrough: false); } ConnectBranches(mainContainer, cancellationToken); } @@ -190,8 +190,8 @@ namespace ICSharpCode.Decompiler.IL { if (currentBlock == null) return; - Debug.Assert(currentBlock.ILRange.IsEmpty); - currentBlock.ILRange = new Interval(currentBlock.ILRange.Start, currentILOffset); + Debug.Assert(currentBlock.HasILRange); + currentBlock.SetILRange(new Interval(currentBlock.StartILOffset, currentILOffset)); if (fallthrough) { if (currentBlock.Instructions.LastOrDefault() is SwitchInstruction switchInst && switchInst.Sections.Last().Body.MatchNop()) { // Instead of putting the default branch after the switch instruction @@ -213,9 +213,7 @@ namespace ICSharpCode.Decompiler.IL branch.TargetBlock = FindBranchTarget(branch.TargetILOffset); if (branch.TargetBlock == null) { branch.ReplaceWith(new InvalidBranch("Could not find block for branch target " - + Disassembler.DisassemblerHelpers.OffsetToString(branch.TargetILOffset)) { - ILRange = branch.ILRange - }); + + Disassembler.DisassemblerHelpers.OffsetToString(branch.TargetILOffset)).WithILRange(branch)); } break; case Leave leave: @@ -224,7 +222,7 @@ namespace ICSharpCode.Decompiler.IL if (leave.TargetContainer == null) { // assign the finally/filter container leave.TargetContainer = containerStack.Peek(); - leave.Value = ILReader.Cast(leave.Value, leave.TargetContainer.ExpectedResultType, null, leave.ILRange.Start); + leave.Value = ILReader.Cast(leave.Value, leave.TargetContainer.ExpectedResultType, null, leave.StartILOffset); } break; case BlockContainer container: @@ -249,7 +247,7 @@ namespace ICSharpCode.Decompiler.IL { foreach (var container in containerStack) { foreach (var block in container.Blocks) { - if (block.ILRange.Start == targetILOffset) + if (block.StartILOffset == targetILOffset) return block; } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index 9e8ccbebb..f6bd1d94e 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -504,9 +504,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow moveNextFunction.ReleaseRef(); foreach (var branch in function.Descendants.OfType()) { if (branch.TargetBlock == setResultAndExitBlock) { - branch.ReplaceWith(new Leave((BlockContainer)function.Body, resultVar == null ? null : new LdLoc(resultVar)) { - ILRange = branch.ILRange - }); + branch.ReplaceWith(new Leave((BlockContainer)function.Body, resultVar == null ? null : new LdLoc(resultVar)).WithILRange(branch)); } } foreach (var leave in function.Descendants.OfType()) { @@ -526,9 +524,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow foreach (var leave in function.Descendants.OfType()) { if (moveNextLeaves.Contains(leave)) { leave.ReplaceWith(new InvalidBranch { - Message = "leave MoveNext - await not detected correctly", - ILRange = leave.ILRange - }); + Message = "leave MoveNext - await not detected correctly" + }.WithILRange(leave)); } } // Delete dead loads of the state cache variable: @@ -951,7 +948,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } // if there's any remaining loads (there shouldn't be), replace them with the constant 1 foreach (LdLoc load in doFinallyBodies.LoadInstructions.ToArray()) { - load.ReplaceWith(new LdcI4(1) { ILRange = load.ILRange }); + load.ReplaceWith(new LdcI4(1).WithILRange(load)); } context.StepEndGroup(keepIfEmpty: true); } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs index df7a328d9..bd1c76287 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInCatchTransform.cs @@ -268,7 +268,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow var outer = BlockContainer.FindClosestContainer(container.Parent); if (outer != null) changedContainers.Add(outer); finallyContainer.Blocks.Add(entryPointOfFinally); - finallyContainer.ILRange = entryPointOfFinally.ILRange; + finallyContainer.AddILRange(entryPointOfFinally); exitOfFinally.Instructions.RemoveRange(tempStore.ChildIndex, 3); exitOfFinally.Instructions.Add(new Leave(finallyContainer)); foreach (var branchToFinally in container.Descendants.OfType()) { @@ -278,9 +278,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow foreach (var newBlock in additionalBlocksInFinally) { newBlock.Remove(); finallyContainer.Blocks.Add(newBlock); - finallyContainer.AddILRange(newBlock.ILRange); + finallyContainer.AddILRange(newBlock); } - tryCatch.ReplaceWith(new TryFinally(tryCatch.TryBlock, finallyContainer) {ILRange = tryCatch.TryBlock.ILRange}); + tryCatch.ReplaceWith(new TryFinally(tryCatch.TryBlock, finallyContainer).WithILRange(tryCatch.TryBlock)); } // clean up all modified containers diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs index 430bc5598..f37cb1fed 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs @@ -109,7 +109,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (DetectExitPoints.CompatibleExitInstruction(ifInst.TrueInst, exitInst)) { // if (...) exitInst; exitInst; context.Step("Use empty block as then-branch", ifInst.TrueInst); - ifInst.TrueInst = new Nop() { ILRange = ifInst.TrueInst.ILRange }; + ifInst.TrueInst = new Nop().WithILRange(ifInst.TrueInst); // false, because we didn't inline a real block // this will cause HandleIfInstruction() to attempt to inline the exitInst. return false; @@ -231,7 +231,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // -> if (...) { ... } else { ... } blockExit; context.Step("Remove redundant 'goto blockExit;' in then-branch", ifInst); if (!(ifInst.TrueInst is Block trueBlock) || trueBlock.Instructions.Count == 1) - ifInst.TrueInst = new Nop { ILRange = ifInst.TrueInst.ILRange }; + ifInst.TrueInst = new Nop().WithILRange(ifInst.TrueInst); else trueBlock.Instructions.RemoveAt(trueBlock.Instructions.Count - 1); @@ -396,7 +396,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.Step("Swap empty then-branch with else-branch", ifInst); var oldTrue = ifInst.TrueInst; ifInst.TrueInst = ifInst.FalseInst; - ifInst.FalseInst = new Nop { ILRange = oldTrue.ILRange }; + ifInst.FalseInst = new Nop().WithILRange(oldTrue); ifInst.Condition = Comp.LogicNot(ifInst.Condition); } @@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// private void OrderIfBlocks(IfInstruction ifInst) { - if (IsEmpty(ifInst.FalseInst) || GetILRange(ifInst.TrueInst).Start <= GetILRange(ifInst.FalseInst).Start) + if (IsEmpty(ifInst.FalseInst) || GetStartILOffset(ifInst.TrueInst, out _) <= GetStartILOffset(ifInst.FalseInst, out _)) return; context.Step("Swap then-branch with else-branch to match IL order", ifInst); @@ -437,14 +437,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow ifInst.Condition = Comp.LogicNot(ifInst.Condition); } - public static Interval GetILRange(ILInstruction inst) + public static int GetStartILOffset(ILInstruction inst, out bool isEmpty) { // some compilers merge the leave instructions for different arguments using stack variables // these get split and inlined, but the ILRange of the value remains a better indicator of the actual location - if (inst is Leave leave && !leave.Value.MatchNop()) - return leave.Value.ILRange; + if (inst is Leave leave && !leave.Value.MatchNop()) { + isEmpty = leave.Value.HasILRange; + return leave.Value.StartILOffset; + } - return inst.ILRange; + isEmpty = inst.HasILRange; + return inst.StartILOffset; } /// @@ -524,13 +527,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // prefer arranging stuff in IL order if (exit1.MatchBranch(out var block1) && exit2.MatchBranch(out var block2)) - return block1.ILRange.Start.CompareTo(block2.ILRange.Start); + return block1.StartILOffset.CompareTo(block2.StartILOffset); // use the IL offsets of the arguments of leave instructions instead of the leaves themselves if possible if (exit1.MatchLeave(out var _, out var arg1) && exit2.MatchLeave(out var _, out var arg2)) - return arg1.ILRange.Start.CompareTo(arg2.ILRange.Start); + return arg1.StartILOffset.CompareTo(arg2.StartILOffset); - return exit1.ILRange.Start.CompareTo(exit2.ILRange.Start); + return exit1.StartILOffset.CompareTo(exit2.StartILOffset); } /// @@ -630,7 +633,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow for (int i = startIndex; i < endIndex; i++) { var inst = block.Instructions[i]; extractedBlock.Instructions.Add(inst); - extractedBlock.AddILRange(inst.ILRange); + extractedBlock.AddILRange(inst); } block.Instructions.RemoveRange(startIndex, endIndex - startIndex); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs index 64bee1b75..d06e00012 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs @@ -60,7 +60,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Move ILRanges of special nop instructions to the previous non-nop instruction. for (int i = block.Instructions.Count - 1; i > 0; i--) { if (block.Instructions[i] is Nop nop && nop.Kind == NopKind.Pop) { - block.Instructions[i - 1].AddILRange(nop.ILRange); + block.Instructions[i - 1].AddILRange(nop); } } @@ -82,8 +82,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (value.MatchLdLoc(out ILVariable v) && v.IsSingleDefinition && v.LoadCount == 1 && block.Instructions[0].MatchStLoc(v, out ILInstruction inst)) { context.Step("Inline variable in return block", block); - inst.AddILRange(ret.Value.ILRange); - inst.AddILRange(block.Instructions[0].ILRange); + inst.AddILRange(ret.Value); + inst.AddILRange(block.Instructions[0]); ret.Value = inst; block.Instructions.RemoveAt(0); } @@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.Step("Simplify branch to branch", branch); var nextBranch = (Branch)targetBlock.Instructions[0]; branch.TargetBlock = nextBranch.TargetBlock; - branch.AddILRange(nextBranch.ILRange); + branch.AddILRange(nextBranch); if (targetBlock.IncomingEdgeCount == 0) targetBlock.Instructions.Clear(); // mark the block for deletion targetBlock = branch.TargetBlock; @@ -133,8 +133,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow context.Step("Replace branch to leave with leave", branch); // Replace branches to 'leave' instruction with the leave instruction var leave2 = leave.Clone(); - if (!branch.ILRange.IsEmpty) // use the ILRange of the branch if possible - leave2.ILRange = branch.ILRange; + if (!branch.HasILRange) // use the ILRange of the branch if possible + leave2.AddILRange(branch); branch.ReplaceWith(leave2); } if (targetBlock.IncomingEdgeCount == 0) @@ -186,13 +186,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; // don't inline block into itself context.Step("CombineBlockWithNextBlock", br); var targetBlock = br.TargetBlock; - if (targetBlock.ILRange.Start < block.ILRange.Start && IsDeadTrueStore(block)) { + if (targetBlock.StartILOffset < block.StartILOffset && IsDeadTrueStore(block)) { // The C# compiler generates a dead store for the condition of while (true) loops. block.Instructions.RemoveRange(block.Instructions.Count - 3, 2); } - if (block.ILRange.IsEmpty) - block.ILRange = targetBlock.ILRange; + if (block.HasILRange) + block.AddILRange(targetBlock); block.Instructions.Remove(br); block.Instructions.AddRange(targetBlock.Instructions); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs index ad4a8e739..b2ff0ef2d 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs @@ -102,7 +102,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow for (int k = j + 1; k < block.Instructions.Count; k++) { newBlock.Instructions.Add(block.Instructions[k]); } - newBlock.ILRange = newBlock.Instructions[0].ILRange; + newBlock.AddILRange(newBlock.Instructions[0]); block.Instructions.RemoveRange(j + 1, newBlock.Instructions.Count); block.Instructions.Add(new Branch(newBlock)); container.Blocks.Insert(i + 1, newBlock); @@ -147,9 +147,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (p.StackType != StackType.Ref) { arrayToPointer = new Conv(arrayToPointer, p.StackType.ToPrimitiveType(), false, Sign.None); } - block.Instructions[block.Instructions.Count - 2] = new StLoc(p, arrayToPointer) { - ILRange = block.Instructions[block.Instructions.Count - 2].ILRange - }; + block.Instructions[block.Instructions.Count - 2] = new StLoc(p, arrayToPointer) + .WithILRange(block.Instructions[block.Instructions.Count - 2]); ((Branch)block.Instructions.Last()).TargetBlock = targetBlock; modified = true; } @@ -356,7 +355,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } - var pinnedRegion = new PinnedRegion(stLoc.Variable, stLoc.Value, body) { ILRange = stLoc.ILRange }; + var pinnedRegion = new PinnedRegion(stLoc.Variable, stLoc.Value, body).WithILRange(stLoc); stLoc.ReplaceWith(pinnedRegion); block.Instructions.RemoveAt(block.Instructions.Count - 1); // remove branch into body ProcessPinnedRegion(pinnedRegion); @@ -414,7 +413,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow foreach (var block in body.Blocks) DetectPinnedRegion(block); body.Blocks.RemoveAll(b => b.Instructions.Count == 0); // remove dummy blocks - body.ILRange = body.EntryPoint.ILRange; + body.SetILRange(body.EntryPoint); } private void MoveArrayToPointerToPinnedRegionInit(PinnedRegion pinnedRegion) @@ -447,8 +446,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow newVar.HasGeneratedName = oldVar.HasGeneratedName; oldVar.Function.Variables.Add(newVar); pinnedRegion.Variable = newVar; - pinnedRegion.Init = new ArrayToPointer(pinnedRegion.Init) { ILRange = arrayToPointer.ILRange }; - conv.ReplaceWith(new LdLoc(newVar) { ILRange = conv.ILRange }); + pinnedRegion.Init = new ArrayToPointer(pinnedRegion.Init).WithILRange(arrayToPointer); + conv.ReplaceWith(new LdLoc(newVar).WithILRange(conv)); } void ReplacePinnedVar(ILVariable oldVar, ILVariable newVar, ILInstruction inst) @@ -457,8 +456,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (inst is Conv conv && conv.Kind == ConversionKind.StopGCTracking && conv.Argument.MatchLdLoc(oldVar) && conv.ResultType == newVar.StackType) { // conv ref->i (ldloc oldVar) // => ldloc newVar - conv.AddILRange(conv.Argument.ILRange); - conv.ReplaceWith(new LdLoc(newVar) { ILRange = conv.ILRange }); + conv.AddILRange(conv.Argument); + conv.ReplaceWith(new LdLoc(newVar).WithILRange(conv)); return; } if (inst is IInstructionWithVariableOperand iwvo && iwvo.Variable == oldVar) { diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs index 0c7e9532b..4d7401978 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs @@ -166,7 +166,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow currentExit = ChooseExit(potentialExits); foreach (var exit in potentialExits) { if (CompatibleExitInstruction(currentExit, exit)) { - exit.ReplaceWith(new Leave(currentContainer) { ILRange = exit.ILRange }); + exit.ReplaceWith(new Leave(currentContainer).WithILRange(exit)); } } Debug.Assert(!currentExit.MatchLeave(currentContainer)); @@ -222,7 +222,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (currentExit == ExitNotYetDetermined && CanIntroduceAsExit(inst)) { potentialExits.Add(inst); } else if (CompatibleExitInstruction(inst, currentExit)) { - inst.ReplaceWith(new Leave(currentContainer) { ILRange = inst.ILRange }); + inst.ReplaceWith(new Leave(currentContainer).WithILRange(inst)); } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs index 43dd6f9b0..72a772070 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs @@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return; Block block = (Block)node.UserData; - if (block.ILRange.Start > exitPointILOffset + if (block.StartILOffset > exitPointILOffset && !HasReachableExit(node) && ((Block)node.UserData).Parent == currentBlockContainer) { @@ -440,7 +440,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // that prevents us from finding a nice exit for the inner loops, causing // unnecessary gotos. exitPoint = node; - exitPointILOffset = block.ILRange.Start; + exitPointILOffset = block.StartILOffset; return; // don't visit children, they are likely to have even later IL offsets and we'd end up // moving almost all of the code into the loop. } @@ -641,12 +641,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Move contents of oldEntryPoint to newEntryPoint // (we can't move the block itself because it might be the target of branch instructions outside the loop) newEntryPoint.Instructions.ReplaceList(oldEntryPoint.Instructions); - newEntryPoint.ILRange = oldEntryPoint.ILRange; + newEntryPoint.AddILRange(oldEntryPoint); oldEntryPoint.Instructions.ReplaceList(new[] { loopContainer }); if (exitTargetBlock != null) oldEntryPoint.Instructions.Add(new Branch(exitTargetBlock)); - loopContainer.ILRange = newEntryPoint.ILRange; + loopContainer.AddILRange(newEntryPoint); MoveBlocksIntoContainer(loop, loopContainer); // Rewrite branches within the loop from oldEntryPoint to newEntryPoint: @@ -654,7 +654,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (branch.TargetBlock == oldEntryPoint) { branch.TargetBlock = newEntryPoint; } else if (branch.TargetBlock == exitTargetBlock) { - branch.ReplaceWith(new Leave(loopContainer) { ILRange = branch.ILRange }); + branch.ReplaceWith(new Leave(loopContainer).WithILRange(branch)); } } } @@ -723,7 +723,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow BlockContainer switchContainer = new BlockContainer(ContainerKind.Switch); Block newEntryPoint = new Block(); - newEntryPoint.ILRange = switchInst.ILRange; + newEntryPoint.AddILRange(switchInst); switchContainer.Blocks.Add(newEntryPoint); newEntryPoint.Instructions.Add(switchInst); block.Instructions[block.Instructions.Count - 1] = switchContainer; @@ -733,13 +733,13 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow block.Instructions.Add(new Branch(exitTargetBlock)); } - switchContainer.ILRange = newEntryPoint.ILRange; + switchContainer.AddILRange(newEntryPoint); MoveBlocksIntoContainer(nodesInSwitch, switchContainer); // Rewrite branches within the loop from oldEntryPoint to newEntryPoint: foreach (var branch in switchContainer.Descendants.OfType()) { if (branch.TargetBlock == exitTargetBlock) { - branch.ReplaceWith(new Leave(switchContainer) { ILRange = branch.ILRange }); + branch.ReplaceWith(new Leave(switchContainer).WithILRange(branch)); } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs index 4cb5014ce..6a4429ec4 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs @@ -180,7 +180,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Remove branch/leave after if; it's getting moved into a section. block.Instructions.RemoveAt(block.Instructions.Count - 1); } - sw.ILRange = block.Instructions[block.Instructions.Count - 1].ILRange; + sw.AddILRange(block.Instructions[block.Instructions.Count - 1]); block.Instructions[block.Instructions.Count - 1] = sw; // mark all inner blocks that were converted to the switch statement for deletion @@ -317,7 +317,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // The switch has a single break target and there is one more hint // The break target cannot be inlined, and should have the highest IL offset of everything targetted by the switch - return breakBlock.ILRange.Start >= analysis.Sections.Select(s => s.Value.MatchBranch(out var b) ? b.ILRange.Start : -1).Max(); + return breakBlock.StartILOffset >= analysis.Sections.Select(s => s.Value.MatchBranch(out var b) ? b.StartILOffset : -1).Max(); } /// diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs index 1136574b2..fc6f6dcc0 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs @@ -649,10 +649,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private BlockContainer ConvertBody(BlockContainer oldBody, StateRangeAnalysis rangeAnalysis) { var blockStateMap = rangeAnalysis.GetBlockStateSetMapping(oldBody); - BlockContainer newBody = new BlockContainer() { ILRange = oldBody.ILRange }; + BlockContainer newBody = new BlockContainer().WithILRange(oldBody); // create all new blocks so that they can be referenced by gotos for (int blockIndex = 0; blockIndex < oldBody.Blocks.Count; blockIndex++) { - newBody.Blocks.Add(new Block { ILRange = oldBody.Blocks[blockIndex].ILRange }); + newBody.Blocks.Add(new Block().WithILRange(oldBody.Blocks[blockIndex])); } // convert contents of blocks @@ -670,14 +670,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // We keep the state-changing instruction around (as first instruction of the new block) // for reconstructing the try-finallys. } else { - newBlock.Instructions.Add(new InvalidExpression("Assigned non-constant to iterator.state field") { - ILRange = oldInst.ILRange - }); + newBlock.Instructions.Add(new InvalidExpression("Assigned non-constant to iterator.state field").WithILRange(oldInst)); continue; // don't copy over this instruction, but continue with the basic block } } else if (field.MemberDefinition.Equals(currentField)) { // create yield return - newBlock.Instructions.Add(new YieldReturn(value) { ILRange = oldInst.ILRange }); + newBlock.Instructions.Add(new YieldReturn(value).WithILRange(oldInst)); ConvertBranchAfterYieldReturn(newBlock, oldBlock, oldInst.ChildIndex + 1); break; // we're done with this basic block } @@ -696,7 +694,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } // copy over the instruction to the new block newBlock.Instructions.Add(oldInst); - newBlock.AddILRange(oldInst.ILRange); + newBlock.AddILRange(oldInst); UpdateBranchTargets(oldInst); } } @@ -781,7 +779,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { if (newBlock.Instructions.Count > 0) { var newBlock2 = new Block(); - newBlock2.ILRange = new Interval(oldInst.ILRange.Start, oldInst.ILRange.Start); + newBlock2.AddILRange(new Interval(oldInst.StartILOffset, oldInst.StartILOffset)); newBody.Blocks.Add(newBlock2); newBlock.Instructions.Add(new Branch(newBlock2)); newBlock = newBlock2; @@ -821,9 +819,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } if (value.MatchLdcI4(0)) { // yield break - leave.ReplaceWith(new Leave(newBody) { ILRange = leave.ILRange }); + leave.ReplaceWith(new Leave(newBody).WithILRange(leave)); } else { - leave.ReplaceWith(new InvalidBranch("Unexpected return in MoveNext()") { ILRange = leave.ILRange }); + leave.ReplaceWith(new InvalidBranch("Unexpected return in MoveNext()").WithILRange(leave)); } } else { if (leave.TargetContainer == oldBody) { @@ -861,25 +859,25 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } if (v.StackType == StackType.Ref) { Debug.Assert(v.Kind == VariableKind.Parameter && v.Index < 0); // this pointer - inst.ReplaceWith(new LdLoc(v) { ILRange = inst.ILRange }); + inst.ReplaceWith(new LdLoc(v).WithILRange(inst)); } else { - inst.ReplaceWith(new LdLoca(v) { ILRange = inst.ILRange }); + inst.ReplaceWith(new LdLoca(v).WithILRange(inst)); } } else if (!isCompiledWithMono && inst.MatchLdThis()) { - inst.ReplaceWith(new InvalidExpression("stateMachine") { ExpectedResultType = inst.ResultType, ILRange = inst.ILRange }); + inst.ReplaceWith(new InvalidExpression("stateMachine") { ExpectedResultType = inst.ResultType }.WithILRange(inst)); } else { foreach (var child in inst.Children) { TranslateFieldsToLocalAccess(function, child, fieldToVariableMap, isCompiledWithMono); } if (inst is LdObj ldobj && ldobj.Target is LdLoca ldloca && ldloca.Variable.StateMachineField != null) { LdLoc ldloc = new LdLoc(ldloca.Variable); - ldloc.AddILRange(ldobj.ILRange); - ldloc.AddILRange(ldloca.ILRange); + ldloc.AddILRange(ldobj); + ldloc.AddILRange(ldloca); inst.ReplaceWith(ldloc); } else if (inst is StObj stobj && stobj.Target is LdLoca ldloca2 && ldloca2.Variable.StateMachineField != null) { StLoc stloc = new StLoc(ldloca2.Variable, stobj.Value); - stloc.AddILRange(stobj.ILRange); - stloc.AddILRange(ldloca2.ILRange); + stloc.AddILRange(stobj); + stloc.AddILRange(ldloca2); inst.ReplaceWith(stloc); } } @@ -988,11 +986,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow finallyMethodToStateRange.Remove(finallyMethod); var tryBlock = new Block(); - tryBlock.ILRange = block.ILRange; + tryBlock.AddILRange(block); tryBlock.Instructions.AddRange(block.Instructions); var tryBlockContainer = new BlockContainer(); tryBlockContainer.Blocks.Add(tryBlock); - tryBlockContainer.ILRange = tryBlock.ILRange; + tryBlockContainer.AddILRange(tryBlock); stateToContainer.Add(state, tryBlockContainer); ILInstruction finallyBlock; @@ -1006,7 +1004,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } block.Instructions.Clear(); - block.Instructions.Add(new TryFinally(tryBlockContainer, finallyBlock) { ILRange = tryBlockContainer.ILRange}); + block.Instructions.Add(new TryFinally(tryBlockContainer, finallyBlock).WithILRange(tryBlockContainer)); } IMethod FindFinallyMethod(int state) diff --git a/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs b/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs new file mode 100644 index 000000000..222d82daa --- /dev/null +++ b/ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ICSharpCode.Decompiler.Util; + +namespace ICSharpCode.Decompiler.IL +{ + internal static class ILInstructionExtensions + { + public static T WithILRange(this T target, ILInstruction sourceInstruction) where T : ILInstruction + { + target.AddILRange(sourceInstruction); + return target; + } + + public static T WithILRange(this T target, Interval range) where T : ILInstruction + { + target.AddILRange(range); + return target; + } + } +} diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index aea71a8c0..4d98af2fd 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -389,8 +389,8 @@ namespace ICSharpCode.Decompiler.IL Warn("Unknown result type (might be due to invalid IL or missing references)"); decodedInstruction.CheckInvariant(ILPhase.InILReader); int end = reader.Offset; - decodedInstruction.ILRange = new Interval(start, end); - UnpackPush(decodedInstruction).ILRange = decodedInstruction.ILRange; + decodedInstruction.AddILRange(new Interval(start, end)); + UnpackPush(decodedInstruction).AddILRange(decodedInstruction); instructionBuilder.Add(decodedInstruction); if (decodedInstruction.HasDirectFlag(InstructionFlags.EndPointUnreachable)) { if (!stackByOffset.TryGetValue(end, out currentStack)) { @@ -429,8 +429,7 @@ namespace ICSharpCode.Decompiler.IL value = new Conv(value, additionalVar.StackType.ToPrimitiveType(), false, Sign.Signed); newInstructions.Add(new StLoc(additionalVar, value) { IsStackAdjustment = true, - ILRange = inst.ILRange - }); + }.WithILRange(inst)); } } } @@ -454,7 +453,7 @@ namespace ICSharpCode.Decompiler.IL } output.Write(" ["); bool isFirstElement = true; - foreach (var element in stackByOffset[inst.ILRange.Start]) { + foreach (var element in stackByOffset[inst.StartILOffset]) { if (isFirstElement) isFirstElement = false; else @@ -465,11 +464,11 @@ namespace ICSharpCode.Decompiler.IL } output.Write(']'); output.WriteLine(); - if (isBranchTarget[inst.ILRange.Start]) + if (isBranchTarget[inst.StartILOffset]) output.Write('*'); else output.Write(' '); - output.WriteLocalReference("IL_" + inst.ILRange.Start.ToString("x4"), inst.ILRange.Start, isDefinition: true); + output.WriteLocalReference("IL_" + inst.StartILOffset.ToString("x4"), inst.StartILOffset, isDefinition: true); output.Write(": "); inst.WriteTo(output, new ILAstWritingOptions()); output.WriteLine(); @@ -1033,7 +1032,7 @@ namespace ICSharpCode.Decompiler.IL var variable = unionFind.Find(inst.Variable); if (variables.Add(variable)) variable.Name = "S_" + (variables.Count - 1); - return new LdLoc(variable) { ILRange = inst.ILRange }; + return new LdLoc(variable).WithILRange(inst); } return inst; } @@ -1045,7 +1044,7 @@ namespace ICSharpCode.Decompiler.IL var variable = unionFind.Find(inst.Variable); if (variables.Add(variable)) variable.Name = "S_" + (variables.Count - 1); - return new StLoc(variable, inst.Value) { ILRange = inst.ILRange }; + return new StLoc(variable, inst.Value).WithILRange(inst); } return inst; } @@ -1064,7 +1063,7 @@ namespace ICSharpCode.Decompiler.IL ILInstruction Peek() { if (currentStack.IsEmpty) { - return new InvalidExpression("Stack underflow") { ILRange = new Interval(reader.Offset, reader.Offset) }; + return new InvalidExpression("Stack underflow").WithILRange(new Interval(reader.Offset, reader.Offset)); } return new LdLoc(currentStack.Peek()); } @@ -1072,7 +1071,7 @@ namespace ICSharpCode.Decompiler.IL ILInstruction Pop() { if (currentStack.IsEmpty) { - return new InvalidExpression("Stack underflow") { ILRange = new Interval(reader.Offset, reader.Offset) }; + return new InvalidExpression("Stack underflow").WithILRange(new Interval(reader.Offset, reader.Offset)); } ILVariable v; currentStack = currentStack.Pop(out v); @@ -1490,7 +1489,7 @@ namespace ICSharpCode.Decompiler.IL int start = reader.Offset - 1; // opCode is always one byte in this case int target = ILParser.DecodeBranchTarget(ref reader, opCode); var condition = Comparison(kind, un); - condition.ILRange = new Interval(start, reader.Offset); + condition.AddILRange(new Interval(start, reader.Offset)); if (!IsInvalidBranch(target)) { MarkBranchTarget(target); return new IfInstruction(condition, new Branch(target)); diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 5dba36269..27e0af93d 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -346,7 +346,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('('); this.argument.WriteTo(output, options); @@ -439,7 +439,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('('); this.left.WriteTo(output, options); @@ -596,7 +596,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('('); this.target.WriteTo(output, options); @@ -971,7 +971,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); variable.WriteTo(output); @@ -2282,7 +2282,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); variable.WriteTo(output); @@ -2357,7 +2357,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); variable.WriteTo(output); @@ -2490,7 +2490,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); variable.WriteTo(output); @@ -2585,7 +2585,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('('); this.value.WriteTo(output, options); @@ -2748,7 +2748,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, Value); @@ -2785,7 +2785,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.I4; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, Value); @@ -2822,7 +2822,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.I8; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, Value); @@ -2859,7 +2859,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.F4; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, Value); @@ -2896,7 +2896,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.F8; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, Value); @@ -2933,7 +2933,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, Value); @@ -3000,7 +3000,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.I; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); method.WriteTo(output); @@ -3048,7 +3048,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); method.WriteTo(output); @@ -3093,7 +3093,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -3132,7 +3132,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); member.WriteTo(output); @@ -3220,7 +3220,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -3355,7 +3355,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) @@ -3503,7 +3503,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) @@ -3616,7 +3616,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (DelayExceptions) output.Write("delayex."); output.Write(OpCode); @@ -3660,7 +3660,7 @@ namespace ICSharpCode.Decompiler.IL public IField Field { get { return field; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); field.WriteTo(output); @@ -3711,7 +3711,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -3756,7 +3756,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -3862,7 +3862,7 @@ namespace ICSharpCode.Decompiler.IL } void OriginalWriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) @@ -3996,7 +3996,7 @@ namespace ICSharpCode.Decompiler.IL } void OriginalWriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) @@ -4062,7 +4062,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -4116,7 +4116,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -4170,7 +4170,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -4284,7 +4284,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -4333,7 +4333,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return type.GetStackType(); } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -4449,7 +4449,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.I4; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -4643,7 +4643,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (DelayExceptions) output.Write("delayex."); if (IsReadOnly) @@ -4747,7 +4747,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('('); this.array.WriteTo(output, options); @@ -4984,7 +4984,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); method.WriteTo(output); @@ -5999,7 +5999,7 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -6081,7 +6081,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); type.WriteTo(output); @@ -6176,7 +6176,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('('); this.value.WriteTo(output, options); @@ -6269,7 +6269,7 @@ namespace ICSharpCode.Decompiler.IL } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('('); this.value.WriteTo(output, options); @@ -6331,7 +6331,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('('); output.Write(')'); diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 2ab4f2091..4d63cc974 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -595,7 +595,7 @@ namespace ICSharpCode.Decompiler.IL public IEnumerable WriteToBody { get { - yield return "ILRange.WriteTo(output, options);"; + yield return "WriteILRange(output, options);"; foreach (string line in WriteOpCodePrefix) yield return line; yield return "output.Write(OpCode);"; diff --git a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs index 8df06d54e..f31db7d29 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs @@ -177,7 +177,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write("." + GetOperatorName(Operator)); if (CheckForOverflow) { diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs index 1ff08ba12..ab04f550e 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs @@ -95,7 +95,7 @@ namespace ICSharpCode.Decompiler.IL public override ILInstruction Clone() { Block clone = new Block(Kind); - clone.ILRange = this.ILRange; + clone.AddILRange(this); clone.Instructions.AddRange(this.Instructions.Select(inst => inst.Clone())); clone.FinalInstruction = this.FinalInstruction.Clone(); return clone; @@ -145,12 +145,12 @@ namespace ICSharpCode.Decompiler.IL /// public string Label { - get { return Disassembler.DisassemblerHelpers.OffsetToString(this.ILRange.Start); } + get { return Disassembler.DisassemblerHelpers.OffsetToString(this.StartILOffset); } } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("Block "); output.WriteLocalReference(Label, this, isDefinition: true); if (Kind != BlockKind.ControlFlow) diff --git a/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs b/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs index 4bb565db2..0e178853b 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs @@ -81,7 +81,7 @@ namespace ICSharpCode.Decompiler.IL public override ILInstruction Clone() { BlockContainer clone = new BlockContainer(); - clone.ILRange = this.ILRange; + clone.AddILRange(this); clone.Blocks.AddRange(this.Blocks.Select(block => (Block)block.Clone())); // Adjust branch instructions to point to the new container foreach (var branch in clone.Descendants.OfType()) { @@ -117,7 +117,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.WriteLocalReference("BlockContainer", this, isDefinition: true); output.Write(' '); switch (Kind) { @@ -181,7 +181,7 @@ namespace ICSharpCode.Decompiler.IL base.CheckInvariant(phase); Debug.Assert(Blocks.Count > 0 && EntryPoint == Blocks[0]); Debug.Assert(!IsConnected || EntryPoint?.IncomingEdgeCount >= 1); - Debug.Assert(EntryPoint == null || Parent is ILFunction || !ILRange.IsEmpty); + Debug.Assert(EntryPoint == null || Parent is ILFunction || !HasILRange); Debug.Assert(Blocks.All(b => b.HasFlag(InstructionFlags.EndPointUnreachable))); Debug.Assert(Blocks.All(b => b.Kind == BlockKind.ControlFlow)); // this also implies that the blocks don't use FinalInstruction Block bodyStartBlock; diff --git a/ICSharpCode.Decompiler/IL/Instructions/Branch.cs b/ICSharpCode.Decompiler/IL/Instructions/Branch.cs index a9e78b330..b42eed3b2 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Branch.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Branch.cs @@ -40,11 +40,11 @@ namespace ICSharpCode.Decompiler.IL public Branch(Block targetBlock) : base(OpCode.Branch) { this.targetBlock = targetBlock ?? throw new ArgumentNullException(nameof(targetBlock)); - this.targetILOffset = targetBlock.ILRange.Start; + this.targetILOffset = targetBlock.StartILOffset; } public int TargetILOffset { - get { return targetBlock != null ? targetBlock.ILRange.Start : targetILOffset; } + get { return targetBlock != null ? targetBlock.StartILOffset : targetILOffset; } } public Block TargetBlock { @@ -113,7 +113,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write(' '); output.WriteLocalReference(TargetLabel, (object)targetBlock ?? TargetILOffset); diff --git a/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs b/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs index 6deb6a8ce..07f980fa7 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs @@ -76,9 +76,7 @@ namespace ICSharpCode.Decompiler.IL { return new CallIndirect(CallingConvention, ReturnType, ParameterTypes, this.Arguments.Select(inst => inst.Clone()), functionPointer.Clone() - ) { - ILRange = this.ILRange - }; + ).WithILRange(this); } public override StackType ResultType => ReturnType.GetStackType(); @@ -91,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("call.indirect "); ReturnType.WriteTo(output); output.Write('('); diff --git a/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs index 0835cab35..fec533c9e 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs @@ -132,7 +132,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (ConstrainedTo != null) { output.Write("constrained["); ConstrainedTo.WriteTo(output, ILNameSyntax.ShortTypeName); diff --git a/ICSharpCode.Decompiler/IL/Instructions/Comp.cs b/ICSharpCode.Decompiler/IL/Instructions/Comp.cs index 4d474bb71..34e4ecf39 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Comp.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Comp.cs @@ -175,7 +175,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (options.UseLogicOperationSugar && MatchLogicNot(out var arg)) { output.Write("logic.not("); arg.WriteTo(output, options); @@ -214,11 +214,6 @@ namespace ICSharpCode.Decompiler.IL { return new Comp(ComparisonKind.Equality, Sign.None, arg, new LdcI4(0)); } - - public static Comp LogicNot(ILInstruction arg, Interval ilrange) - { - return new Comp(ComparisonKind.Equality, Sign.None, arg, new LdcI4(0)) { ILRange = ilrange }; - } } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs index 0c599ee35..753c3be1a 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs @@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.IL this.Operator = binary.Operator; this.IsLifted = binary.IsLifted; this.type = type; - this.ILRange = binary.ILRange; + this.AddILRange(binary); Debug.Assert(compoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue || (Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub)); Debug.Assert(IsValidCompoundAssignmentTarget(Target)); } @@ -172,7 +172,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write("." + BinaryNumericInstruction.GetOperatorName(Operator)); if (CompoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue) @@ -216,7 +216,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (CompoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue) @@ -253,7 +253,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write("." + Operation.ToString().ToLower()); DynamicInstruction.WriteBinderFlags(BinderFlags, output, options); diff --git a/ICSharpCode.Decompiler/IL/Instructions/Conv.cs b/ICSharpCode.Decompiler/IL/Instructions/Conv.cs index 2c07a2143..cd1b86959 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Conv.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Conv.cs @@ -305,7 +305,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (CheckForOverflow) { output.Write(".ovf"); diff --git a/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs index 76aa62fec..1eb663f63 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs @@ -128,7 +128,7 @@ namespace ICSharpCode.Decompiler.IL { public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -180,7 +180,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -224,7 +224,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -260,7 +260,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -297,7 +297,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -329,7 +329,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -361,7 +361,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -397,7 +397,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -438,7 +438,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -484,7 +484,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -529,7 +529,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); @@ -559,7 +559,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); WriteBinderFlags(output, options); output.Write(' '); diff --git a/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs b/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs index 3fa452e24..059572ff5 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs @@ -18,7 +18,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (IsChecked) output.Write(".checked"); output.Write(' '); diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs index b12654d6c..cbebd1c14 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs @@ -121,7 +121,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (Method != null) { output.Write(' '); @@ -183,7 +183,7 @@ namespace ICSharpCode.Decompiler.IL void MarkUsedILRanges(ILInstruction inst) { if (CSharp.SequencePointBuilder.HasUsableILRange(inst)) { - usedILRanges.Add(new LongInterval(inst.ILRange.Start, inst.ILRange.End)); + usedILRanges.Add(new LongInterval(inst.StartILOffset, inst.EndILOffset)); } if (!(inst is ILFunction)) { foreach (var child in inst.Children) { diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs index b7ecdb361..cc400ef3b 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs @@ -206,19 +206,19 @@ namespace ICSharpCode.Decompiler.IL /// /// Gets the ILRange for this instruction alone, ignoring the operands. /// - public Interval ILRange; + private Interval ILRange; public void AddILRange(Interval newRange) { - if (newRange.IsEmpty) { - return; - } if (this.ILRange.IsEmpty) { this.ILRange = newRange; return; } - if (newRange.Start <= this.ILRange.Start) { - if (newRange.End < this.ILRange.Start) { + if (newRange.IsEmpty) { + return; + } + if (newRange.Start <= this.StartILOffset) { + if (newRange.End < this.StartILOffset) { this.ILRange = newRange; // use the earlier range } else { // join overlapping ranges @@ -226,10 +226,38 @@ namespace ICSharpCode.Decompiler.IL } } else if (newRange.Start <= this.ILRange.End) { // join overlapping ranges - this.ILRange = new Interval(this.ILRange.Start, Math.Max(newRange.End, this.ILRange.End)); + this.ILRange = new Interval(this.StartILOffset, Math.Max(newRange.End, this.ILRange.End)); } } + public void AddILRange(ILInstruction sourceInstruction) + { + AddILRange(sourceInstruction.ILRange); + } + + public void SetILRange(ILInstruction sourceInstruction) + { + ILRange = sourceInstruction.ILRange; + } + + public void SetILRange(Interval range) + { + ILRange = range; + } + + public int StartILOffset => ILRange.Start; + + public int EndILOffset => ILRange.End; + + public bool HasILRange => ILRange.IsEmpty; + + public IEnumerable ILRanges => new[] { ILRange }; + + public void WriteILRange(ITextOutput output, ILAstWritingOptions options) + { + ILRange.WriteTo(output, options); + } + /// /// Writes the ILAst to the text output. /// diff --git a/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs index 5926dfdd0..9f22e0d34 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs @@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); if (options.UseLogicOperationSugar) { if (MatchLogicAnd(out var lhs, out var rhs)) { output.Write("logic.and("); diff --git a/ICSharpCode.Decompiler/IL/Instructions/LdLen.cs b/ICSharpCode.Decompiler/IL/Instructions/LdLen.cs index 82f65eb32..4d520883d 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/LdLen.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/LdLen.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write('.'); output.Write(resultType); diff --git a/ICSharpCode.Decompiler/IL/Instructions/Leave.cs b/ICSharpCode.Decompiler/IL/Instructions/Leave.cs index 387a90e86..d0acbd891 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Leave.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Leave.cs @@ -111,7 +111,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (targetContainer != null) { output.Write(' '); diff --git a/ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs index b38c399bc..e30ec162b 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.Decompiler.IL { public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("lock ("); OnExpression.WriteTo(output, options); output.WriteLine(") {"); diff --git a/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs index 3f4a08fd9..d4e8bc7c1 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL { if (options.UseFieldSugar) { if (this.MatchLdFld(out var target, out var field)) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("ldfld "); field.WriteTo(output); output.Write('('); @@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.IL output.Write(')'); return; } else if (this.MatchLdsFld(out field)) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("ldsfld "); field.WriteTo(output); return; @@ -65,7 +65,7 @@ namespace ICSharpCode.Decompiler.IL { if (options.UseFieldSugar) { if (this.MatchStFld(out var target, out var field, out var value)) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("stfld "); field.WriteTo(output); output.Write('('); @@ -75,7 +75,7 @@ namespace ICSharpCode.Decompiler.IL output.Write(')'); return; } else if (this.MatchStsFld(out field, out value)) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("stsfld "); field.WriteTo(output); output.Write('('); diff --git a/ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs index 04606493a..7f3e07816 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs @@ -91,7 +91,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); output.Write("("); valueInst.WriteTo(output, options); diff --git a/ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs index bb3432835..0882e9149 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs @@ -26,7 +26,7 @@ namespace ICSharpCode.Decompiler.IL { public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); // the non-custom WriteTo would add useless parentheses } @@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (Kind != NopKind.Normal) { output.Write("." + Kind.ToString().ToLowerInvariant()); @@ -73,7 +73,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (!string.IsNullOrEmpty(Message)) { output.Write("(\""); @@ -100,7 +100,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (!string.IsNullOrEmpty(Message)) { output.Write("(\""); diff --git a/ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs b/ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs index cd24f1e21..f000eb36d 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs @@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("string.to.int ("); Argument.WriteTo(output, options); output.Write(", { "); diff --git a/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs index ef60070c2..6faacc0a0 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs @@ -76,7 +76,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("switch"); if (IsLifted) output.Write(".lifted"); @@ -125,7 +125,7 @@ namespace ICSharpCode.Decompiler.IL public override ILInstruction Clone() { var clone = new SwitchInstruction(value.Clone()); - clone.ILRange = this.ILRange; + clone.AddILRange(this); clone.Value = value.Clone(); clone.Sections.AddRange(this.Sections.Select(h => (SwitchSection)h.Clone())); return clone; @@ -182,7 +182,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.WriteLocalReference("case", this, isDefinition: true); output.Write(' '); if (HasNullLabel) { diff --git a/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs index 93889bbbd..0158d557a 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs @@ -60,14 +60,14 @@ namespace ICSharpCode.Decompiler.IL public override ILInstruction Clone() { var clone = new TryCatch(TryBlock.Clone()); - clone.ILRange = this.ILRange; + clone.AddILRange(this); clone.Handlers.AddRange(this.Handlers.Select(h => (TryCatchHandler)h.Clone())); return clone; } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(".try "); TryBlock.WriteTo(output, options); foreach (var handler in Handlers) { @@ -162,7 +162,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("catch "); if (variable != null) { output.WriteLocalReference(variable.Name, variable, isDefinition: true); @@ -197,14 +197,12 @@ namespace ICSharpCode.Decompiler.IL public override ILInstruction Clone() { - return new TryFinally(TryBlock.Clone(), finallyBlock.Clone()) { - ILRange = this.ILRange - }; + return new TryFinally(TryBlock.Clone(), finallyBlock.Clone()).WithILRange(this); } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(".try "); TryBlock.WriteTo(output, options); output.Write(" finally "); @@ -293,14 +291,12 @@ namespace ICSharpCode.Decompiler.IL public override ILInstruction Clone() { - return new TryFault(TryBlock.Clone(), faultBlock.Clone()) { - ILRange = this.ILRange - }; + return new TryFault(TryBlock.Clone(), faultBlock.Clone()).WithILRange(this); } public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(".try "); TryBlock.WriteTo(output, options); output.Write(" fault "); diff --git a/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs index 0773fc888..ed4230f22 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs @@ -51,7 +51,7 @@ namespace ICSharpCode.Decompiler.IL public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write(OpCode); if (IsLifted) { output.Write(".lifted"); diff --git a/ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs index 2a9e79ce3..61913e619 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.IL { public override void WriteTo(ITextOutput output, ILAstWritingOptions options) { - ILRange.WriteTo(output, options); + WriteILRange(output, options); output.Write("using ("); Variable.WriteTo(output); output.Write(" = "); diff --git a/ICSharpCode.Decompiler/IL/PointerArithmeticOffset.cs b/ICSharpCode.Decompiler/IL/PointerArithmeticOffset.cs index 46e4598a9..1b7298735 100644 --- a/ICSharpCode.Decompiler/IL/PointerArithmeticOffset.cs +++ b/ICSharpCode.Decompiler/IL/PointerArithmeticOffset.cs @@ -44,14 +44,14 @@ namespace ICSharpCode.Decompiler.IL return countOffsetInst; } } else if (byteOffsetInst.UnwrapConv(ConversionKind.SignExtend) is SizeOf sizeOf && sizeOf.Type.Equals(pointerType.ElementType)) { - return new LdcI4(1) { ILRange = byteOffsetInst.ILRange }; + return new LdcI4(1).WithILRange(byteOffsetInst); } else if (byteOffsetInst.MatchLdcI(out long val)) { // If the offset is a constant, it's possible that the compiler // constant-folded the multiplication. if (elementSize > 0 && (val % elementSize == 0) && val > 0) { val /= elementSize.Value; if (val <= int.MaxValue) { - return new LdcI4((int)val) { ILRange = byteOffsetInst.ILRange }; + return new LdcI4((int)val).WithILRange(byteOffsetInst); } } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/CombineExitsTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/CombineExitsTransform.cs index 8da6ceb66..b1571e1b8 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CombineExitsTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CombineExitsTransform.cs @@ -41,9 +41,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms // leave (elseValue) // => // leave (if (cond) value else elseValue) - IfInstruction value = new IfInstruction(ifInst.Condition, leave.Value, leaveElse.Value) { ILRange = ifInst.ILRange }; - Leave combinedLeave = new Leave(leave.TargetContainer, value) { ILRange = leaveElse.ILRange }; - combinedLeave.AddILRange(leave.ILRange); + IfInstruction value = new IfInstruction(ifInst.Condition, leave.Value, leaveElse.Value); + value.AddILRange(ifInst); + Leave combinedLeave = new Leave(leave.TargetContainer, value); + combinedLeave.AddILRange(leaveElse); + combinedLeave.AddILRange(leave); ifInst.ReplaceWith(combinedLeave); block.Instructions.RemoveAt(combinedLeave.ChildIndex + 1); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs index b2e7a984b..3ca89cfb5 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs @@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } else { // evaluate the value for its side-effects context.Step("remove dead store to stack: evaluate the value for its side-effects", block.Instructions[i]); - copiedExpr.AddILRange(block.Instructions[i].ILRange); + copiedExpr.AddILRange(block.Instructions[i]); block.Instructions[i] = copiedExpr; } } else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr)) { @@ -111,7 +111,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var arg = copiedExpr.Children[j]; var type = context.TypeSystem.FindType(arg.ResultType.ToKnownTypeCode()); uninlinedArgs[j] = new ILVariable(VariableKind.StackSlot, type, arg.ResultType) { - Name = "C_" + arg.ILRange.Start, + Name = "C_" + arg.StartILOffset, HasGeneratedName = true, }; block.Instructions.Insert(i++, new StLoc(uninlinedArgs[j], arg)); diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs index 3a183fdf8..dfdda704c 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms foreach (var inst in function.Descendants) { cancellationToken.ThrowIfCancellationRequested(); if (inst is NewObj call) { - context.StepStartGroup($"TransformDelegateConstruction {call.ILRange}", call); + context.StepStartGroup($"TransformDelegateConstruction {call.StartILOffset}", call); ILFunction f = TransformDelegateConstruction(call, out ILInstruction target); if (f != null && target is IInstructionWithVariableOperand instWithVar) { if (instWithVar.Variable.Kind == VariableKind.Local) { @@ -65,7 +65,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } } - foreach (var target in targetsToReplace.OrderByDescending(t => ((ILInstruction)t).ILRange.Start)) { + foreach (var target in targetsToReplace.OrderByDescending(t => ((ILInstruction)t).StartILOffset)) { context.Step($"TransformDisplayClassUsages {target.Variable}", (ILInstruction)target); function.AcceptVisitor(new TransformDisplayClassUsages(function, target, target.Variable.CaptureScope, orphanedVariableInits, translatedDisplayClasses)); } @@ -204,9 +204,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms nestedContext.StepStartGroup("DelegateConstruction (nested lambdas)", function); ((IILTransform)new DelegateConstruction()).Run(function, nestedContext); nestedContext.StepEndGroup(); - function.AddILRange(target.ILRange); - function.AddILRange(value.ILRange); - function.AddILRange(value.Arguments[1].ILRange); + function.AddILRange(target); + function.AddILRange(value); + function.AddILRange(value.Arguments[1]); return function; } @@ -322,7 +322,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms field = (IField)field.MemberDefinition; ILInstruction value; if (initValues.TryGetValue(field, out DisplayClassVariable info)) { - inst.ReplaceWith(new StLoc(info.variable, inst.Value) { ILRange = inst.ILRange }); + inst.ReplaceWith(new StLoc(info.variable, inst.Value).WithILRange(inst)); } else { if (inst.Value.MatchLdLoc(out var v) && v.Kind == VariableKind.Parameter && currentFunction == v.Function) { // special case for parameters: remove copies of parameter values. @@ -333,7 +333,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; v = currentFunction.RegisterVariable(VariableKind.Local, field.Type, field.Name); v.CaptureScope = captureScope; - inst.ReplaceWith(new StLoc(v, inst.Value) { ILRange = inst.ILRange }); + inst.ReplaceWith(new StLoc(v, inst.Value).WithILRange(inst)); value = new LdLoc(v); } initValues.Add(field, new DisplayClassVariable { value = value, variable = v }); @@ -348,7 +348,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!initValues.TryGetValue((IField)field.MemberDefinition, out DisplayClassVariable info)) return; var replacement = info.value.Clone(); - replacement.ILRange = inst.ILRange; + replacement.SetILRange(inst); inst.ReplaceWith(replacement); } @@ -358,7 +358,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (inst.Target.MatchLdThis() && inst.Field.Name == "$this" && inst.Field.MemberDefinition.ReflectionName.Contains("c__Iterator")) { var variable = currentFunction.Variables.First((f) => f.Index == -1); - inst.ReplaceWith(new LdLoca(variable) { ILRange = inst.ILRange }); + inst.ReplaceWith(new LdLoca(variable).WithILRange(inst)); } if (inst.Parent is LdObj || inst.Parent is StObj) return; @@ -370,11 +370,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; var v = currentFunction.RegisterVariable(VariableKind.Local, field.Type, field.Name); v.CaptureScope = captureScope; - inst.ReplaceWith(new LdLoca(v) { ILRange = inst.ILRange }); + inst.ReplaceWith(new LdLoca(v).WithILRange(inst)); var value = new LdLoc(v); initValues.Add(field, new DisplayClassVariable { value = value, variable = v }); } else if (info.value is LdLoc l) { - inst.ReplaceWith(new LdLoca(l.Variable) { ILRange = inst.ILRange }); + inst.ReplaceWith(new LdLoca(l.Variable).WithILRange(inst)); } else { Debug.Fail("LdFlda pattern not supported!"); } @@ -384,7 +384,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { base.VisitNumericCompoundAssign(inst); if (inst.Target.MatchLdLoc(out var v)) { - inst.ReplaceWith(new StLoc(v, new BinaryNumericInstruction(inst.Operator, inst.Target, inst.Value, inst.CheckForOverflow, inst.Sign) { ILRange = inst.ILRange })); + inst.ReplaceWith(new StLoc(v, new BinaryNumericInstruction(inst.Operator, inst.Target, inst.Value, inst.CheckForOverflow, inst.Sign).WithILRange(inst))); } } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs index c9fa38583..f60e2d490 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/EarlyExpressionTransforms.cs @@ -57,7 +57,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms && !inst.IsVolatile) { context.Step($"stobj(ldloca {v.Name}, ...) => stloc {v.Name}(...)", inst); - inst.ReplaceWith(new StLoc(v, inst.Value) { ILRange = inst.ILRange }); + inst.ReplaceWith(new StLoc(v, inst.Value).WithILRange(inst)); return true; } return false; @@ -77,7 +77,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms && !inst.IsVolatile) { context.Step($"ldobj(ldloca {v.Name}) => ldloc {v.Name}", inst); - inst.ReplaceWith(new LdLoc(v) { ILRange = inst.ILRange }); + inst.ReplaceWith(new LdLoc(v).WithILRange(inst)); return true; } return false; @@ -102,7 +102,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // call(ref, ...) // => stobj(ref, newobj(...)) var newObj = new NewObj(inst.Method); - newObj.ILRange = inst.ILRange; + newObj.AddILRange(inst); newObj.Arguments.AddRange(inst.Arguments.Skip(1)); newObj.ILStackWasEmpty = inst.ILStackWasEmpty; var expr = new StObj(inst.Arguments[0], newObj, inst.Method.DeclaringType); diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index ea3f59466..77e3328c4 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // if (comp(x != 0)) ==> if (x) // comp(comp(...) != 0) => comp(...) context.Step("Remove redundant comp(... != 0)", inst); - inst.Left.AddILRange(inst.ILRange); + inst.Left.AddILRange(inst); inst.ReplaceWith(inst.Left); inst.Left.AcceptVisitor(this); return; @@ -129,7 +129,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // This is a special case where the C# compiler doesn't generate conv.i4 after ldlen. context.Step("comp(ldlen.i4 array == ldc.i4 0)", inst); inst.InputType = StackType.I4; - inst.Left.ReplaceWith(new LdLen(StackType.I4, array) { ILRange = inst.Left.ILRange }); + inst.Left.ReplaceWith(new LdLen(StackType.I4, array).WithILRange(inst.Left)); inst.Right = rightWithoutConv; } else if (inst.Left is Conv conv && conv.TargetType == PrimitiveType.I && conv.Argument.ResultType == StackType.O) { // C++/CLI sometimes uses this weird comparison with null: @@ -137,8 +137,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // -> comp(ldloc obj == ldnull) inst.InputType = StackType.O; inst.Left = conv.Argument; - inst.Right = new LdNull { ILRange = inst.Right.ILRange }; - inst.Right.AddILRange(rightWithoutConv.ILRange); + inst.Right = new LdNull().WithILRange(inst.Right); + inst.Right.AddILRange(rightWithoutConv); } } @@ -161,8 +161,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms && (!inst.CheckForOverflow || context.Settings.AssumeArrayLengthFitsIntoInt32)) { context.Step("conv.i4(ldlen array) => ldlen.i4(array)", inst); - inst.AddILRange(inst.Argument.ILRange); - inst.ReplaceWith(new LdLen(inst.TargetType.GetStackType(), array) { ILRange = inst.ILRange }); + inst.AddILRange(inst.Argument); + inst.ReplaceWith(new LdLen(inst.TargetType.GetStackType(), array).WithILRange(inst)); } } @@ -172,7 +172,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (inst.Type.IsReferenceType == true && inst.Argument.ResultType == inst.ResultType) { // For reference types, box is a no-op. context.Step("box ref-type(arg) => arg", inst); - inst.Argument.AddILRange(inst.ILRange); + inst.Argument.AddILRange(inst); inst.ReplaceWith(inst.Argument); } } @@ -209,7 +209,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if ((!comp.InputType.IsFloatType() && !comp.IsLifted) || comp.Kind.IsEqualityOrInequality()) { context.Step("push negation into comparison", inst); comp.Kind = comp.Kind.Negate(); - comp.AddILRange(inst.ILRange); + comp.AddILRange(inst); inst.ReplaceWith(comp); } comp.AcceptVisitor(this); @@ -220,9 +220,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms IfInstruction ifInst = (IfInstruction)arg; var ldc0 = ifInst.FalseInst; Debug.Assert(ldc0.MatchLdcI4(0)); - ifInst.Condition = Comp.LogicNot(lhs, inst.ILRange); - ifInst.TrueInst = new LdcI4(1) { ILRange = ldc0.ILRange }; - ifInst.FalseInst = Comp.LogicNot(rhs, inst.ILRange); + ifInst.Condition = Comp.LogicNot(lhs).WithILRange(inst); + ifInst.TrueInst = new LdcI4(1).WithILRange(ldc0); + ifInst.FalseInst = Comp.LogicNot(rhs).WithILRange(inst); inst.ReplaceWith(ifInst); ifInst.AcceptVisitor(this); } else if (arg.MatchLogicOr(out lhs, out rhs)) { @@ -232,9 +232,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms IfInstruction ifInst = (IfInstruction)arg; var ldc1 = ifInst.TrueInst; Debug.Assert(ldc1.MatchLdcI4(1)); - ifInst.Condition = Comp.LogicNot(lhs, inst.ILRange); - ifInst.TrueInst = Comp.LogicNot(rhs, inst.ILRange); - ifInst.FalseInst = new LdcI4(0) { ILRange = ldc1.ILRange }; + ifInst.Condition = Comp.LogicNot(lhs).WithILRange(inst); + ifInst.TrueInst = Comp.LogicNot(rhs).WithILRange(inst); + ifInst.FalseInst = new LdcI4(0).WithILRange(ldc1); inst.ReplaceWith(ifInst); ifInst.AcceptVisitor(this); } else { @@ -324,7 +324,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var newVariable = initializerVariable.Function.RegisterVariable(VariableKind.InitializerTarget, type); foreach (var load in initializerVariable.LoadInstructions.ToArray()) { ILInstruction newInst = new LdLoc(newVariable); - newInst.AddILRange(load.ILRange); + newInst.AddILRange(load); if (load.Parent != initializer) newInst = new Conv(newInst, PrimitiveType.I, false, Sign.None); load.ReplaceWith(newInst); @@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } if (transformed != null) { context.Step("User-defined short-circuiting logic operator (roslyn pattern)", condition); - transformed.AddILRange(inst.ILRange); + transformed.AddILRange(inst); inst.ReplaceWith(transformed); return; } @@ -552,7 +552,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (trueInst.Instructions[0].MatchStLoc(out v, out value1) && falseInst.Instructions[0].MatchStLoc(v, out value2)) { context.Step("conditional operator", inst); var newIf = new IfInstruction(Comp.LogicNot(inst.Condition), value2, value1); - newIf.ILRange = inst.ILRange; + newIf.AddILRange(inst); inst.ReplaceWith(new StLoc(v, newIf)); context.RequestRerun(); // trigger potential inlining of the newly created StLoc return newIf; diff --git a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs index d9afadd56..0573d4114 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs @@ -186,9 +186,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms } // combine all conditions and the exit instruction into one IfInstruction: IfInstruction condition = null; - conditionBlock.AddILRange(exit.ILRange); + conditionBlock.AddILRange(exit); foreach (var inst in conditions) { - conditionBlock.AddILRange(inst.ILRange); + conditionBlock.AddILRange(inst); if (condition == null) { condition = inst; if (swap) { @@ -414,7 +414,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // move the increment instruction: newIncremenBlock.Instructions.Add(secondToLast); newIncremenBlock.Instructions.Add(last); - newIncremenBlock.AddILRange(secondToLast.ILRange); + newIncremenBlock.AddILRange(secondToLast); whileLoopBody.Instructions.RemoveRange(secondToLastIndex, 2); whileLoopBody.Instructions.Add(new Branch(newIncremenBlock)); // complete transform. diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs index d042d0b3f..59d48844f 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs @@ -106,14 +106,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms ctorCallStart = function.Descendants.FirstOrDefault(d => d is CallInstruction call && !(call is NewObj) && call.Method.IsConstructor && call.Method.DeclaringType.IsReferenceType == true - && call.Parent is Block)?.ILRange.Start ?? -1; + && call.Parent is Block)?.StartILOffset ?? -1; } - if (inst.ILRange.InclusiveEnd >= ctorCallStart.GetValueOrDefault()) + if (inst.EndILOffset > ctorCallStart.GetValueOrDefault()) return false; var topLevelInst = inst.Ancestors.LastOrDefault(instr => instr.Parent is Block); if (topLevelInst == null) return false; - return topLevelInst.ILRange.InclusiveEnd < ctorCallStart.GetValueOrDefault(); + return topLevelInst.EndILOffset <= ctorCallStart.GetValueOrDefault(); } internal static bool IsCatchWhenBlock(Block block) @@ -184,7 +184,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms int pos = stloc.ChildIndex; if (DoInline(v, stloc.Value, block.Instructions.ElementAtOrDefault(pos + 1), options, context)) { // Assign the ranges of the stloc instruction: - stloc.Value.AddILRange(stloc.ILRange); + stloc.Value.AddILRange(stloc); // Remove the stloc instruction: Debug.Assert(block.Instructions[pos] == stloc); block.Instructions.RemoveAt(pos); @@ -200,7 +200,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } else if (v.Kind == VariableKind.StackSlot) { context.Step("Remove dead store, but keep expression", stloc); // Assign the ranges of the stloc instruction: - stloc.Value.AddILRange(stloc.ILRange); + stloc.Value.AddILRange(stloc); // Remove the stloc, but keep the inner expression stloc.ReplaceWith(stloc.Value); return true; @@ -233,7 +233,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step($"Inline variable '{v.Name}'", inlinedExpression); // Assign the ranges of the ldloc instruction: - inlinedExpression.AddILRange(loadInst.ILRange); + inlinedExpression.AddILRange(loadInst); if (loadInst.OpCode == OpCode.LdLoca) { // it was an ldloca instruction, so we need to use the pseudo-opcode 'addressof' diff --git a/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs index 956da5a47..1c273dd76 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs @@ -86,7 +86,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("LockTransformMCS", block); block.Instructions.RemoveAt(i - 1); block.Instructions.RemoveAt(i - 2); - body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock) { ILRange = objectStore.ILRange }); + body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock).WithILRange(objectStore)); return true; } @@ -129,7 +129,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("LockTransformV2", block); block.Instructions.RemoveAt(i - 1); block.Instructions.RemoveAt(i - 2); - body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock) { ILRange = objectStore.ILRange }); + body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock).WithILRange(objectStore)); return true; } @@ -173,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("LockTransformV4", block); block.Instructions.RemoveAt(i - 1); tryContainer.EntryPoint.Instructions.RemoveAt(0); - body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock) { ILRange = objectStore.ILRange }); + body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock).WithILRange(objectStore)); return true; } @@ -219,7 +219,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms block.Instructions.RemoveAt(i - 1); block.Instructions.RemoveAt(i - 2); tryContainer.EntryPoint.Instructions.RemoveAt(0); - body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock) { ILRange = objectStore.ILRange }); + body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock).WithILRange(objectStore)); return true; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs index 7f0b6f428..979fb1307 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs @@ -71,7 +71,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// Check if "condition ? trueInst : falseInst" can be simplified using the null-conditional operator. /// Returns the replacement instruction, or null if no replacement is possible. /// - internal ILInstruction Run(ILInstruction condition, ILInstruction trueInst, ILInstruction falseInst, Interval ilRange) + internal ILInstruction Run(ILInstruction condition, ILInstruction trueInst, ILInstruction falseInst) { Debug.Assert(context.Settings.NullPropagation); Debug.Assert(!condition.MatchLogicNot(out _), "Caller should pass in positive condition"); @@ -80,16 +80,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms return null; if (comp.Kind == ComparisonKind.Equality) { // testedVar == null ? trueInst : falseInst - return TryNullPropagation(testedVar, falseInst, trueInst, Mode.ReferenceType, ilRange); + return TryNullPropagation(testedVar, falseInst, trueInst, Mode.ReferenceType); } else if (comp.Kind == ComparisonKind.Inequality) { - return TryNullPropagation(testedVar, trueInst, falseInst, Mode.ReferenceType, ilRange); + return TryNullPropagation(testedVar, trueInst, falseInst, Mode.ReferenceType); } } else if (NullableLiftingTransform.MatchHasValueCall(condition, out ILInstruction loadInst)) { // loadInst.HasValue ? trueInst : falseInst if (loadInst.MatchLdLoca(out testedVar)) { - return TryNullPropagation(testedVar, trueInst, falseInst, Mode.NullableByValue, ilRange); + return TryNullPropagation(testedVar, trueInst, falseInst, Mode.NullableByValue); } else if (loadInst.MatchLdLoc(out testedVar)) { - return TryNullPropagation(testedVar, trueInst, falseInst, Mode.NullableByReference, ilRange); + return TryNullPropagation(testedVar, trueInst, falseInst, Mode.NullableByReference); } } return null; @@ -99,7 +99,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// testedVar != null ? nonNullInst : nullInst /// ILInstruction TryNullPropagation(ILVariable testedVar, ILInstruction nonNullInst, ILInstruction nullInst, - Mode mode, Interval ilRange) + Mode mode) { bool removedRewrapOrNullableCtor = false; if (NullableLiftingTransform.MatchNullableCtor(nonNullInst, out _, out var arg)) { @@ -118,13 +118,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms // testedVar != null ? testedVar.AccessChain : null // => testedVar?.AccessChain IntroduceUnwrap(testedVar, varLoad, mode); - return new NullableRewrap(nonNullInst) { ILRange = ilRange }; + return new NullableRewrap(nonNullInst); } else if (nullInst.MatchDefaultValue(out var type) && type.IsKnownType(KnownTypeCode.NullableOfT)) { context.Step($"Null propagation (mode={mode}, output=value type)", nonNullInst); // testedVar != null ? testedVar.AccessChain : default(T?) // => testedVar?.AccessChain IntroduceUnwrap(testedVar, varLoad, mode); - return new NullableRewrap(nonNullInst) { ILRange = ilRange }; + return new NullableRewrap(nonNullInst); } else if (!removedRewrapOrNullableCtor && NullableType.IsNonNullableValueType(returnType)) { context.Step($"Null propagation (mode={mode}, output=null coalescing)", nonNullInst); // testedVar != null ? testedVar.AccessChain : nullInst @@ -136,8 +136,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms new NullableRewrap(nonNullInst), nullInst ) { - UnderlyingResultType = nullInst.ResultType, - ILRange = ilRange + UnderlyingResultType = nullInst.ResultType }; } return null; @@ -180,7 +179,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms IntroduceUnwrap(testedVar, varLoad, mode); ifInst.ReplaceWith(new NullableRewrap( bodyInst - ) { ILRange = ifInst.ILRange }); + ).WithILRange(ifInst)); } bool IsValidAccessChain(ILVariable testedVar, Mode mode, ILInstruction inst, out ILInstruction finalLoad) @@ -286,15 +285,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms Debug.Assert(NullableLiftingTransform.MatchGetValueOrDefault(varLoad, testedVar)); replacement = new NullableUnwrap( varLoad.ResultType, - new LdLoc(testedVar) { ILRange = varLoad.Children[0].ILRange } - ) { ILRange = varLoad.ILRange }; + new LdLoc(testedVar).WithILRange(varLoad.Children[0]) + ).WithILRange(varLoad); break; case Mode.NullableByReference: replacement = new NullableUnwrap( varLoad.ResultType, - new LdLoc(testedVar) { ILRange = varLoad.Children[0].ILRange }, + new LdLoc(testedVar).WithILRange(varLoad.Children[0]), refInput: true - ) { ILRange = varLoad.ILRange }; + ).WithILRange(varLoad); break; default: throw new ArgumentOutOfRangeException("mode"); diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs index 6879392fd..85e2bcc76 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs @@ -147,7 +147,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } if (context.Settings.NullPropagation && !NullPropagationTransform.IsProtectedIfInst(ifInst as IfInstruction)) { var nullPropagated = new NullPropagationTransform(context) - .Run(condition, trueInst, falseInst, ifInst.ILRange); + .Run(condition, trueInst, falseInst)?.WithILRange(ifInst); if (nullPropagated != null) return nullPropagated; } @@ -156,7 +156,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (AnalyzeCondition(condition)) { // (v1 != null && ... && vn != null) ? trueInst : falseInst // => normal lifting - return LiftNormal(trueInst, falseInst, ilrange: ifInst.ILRange); + return LiftNormal(trueInst, falseInst)?.WithILRange(ifInst); } if (MatchCompOrDecimal(condition, out var comp)) { // This might be a C#-style lifted comparison @@ -206,36 +206,36 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("NullableLiftingTransform: v == true", ifInst); return new Comp(ComparisonKind.Equality, ComparisonLiftingKind.CSharp, StackType.I4, Sign.None, - new LdLoc(v) { ILRange = trueInst.ILRange }, - new LdcI4(1) { ILRange = falseInst.ILRange } - ) { ILRange = ifInst.ILRange }; + new LdLoc(v).WithILRange(trueInst), + new LdcI4(1).WithILRange(falseInst) + ).WithILRange(ifInst); } else if (trueInst.MatchLdcI4(0) && MatchHasValueCall(falseInst, v)) { // v.GetValueOrDefault() ? false : v.HasValue // ==> v == false context.Step("NullableLiftingTransform: v == false", ifInst); return new Comp(ComparisonKind.Equality, ComparisonLiftingKind.CSharp, StackType.I4, Sign.None, - new LdLoc(v) { ILRange = falseInst.ILRange }, + new LdLoc(v).WithILRange(falseInst), trueInst // LdcI4(0) - ) { ILRange = ifInst.ILRange }; + ).WithILRange(ifInst); } else if (MatchNegatedHasValueCall(trueInst, v) && falseInst.MatchLdcI4(1)) { // v.GetValueOrDefault() ? !v.HasValue : true // ==> v != true context.Step("NullableLiftingTransform: v != true", ifInst); return new Comp(ComparisonKind.Inequality, ComparisonLiftingKind.CSharp, StackType.I4, Sign.None, - new LdLoc(v) { ILRange = trueInst.ILRange }, + new LdLoc(v).WithILRange(trueInst), falseInst // LdcI4(1) - ) { ILRange = ifInst.ILRange }; + ).WithILRange(ifInst); } else if (trueInst.MatchLdcI4(1) && MatchNegatedHasValueCall(falseInst, v)) { // v.GetValueOrDefault() ? true : !v.HasValue // ==> v != false context.Step("NullableLiftingTransform: v != false", ifInst); return new Comp(ComparisonKind.Inequality, ComparisonLiftingKind.CSharp, StackType.I4, Sign.None, - new LdLoc(v) { ILRange = falseInst.ILRange }, - new LdcI4(0) { ILRange = trueInst.ILRange } - ) { ILRange = ifInst.ILRange }; + new LdLoc(v).WithILRange(falseInst), + new LdcI4(0).WithILRange(trueInst) + ).WithILRange(ifInst); } } // Handle & and | on bool?: @@ -246,7 +246,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // condition ? v : (bool?)false // => condition & v context.Step("NullableLiftingTransform: 3vl.bool.and(bool, bool?)", ifInst); - return new ThreeValuedBoolAnd(condition, trueInst) { ILRange = ifInst.ILRange }; + return new ThreeValuedBoolAnd(condition, trueInst).WithILRange(ifInst); } if (falseInst.MatchLdLoc(out var v2)) { // condition ? v : v2 @@ -254,10 +254,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms // (nullable1.GetValueOrDefault() || (!nullable2.GetValueOrDefault() && !nullable1.HasValue)) ? v : v2 if (v == nullable1 && v2 == nullable2) { context.Step("NullableLiftingTransform: 3vl.bool.or(bool?, bool?)", ifInst); - return new ThreeValuedBoolOr(trueInst, falseInst) { ILRange = ifInst.ILRange }; + return new ThreeValuedBoolOr(trueInst, falseInst).WithILRange(ifInst); } else if (v == nullable2 && v2 == nullable1) { context.Step("NullableLiftingTransform: 3vl.bool.and(bool?, bool?)", ifInst); - return new ThreeValuedBoolAnd(falseInst, trueInst) { ILRange = ifInst.ILRange }; + return new ThreeValuedBoolAnd(falseInst, trueInst).WithILRange(ifInst); } } } @@ -267,7 +267,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // condition ? (bool?)true : v // => condition | v context.Step("NullableLiftingTransform: 3vl.logic.or(bool, bool?)", ifInst); - return new ThreeValuedBoolOr(condition, falseInst) { ILRange = ifInst.ILRange }; + return new ThreeValuedBoolOr(condition, falseInst).WithILRange(ifInst); } } return null; @@ -382,9 +382,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal ILInstruction MakeLifted(ComparisonKind newComparisonKind, ILInstruction left, ILInstruction right) { if (Instruction is Comp comp) { - return new Comp(newComparisonKind, ComparisonLiftingKind.CSharp, comp.InputType, comp.Sign, left, right) { - ILRange = Instruction.ILRange - }; + return new Comp(newComparisonKind, ComparisonLiftingKind.CSharp, comp.InputType, comp.Sign, left, right).WithILRange(Instruction); } else if (Instruction is Call call) { IMethod method; if (newComparisonKind == Kind) { @@ -400,10 +398,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return new Call(CSharp.Resolver.CSharpOperators.LiftUserDefinedOperator(method)) { Arguments = { left, right }, ConstrainedTo = call.ConstrainedTo, - ILRange = call.ILRange, ILStackWasEmpty = call.ILStackWasEmpty, IsTail = call.IsTail - }; + }.WithILRange(call); } else { return null; } @@ -531,10 +528,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return new Call(liftedOperator) { Arguments = { left, right }, ConstrainedTo = call.ConstrainedTo, - ILRange = call.ILRange, ILStackWasEmpty = call.ILStackWasEmpty, IsTail = call.IsTail, - }; + }.WithILRange(call); } return null; } @@ -549,7 +545,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// where the v1,...,vn are the this.nullableVars. /// If lifting fails, returns null. /// - ILInstruction LiftNormal(ILInstruction trueInst, ILInstruction falseInst, Interval ilrange) + ILInstruction LiftNormal(ILInstruction trueInst, ILInstruction falseInst) { if (trueInst.MatchIfInstructionPositiveCondition(out var nestedCondition, out var nestedTrue, out var nestedFalse)) { // Sometimes Roslyn generates pointless conditions like: @@ -569,8 +565,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // => v ?? fallback context.Step("v.HasValue ? v : fallback => v ?? fallback", trueInst); return new NullCoalescingInstruction(NullCoalescingKind.Nullable, trueInst, falseInst) { - UnderlyingResultType = NullableType.GetUnderlyingType(nullableVars[0].Type).GetStackType(), - ILRange = ilrange + UnderlyingResultType = NullableType.GetUnderlyingType(nullableVars[0].Type).GetStackType() }; } else if (trueInst is Call call && !call.IsLifted && CSharp.Resolver.CSharpOperators.IsComparisonOperator(call.Method) @@ -592,10 +587,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return new Call(liftedOperator) { Arguments = { left, right }, ConstrainedTo = call.ConstrainedTo, - ILRange = call.ILRange, ILStackWasEmpty = call.ILStackWasEmpty, IsTail = call.IsTail - }; + }.WithILRange(call); } } } @@ -619,9 +613,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms inputUType.GetStackType(), inputUType.GetSign(), utype.ToPrimitiveType(), checkForOverflow: false, isLifted: true - ) { - ILRange = ilrange - }; + ); } } else { context.Step("NullableLiftingTransform.DoLift", trueInst); @@ -639,15 +631,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms } if (isNullCoalescingWithNonNullableFallback) { lifted = new NullCoalescingInstruction(NullCoalescingKind.NullableWithValueFallback, lifted, falseInst) { - UnderlyingResultType = exprToLift.ResultType, - ILRange = ilrange + UnderlyingResultType = exprToLift.ResultType }; } else if (!MatchNull(falseInst, utype)) { // Normal lifting, but the falseInst isn't `default(utype?)` // => use the `??` operator to provide the fallback value. lifted = new NullCoalescingInstruction(NullCoalescingKind.Nullable, lifted, falseInst) { - UnderlyingResultType = exprToLift.ResultType, - ILRange = ilrange + UnderlyingResultType = exprToLift.ResultType }; } return lifted; @@ -681,7 +671,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } if (foundIndices.Any()) - return (new LdLoc(inputVar) { ILRange = inst.ILRange }, foundIndices); + return (new LdLoc(inputVar).WithILRange(inst), foundIndices); else return (null, null); } else if (inst is Conv conv) { @@ -693,17 +683,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms // (thus causing it not to throw when any of them is null). return (null, null); } - var newInst = new Conv(arg, conv.InputType, conv.InputSign, conv.TargetType, conv.CheckForOverflow, isLifted: true) { - ILRange = conv.ILRange - }; + var newInst = new Conv(arg, conv.InputType, conv.InputSign, conv.TargetType, conv.CheckForOverflow, isLifted: true).WithILRange(conv); return (newInst, bits); } } else if (inst is BitNot bitnot) { var (arg, bits) = DoLift(bitnot.Argument); if (arg != null) { - var newInst = new BitNot(arg, isLifted: true, stackType: bitnot.ResultType) { - ILRange = bitnot.ILRange - }; + var newInst = new BitNot(arg, isLifted: true, stackType: bitnot.ResultType).WithILRange(bitnot); return (newInst, bits); } } else if (inst is BinaryNumericInstruction binary) { @@ -720,9 +706,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms binary.LeftInputType, binary.RightInputType, binary.CheckForOverflow, binary.Sign, isLifted: true - ) { - ILRange = binary.ILRange - }; + ).WithILRange(binary); return (newInst, bits); } } else if (inst is Comp comp && !comp.IsLifted && comp.Kind == ComparisonKind.Equality @@ -734,9 +718,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // except for operator! on bool?. var (arg, bits) = DoLift(comp.Left); Debug.Assert(arg != null); - var newInst = new Comp(comp.Kind, ComparisonLiftingKind.ThreeValuedLogic, comp.InputType, comp.Sign, arg, comp.Right.Clone()) { - ILRange = comp.ILRange - }; + var newInst = new Comp(comp.Kind, ComparisonLiftingKind.ThreeValuedLogic, comp.InputType, comp.Sign, arg, comp.Right.Clone()).WithILRange(comp); return (newInst, bits); } else if (inst is Call call && call.Method.IsOperator) { // Lifted user-defined operators, except for comparison operators (as those return bool, not bool?) @@ -765,8 +747,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms ConstrainedTo = call.ConstrainedTo, IsTail = call.IsTail, ILStackWasEmpty = call.ILStackWasEmpty, - ILRange = call.ILRange - }; + }.WithILRange(call); newInst.Arguments.AddRange(newArgs); return (newInst, newBits); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs index 2bbefce3a..1e430c443 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs @@ -136,9 +136,9 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(ifInst != block.Instructions.Last()); - var trueRange = ConditionDetection.GetILRange(ifInst.TrueInst); - var falseRange = ConditionDetection.GetILRange(block.Instructions[block.Instructions.IndexOf(ifInst)+1]); - if (!trueRange.IsEmpty && !falseRange.IsEmpty && falseRange.Start < trueRange.Start) + var trueRangeStart = ConditionDetection.GetStartILOffset(ifInst.TrueInst, out bool trueRangeIsEmpty); + var falseRangeStart = ConditionDetection.GetStartILOffset(block.Instructions[block.Instructions.IndexOf(ifInst)+1], out bool falseRangeIsEmpty); + if (!trueRangeIsEmpty && !falseRangeIsEmpty && falseRangeStart < trueRangeStart) ConditionDetection.InvertIf(block, ifInst, context); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs index 066dc02b3..a8cd90ee0 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms for (int i = block.Instructions.Count - 1; i >= 0; i--) { SwitchInstruction newSwitch; if (MatchSwitchOnNullable(block.Instructions, i, out newSwitch)) { - newSwitch.ILRange = block.Instructions[i - 2].ILRange; + newSwitch.AddILRange(block.Instructions[i - 2]); block.Instructions[i + 1].ReplaceWith(newSwitch); block.Instructions.RemoveRange(i - 2, 3); i -= 2; @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms continue; } if (MatchRoslynSwitchOnNullable(block.Instructions, i, out newSwitch)) { - newSwitch.ILRange = block.Instructions[i - 1].ILRange; + newSwitch.AddILRange(block.Instructions[i - 1]); block.Instructions[i - 1].ReplaceWith(newSwitch); block.Instructions.RemoveRange(i, 2); i--; diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs index 527f9ad9f..bdd424c49 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs @@ -219,17 +219,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms var inst = new SwitchInstruction(stringToInt); inst.Sections.AddRange(sections); if (extraLoad) { - inst.ILRange = instructions[i - 2].ILRange; + inst.AddILRange(instructions[i - 2]); instructions[i - 2].ReplaceWith(inst); instructions.RemoveRange(i - 1, 3); i -= 2; } else { if (keepAssignmentBefore) { - inst.ILRange = instructions[i].ILRange; + inst.AddILRange(instructions[i]); instructions[i].ReplaceWith(inst); instructions.RemoveAt(i + 1); } else { - inst.ILRange = instructions[i - 1].ILRange; + inst.AddILRange(instructions[i - 1]); instructions[i - 1].ReplaceWith(inst); instructions.RemoveRange(i, 2); i--; @@ -308,7 +308,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var inst = new SwitchInstruction(stringToInt); inst.Sections.AddRange(sections); - inst.ILRange = instructions[i - 1].ILRange; + inst.AddILRange(instructions[i - 1]); instructions[i].ReplaceWith(inst); instructions.RemoveAt(i + 1); instructions.RemoveAt(i - 1); @@ -477,8 +477,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!right.MatchLdcI4(0)) return false; - sections.Add(new SwitchSection() { Body = ifInst.TrueInst, Labels = new LongSet(0), ILRange = ifInst.ILRange }); - sections.Add(new SwitchSection() { Body = switchBlock.Instructions[1], Labels = new LongSet(0).Invert(), ILRange = switchBlock.Instructions[1].ILRange }); + sections.Add(new SwitchSection() { Body = ifInst.TrueInst, Labels = new LongSet(0) }.WithILRange(ifInst)); + sections.Add(new SwitchSection() { Body = switchBlock.Instructions[1], Labels = new LongSet(0).Invert() }.WithILRange(switchBlock.Instructions[1])); break; } // mcs: map sections without a value to the default section, if possible @@ -501,12 +501,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms instructions[i + 1].ReplaceWith(inst); if (keepAssignmentBefore) { // delete if (comp(ldloc switchValueVar == ldnull)) - inst.ILRange = instructions[i].ILRange; + inst.AddILRange(instructions[i]); instructions.RemoveAt(i); i--; } else { // delete both the if and the assignment before - inst.ILRange = instructions[i - 1].ILRange; + inst.AddILRange(instructions[i - 1]); instructions.RemoveRange(i - 1, 2); i -= 2; } @@ -721,7 +721,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var stringToInt = new StringToInt(switchValue, stringValues); var inst = new SwitchInstruction(stringToInt); inst.Sections.AddRange(sections); - inst.ILRange = block.Instructions[i].ILRange; + inst.AddILRange(block.Instructions[i]); block.Instructions[i].ReplaceWith(inst); block.Instructions.RemoveRange(i + 1, 3); info.Transformed = true; @@ -819,11 +819,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms newSwitch.Sections.Add(new SwitchSection { Labels = defaultLabel, Body = defaultSection.Body }); instructions[i].ReplaceWith(newSwitch); if (keepAssignmentBefore) { - newSwitch.ILRange = instructions[i - 1].ILRange; + newSwitch.AddILRange(instructions[i - 1]); instructions.RemoveAt(i - 1); i--; } else { - newSwitch.ILRange = instructions[i - 2].ILRange; + newSwitch.AddILRange(instructions[i - 2]); instructions.RemoveRange(i - 2, 2); i -= 2; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index 541fb85bc..33a308ca1 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -321,7 +321,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } else { return false; } - newInst.AddILRange(setterValue.ILRange); + newInst.AddILRange(setterValue); if (storeInSetter != null) { storeInSetter.Value = newInst; newInst = storeInSetter; diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index e8ed3b526..6f8b63741 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -152,13 +152,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!ReadParameters(instruction.Arguments[1], parameterList, parameterVariablesList, new SimpleTypeResolveContext(context.Function.Method))) return (null, SpecialType.UnknownType); var container = new BlockContainer(); - container.ILRange = instruction.ILRange; + container.AddILRange(instruction); var functionType = instruction.Method.ReturnType.TypeArguments[0]; var returnType = functionType.GetDelegateInvokeMethod()?.ReturnType; var function = new ILFunction(returnType, parameterList, context.Function.GenericContext, container); function.DelegateType = functionType; function.Variables.AddRange(parameterVariablesList); - function.ILRange = instruction.ILRange; + function.AddILRange(instruction); lambdaStack.Push(function); var (bodyInstruction, type) = ConvertInstruction(instruction.Arguments[0]); lambdaStack.Pop(); diff --git a/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs index 680b1679e..826228b99 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/UserDefinedLogicTransform.cs @@ -97,9 +97,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (s.IsUsedWithin(call.Arguments[1])) return false; context.Step("User-defined short-circuiting logic operator (legacy pattern)", condition); - ((StLoc)block.Instructions[pos]).Value = new UserDefinedLogicOperator(call.Method, lhsInst, call.Arguments[1]) { - ILRange = call.ILRange - }; + ((StLoc)block.Instructions[pos]).Value = new UserDefinedLogicOperator(call.Method, lhsInst, call.Arguments[1]) + .WithILRange(call); block.Instructions.RemoveAt(pos + 1); context.RequestRerun(); // the 'stloc s' may now be eligible for inlining return true; @@ -148,9 +147,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return null; var result = new UserDefinedLogicOperator(call.Method, call.Arguments[0], call.Arguments[1]); - result.AddILRange(condition.ILRange); - result.AddILRange(trueInst.ILRange); - result.AddILRange(call.ILRange); + result.AddILRange(condition); + result.AddILRange(trueInst); + result.AddILRange(call); return result; } @@ -242,9 +241,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return null; var logicInst = new DynamicLogicOperatorInstruction(binary.BinderFlags, logicOp, binary.CallingContext, binary.LeftArgumentInfo, binary.Left, binary.RightArgumentInfo, binary.Right) - { - ILRange = binary.ILRange - }; + .WithILRange(binary); if (rhsUnary != null) { rhsUnary.Operand = logicInst; return rhsUnary; diff --git a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs index a36fd7753..adccfffa6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/UsingTransform.cs @@ -87,7 +87,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.Step("UsingTransform", tryFinally); storeInst.Variable.Kind = VariableKind.UsingLocal; block.Instructions.RemoveAt(i); - block.Instructions[i - 1] = new UsingInstruction(storeInst.Variable, storeInst.Value, tryFinally.TryBlock) { ILRange = storeInst.ILRange }; + block.Instructions[i - 1] = new UsingInstruction(storeInst.Variable, storeInst.Value, tryFinally.TryBlock).WithILRange(storeInst); return true; }