From 22e9791f866fcb74078942819164fd881d68816c Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 16 Jul 2022 11:43:52 +0200 Subject: [PATCH 1/3] Update RoslynToolset to 4.3.0-2.final --- .../Helpers/RoslynToolset.cs | 26 ++++++++++++------- .../Helpers/Tester.cs | 6 ++--- packages.props | 2 +- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs b/ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs index 42250c4a9..cf53163d6 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/RoslynToolset.cs @@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers this.baseDir = baseDir; } - protected async Task FetchPackage(string packageName, string version, string outputPath) + protected async Task FetchPackage(string packageName, string version, string sourcePath, string outputPath) { ILogger logger = NullLogger.Instance; CancellationToken cancellationToken = CancellationToken.None; @@ -65,8 +65,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers using PackageArchiveReader packageReader = new PackageArchiveReader(packageStream); NuspecReader nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken).ConfigureAwait(false); - var files = await packageReader.GetFilesAsync(cancellationToken).ConfigureAwait(false); - files = files.Where(f => f.StartsWith("tools", StringComparison.OrdinalIgnoreCase)); + var files = (await packageReader.GetFilesAsync(cancellationToken).ConfigureAwait(false)).ToArray(); + files = files.Where(f => f.StartsWith(sourcePath, StringComparison.OrdinalIgnoreCase)).ToArray(); await packageReader.CopyFilesAsync(outputPath, files, (sourceFile, targetPath, fileStream) => { fileStream.CopyToFile(targetPath); @@ -87,15 +87,15 @@ namespace ICSharpCode.Decompiler.Tests.Helpers { } - public async Task Fetch(string version) + public async Task Fetch(string version, string packageName = "Microsoft.Net.Compilers.Toolset", string sourcePath = "tasks/net472") { - string path = Path.Combine(baseDir, version, "tools"); + string path = Path.Combine(baseDir, version, sourcePath); if (!Directory.Exists(path)) { - await FetchPackage("Microsoft.Net.Compilers", version, Path.Combine(baseDir, version)).ConfigureAwait(false); + await FetchPackage(packageName, version, sourcePath, Path.Combine(baseDir, version)).ConfigureAwait(false); } - installedCompilers.Add(version, path); + installedCompilers.Add(SanitizeVersion(version), path); } public string GetCSharpCompiler(string version) @@ -110,10 +110,18 @@ namespace ICSharpCode.Decompiler.Tests.Helpers string GetCompiler(string compiler, string version) { - if (installedCompilers.TryGetValue(version, out var path)) + if (installedCompilers.TryGetValue(SanitizeVersion(version), out var path)) return Path.Combine(path, compiler); throw new NotSupportedException($"Cannot find {compiler} {version}, please add it to the initialization."); } + + internal static string SanitizeVersion(string version) + { + int index = version.IndexOf("-"); + if (index > 0) + return version.Remove(index); + return version; + } } class VsWhereToolset : AbstractToolset @@ -130,7 +138,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers string path = Path.Combine(baseDir, "tools"); if (!Directory.Exists(path)) { - await FetchPackage("vswhere", "2.8.4", baseDir).ConfigureAwait(false); + await FetchPackage("vswhere", "2.8.4", "tools", baseDir).ConfigureAwait(false); } vswherePath = Path.Combine(path, "vswhere.exe"); } diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index a116a04cd..c2ecd3f70 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -113,8 +113,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers internal static async Task Initialize() { - await roslynToolset.Fetch("1.3.2").ConfigureAwait(false); - await roslynToolset.Fetch("2.10.0").ConfigureAwait(false); + await roslynToolset.Fetch("1.3.2", "Microsoft.Net.Compilers", "tools").ConfigureAwait(false); + await roslynToolset.Fetch("2.10.0", "Microsoft.Net.Compilers", "tools").ConfigureAwait(false); await roslynToolset.Fetch("3.11.0").ConfigureAwait(false); await roslynToolset.Fetch(roslynLatestVersion).ConfigureAwait(false); @@ -432,7 +432,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers if (roslynVersion != "legacy") { otherOptions += "/shared "; - if (!targetNet40 && Version.Parse(roslynVersion).Major > 2) + if (!targetNet40 && Version.Parse(RoslynToolset.SanitizeVersion(roslynVersion)).Major > 2) { if (flags.HasFlag(CompilerOptions.NullableEnable)) otherOptions += "/nullable+ "; diff --git a/packages.props b/packages.props index fe4e90748..375a60ef8 100644 --- a/packages.props +++ b/packages.props @@ -14,7 +14,7 @@ 6.0.0 - 4.1.0 + 4.3.0-2.final 0.11.4 6.1.3.50 2.7.4 From 3c847b56a29d27cf6330bbd146a98569aa547f64 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 16 Jul 2022 12:20:12 +0200 Subject: [PATCH 2/3] Fix decompilation of async streams compiled with Roslyn 4.2 --- .../IL/ControlFlow/AsyncAwaitDecompiler.cs | 16 ++++++++++++---- .../IL/Instructions/PatternMatching.cs | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index 335dffa36..c6b54ad44 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -725,6 +725,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow throw new SymbolicAnalysisFailedException(); finalStateKnown = true; pos++; + if (pos + 2 == block.Instructions.Count && block.MatchIfAtEndOfBlock(out var condition, out var trueInst, out var falseInst)) { if (MatchDisposeCombinedTokens(blockContainer, condition, trueInst, falseInst, blocksAnalyzed, out var setResultAndExitBlock)) @@ -807,7 +808,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // https://github.com/dotnet/roslyn/pull/39735 hoisted local cleanup if (!target.MatchLdThis()) throw new SymbolicAnalysisFailedException(); - if (!(value.MatchLdNull() || value is DefaultValue)) + if (!value.MatchDefaultOrNullOrZero()) throw new SymbolicAnalysisFailedException(); pos++; } @@ -1441,13 +1442,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow pos--; } - if (pos < 0 || !block.Instructions[pos].MatchStFld(out var target, out var field, out yieldValue)) + if (pos < 0 || !MatchCurrentAssignment(block.Instructions[pos], out yieldValue)) + return false; + + block.Instructions.RemoveRange(pos, block.Instructions.Count - pos); + return true; + } + + bool MatchCurrentAssignment(ILInstruction inst, out ILInstruction value) + { + if (!inst.MatchStFld(out var target, out var field, out value)) return false; if (!StackSlotValue(target).MatchLdThis()) return false; // TODO: check that we are accessing the current field (compare with get_Current) - - block.Instructions.RemoveRange(pos, block.Instructions.Count - pos); return true; } #endregion diff --git a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs index aa42395b4..5c5391723 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs @@ -553,6 +553,23 @@ namespace ICSharpCode.Decompiler.IL return false; } + public bool MatchDefaultOrNullOrZero() + { + switch (this) + { + case LdNull _: + case LdcF4 { Value: 0 }: + case LdcF8 { Value: 0 }: + case LdcI4 { Value: 0 }: + case LdcI8 { Value: 0 }: + case DefaultValue _: + return true; + default: + return false; + } + } + + /// /// If this instruction is a conversion of the specified kind, return its argument. /// Otherwise, return the instruction itself. From 1f1e95d7a1dffb61aae4a0fe17ce111d1bb3368e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 16 Jul 2022 12:22:20 +0200 Subject: [PATCH 3/3] Update RecordDecompiler for Roslyn 4.3.0. --- .../CSharp/RecordDecompiler.cs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs index f76cb2fe1..455c8b21b 100644 --- a/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs @@ -354,6 +354,17 @@ namespace ICSharpCode.Decompiler.CSharp && IsRecordType(method.Parameters[0].Type); } + private bool IsAllowedAttribute(IAttribute attribute) + { + switch (attribute.AttributeType.ReflectionName) + { + case "System.Runtime.CompilerServices.CompilerGeneratedAttribute": + return true; + default: + return false; + } + } + private bool IsGeneratedCopyConstructor(IMethod method) { /* @@ -362,7 +373,7 @@ namespace ICSharpCode.Decompiler.CSharp leave IL_0000 (nop) */ Debug.Assert(method.IsConstructor && method.Parameters.Count == 1); - if (method.GetAttributes().Any() || method.GetReturnTypeAttributes().Any()) + if (method.GetAttributes().Any(attr => !IsAllowedAttribute(attr)) || method.GetReturnTypeAttributes().Any()) return false; if (method.Accessibility != Accessibility.Protected && (!isSealed || method.Accessibility != Accessibility.Private)) return false; @@ -461,7 +472,7 @@ namespace ICSharpCode.Decompiler.CSharp return false; if (!isSealed && !method.IsOverridable) return false; - if (method.GetAttributes().Any() || method.GetReturnTypeAttributes().Any()) + if (method.GetAttributes().Any(attr => !IsAllowedAttribute(attr)) || method.GetReturnTypeAttributes().Any()) return false; if (method.Accessibility != Accessibility.Protected && (!isSealed || method.Accessibility != Accessibility.Private)) return false; @@ -637,7 +648,7 @@ namespace ICSharpCode.Decompiler.CSharp return false; if (method.IsSealed) return false; - if (method.GetAttributes().Any() || method.GetReturnTypeAttributes().Any()) + if (method.GetAttributes().Any(attr => !IsAllowedAttribute(attr)) || method.GetReturnTypeAttributes().Any()) return false; var body = DecompileBody(method); if (body == null) @@ -711,7 +722,7 @@ namespace ICSharpCode.Decompiler.CSharp return false; if (!isSealed && !method.IsOverridable) return false; - if (method.GetAttributes().Any() || method.GetReturnTypeAttributes().Any()) + if (method.GetAttributes().Any(attr => !IsAllowedAttribute(attr)) || method.GetReturnTypeAttributes().Any()) return false; if (orderedMembers == null) return false; @@ -901,7 +912,7 @@ namespace ICSharpCode.Decompiler.CSharp return false; if (!method.IsOverride || method.IsSealed) return false; - if (method.GetAttributes().Any() || method.GetReturnTypeAttributes().Any()) + if (method.GetAttributes().Any(attr => !IsAllowedAttribute(attr)) || method.GetReturnTypeAttributes().Any()) return false; if (orderedMembers == null) return false;