diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs index 7cccce8bd..689b2860d 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs @@ -16,12 +16,10 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; @@ -109,7 +107,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (objectVariable.LoadCount != 1 || objectVariable.StoreCount > 2) continue; - var beforeExceptionCaptureBlock = (Block)LocalFunctionDecompiler.GetStatement(objectVariable.LoadInstructions[0])?.Parent; + var beforeExceptionCaptureBlock = Block.FindClosestBlock(objectVariable.LoadInstructions[0]); if (beforeExceptionCaptureBlock == null) continue; diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs index 479a8f207..06ea213f0 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs @@ -383,6 +383,22 @@ namespace ICSharpCode.Decompiler.IL return null; } + /// + /// Gets the closest ancestor that is child of a control-flow (top-level) Block. + /// Returns null, if the instruction is not a descendant of a Block. + /// + public static ILInstruction? GetContainingStatement(ILInstruction inst) + { + var curr = inst; + while (curr != null) + { + if (curr.Parent is Block { Kind: BlockKind.ControlFlow }) + return curr; + curr = curr.Parent; + } + return null; + } + public bool MatchInlineAssignBlock([NotNullWhen(true)] out CallInstruction? call, [NotNullWhen(true)] out ILInstruction? value) { call = null; diff --git a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs index f68c6d076..75b3860d9 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs @@ -16,9 +16,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; @@ -107,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // We are only interested in store "statements" copying the exception variable // without modifying it. - var statement = LocalFunctionDecompiler.GetStatement(load); + var statement = Block.GetContainingStatement(load); if (!(statement is StLoc stloc)) { i++; diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index 7d36fb9e2..f73f624f1 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -312,25 +312,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms protected internal override void VisitNewObj(NewObj inst) { - Block block; if (TransformSpanTCtorContainingStackAlloc(inst, out ILInstruction locallocSpan)) { context.Step("new Span(stackalloc) -> stackalloc Span", inst); inst.ReplaceWith(locallocSpan); - block = null; - ILInstruction stmt = locallocSpan; - while (stmt.Parent != null) - { - if (stmt.Parent is Block b) - { - block = b; - break; - } - stmt = stmt.Parent; - } + ILInstruction stmt = Block.GetContainingStatement(locallocSpan); // Special case to eliminate extra store if (stmt.GetNextSibling() is StLoc storeStmt && storeStmt.Value is LdLoc) - ILInlining.InlineIfPossible(block, stmt.ChildIndex, context); + ILInlining.InlineIfPossible((Block)stmt.Parent, stmt.ChildIndex, context); return; } if (TransformArrayInitializers.TransformSpanTArrayInitialization(inst, context, out var replacement)) diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index c377238c1..4b73758b5 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -575,17 +575,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms && TransformDisplayClassUsage.IsPotentialClosure(context.CurrentTypeDefinition, type); } - internal static ILInstruction GetStatement(ILInstruction inst) - { - while (inst.Parent != null) - { - if (inst.Parent is Block b && b.Kind == BlockKind.ControlFlow) - return inst; - inst = inst.Parent; - } - return inst; - } - LocalFunctionMethod ReduceToLocalFunction(IMethod method, int typeParametersToRemove) { int parametersToRemove = 0; @@ -747,7 +736,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (variable.Kind == VariableKind.Parameter) return null; if (type.Kind == TypeKind.Struct) - return GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First()); + return Block.GetContainingStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First()); else return (StLoc)variable.StoreInstructions[0]; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs index c433c3b81..103c77d79 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs @@ -604,7 +604,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (context.Settings.LocalFunctions && closureType?.Kind == TypeKind.Struct && variable.UsesInitialValue && IsPotentialClosure(context, closureType)) { - initializer = LocalFunctionDecompiler.GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First()); + initializer = Block.GetContainingStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First()); return true; } return false;