Browse Source

Merge branch '5.0.x' of https://github.com/icsharpcode/ILSpy

pull/1725/head
Siegfried Pammer 6 years ago
parent
commit
a89111b914
  1. 2
      BuildTools/appveyor-install.ps1
  2. 2
      BuildTools/pipelines-install.ps1
  3. 2
      BuildTools/update-assemblyinfo.ps1
  4. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  5. 17
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/FloatingPointArithmetic.cs
  6. 18
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs
  7. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs
  8. 23
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoExtensionMethods.Expected.cs
  9. 17
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoExtensionMethods.cs
  10. 69
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoExtensionMethods.opt.roslyn.il
  11. 81
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoExtensionMethods.roslyn.il
  12. 8
      ICSharpCode.Decompiler.Tests/UglyTestRunner.cs
  13. 32
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  14. 16
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  15. 22
      ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
  16. 32
      ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
  17. 10
      ILSpy/MainWindow.xaml.cs
  18. 2
      ILSpy/Properties/AssemblyInfo.template.cs
  19. 1
      appveyor.yml
  20. 5
      azure-pipelines.yml

2
BuildTools/appveyor-install.ps1

@ -4,7 +4,7 @@ $baseCommit = "d779383cb85003d6dabeb976f0845631e07bf463";
$baseCommitRev = 1; $baseCommitRev = 1;
# make sure this list matches artifacts-only branches list in appveyor.yml! # make sure this list matches artifacts-only branches list in appveyor.yml!
$masterBranches = @("master", "3.2.x"); $masterBranches = @("master", "5.0.x");
$globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs"; $globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs";

2
BuildTools/pipelines-install.ps1

@ -4,7 +4,7 @@ $baseCommit = "d779383cb85003d6dabeb976f0845631e07bf463";
$baseCommitRev = 1; $baseCommitRev = 1;
# make sure this list matches artifacts-only branches list in azure-pipelines.yml! # make sure this list matches artifacts-only branches list in azure-pipelines.yml!
$masterBranches = @("master", "3.2.x"); $masterBranches = @("master", "5.0.x");
$globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs"; $globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs";

2
BuildTools/update-assemblyinfo.ps1

@ -4,7 +4,7 @@ $baseCommit = "d779383cb85003d6dabeb976f0845631e07bf463";
$baseCommitRev = 1; $baseCommitRev = 1;
# make sure this list matches artifacts-only branches list in appveyor.yml! # make sure this list matches artifacts-only branches list in appveyor.yml!
$masterBranches = @("master", "3.2.x"); $masterBranches = @("master", "5.0.x");
$globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs"; $globalAssemblyInfoTemplateFile = "ILSpy/Properties/AssemblyInfo.template.cs";

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -82,6 +82,8 @@
<Compile Include="TestCases\ILPretty\ConstantBlobs.cs" /> <Compile Include="TestCases\ILPretty\ConstantBlobs.cs" />
<Compile Include="TestCases\Pretty\OutVariables.cs" /> <Compile Include="TestCases\Pretty\OutVariables.cs" />
<Compile Include="TestCases\Pretty\CustomTaskType.cs" /> <Compile Include="TestCases\Pretty\CustomTaskType.cs" />
<None Include="TestCases\Ugly\NoExtensionMethods.Expected.cs" />
<Compile Include="TestCases\Ugly\NoExtensionMethods.cs" />
<None Include="TestCases\VBPretty\VBCompoundAssign.cs" /> <None Include="TestCases\VBPretty\VBCompoundAssign.cs" />
<Compile Include="TestCases\Pretty\ThrowExpressions.cs" /> <Compile Include="TestCases\Pretty\ThrowExpressions.cs" />
<None Include="TestCases\ILPretty\Issue1145.cs" /> <None Include="TestCases\ILPretty\Issue1145.cs" />

17
ICSharpCode.Decompiler.Tests/TestCases/Correctness/FloatingPointArithmetic.cs

@ -7,6 +7,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
public static int Main(string[] args) public static int Main(string[] args)
{ {
Issue999(); Issue999();
Issue1656();
return 0; return 0;
} }
@ -20,5 +21,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{ {
return 0.99f * v + 0.01f; return 0.99f * v + 0.01f;
} }
static void Issue1656()
{
double primary = 'B';
CxAssert((++primary) == 'C');
CxAssert((--primary) == 'B');
CxAssert((primary++) == 'B');
CxAssert((primary--) == 'C');
}
static void CxAssert(bool v)
{
if (!v) {
throw new InvalidOperationException();
}
}
} }
} }

18
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Async.cs

@ -167,6 +167,24 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}; };
} }
public static async Task AlwaysThrow()
{
throw null;
}
public static async Task InfiniteLoop()
{
while (true) {
}
}
public static async Task InfiniteLoopWithAwait()
{
while (true) {
await Task.Delay(10);
}
}
#if CS70 #if CS70
public static async Task<int> AsyncLocalFunctions() public static async Task<int> AsyncLocalFunctions()
{ {

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CustomTaskType.cs

@ -1,4 +1,6 @@
using System; #pragma warning disable 1998
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;

23
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoExtensionMethods.Expected.cs

@ -0,0 +1,23 @@
using System;
using System.Runtime.CompilerServices;
[assembly: Extension]
namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly
{
[Extension]
internal static class NoExtensionMethods
{
[Extension]
internal static Func<T> AsFunc<T>(T value) where T : class
{
return new Func<T>(value, __ldftn(Return));
}
[Extension]
private static T Return<T>(T value)
{
return value;
}
}
}

17
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoExtensionMethods.cs

@ -0,0 +1,17 @@
using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly
{
internal static class NoExtensionMethods
{
internal static Func<T> AsFunc<T>(this T value) where T : class
{
return new Func<T>(value.Return);
}
private static T Return<T>(this T value)
{
return value;
}
}
}

69
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoExtensionMethods.opt.roslyn.il

@ -0,0 +1,69 @@
// 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 NoExtensionMethods
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.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 NoExtensionMethods.dll
.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
// =============== CLASS MEMBERS DECLARATION ===================
.class private abstract auto ansi sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoExtensionMethods
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method assembly hidebysig static class [mscorlib]System.Func`1<!!T>
AsFunc<class T>(!!T 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
// Code size 18 (0x12)
.maxstack 8
IL_0000: ldarg.0
IL_0001: box !!T
IL_0006: ldftn !!0 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoExtensionMethods::Return<!!0>(!!0)
IL_000c: newobj instance void class [mscorlib]System.Func`1<!!T>::.ctor(object,
native int)
IL_0011: ret
} // end of method NoExtensionMethods::AsFunc
.method private hidebysig static !!T Return<T>(!!T 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ret
} // end of method NoExtensionMethods::Return
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoExtensionMethods
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

81
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoExtensionMethods.roslyn.il

@ -0,0 +1,81 @@
// 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 NoExtensionMethods
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.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 NoExtensionMethods.dll
.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
// =============== CLASS MEMBERS DECLARATION ===================
.class private abstract auto ansi sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoExtensionMethods
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method assembly hidebysig static class [mscorlib]System.Func`1<!!T>
AsFunc<class T>(!!T 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
// Code size 23 (0x17)
.maxstack 2
.locals init (class [mscorlib]System.Func`1<!!T> V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: box !!T
IL_0007: ldftn !!0 ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoExtensionMethods::Return<!!0>(!!0)
IL_000d: newobj instance void class [mscorlib]System.Func`1<!!T>::.ctor(object,
native int)
IL_0012: stloc.0
IL_0013: br.s IL_0015
IL_0015: ldloc.0
IL_0016: ret
} // end of method NoExtensionMethods::AsFunc
.method private hidebysig static !!T Return<T>(!!T 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 1
.locals init (!!T V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: stloc.0
IL_0003: br.s IL_0005
IL_0005: ldloc.0
IL_0006: ret
} // end of method NoExtensionMethods::Return
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoExtensionMethods
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

8
ICSharpCode.Decompiler.Tests/UglyTestRunner.cs

@ -83,6 +83,14 @@ namespace ICSharpCode.Decompiler.Tests
}); });
} }
[Test]
public void NoExtensionMethods([ValueSource("roslynOnlyOptions")] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
ExtensionMethods = false
});
}
void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null) void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
{ {
Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings); Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings);

32
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -1235,6 +1235,11 @@ namespace ICSharpCode.Decompiler.CSharp
default: default:
throw new ArgumentException($"Unknown instruction type: {func.OpCode}"); throw new ArgumentException($"Unknown instruction type: {func.OpCode}");
} }
if (method.IsStatic && !method.IsExtensionMethod) {
var argumentList = BuildArgumentList(expectedTargetDetails, null, inst.Method,
0, inst.Arguments, null);
return HandleConstructorCall(new ExpectedTargetDetails { CallOpCode = OpCode.NewObj }, null, inst.Method, argumentList).WithILInstruction(inst);
}
return HandleDelegateConstruction(inst.Method.DeclaringType, method, expectedTargetDetails, thisArg, inst); return HandleDelegateConstruction(inst.Method.DeclaringType, method, expectedTargetDetails, thisArg, inst);
} }
@ -1243,9 +1248,15 @@ namespace ICSharpCode.Decompiler.CSharp
return HandleDelegateConstruction(inst.Type, inst.Method, new ExpectedTargetDetails { CallOpCode = OpCode.CallVirt }, inst.Argument, inst); return HandleDelegateConstruction(inst.Type, inst.Method, new ExpectedTargetDetails { CallOpCode = OpCode.CallVirt }, inst.Argument, inst);
} }
TranslatedExpression HandleDelegateConstruction(IType delegateType, IMethod method, ExpectedTargetDetails expectedTargetDetails, ILInstruction thisArg, ILInstruction inst) internal ExpressionWithResolveResult BuildMethodReference(IMethod method, bool isVirtual)
{
var expr = BuildDelegateReference(method, invokeMethod: null, new ExpectedTargetDetails { CallOpCode = isVirtual ? OpCode.CallVirt : OpCode.Call }, thisArg: null);
expr.Expression.RemoveAnnotations<ResolveResult>();
return expr.Expression.WithRR(new MemberResolveResult(null, method));
}
ExpressionWithResolveResult BuildDelegateReference(IMethod method, IMethod invokeMethod, ExpectedTargetDetails expectedTargetDetails, ILInstruction thisArg)
{ {
var invokeMethod = delegateType.GetDelegateInvokeMethod();
TranslatedExpression target; TranslatedExpression target;
IType targetType; IType targetType;
bool requireTarget; bool requireTarget;
@ -1331,27 +1342,32 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
requireTarget = !method.IsLocalFunction && (step & 1) != 0; requireTarget = !method.IsLocalFunction && (step & 1) != 0;
Expression targetExpression; ExpressionWithResolveResult targetExpression;
Debug.Assert(result != null); Debug.Assert(result != null);
if (requireTarget) { if (requireTarget) {
Debug.Assert(target.Expression != null); Debug.Assert(target.Expression != null);
var mre = new MemberReferenceExpression(target, methodName); var mre = new MemberReferenceExpression(target, methodName);
if ((step & 2) != 0) if ((step & 2) != 0)
mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
mre.WithRR(result); targetExpression = mre.WithRR(result);
targetExpression = mre;
} else { } else {
var ide = new IdentifierExpression(methodName); var ide = new IdentifierExpression(methodName);
if ((step & 2) != 0) if ((step & 2) != 0)
ide.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); ide.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
ide.WithRR(result); targetExpression = ide.WithRR(result);
targetExpression = ide;
} }
return targetExpression;
}
TranslatedExpression HandleDelegateConstruction(IType delegateType, IMethod method, ExpectedTargetDetails expectedTargetDetails, ILInstruction thisArg, ILInstruction inst)
{
var invokeMethod = delegateType.GetDelegateInvokeMethod();
var targetExpression = BuildDelegateReference(method, invokeMethod, expectedTargetDetails, thisArg);
var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(delegateType), targetExpression) var oce = new ObjectCreateExpression(expressionBuilder.ConvertType(delegateType), targetExpression)
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ConversionResolveResult( .WithRR(new ConversionResolveResult(
delegateType, delegateType,
result, targetExpression.ResolveResult,
Conversion.MethodGroupConversion(method, expectedTargetDetails.CallOpCode == OpCode.CallVirt, false))); Conversion.MethodGroupConversion(method, expectedTargetDetails.CallOpCode == OpCode.CallVirt, false)));
return oce; return oce;
} }

16
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -3134,6 +3134,22 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new OperatorResolveResult(SpecialType.Dynamic, inst.Operation, new[] { target.ResolveResult, value.ResolveResult })); .WithRR(new OperatorResolveResult(SpecialType.Dynamic, inst.Operation, new[] { target.ResolveResult, value.ResolveResult }));
} }
protected internal override TranslatedExpression VisitLdFtn(LdFtn inst, TranslationContext context)
{
ExpressionWithResolveResult delegateRef = new CallBuilder(this, typeSystem, settings).BuildMethodReference(inst.Method, isVirtual: false);
return new InvocationExpression(new IdentifierExpression("__ldftn"), delegateRef)
.WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.IntPtr)))
.WithILInstruction(inst);
}
protected internal override TranslatedExpression VisitLdVirtFtn(LdVirtFtn inst, TranslationContext context)
{
ExpressionWithResolveResult delegateRef = new CallBuilder(this, typeSystem, settings).BuildMethodReference(inst.Method, isVirtual: true);
return new InvocationExpression(new IdentifierExpression("__ldvirtftn"), delegateRef)
.WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.IntPtr)))
.WithILInstruction(inst);
}
protected internal override TranslatedExpression VisitInvalidBranch(InvalidBranch inst, TranslationContext context) protected internal override TranslatedExpression VisitInvalidBranch(InvalidBranch inst, TranslationContext context)
{ {
string message = "Error"; string message = "Error";

22
ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs

@ -85,6 +85,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
TryCatch mainTryCatch; TryCatch mainTryCatch;
Block setResultAndExitBlock; // block that is jumped to for return statements Block setResultAndExitBlock; // block that is jumped to for return statements
int finalState; // final state after the setResultAndExitBlock int finalState; // final state after the setResultAndExitBlock
bool finalStateKnown;
ILVariable resultVar; // the variable that gets returned by the setResultAndExitBlock ILVariable resultVar; // the variable that gets returned by the setResultAndExitBlock
ILVariable doFinallyBodies; ILVariable doFinallyBodies;
@ -352,7 +353,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
moveNextFunction = YieldReturnDecompiler.CreateILAst(moveNextMethod, context); moveNextFunction = YieldReturnDecompiler.CreateILAst(moveNextMethod, context);
if (!(moveNextFunction.Body is BlockContainer blockContainer)) if (!(moveNextFunction.Body is BlockContainer blockContainer))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (blockContainer.Blocks.Count != 2) if (blockContainer.Blocks.Count != 2 && blockContainer.Blocks.Count != 1)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (blockContainer.EntryPoint.IncomingEdgeCount != 1) if (blockContainer.EntryPoint.IncomingEdgeCount != 1)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
@ -389,7 +390,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
doFinallyBodies = initDoFinallyBodies.Variable; doFinallyBodies = initDoFinallyBodies.Variable;
} }
setResultAndExitBlock = blockContainer.Blocks[1]; setResultAndExitBlock = blockContainer.Blocks.ElementAtOrDefault(1);
if (setResultAndExitBlock == null) {
// This block can be absent if the function never exits normally,
// but always throws an exception/loops infinitely.
resultVar = null;
finalStateKnown = false; // final state will be detected in ValidateCatchBlock() instead
return;
}
// stobj System.Int32(ldflda [Field ICSharpCode.Decompiler.Tests.TestCases.Pretty.Async+<SimpleBoolTaskMethod>d__7.<>1__state](ldloc this), ldc.i4 -2) // stobj System.Int32(ldflda [Field ICSharpCode.Decompiler.Tests.TestCases.Pretty.Async+<SimpleBoolTaskMethod>d__7.<>1__state](ldloc this), ldc.i4 -2)
// call SetResult(ldflda [Field ICSharpCode.Decompiler.Tests.TestCases.Pretty.Async+<SimpleBoolTaskMethod>d__7.<>t__builder](ldloc this), ldloc result) // call SetResult(ldflda [Field ICSharpCode.Decompiler.Tests.TestCases.Pretty.Async+<SimpleBoolTaskMethod>d__7.<>t__builder](ldloc this), ldloc result)
// leave IL_0000 // leave IL_0000
@ -397,6 +405,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (!MatchStateAssignment(setResultAndExitBlock.Instructions[0], out finalState)) if (!MatchStateAssignment(setResultAndExitBlock.Instructions[0], out finalState))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
finalStateKnown = true;
if (!MatchCall(setResultAndExitBlock.Instructions[1], "SetResult", out var args)) if (!MatchCall(setResultAndExitBlock.Instructions[1], "SetResult", out var args))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (!IsBuilderFieldOnThis(args[0])) if (!IsBuilderFieldOnThis(args[0]))
@ -442,8 +451,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (!stloc.Value.MatchLdLoc(handler.Variable)) if (!stloc.Value.MatchLdLoc(handler.Variable))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
// stfld <>1__state(ldloc this, ldc.i4 -2) // stfld <>1__state(ldloc this, ldc.i4 -2)
if (!MatchStateAssignment(catchBlock.Instructions[1], out int newState) || newState != finalState) if (!MatchStateAssignment(catchBlock.Instructions[1], out int newState))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (finalStateKnown) {
if (newState != finalState)
throw new SymbolicAnalysisFailedException();
} else {
finalState = newState;
finalStateKnown = true;
}
// call SetException(ldfld <>t__builder(ldloc this), ldloc exception) // call SetException(ldfld <>t__builder(ldloc this), ldloc exception)
if (!MatchCall(catchBlock.Instructions[2], "SetException", out var args)) if (!MatchCall(catchBlock.Instructions[2], "SetException", out var args))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();

32
ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs

@ -18,6 +18,7 @@
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
@ -31,7 +32,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// then we can replace the variable with the argument. /// then we can replace the variable with the argument.
/// 2) assignments of address-loading instructions to local variables /// 2) assignments of address-loading instructions to local variables
/// </summary> /// </summary>
public class CopyPropagation : IBlockTransform, IILTransform public class CopyPropagation : IILTransform
{ {
public static void Propagate(StLoc store, ILTransformContext context) public static void Propagate(StLoc store, ILTransformContext context)
{ {
@ -41,26 +42,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms
DoPropagate(store.Variable, store.Value, block, ref i, context); DoPropagate(store.Variable, store.Value, block, ref i, context);
} }
public void Run(Block block, BlockTransformContext context)
{
RunOnBlock(block, context);
}
public void Run(ILFunction function, ILTransformContext context) public void Run(ILFunction function, ILTransformContext context)
{ {
var splitVariables = new HashSet<ILVariable>(ILVariableEqualityComparer.Instance);
foreach (var g in function.Variables.GroupBy(v => v, ILVariableEqualityComparer.Instance)) {
if (g.Count() > 1) {
splitVariables.Add(g.Key);
}
}
foreach (var block in function.Descendants.OfType<Block>()) { foreach (var block in function.Descendants.OfType<Block>()) {
if (block.Kind != BlockKind.ControlFlow) if (block.Kind != BlockKind.ControlFlow)
continue; continue;
RunOnBlock(block, context); RunOnBlock(block, context, splitVariables);
} }
} }
static void RunOnBlock(Block block, ILTransformContext context) static void RunOnBlock(Block block, ILTransformContext context, HashSet<ILVariable> splitVariables = null)
{ {
for (int i = 0; i < block.Instructions.Count; i++) { for (int i = 0; i < block.Instructions.Count; i++) {
ILVariable v; if (block.Instructions[i].MatchStLoc(out ILVariable v, out ILInstruction copiedExpr)) {
ILInstruction copiedExpr;
if (block.Instructions[i].MatchStLoc(out v, out copiedExpr)) {
if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot) { if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot) {
// dead store to stack // dead store to stack
if (SemanticHelper.IsPure(copiedExpr.Flags)) { if (SemanticHelper.IsPure(copiedExpr.Flags)) {
@ -76,18 +76,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms
copiedExpr.AddILRange(block.Instructions[i]); copiedExpr.AddILRange(block.Instructions[i]);
block.Instructions[i] = copiedExpr; block.Instructions[i] = copiedExpr;
} }
} else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr)) { } else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr, splitVariables)) {
DoPropagate(v, copiedExpr, block, ref i, context); DoPropagate(v, copiedExpr, block, ref i, context);
} }
} }
} }
} }
static bool CanPerformCopyPropagation(ILVariable target, ILInstruction value) static bool CanPerformCopyPropagation(ILVariable target, ILInstruction value, HashSet<ILVariable> splitVariables)
{ {
Debug.Assert(target.StackType == value.ResultType); Debug.Assert(target.StackType == value.ResultType);
if (target.Type.IsSmallIntegerType()) if (target.Type.IsSmallIntegerType())
return false; return false;
if (splitVariables != null && splitVariables.Contains(target)) {
return false; // non-local code move might change semantics when there's split variables
}
switch (value.OpCode) { switch (value.OpCode) {
case OpCode.LdLoca: case OpCode.LdLoca:
// case OpCode.LdElema: // case OpCode.LdElema:
@ -100,6 +103,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true; return true;
case OpCode.LdLoc: case OpCode.LdLoc:
var v = ((LdLoc)value).Variable; var v = ((LdLoc)value).Variable;
if (splitVariables != null && splitVariables.Contains(v)) {
return false; // non-local code move might change semantics when there's split variables
}
switch (v.Kind) { switch (v.Kind) {
case VariableKind.Parameter: case VariableKind.Parameter:
// Parameters can be copied only if they aren't assigned to (directly or indirectly via ldarga) // Parameters can be copied only if they aren't assigned to (directly or indirectly via ldarga)

10
ILSpy/MainWindow.xaml.cs

@ -331,6 +331,10 @@ namespace ICSharpCode.ILSpy
} }
} }
} }
} else if (navigateTo == "none") {
// Don't navigate anywhere; start empty.
// Used by ILSpy VS addin, it'll send us the real location to navigate to via IPC.
found = true;
} else { } else {
IEntity mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies)); IEntity mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies));
if (mr != null && mr.ParentModule.PEFile != null) { if (mr != null && mr.ParentModule.PEFile != null) {
@ -354,15 +358,15 @@ namespace ICSharpCode.ILSpy
} }
} else if (spySettings != null) { } else if (spySettings != null) {
SharpTreeNode node = null; SharpTreeNode node = null;
if (sessionSettings.ActiveTreeViewPath?.Length > 0) { if (activeTreeViewPath?.Length > 0) {
foreach (var asm in assemblyList.GetAssemblies()) { foreach (var asm in assemblyList.GetAssemblies()) {
if (asm.FileName == sessionSettings.ActiveTreeViewPath[0]) { if (asm.FileName == activeTreeViewPath[0]) {
// FindNodeByPath() blocks the UI if the assembly is not yet loaded, // FindNodeByPath() blocks the UI if the assembly is not yet loaded,
// so use an async wait instead. // so use an async wait instead.
await asm.GetPEFileAsync().Catch<Exception>(ex => { }); await asm.GetPEFileAsync().Catch<Exception>(ex => { });
} }
} }
node = FindNodeByPath(sessionSettings.ActiveTreeViewPath, true); node = FindNodeByPath(activeTreeViewPath, true);
} }
if (treeView.SelectedItem == initialSelection) { if (treeView.SelectedItem == initialSelection) {
if (node != null) { if (node != null) {

2
ILSpy/Properties/AssemblyInfo.template.cs

@ -37,7 +37,7 @@ internal static class RevisionClass
{ {
public const string Major = "6"; public const string Major = "6";
public const string Minor = "0"; public const string Minor = "0";
public const string Build = "0"; public const string Build = "1";
public const string Revision = "$INSERTREVISION$"; public const string Revision = "$INSERTREVISION$";
public const string VersionName = "alpha1"; public const string VersionName = "alpha1";

1
appveyor.yml

@ -42,6 +42,7 @@ for:
- branches: - branches:
only: only:
- master - master
- 5.0.x
artifacts: artifacts:
- path: ILSpy_binaries.zip - path: ILSpy_binaries.zip
name: ILSpy %APPVEYOR_REPO_BRANCH% %ILSPY_VERSION_NUMBER% binaries name: ILSpy %APPVEYOR_REPO_BRANCH% %ILSPY_VERSION_NUMBER% binaries

5
azure-pipelines.yml

@ -1,11 +1,10 @@
trigger: trigger:
- master - master
- msix - 5.0.x
- 3.2.x
pr: pr:
- master - master
- 3.2.x - 5.0.x
variables: variables:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true

Loading…
Cancel
Save