Browse Source

Implement catch-when and remove local copy of exception slot.

pull/863/head
Siegfried Pammer 8 years ago
parent
commit
c34541ad4c
  1. 2
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  2. 10
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.il
  3. 10
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.opt.il
  4. 103
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.opt.roslyn.il
  5. 114
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.roslyn.il
  6. 1
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  7. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  8. 2
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  9. 39
      ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
  10. 113
      ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs
  11. 38
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  12. 10
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

2
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -92,7 +92,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -92,7 +92,7 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
public void ExceptionHandling([Values(CompilerOptions.None, CompilerOptions.Optimize)] CompilerOptions cscOptions)
public void ExceptionHandling([ValueSource("defaultOptions")] CompilerOptions cscOptions)
{
Run(cscOptions: cscOptions);
}

10
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly gqt5jzz5
.assembly ejk2wcey
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module gqt5jzz5.dll
// MVID: {1567B13E-0DA5-4C78-90CC-FF153FC2F5EA}
.module ejk2wcey.dll
// MVID: {FBD2FAE4-D125-4C61-B03A-EB51D0392AD4}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x017B0000
// Image base: 0x02F20000
// =============== CLASS MEMBERS DECLARATION ===================
@ -111,4 +111,4 @@ @@ -111,4 +111,4 @@
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\ExceptionHandling.res
// WARNING: Created Win32 resource file ../../../TestCases/Pretty\ExceptionHandling.res

10
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.opt.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly o1rsjnei
.assembly '5yiid5o5'
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module o1rsjnei.dll
// MVID: {B8D4207B-6DCF-46D1-AF73-74B4CDFFDE2A}
.module '5yiid5o5.dll'
// MVID: {0663308F-828F-4074-8F95-7D8DB8535889}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x01800000
// Image base: 0x02EC0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -97,4 +97,4 @@ @@ -97,4 +97,4 @@
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\ExceptionHandling.opt.res
// WARNING: Created Win32 resource file ../../../TestCases/Pretty\ExceptionHandling.opt.res

103
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.opt.roslyn.il

@ -0,0 +1,103 @@ @@ -0,0 +1,103 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Copyright (c) Microsoft Corporation. All rights reserved.
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly ExceptionHandling
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module ExceptionHandling.dll
// MVID: {94F74EA5-9EAF-4F51-8FC3-7F9FB3A51DE4}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x023F0000
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExceptionHandling
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance bool B(int32 i) cil managed
{
} // end of method ExceptionHandling::B
.method public hidebysig newslot abstract virtual
instance void M(int32 i) cil managed
{
} // end of method ExceptionHandling::M
.method public hidebysig instance bool
ConditionalReturnInThrow() cil managed
{
// Code size 28 (0x1c)
.maxstack 2
.locals init (bool V_0)
.try
{
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExceptionHandling::B(int32)
IL_0007: brfalse.s IL_0013
IL_0009: ldarg.0
IL_000a: ldc.i4.1
IL_000b: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExceptionHandling::B(int32)
IL_0010: stloc.0
IL_0011: leave.s IL_001a
IL_0013: leave.s IL_0018
} // end .try
catch [mscorlib]System.Object
{
IL_0015: pop
IL_0016: leave.s IL_0018
} // end handler
IL_0018: ldc.i4.0
IL_0019: ret
IL_001a: ldloc.0
IL_001b: ret
} // end of method ExceptionHandling::ConditionalReturnInThrow
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method ExceptionHandling::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExceptionHandling
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

114
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExceptionHandling.roslyn.il

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Copyright (c) Microsoft Corporation. All rights reserved.
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly ExceptionHandling
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module ExceptionHandling.dll
// MVID: {BD40B406-5ECB-4E3A-BB48-79827F1BFB21}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x02A10000
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExceptionHandling
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance bool B(int32 i) cil managed
{
} // end of method ExceptionHandling::B
.method public hidebysig newslot abstract virtual
instance void M(int32 i) cil managed
{
} // end of method ExceptionHandling::M
.method public hidebysig instance bool
ConditionalReturnInThrow() cil managed
{
// Code size 38 (0x26)
.maxstack 2
.locals init (bool V_0,
bool V_1)
IL_0000: nop
.try
{
IL_0001: nop
IL_0002: ldarg.0
IL_0003: ldc.i4.0
IL_0004: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExceptionHandling::B(int32)
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: brfalse.s IL_0018
IL_000d: nop
IL_000e: ldarg.0
IL_000f: ldc.i4.1
IL_0010: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExceptionHandling::B(int32)
IL_0015: stloc.1
IL_0016: leave.s IL_0024
IL_0018: nop
IL_0019: leave.s IL_0020
} // end .try
catch [mscorlib]System.Object
{
IL_001b: pop
IL_001c: nop
IL_001d: nop
IL_001e: leave.s IL_0020
} // end handler
IL_0020: ldc.i4.0
IL_0021: stloc.1
IL_0022: br.s IL_0024
IL_0024: ldloc.1
IL_0025: ret
} // end of method ExceptionHandling::ConditionalReturnInThrow
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method ExceptionHandling::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.ExceptionHandling
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

1
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -73,6 +73,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -73,6 +73,7 @@ namespace ICSharpCode.Decompiler.CSharp
new DetectPinnedRegions(), // must run after inlining but before non-critical control flow transforms
new YieldReturnDecompiler(), // must run after inlining but before loop detection
new AsyncAwaitDecompiler(), // must run after inlining but before loop detection
new DetectCatchWhenConditionBlocks(), // must run after inlining but before loop detection
new DetectExitPoints(canIntroduceExitForReturn: false),
new BlockILTransform {
PostOrderTransforms = {

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -278,6 +278,7 @@ @@ -278,6 +278,7 @@
<Compile Include="IL\ControlFlow\YieldReturnDecompiler.cs" />
<Compile Include="IL\DetectedLoop.cs" />
<Compile Include="IL\Transforms\AssignVariableNames.cs" />
<Compile Include="IL\Transforms\DetectCatchWhenConditionBlocks.cs" />
<Compile Include="IL\Transforms\NullCoalescingTransform.cs" />
<Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" />
<Compile Include="Output\TextTokenWriter.cs" />

2
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.IL @@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction filter;
if (eh.HandlerType == Mono.Cecil.Cil.ExceptionHandlerType.Filter) {
var filterBlock = new BlockContainer();
var filterBlock = new BlockContainer(StackType.I4);
filterBlock.ILRange = new Interval(eh.FilterStart.Offset, eh.HandlerStart.Offset);
filterBlock.Blocks.Add(new Block());
handlerContainers.Add(filterBlock.ILRange.Start, filterBlock);

39
ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs

@ -161,7 +161,18 @@ namespace ICSharpCode.Decompiler.IL @@ -161,7 +161,18 @@ namespace ICSharpCode.Decompiler.IL
value = null;
return false;
}
public bool MatchLeave(BlockContainer targetContainer, out ILInstruction value)
{
var inst = this as Leave;
if (inst != null && targetContainer == inst.TargetContainer) {
value = inst.Value;
return true;
}
value = null;
return false;
}
public bool MatchLeave(out BlockContainer targetContainer)
{
var inst = this as Leave;
@ -280,7 +291,31 @@ namespace ICSharpCode.Decompiler.IL @@ -280,7 +291,31 @@ namespace ICSharpCode.Decompiler.IL
right = null;
return false;
}
/// <summary>
/// Matches comp(left != right) or logic.not(comp(left == right)).
/// </summary>
public bool MatchCompNotEquals(out ILInstruction left, out ILInstruction right)
{
ComparisonKind op;
Comp comp;
if (this is LogicNot logicNot) {
op = ComparisonKind.Equality;
comp = logicNot.Argument as Comp;
} else {
op = ComparisonKind.Inequality;
comp = this as Comp;
}
if (comp != null && comp.Kind == op) {
left = comp.Left;
right = comp.Right;
return true;
}
left = null;
right = null;
return false;
}
public bool MatchLdsFld(IField field)
{
if (this is LdObj ldobj && ldobj.Target is LdsFlda ldsflda) {

113
ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
// Copyright (c) 2017 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL.Transforms
{
public class DetectCatchWhenConditionBlocks : IILTransform
{
public void Run(ILFunction function, ILTransformContext context)
{
foreach (var catchBlock in function.Descendants.OfType<TryCatchHandler>()) {
if (catchBlock.Filter is BlockContainer container && MatchCatchWhenEntryPoint(container, container.EntryPoint, out var exceptionType, out var exceptionSlot, out var whenConditionBlock)) {
// set exceptionType
catchBlock.Variable.Type = exceptionType;
// Block entryPoint (incoming: 1) {
// stloc temp(isinst exceptionType(ldloc exceptionVar))
// if (comp(ldloc temp != ldnull)) br whenConditionBlock
// br falseBlock
// }
// =>
// Block entryPoint (incoming: 1) {
// stloc temp(ldloc exceptionSlot)
// br whenConditionBlock
// }
var instructions = container.EntryPoint.Instructions;
((StLoc)instructions[0]).Value = exceptionSlot;
instructions[1].ReplaceWith(new Branch(whenConditionBlock));
instructions.RemoveAt(2);
container.SortBlocks(deleteUnreachableBlocks: true);
}
}
}
/// <summary>
/// Block entryPoint (incoming: 1) {
/// stloc temp(isinst exceptionType(ldloc exceptionVar))
/// if (comp(ldloc temp != ldnull)) br whenConditionBlock
/// br falseBlock
/// }
/// </summary>
bool MatchCatchWhenEntryPoint(BlockContainer container, Block entryPoint, out IType exceptionType, out ILInstruction exceptionSlot, out Block whenConditionBlock)
{
exceptionType = null;
exceptionSlot = null;
whenConditionBlock = null;
if (entryPoint == null || entryPoint.IncomingEdgeCount != 1 || entryPoint.Instructions.Count != 3)
return false;
if (!entryPoint.Instructions[0].MatchStLoc(out var temp, out var isinst) ||
temp.Kind != VariableKind.StackSlot || !isinst.MatchIsInst(out exceptionSlot, out exceptionType))
return false;
if (!exceptionSlot.MatchLdLoc(out var exceptionVar) || exceptionVar.Kind != VariableKind.Exception)
return false;
if (!entryPoint.Instructions[1].MatchIfInstruction(out var condition, out var branch))
return false;
if (!condition.MatchCompNotEquals(out var left, out var right))
return false;
if (!entryPoint.Instructions[2].MatchBranch(out var falseBlock) || !MatchFalseBlock(container, falseBlock, out var returnVar, out var exitBlock))
return false;
if ((left.MatchLdNull() && right.MatchLdLoc(temp)) || (right.MatchLdNull() && left.MatchLdLoc(temp))) {
return branch.MatchBranch(out whenConditionBlock);
}
return false;
}
/// <summary>
/// Block falseBlock (incoming: 1) {
/// stloc returnVar(ldc.i4 0)
/// br exitBlock
/// }
/// </summary>
bool MatchFalseBlock(BlockContainer container, Block falseBlock, out ILVariable returnVar, out Block exitBlock)
{
returnVar = null;
exitBlock = null;
if (falseBlock.IncomingEdgeCount != 1 || falseBlock.Instructions.Count != 2)
return false;
return falseBlock.Instructions[0].MatchStLoc(out returnVar, out var zero) &&
zero.MatchLdcI4(0) && falseBlock.Instructions[1].MatchBranch(out exitBlock) &&
MatchExitBlock(container, exitBlock, returnVar);
}
/// <summary>
/// Block exitBlock(incoming: 2) {
/// leave container(ldloc returnVar)
/// }
/// </summary>
bool MatchExitBlock(BlockContainer container, Block exitBlock, ILVariable returnVar)
{
if (exitBlock.IncomingEdgeCount != 2 || exitBlock.Instructions.Count != 1)
return false;
return exitBlock.Instructions[0].MatchLeave(container, out var value) &&
value.MatchLdLoc(returnVar);
}
}
}

38
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -320,4 +320,42 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -320,4 +320,42 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
}
protected internal override void VisitTryCatchHandler(TryCatchHandler inst)
{
base.VisitTryCatchHandler(inst);
if (inst.Filter is BlockContainer filterContainer && filterContainer.Blocks.Count == 1) {
TransformCatchWhen(inst, filterContainer.EntryPoint);
}
if (inst.Body is BlockContainer catchContainer)
TransformCatchVariable(inst, catchContainer.EntryPoint);
}
/// <summary>
/// Transform local exception variable.
/// </summary>
void TransformCatchVariable(TryCatchHandler handler, Block entryPoint)
{
if (!entryPoint.Instructions[0].MatchStLoc(out var exceptionVar, out var exceptionSlotLoad))
return;
if (!exceptionVar.IsSingleDefinition || exceptionVar.Kind != VariableKind.Local)
return;
if (!exceptionSlotLoad.MatchLdLoc(handler.Variable) || !handler.Variable.IsSingleDefinition || handler.Variable.LoadCount != 1)
return;
handler.Variable = exceptionVar;
exceptionVar.Kind = VariableKind.Exception;
entryPoint.Instructions.RemoveAt(0);
}
/// <summary>
/// Inline condition from catch-when condition BlockContainer, if possible.
/// </summary>
void TransformCatchWhen(TryCatchHandler handler, Block entryPoint)
{
TransformCatchVariable(handler, entryPoint);
if (entryPoint.Instructions.Count == 1 && entryPoint.Instructions[0].MatchLeave(out _, out var condition)) {
handler.Filter = condition;
}
}
}
}

10
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
bool modified = false;
int i = 0;
while (i < block.Instructions.Count) {
if (InlineOneIfPossible(block, i, aggressive: false, context: context)) {
if (InlineOneIfPossible(block, i, aggressive: IsCatchWhenBlock(block), context: context)) {
modified = true;
i = Math.Max(0, i - 1);
// Go back one step
@ -56,7 +56,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -56,7 +56,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
return modified;
}
static bool IsCatchWhenBlock(Block block)
{
return block.Parent is BlockContainer container && container.Parent is TryCatchHandler handler
&& handler.Filter == container && block == container.EntryPoint;
}
/// <summary>
/// Inlines instructions before pos into block.Instructions[pos].
/// </summary>

Loading…
Cancel
Save