Browse Source

Merge branch 'master' of github.com:icsharpcode/ILSpy into foreach-array

pull/946/head
Siegfried Pammer 8 years ago
parent
commit
cde912c473
  1. 6
      BuildTools/appveyor-install.ps1
  2. 1
      BuildTools/update-assemblyinfo.ps1
  3. 30
      ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpPatternTests.cs
  4. 64
      ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs
  5. 64
      ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpUsing.fs.Release.cs
  6. 87
      ICSharpCode.Decompiler.Tests/FSharpPatterns/TestHelpers.cs
  7. 99
      ICSharpCode.Decompiler.Tests/FSharpPatterns/ToolLocator.cs
  8. 11
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  9. 26
      ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
  10. 6
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  11. 46
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs
  12. 148
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/UnsafeCode.cs
  13. 1
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/.gitignore
  14. 30
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops.fs
  15. 209
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs
  16. 586
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.il
  17. 210
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs
  18. 561
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.il
  19. 0
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing.fs
  20. 58
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.cs
  21. 0
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.il
  22. 58
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.cs
  23. 0
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.il
  24. 1
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/.gitignore
  25. 11
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.cs
  26. 60
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.il
  27. 43
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.opt.il
  28. 37
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.opt.roslyn.il
  29. 53
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.roslyn.il
  30. 288
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  31. 1149
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il
  32. 904
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il
  33. 910
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il
  34. 1155
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il
  35. 192
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  36. 428
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  37. 10
      ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs
  38. 36
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  39. 0
      ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs
  40. 29
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs
  41. 9
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs
  42. 4
      ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs
  43. 43
      ICSharpCode.Decompiler/DecompilerSettings.cs
  44. 2
      ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs
  45. 352
      ICSharpCode.Decompiler/DotNetCore/UniversalAssemblyResolver.cs
  46. 18
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  47. 15
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template
  48. 17
      ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
  49. 2
      ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs
  50. 2
      ICSharpCode.Decompiler/IL/Instructions.cs
  51. 3
      ICSharpCode.Decompiler/IL/Instructions.tt
  52. 19
      ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs
  53. 13
      ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
  54. 13
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
  55. 4
      ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
  56. 14
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  57. 28
      ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs
  58. 14
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  59. 23
      ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs
  60. 5
      ICSharpCode.Decompiler/Util/EmptyList.cs
  61. 24
      ILSpy/Commands/SortAssemblyListCommand.cs
  62. 1
      ILSpy/ILSpy.csproj
  63. BIN
      ILSpy/Images/CollapseAll.png
  64. 7
      ILSpy/Languages/CSharpHighlightingTokenWriter.cs
  65. 2
      ILSpy/Languages/CSharpLanguage.cs
  66. 10
      ILSpy/OpenListDialog.xaml
  67. 13
      ILSpy/OpenListDialog.xaml.cs
  68. 2
      ILSpy/Properties/AssemblyInfo.template.cs
  69. 4
      ILSpy/TreeNodes/TypeTreeNode.cs
  70. 4
      appveyor.yml

6
BuildTools/appveyor-install.ps1

@ -32,5 +32,7 @@ if ($env:APPVEYOR_PULL_REQUEST_NUMBER) { @@ -32,5 +32,7 @@ if ($env:APPVEYOR_PULL_REQUEST_NUMBER) {
$revision = [Int32]::Parse((git rev-list --count "$baseCommit..HEAD")) + $baseCommitRev;
$newVersion="$major.$minor.$build.$revision";
$env:appveyor_build_version="$newVersion$branch$versionName$suffix";
appveyor UpdateBuild -Version "$newVersion$branch$versionName$suffix";
$env:APPVEYOR_BUILD_VERSION="$newVersion$branch$versionName$suffix";
$env:ILSPY_VERSION_NUMBER="$newVersion$branch$versionName$suffix";
appveyor UpdateBuild -Version "$newVersion$branch$versionName$suffix";
Write-Host "new version: $newVersion$branch$versionName$suffix";

1
BuildTools/update-assemblyinfo.ps1

@ -42,6 +42,7 @@ function gitBranch() { @@ -42,6 +42,7 @@ function gitBranch() {
$templateFiles = (
@{Input=$globalAssemblyInfoTemplateFile; Output="ILSpy/Properties/AssemblyInfo.cs"},
@{Input="ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs"; Output="ICSharpCode.Decompiler/Properties/AssemblyInfo.cs"},
@{Input="ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template"; Output="ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec"},
@{Input="ILSpy/Properties/app.config.template"; Output = "ILSpy/app.config"}
);
[string]$mutexId = "ILSpyUpdateAssemblyInfo" + $PSScriptRoot.GetHashCode();

30
ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpPatternTests.cs

@ -1,30 +0,0 @@ @@ -1,30 +0,0 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
[TestFixture]
public class FSharpPatternTests
{
[Test]
public void FSharpUsingDecompilesToCSharpUsing_Debug()
{
var ilCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Debug.il");
var csharpCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Debug.cs");
TestHelpers.RunIL(ilCode, csharpCode);
}
[Test]
public void FSharpUsingDecompilesToCSharpUsing_Release()
{
var ilCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Release.il");
var csharpCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Release.cs");
TestHelpers.RunIL(ilCode, csharpCode);
}
}
}

64
ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs

@ -1,64 +0,0 @@ @@ -1,64 +0,0 @@
using System;
using System.IO;
public static class FSharpUsingPatterns
{
public static void sample1()
{
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)1);
}
}
public static void sample2()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)2);
Console.WriteLine("some text");
}
}
public static void sample3()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)3);
}
Console.WriteLine("some text");
}
public static void sample4()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
Console.WriteLine("read:" + firstByte.ToString());
}
public static void sample5()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
int num3;
using (FileStream fs = File.OpenRead("x.txt"))
{
int num2 = fs.ReadByte();
num3 = fs.ReadByte();
}
int secondByte = num3;
Console.WriteLine("read: {0}, {1}", firstByte, secondByte);
}
}

64
ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpUsing.fs.Release.cs

@ -1,64 +0,0 @@ @@ -1,64 +0,0 @@
using System;
using System.IO;
public static class FSharpUsingPatterns
{
public static void sample1()
{
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(1);
}
}
public static void sample2()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(2);
Console.WriteLine("some text");
}
}
public static void sample3()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(3);
}
Console.WriteLine("some text");
}
public static void sample4()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
Console.WriteLine("read:" + firstByte.ToString());
}
public static void sample5()
{
Console.WriteLine("some text");
int secondByte;
using (FileStream fs = File.OpenRead("x.txt"))
{
secondByte = fs.ReadByte();
}
int firstByte = secondByte;
int num2;
using (FileStream fs = File.OpenRead("x.txt"))
{
int num = fs.ReadByte();
num2 = fs.ReadByte();
}
secondByte = num2;
Console.WriteLine("read: {0}, {1}", firstByte, secondByte);
}
}

87
ICSharpCode.Decompiler.Tests/FSharpPatterns/TestHelpers.cs

@ -1,87 +0,0 @@ @@ -1,87 +0,0 @@
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Tests.Helpers;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
public class TestHelpers
{
public static string FuzzyReadResource(string resourceName)
{
var asm = Assembly.GetExecutingAssembly();
var allResources = asm.GetManifestResourceNames();
var fullResourceName = allResources.Single(r => r.EndsWith(resourceName, StringComparison.OrdinalIgnoreCase));
return new StreamReader(asm.GetManifestResourceStream(fullResourceName)).ReadToEnd();
}
static Lazy<string> ilasm = new Lazy<string>(() => ToolLocator.FindTool("ilasm.exe"));
static Lazy<string> ildasm = new Lazy<string>(() => ToolLocator.FindTool("ildasm.exe"));
public static string CompileIL(string source)
{
if (ilasm.Value == null)
Assert.NotNull(ilasm.Value, "Could not find ILASM.exe");
var tmp = Path.GetTempFileName();
File.Delete(tmp);
var sourceFile = Path.ChangeExtension(tmp, ".il");
File.WriteAllText(sourceFile, source);
var asmFile = Path.ChangeExtension(sourceFile, ".dll");
var args = string.Format("{0} /dll /debug /output:{1}", sourceFile, asmFile);
using (var proc = Process.Start(new ProcessStartInfo(ilasm.Value, args) { UseShellExecute = false, }))
{
proc.WaitForExit();
Assert.AreEqual(0, proc.ExitCode);
}
File.Delete(sourceFile);
Assert.True(File.Exists(asmFile), "Assembly File does not exist");
return asmFile;
}
public static void RunIL(string ilCode, string expectedCSharpCode)
{
var asmFilePath = CompileIL(ilCode);
CompareAssemblyAgainstCSharp(expectedCSharpCode, asmFilePath);
}
private static void CompareAssemblyAgainstCSharp(string expectedCSharpCode, string asmFilePath)
{
var module = ModuleDefinition.ReadModule(asmFilePath);
try
{
try { module.ReadSymbols(); } catch { }
AstBuilder decompiler = new AstBuilder(new DecompilerContext(module));
decompiler.AddAssembly(module);
new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
StringWriter output = new StringWriter();
// the F# assembly contains a namespace `<StartupCode$tmp6D55>` where the part after tmp is randomly generated.
// remove this from the ast to simplify the diff
var startupCodeNode = decompiler.SyntaxTree.Children.OfType<NamespaceDeclaration>().SingleOrDefault(d => d.Name.StartsWith("<StartupCode$", StringComparison.Ordinal));
if (startupCodeNode != null)
startupCodeNode.Remove();
decompiler.GenerateCode(new PlainTextOutput(output));
var fullCSharpCode = output.ToString();
CodeAssert.AreEqual(expectedCSharpCode, output.ToString());
}
finally
{
File.Delete(asmFilePath);
File.Delete(Path.ChangeExtension(asmFilePath, ".pdb"));
}
}
}
}

99
ICSharpCode.Decompiler.Tests/FSharpPatterns/ToolLocator.cs

@ -1,99 +0,0 @@ @@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
public class ToolLocator
{
public static string FindTool(string fileName)
{
var allPaths = FindPathForDotNetFramework().Concat(FindPathForWindowsSdk());
return allPaths.Select(dir => Path.Combine(dir, fileName)).FirstOrDefault(File.Exists);
}
private static IEnumerable<string> FindPathForWindowsSdk()
{
string[] windowsSdkPaths = new[]
{
@"Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v8.0A\bin\",
@"Microsoft SDKs\Windows\v8.0\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v8.0\bin\",
@"Microsoft SDKs\Windows\v7.1A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v7.1A\bin\",
@"Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v7.0A\bin\",
@"Microsoft SDKs\Windows\v6.1A\bin\",
@"Microsoft SDKs\Windows\v6.0A\bin\",
@"Microsoft SDKs\Windows\v6.0\bin\",
@"Microsoft.NET\FrameworkSDK\bin"
};
foreach (var possiblePath in windowsSdkPaths)
{
string fullPath = string.Empty;
// Check alternate program file paths as well as 64-bit versions.
if (Environment.Is64BitProcess)
{
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), possiblePath, "x64");
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), possiblePath, "x64");
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
}
private static IEnumerable<string> FindPathForDotNetFramework()
{
string[] frameworkPaths = new[]
{
@"Microsoft.NET\Framework\v4.0.30319",
@"Microsoft.NET\Framework\v2.0.50727"
};
foreach (var possiblePath in frameworkPaths)
{
string fullPath = string.Empty;
if (Environment.Is64BitProcess)
{
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), possiblePath.Replace(@"\Framework\", @"\Framework64\"));
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
}
}
}

11
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -45,6 +45,12 @@ @@ -45,6 +45,12 @@
<ItemGroup>
<None Include="TestCases\Correctness\Jmp.il" />
<None Include="TestCases\ILPretty\FSharpLoops.fs" />
<None Include="TestCases\ILPretty\FSharpLoops_Debug.il" />
<None Include="TestCases\ILPretty\FSharpLoops_Release.il" />
<None Include="TestCases\ILPretty\FSharpUsing.fs" />
<None Include="TestCases\ILPretty\FSharpUsing_Debug.il" />
<None Include="TestCases\ILPretty\FSharpUsing_Release.il" />
<None Include="TestCases\Correctness\BitNot.il" />
<None Include="TestCases\Correctness\Readme.txt" />
</ItemGroup>
@ -52,7 +58,11 @@ @@ -52,7 +58,11 @@
<ItemGroup>
<Compile Include="DataFlowTest.cs" />
<Compile Include="TestCases\Correctness\LINQRaytracer.cs" />
<None Include="TestCases\ILPretty\FSharpLoops_Debug.cs" />
<None Include="TestCases\ILPretty\FSharpLoops_Release.cs" />
<Compile Include="TestCases\Pretty\DelegateConstruction.cs" />
<None Include="TestCases\ILPretty\FSharpUsing_Debug.cs" />
<None Include="TestCases\ILPretty\FSharpUsing_Release.cs" />
<Compile Include="Helpers\CodeAssert.cs" />
<Compile Include="Helpers\SdkUtility.cs" />
<Compile Include="Helpers\RemoveCompilerAttribute.cs" />
@ -66,6 +76,7 @@ @@ -66,6 +76,7 @@
<Compile Include="TestCases\Correctness\Using.cs" />
<Compile Include="TestCases\ILPretty\Issue379.cs" />
<Compile Include="TestCases\Pretty\FixProxyCalls.cs" />
<Compile Include="TestCases\Pretty\UnsafeCode.cs" />
<Compile Include="TestCases\Pretty\InitializerTests.cs" />
<None Include="TestCases\ILPretty\Issue646.cs" />
<Compile Include="TestCases\Pretty\Async.cs" />

26
ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs

@ -41,7 +41,31 @@ namespace ICSharpCode.Decompiler.Tests @@ -41,7 +41,31 @@ namespace ICSharpCode.Decompiler.Tests
{
Run();
}
[Test]
public void FSharpUsing_Debug()
{
Run();
}
[Test]
public void FSharpUsing_Release()
{
Run();
}
[Test, Ignore]
public void FSharpLoops_Debug()
{
Run();
}
[Test, Ignore]
public void FSharpLoops_Release()
{
Run();
}
void Run([CallerMemberName] string testName = null)
{
var ilFile = Path.Combine(TestCasePath, testName + ".il");

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -181,6 +181,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -181,6 +181,12 @@ namespace ICSharpCode.Decompiler.Tests
Run(cscOptions: cscOptions);
}
[Test]
public void UnsafeCode([ValueSource("defaultOptions")] CompilerOptions cscOptions)
{
Run(cscOptions: cscOptions);
}
[Test]
public void PInvoke([ValueSource("defaultOptions")] CompilerOptions cscOptions)
{

46
ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs

@ -25,6 +25,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -25,6 +25,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void Main()
{
InterestingConstants();
TruncatedComp();
}
static void Print<T>(T val)
@ -46,5 +47,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -46,5 +47,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Print(val2);
Print(2147483648u);
}
static void TruncatedComp()
{
Console.WriteLine("TruncatedComp1(1):");
TruncatedComp1(1);
Console.WriteLine("TruncatedComp1(-1):");
TruncatedComp1(-1);
Console.WriteLine("TruncatedComp1(0x100000001):");
TruncatedComp1(0x100000001);
Console.WriteLine("TruncatedComp1(long.MinValue):");
TruncatedComp1(long.MinValue);
Console.WriteLine("TruncatedComp2(1):");
TruncatedComp2(1, 1);
Console.WriteLine("TruncatedComp2(-1):");
TruncatedComp2(-1, -1);
Console.WriteLine("TruncatedComp2(0x100000001):");
TruncatedComp2(0x100000001, 1);
Console.WriteLine("TruncatedComp2(long.MinValue):");
TruncatedComp2(long.MinValue, int.MinValue);
}
static void TruncatedComp1(long val)
{
Print((int)val == val);
Print(val == (int)val);
Print(val < (int)val);
Print((int)val >= val);
}
static void TruncatedComp2(long val1, int val2)
{
Print(val1 == val2);
Print((int)val1 == val2);
Print(val1 < val2);
Print((int)val1 < val2);
Print(val1 <= val2);
Print((int)val1 <= val2);
}
}
}

148
ICSharpCode.Decompiler.Tests/TestCases/Correctness/UnsafeCode.cs

@ -22,7 +22,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -22,7 +22,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{
public class UnsafeCode
{
struct SimpleStruct
private struct SimpleStruct
{
public int X;
public double Y;
@ -34,58 +34,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -34,58 +34,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
// (but for now, it's already valuable knowing whether the decompiled code can be re-compiled)
}
public unsafe int* NullPointer
{
get {
return null;
}
}
public unsafe int* PointerCast(long* p)
{
return (int*)p;
}
public unsafe long ConvertDoubleToLong(double d)
{
return *(long*)(&d);
}
public unsafe double ConvertLongToDouble(long d)
{
return *(double*)(&d);
}
public unsafe int ConvertFloatToInt(float d)
{
return *(int*)(&d);
}
public unsafe float ConvertIntToFloat(int d)
{
return *(float*)(&d);
}
public unsafe void PassRefParameterAsPointer(ref int p)
{
fixed (int* ptr = &p) {
this.PassPointerAsRefParameter(ptr);
}
}
public unsafe void PassPointerAsRefParameter(int* p)
{
this.PassRefParameterAsPointer(ref *p);
}
public unsafe void AddressInMultiDimensionalArray(double[,] matrix)
{
fixed (double* ptr = &matrix[1, 2]) {
this.PointerReferenceExpression(ptr);
this.PointerReferenceExpression(ptr);
}
}
public unsafe int MultipleExitsOutOfFixedBlock(int[] arr)
{
fixed (int* ptr = &arr[0]) {
@ -101,42 +49,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -101,42 +49,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Console.WriteLine("outside");
return 2;
}
public unsafe void FixedStringAccess(string text)
{
fixed (char* ptr = text) {
char* ptr2 = ptr;
while (*ptr2 != '\0') {
*ptr2 = 'A';
ptr2++;
}
}
}
public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val)
{
fixed (long* ptr = array) {
((double*)ptr)[index] = val;
}
}
public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val)
{
fixed (long* ptr = &array[index]) {
*(double*)ptr = val;
}
}
public unsafe string PointerReferenceExpression(double* d)
{
return d->ToString();
}
public unsafe string PointerReferenceExpression2(long addr)
{
return ((int*)addr)->ToString();
}
public unsafe void FixMultipleStrings(string text)
{
fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text) {
@ -146,66 +59,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -146,66 +59,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
}
}
public unsafe string StackAlloc(int count)
{
char* ptr = stackalloc char[count];
char* ptr2 = stackalloc char[100];
for (int i = 0; i < count; i++) {
ptr[i] = (char)i;
}
return this.PointerReferenceExpression((double*)ptr);
}
public unsafe string StackAllocStruct(int count)
{
SimpleStruct* s = stackalloc SimpleStruct[checked(count * 2)];
SimpleStruct* p = stackalloc SimpleStruct[10];
return this.PointerReferenceExpression(&s->Y);
}
public unsafe int* PointerArithmetic(int* p)
{
return p + 2;
}
public unsafe byte* PointerArithmetic2(long* p, int y, int x)
{
return (byte*)((short*)p + (y * x));
}
public unsafe long* PointerArithmetic3(long* p)
{
return (long*)((byte*)p + 3);
}
public unsafe long* PointerArithmetic4(void* p)
{
return (long*)((byte*)p + 3);
}
public unsafe int PointerArithmetic5(void* p, byte* q, int i)
{
return (int)(q[i] + *(byte*)p);
}
public unsafe int PointerSubtraction(long* p, long* q)
{
return (int)((long)(p - q));
}
public unsafe int PointerSubtraction2(long* p, short* q)
{
return (int)((long)((byte*)p - (byte*)q));
}
public unsafe int PointerSubtraction3(void* p, void* q)
{
return (int)((long)((byte*)p - (byte*)q));
}
unsafe ~UnsafeCode()
{
this.PassPointerAsRefParameter(this.NullPointer);
}
}
}

1
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/.gitignore vendored

@ -0,0 +1 @@ @@ -0,0 +1 @@
/*.dll

30
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops.fs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
open System
let disposable() = { new IDisposable with member x.Dispose() = () }
let getSeq() = seq { yield 1; }
let getList() = [ 1 ]
let getArray() = [| 1 |]
[<EntryPoint>]
let main argv =
// nested using scopes?
use disp1 =
use disp2 = disposable()
Console.WriteLine "Hello 1"
disposable()
// for loop over seq
for i in getSeq() do
Console.WriteLine i
// for loop over list
for i in getList() do
Console.WriteLine i
// for loop over array
for i in getArray() do
Console.WriteLine i
0 // return an integer exit code

209
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.cs

@ -0,0 +1,209 @@ @@ -0,0 +1,209 @@
// C:\Users\Siegfried\Documents\Visual Studio 2017\Projects\ConsoleApp13\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe
// ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// Global type: <Module>
// Entry point: Program.main
// Architecture: AnyCPU (32-bit preferred)
// Runtime: .NET 4.0
using Microsoft.FSharp.Collections;
using Microsoft.FSharp.Core;
using Microsoft.FSharp.Core.CompilerServices;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
[assembly: FSharpInterfaceDataVersion(2, 0, 0)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: AssemblyTitle("ConsoleApplication1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ConsoleApplication1")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("e0674ff5-5e8f-4d4e-a88f-e447192454c7")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations)]
[assembly: AssemblyVersion("1.0.0.0")]
[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
[Serializable]
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
[CompilationMapping(SourceConstructFlags.Closure)]
internal sealed class disposable@3 : IDisposable
{
public disposable@3()
{
((object)this)..ctor();
}
private void System-IDisposable-Dispose()
{
}
void IDisposable.Dispose()
{
//ILSpy generated this explicit interface implementation from .override directive in System-IDisposable-Dispose
this.System-IDisposable-Dispose();
}
}
[Serializable]
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
[CompilationMapping(SourceConstructFlags.Closure)]
internal sealed class getSeq@5 : GeneratedSequenceBase<int>
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
public int pc = pc;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
public int current = current;
public getSeq@5(int pc, int current)
{
}
public override int GenerateNext(ref IEnumerable<int> next)
{
switch (this.pc)
{
default:
this.pc = 1;
this.current = 1;
return 1;
case 1:
this.pc = 2;
break;
case 2:
break;
}
this.current = 0;
return 0;
}
public override void Close()
{
this.pc = 2;
}
public override bool get_CheckClose()
{
switch (this.pc)
{
default:
return false;
case 0:
case 2:
return false;
}
}
[CompilerGenerated]
[DebuggerNonUserCode]
public override int get_LastGenerated()
{
return this.current;
}
[CompilerGenerated]
[DebuggerNonUserCode]
public override IEnumerator<int> GetFreshEnumerator()
{
return new getSeq@5(0, 0);
}
}
public static IDisposable disposable()
{
return new disposable@3();
}
public static IEnumerable<int> getSeq()
{
return new getSeq@5(0, 0);
}
public static FSharpList<int> getList()
{
return FSharpList<int>.Cons(1, FSharpList<int>.Empty);
}
public static int[] getArray()
{
return new int[1]
{
1
};
}
[EntryPoint]
public static int main(string[] argv)
{
IDisposable disposable = default(IDisposable);
using (Program.disposable())
{
Console.WriteLine("Hello 1");
disposable = Program.disposable();
}
using (disposable)
{
IEnumerable<int> seq = Program.getSeq();
using (IEnumerator<int> enumerator = seq.GetEnumerator())
{
while (true)
{
if (!enumerator.MoveNext())
break;
int k = enumerator.Current;
Console.WriteLine(k);
}
}
FSharpList<int> fSharpList = Program.getList();
FSharpList<int> tailOrNull = fSharpList.TailOrNull;
while (true)
{
if (tailOrNull == null)
break;
int j = fSharpList.HeadOrDefault;
Console.WriteLine(j);
fSharpList = tailOrNull;
tailOrNull = fSharpList.TailOrNull;
}
int[] array = Program.getArray();
for (int l = 0; l < array.Length; l++)
{
int i = array[l];
Console.WriteLine(i);
}
return 0;
}
}
}
namespace <StartupCode$ConsoleApplication1>
{
internal static class $Program
{
}
internal static class $AssemblyInfo
{
}
}
namespace <StartupCode$ConsoleApplication1>.$.NETFramework,Version=v4.6.1
{
internal static class AssemblyAttributes
{
}
}

586
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Debug.il

@ -0,0 +1,586 @@ @@ -0,0 +1,586 @@
// C:\Users\Siegfried\Documents\Visual Studio 2017\Projects\ConsoleApp13\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe
.assembly extern mscorlib
{
.publickeytoken = (
b7 7a 5c 56 19 34 e0 89
)
.ver 4:0:0:0
}
.assembly extern FSharp.Core
{
.publickeytoken = (
b0 3f 5f 7f 11 d5 0a 3a
)
.ver 4:4:1:0
}
.assembly ConsoleApplication1
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, int32, int32) = (
01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = (
01 00 1c 2e 4e 45 54 46 72 61 6d 65 77 6f 72 6b
2c 56 65 72 73 69 6f 6e 3d 76 34 2e 36 2e 31 01
00 54 0e 14 46 72 61 6d 65 77 6f 72 6b 44 69 73
70 6c 61 79 4e 61 6d 65 14 2e 4e 45 54 20 46 72
61 6d 65 77 6f 72 6b 20 34 2e 36 2e 31
)
.custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = (
01 00 13 43 6f 6e 73 6f 6c 65 41 70 70 6c 69 63
61 74 69 6f 6e 31 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = (
01 00 13 43 6f 6e 73 6f 6c 65 41 70 70 6c 69 63
61 74 69 6f 6e 31 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = (
01 00 12 43 6f 70 79 72 69 67 68 74 20 c2 a9 20
20 32 30 31 37 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyCultureAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = (
01 00 24 65 30 36 37 34 66 66 35 2d 35 65 38 66
2d 34 64 34 65 2d 61 38 38 66 2d 65 34 34 37 31
39 32 34 35 34 63 37 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyVersionAttribute::.ctor(string) = (
01 00 07 31 2e 30 2e 30 2e 30 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = (
01 00 07 31 2e 30 2e 30 2e 30 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
01 00 01 01 00 00 00 00
)
.hash algorithm 0x00008004 // SHA1
.ver 1:0:0:0
}
.module ConsoleApplication1.exe
// MVID: {59F64D20-6A1F-D4CE-A745-0383204DF659}
.corflags 0x00020003 // ILOnly, Required32Bit, Preferred32Bit
.class private auto ansi '<Module>'
extends [mscorlib]System.Object
{
} // end of class <Module>
.class public auto ansi abstract sealed Program
extends [mscorlib]System.Object
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
01 00 07 00 00 00 00 00
)
// Nested Types
.class nested assembly auto auto sealed specialname serializable beforefieldinit disposable@3
extends [mscorlib]System.Object
implements [mscorlib]System.IDisposable
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
01 00 06 00 00 00 00 00
)
// Methods
.method public specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x21c8
// Code size 9 (0x9)
.maxstack 8
IL_0000: ldarg.0
IL_0001: callvirt instance void [mscorlib]System.Object::.ctor()
IL_0006: ldarg.0
IL_0007: pop
IL_0008: ret
} // end of method disposable@3::.ctor
.method private final hidebysig newslot virtual
instance void 'System-IDisposable-Dispose' () cil managed
{
.override method instance void [mscorlib]System.IDisposable::Dispose()
// Method begins at RVA 0x21d4
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method disposable@3::'System-IDisposable-Dispose'
} // end of class disposable@3
.class nested assembly auto auto sealed specialname serializable beforefieldinit getSeq@5
extends class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1<int32>
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
01 00 06 00 00 00 00 00
)
// Fields
.field public int32 pc
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
01 00 00 00
)
.field public int32 current
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
01 00 00 00
)
// Methods
.method public specialname rtspecialname
instance void .ctor (
int32 pc,
int32 current
) cil managed
{
// Method begins at RVA 0x21d8
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 Program/getSeq@5::pc
IL_0007: ldarg.0
IL_0008: ldarg.2
IL_0009: stfld int32 Program/getSeq@5::current
IL_000e: ldarg.0
IL_000f: call instance void class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1<int32>::.ctor()
IL_0014: ret
} // end of method getSeq@5::.ctor
.method public strict virtual
instance int32 GenerateNext (
class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>& next
) cil managed
{
// Method begins at RVA 0x21f0
// Code size 66 (0x42)
.maxstack 6
IL_0000: ldarg.0
IL_0001: ldfld int32 Program/getSeq@5::pc
IL_0006: ldc.i4.1
IL_0007: sub
IL_0008: switch (IL_0017, IL_0019)
IL_0015: br.s IL_0021
IL_0017: br.s IL_001b
IL_0019: br.s IL_001e
IL_001b: nop
IL_001c: br.s IL_0032
IL_001e: nop
IL_001f: br.s IL_0039
IL_0021: nop
IL_0022: ldarg.0
IL_0023: ldc.i4.1
IL_0024: stfld int32 Program/getSeq@5::pc
IL_0029: ldarg.0
IL_002a: ldc.i4.1
IL_002b: stfld int32 Program/getSeq@5::current
IL_0030: ldc.i4.1
IL_0031: ret
IL_0032: ldarg.0
IL_0033: ldc.i4.2
IL_0034: stfld int32 Program/getSeq@5::pc
IL_0039: ldarg.0
IL_003a: ldc.i4.0
IL_003b: stfld int32 Program/getSeq@5::current
IL_0040: ldc.i4.0
IL_0041: ret
} // end of method getSeq@5::GenerateNext
.method public strict virtual
instance void Close () cil managed
{
// Method begins at RVA 0x2240
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: stfld int32 Program/getSeq@5::pc
IL_0007: ret
} // end of method getSeq@5::Close
.method public strict virtual
instance bool get_CheckClose () cil managed
{
// Method begins at RVA 0x224c
// Code size 45 (0x2d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 Program/getSeq@5::pc
IL_0006: switch (IL_0019, IL_001b, IL_001d)
IL_0017: br.s IL_0028
IL_0019: br.s IL_001f
IL_001b: br.s IL_0022
IL_001d: br.s IL_0025
IL_001f: nop
IL_0020: br.s IL_002b
IL_0022: nop
IL_0023: br.s IL_0029
IL_0025: nop
IL_0026: br.s IL_002b
IL_0028: nop
IL_0029: ldc.i4.0
IL_002a: ret
IL_002b: ldc.i4.0
IL_002c: ret
} // end of method getSeq@5::get_CheckClose
.method public strict virtual
instance int32 get_LastGenerated () cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x227c
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 Program/getSeq@5::current
IL_0006: ret
} // end of method getSeq@5::get_LastGenerated
.method public strict virtual
instance class [mscorlib]System.Collections.Generic.IEnumerator`1<int32> GetFreshEnumerator () cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2284
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: ldc.i4.0
IL_0002: newobj instance void Program/getSeq@5::.ctor(int32, int32)
IL_0007: ret
} // end of method getSeq@5::GetFreshEnumerator
} // end of class getSeq@5
// Methods
.method public static
class [mscorlib]System.IDisposable disposable () cil managed
{
// Method begins at RVA 0x2050
// Code size 6 (0x6)
.maxstack 8
IL_0000: newobj instance void Program/disposable@3::.ctor()
IL_0005: ret
} // end of method Program::disposable
.method public static
class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> getSeq () cil managed
{
// Method begins at RVA 0x2058
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: ldc.i4.0
IL_0002: newobj instance void Program/getSeq@5::.ctor(int32, int32)
IL_0007: ret
} // end of method Program::getSeq
.method public static
class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> getList () cil managed
{
// Method begins at RVA 0x2064
// Code size 12 (0xc)
.maxstack 8
IL_0000: ldc.i4.1
IL_0001: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_Empty()
IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0>)
IL_000b: ret
} // end of method Program::getList
.method public static
int32[] getArray () cil managed
{
// Method begins at RVA 0x2074
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldc.i4.1
IL_0001: newarr [mscorlib]System.Int32
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4.1
IL_0009: stelem.any [mscorlib]System.Int32
IL_000e: ret
} // end of method Program::getArray
.method public static
int32 main (
string[] argv
) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2084
// Code size 270 (0x10e)
.maxstack 4
.entrypoint
.locals init (
[0] class [mscorlib]System.IDisposable,
[1] class [mscorlib]System.IDisposable,
[2] class [mscorlib]System.IDisposable,
[3] class [mscorlib]System.IDisposable,
[4] int32,
[5] class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>,
[6] class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>,
[7] class [FSharp.Core]Microsoft.FSharp.Core.Unit,
[8] int32,
[9] class [mscorlib]System.IDisposable,
[10] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>,
[11] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>,
[12] int32,
[13] int32[],
[14] int32,
[15] int32,
[16] class [mscorlib]System.IDisposable
)
IL_0000: call class [mscorlib]System.IDisposable Program::disposable()
IL_0005: stloc.1
.try
{
IL_0006: ldstr "Hello 1"
IL_000b: call void [mscorlib]System.Console::WriteLine(string)
IL_0010: call class [mscorlib]System.IDisposable Program::disposable()
IL_0015: stloc.2
IL_0016: leave.s IL_0032
} // end .try
finally
{
IL_0018: ldloc.1
IL_0019: isinst [mscorlib]System.IDisposable
IL_001e: stloc.3
IL_001f: ldloc.3
IL_0020: brfalse.s IL_0024
IL_0022: br.s IL_0026
IL_0024: br.s IL_002f
IL_0026: ldloc.3
IL_0027: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_002c: ldnull
IL_002d: pop
IL_002e: endfinally
IL_002f: ldnull
IL_0030: pop
IL_0031: endfinally
} // end handler
IL_0032: ldloc.2
IL_0033: stloc.0
.try
{
IL_0034: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> Program::getSeq()
IL_0039: stloc.s 5
IL_003b: ldloc.s 5
IL_003d: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
IL_0042: stloc.s 6
.try
{
// loop start (head: IL_0044)
IL_0044: ldloc.s 6
IL_0046: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_004b: brfalse.s IL_0060
IL_004d: ldloc.s 6
IL_004f: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
IL_0054: stloc.s 8
IL_0056: ldloc.s 8
IL_0058: call void [mscorlib]System.Console::WriteLine(int32)
IL_005d: nop
IL_005e: br.s IL_0044
// end loop
IL_0060: ldnull
IL_0061: stloc.s 7
IL_0063: leave.s IL_0083
} // end .try
finally
{
IL_0065: ldloc.s 6
IL_0067: isinst [mscorlib]System.IDisposable
IL_006c: stloc.s 9
IL_006e: ldloc.s 9
IL_0070: brfalse.s IL_0074
IL_0072: br.s IL_0076
IL_0074: br.s IL_0080
IL_0076: ldloc.s 9
IL_0078: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_007d: ldnull
IL_007e: pop
IL_007f: endfinally
IL_0080: ldnull
IL_0081: pop
IL_0082: endfinally
} // end handler
IL_0083: ldloc.s 7
IL_0085: pop
IL_0086: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> Program::getList()
IL_008b: stloc.s 10
IL_008d: ldloc.s 10
IL_008f: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
IL_0094: stloc.s 11
// loop start (head: IL_0096)
IL_0096: ldloc.s 11
IL_0098: ldnull
IL_0099: cgt.un
IL_009b: brfalse.s IL_00bd
IL_009d: ldloc.s 10
IL_009f: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_HeadOrDefault()
IL_00a4: stloc.s 12
IL_00a6: ldloc.s 12
IL_00a8: call void [mscorlib]System.Console::WriteLine(int32)
IL_00ad: ldloc.s 11
IL_00af: stloc.s 10
IL_00b1: ldloc.s 10
IL_00b3: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
IL_00b8: stloc.s 11
IL_00ba: nop
IL_00bb: br.s IL_0096
// end loop
IL_00bd: call int32[] Program::getArray()
IL_00c2: stloc.s 13
IL_00c4: ldc.i4.0
IL_00c5: stloc.s 14
IL_00c7: br.s IL_00e1
// loop start (head: IL_00e1)
IL_00c9: ldloc.s 13
IL_00cb: ldloc.s 14
IL_00cd: ldelem.any [mscorlib]System.Int32
IL_00d2: stloc.s 15
IL_00d4: ldloc.s 15
IL_00d6: call void [mscorlib]System.Console::WriteLine(int32)
IL_00db: ldloc.s 14
IL_00dd: ldc.i4.1
IL_00de: add
IL_00df: stloc.s 14
IL_00e1: ldloc.s 14
IL_00e3: ldloc.s 13
IL_00e5: ldlen
IL_00e6: conv.i4
IL_00e7: blt.s IL_00c9
// end loop
IL_00e9: ldc.i4.0
IL_00ea: stloc.s 4
IL_00ec: leave.s IL_010b
} // end .try
finally
{
IL_00ee: ldloc.0
IL_00ef: isinst [mscorlib]System.IDisposable
IL_00f4: stloc.s 16
IL_00f6: ldloc.s 16
IL_00f8: brfalse.s IL_00fc
IL_00fa: br.s IL_00fe
IL_00fc: br.s IL_0108
IL_00fe: ldloc.s 16
IL_0100: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0105: ldnull
IL_0106: pop
IL_0107: endfinally
IL_0108: ldnull
IL_0109: pop
IL_010a: endfinally
} // end handler
IL_010b: ldloc.s 4
IL_010d: ret
} // end of method Program::main
} // end of class Program
.class private auto ansi abstract sealed '<StartupCode$ConsoleApplication1>.$Program'
extends [mscorlib]System.Object
{
} // end of class <StartupCode$ConsoleApplication1>.$Program
.class private auto ansi abstract sealed '<StartupCode$ConsoleApplication1>.$AssemblyInfo'
extends [mscorlib]System.Object
{
} // end of class <StartupCode$ConsoleApplication1>.$AssemblyInfo
.class private auto ansi abstract sealed '<StartupCode$ConsoleApplication1>.$.NETFramework,Version=v4.6.1.AssemblyAttributes'
extends [mscorlib]System.Object
{
} // end of class <StartupCode$ConsoleApplication1>.$.NETFramework,Version=v4.6.1.AssemblyAttributes

210
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.cs

@ -0,0 +1,210 @@ @@ -0,0 +1,210 @@
// C:\Users\Siegfried\Documents\Visual Studio 2017\Projects\ConsoleApp13\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
// ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// Global type: <Module>
// Entry point: Program.main
// Architecture: AnyCPU (32-bit preferred)
// Runtime: .NET 4.0
using Microsoft.FSharp.Collections;
using Microsoft.FSharp.Core;
using Microsoft.FSharp.Core.CompilerServices;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
[assembly: FSharpInterfaceDataVersion(2, 0, 0)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: AssemblyTitle("ConsoleApplication1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ConsoleApplication1")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("e0674ff5-5e8f-4d4e-a88f-e447192454c7")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.None)]
[assembly: AssemblyVersion("1.0.0.0")]
[CompilationMapping(SourceConstructFlags.Module)]
public static class Program
{
[Serializable]
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
[CompilationMapping(SourceConstructFlags.Closure)]
internal sealed class disposable@3 : IDisposable
{
public disposable@3()
{
((object)this)..ctor();
}
private void System-IDisposable-Dispose()
{
}
void IDisposable.Dispose()
{
//ILSpy generated this explicit interface implementation from .override directive in System-IDisposable-Dispose
this.System-IDisposable-Dispose();
}
}
[Serializable]
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
[CompilationMapping(SourceConstructFlags.Closure)]
internal sealed class getSeq@5 : GeneratedSequenceBase<int>
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
public int pc = pc;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
[DebuggerNonUserCode]
public int current = current;
public getSeq@5(int pc, int current)
{
}
public override int GenerateNext(ref IEnumerable<int> next)
{
switch (this.pc)
{
default:
this.pc = 1;
this.current = 1;
return 1;
case 1:
this.pc = 2;
break;
case 2:
break;
}
this.current = 0;
return 0;
}
public override void Close()
{
this.pc = 2;
}
public override bool get_CheckClose()
{
switch (this.pc)
{
default:
return false;
case 0:
case 2:
return false;
}
}
[CompilerGenerated]
[DebuggerNonUserCode]
public override int get_LastGenerated()
{
return this.current;
}
[CompilerGenerated]
[DebuggerNonUserCode]
public override IEnumerator<int> GetFreshEnumerator()
{
return new getSeq@5(0, 0);
}
}
public static IDisposable disposable()
{
return new disposable@3();
}
public static IEnumerable<int> getSeq()
{
return new getSeq@5(0, 0);
}
public static FSharpList<int> getList()
{
return FSharpList<int>.Cons(1, FSharpList<int>.Empty);
}
public static int[] getArray()
{
return new int[1]
{
1
};
}
[EntryPoint]
public static int main(string[] argv)
{
IDisposable disposable = default(IDisposable);
using (Program.disposable())
{
Console.WriteLine("Hello 1");
disposable = Program.disposable();
}
using (disposable)
{
IEnumerable<int> seq = Program.getSeq();
using (IEnumerator<int> enumerator = seq.GetEnumerator())
{
while (true)
{
if (!enumerator.MoveNext())
break;
Console.WriteLine(enumerator.Current);
}
}
FSharpList<int> fSharpList = FSharpList<int>.Cons(1, FSharpList<int>.Empty);
FSharpList<int> tailOrNull = fSharpList.TailOrNull;
while (true)
{
if (tailOrNull == null)
break;
int j = fSharpList.HeadOrDefault;
Console.WriteLine(j);
fSharpList = tailOrNull;
tailOrNull = fSharpList.TailOrNull;
}
int[] array = new int[1]
{
1
};
for (int j = 0; j < array.Length; j++)
{
Console.WriteLine(array[j]);
}
return 0;
}
}
}
namespace <StartupCode$ConsoleApplication1>
{
internal static class $Program
{
}
internal static class $AssemblyInfo
{
}
}
namespace <StartupCode$ConsoleApplication1>.$.NETFramework,Version=v4.6.1
{
internal static class AssemblyAttributes
{
}
}

561
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpLoops_Release.il

@ -0,0 +1,561 @@ @@ -0,0 +1,561 @@
// C:\Users\Siegfried\Documents\Visual Studio 2017\Projects\ConsoleApp13\ConsoleApplication1\bin\Release\ConsoleApplication1.exe
.assembly extern mscorlib
{
.publickeytoken = (
b7 7a 5c 56 19 34 e0 89
)
.ver 4:0:0:0
}
.assembly extern FSharp.Core
{
.publickeytoken = (
b0 3f 5f 7f 11 d5 0a 3a
)
.ver 4:4:1:0
}
.assembly ConsoleApplication1
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, int32, int32) = (
01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = (
01 00 1c 2e 4e 45 54 46 72 61 6d 65 77 6f 72 6b
2c 56 65 72 73 69 6f 6e 3d 76 34 2e 36 2e 31 01
00 54 0e 14 46 72 61 6d 65 77 6f 72 6b 44 69 73
70 6c 61 79 4e 61 6d 65 14 2e 4e 45 54 20 46 72
61 6d 65 77 6f 72 6b 20 34 2e 36 2e 31
)
.custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = (
01 00 13 43 6f 6e 73 6f 6c 65 41 70 70 6c 69 63
61 74 69 6f 6e 31 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = (
01 00 13 43 6f 6e 73 6f 6c 65 41 70 70 6c 69 63
61 74 69 6f 6e 31 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = (
01 00 12 43 6f 70 79 72 69 67 68 74 20 c2 a9 20
20 32 30 31 37 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyCultureAttribute::.ctor(string) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = (
01 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = (
01 00 24 65 30 36 37 34 66 66 35 2d 35 65 38 66
2d 34 64 34 65 2d 61 38 38 66 2d 65 34 34 37 31
39 32 34 35 34 63 37 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyVersionAttribute::.ctor(string) = (
01 00 07 31 2e 30 2e 30 2e 30 00 00
)
.custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = (
01 00 07 31 2e 30 2e 30 2e 30 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
01 00 00 00 00 00 00 00
)
.hash algorithm 0x00008004 // SHA1
.ver 1:0:0:0
}
.module ConsoleApplication1.exe
// MVID: {59F64D28-6A1F-D4CE-A745-0383284DF659}
.corflags 0x00020003 // ILOnly, Required32Bit, Preferred32Bit
.class private auto ansi '<Module>'
extends [mscorlib]System.Object
{
} // end of class <Module>
.class public auto ansi abstract sealed Program
extends [mscorlib]System.Object
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
01 00 07 00 00 00 00 00
)
// Nested Types
.class nested assembly auto auto sealed specialname serializable beforefieldinit disposable@3
extends [mscorlib]System.Object
implements [mscorlib]System.IDisposable
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
01 00 06 00 00 00 00 00
)
// Methods
.method public specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x21bc
// Code size 9 (0x9)
.maxstack 8
IL_0000: ldarg.0
IL_0001: callvirt instance void [mscorlib]System.Object::.ctor()
IL_0006: ldarg.0
IL_0007: pop
IL_0008: ret
} // end of method disposable@3::.ctor
.method private final hidebysig newslot virtual
instance void 'System-IDisposable-Dispose' () cil managed
{
.override method instance void [mscorlib]System.IDisposable::Dispose()
// Method begins at RVA 0x21c8
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method disposable@3::'System-IDisposable-Dispose'
} // end of class disposable@3
.class nested assembly auto auto sealed specialname serializable beforefieldinit getSeq@5
extends class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1<int32>
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
01 00 06 00 00 00 00 00
)
// Fields
.field public int32 pc
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
01 00 00 00
)
.field public int32 current
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
01 00 00 00
)
// Methods
.method public specialname rtspecialname
instance void .ctor (
int32 pc,
int32 current
) cil managed
{
// Method begins at RVA 0x21cc
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 Program/getSeq@5::pc
IL_0007: ldarg.0
IL_0008: ldarg.2
IL_0009: stfld int32 Program/getSeq@5::current
IL_000e: ldarg.0
IL_000f: call instance void class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1<int32>::.ctor()
IL_0014: ret
} // end of method getSeq@5::.ctor
.method public strict virtual
instance int32 GenerateNext (
class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>& next
) cil managed
{
// Method begins at RVA 0x21e4
// Code size 62 (0x3e)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 Program/getSeq@5::pc
IL_0006: ldc.i4.1
IL_0007: sub
IL_0008: switch (IL_0018, IL_001b)
IL_0015: nop
IL_0016: br.s IL_001e
IL_0018: nop
IL_0019: br.s IL_002e
IL_001b: nop
IL_001c: br.s IL_0035
IL_001e: ldarg.0
IL_001f: ldc.i4.1
IL_0020: stfld int32 Program/getSeq@5::pc
IL_0025: ldarg.0
IL_0026: ldc.i4.1
IL_0027: stfld int32 Program/getSeq@5::current
IL_002c: ldc.i4.1
IL_002d: ret
IL_002e: ldarg.0
IL_002f: ldc.i4.2
IL_0030: stfld int32 Program/getSeq@5::pc
IL_0035: ldarg.0
IL_0036: ldc.i4.0
IL_0037: stfld int32 Program/getSeq@5::current
IL_003c: ldc.i4.0
IL_003d: ret
} // end of method getSeq@5::GenerateNext
.method public strict virtual
instance void Close () cil managed
{
// Method begins at RVA 0x2224
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: stfld int32 Program/getSeq@5::pc
IL_0007: ret
} // end of method getSeq@5::Close
.method public strict virtual
instance bool get_CheckClose () cil managed
{
// Method begins at RVA 0x2230
// Code size 39 (0x27)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 Program/getSeq@5::pc
IL_0006: switch (IL_001a, IL_001d, IL_0020)
IL_0017: nop
IL_0018: br.s IL_0023
IL_001a: nop
IL_001b: br.s IL_0025
IL_001d: nop
IL_001e: br.s IL_0023
IL_0020: nop
IL_0021: br.s IL_0025
IL_0023: ldc.i4.0
IL_0024: ret
IL_0025: ldc.i4.0
IL_0026: ret
} // end of method getSeq@5::get_CheckClose
.method public strict virtual
instance int32 get_LastGenerated () cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2258
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 Program/getSeq@5::current
IL_0006: ret
} // end of method getSeq@5::get_LastGenerated
.method public strict virtual
instance class [mscorlib]System.Collections.Generic.IEnumerator`1<int32> GetFreshEnumerator () cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2260
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: ldc.i4.0
IL_0002: newobj instance void Program/getSeq@5::.ctor(int32, int32)
IL_0007: ret
} // end of method getSeq@5::GetFreshEnumerator
} // end of class getSeq@5
// Methods
.method public static
class [mscorlib]System.IDisposable disposable () cil managed
{
// Method begins at RVA 0x2050
// Code size 6 (0x6)
.maxstack 8
IL_0000: newobj instance void Program/disposable@3::.ctor()
IL_0005: ret
} // end of method Program::disposable
.method public static
class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> getSeq () cil managed
{
// Method begins at RVA 0x2058
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: ldc.i4.0
IL_0002: newobj instance void Program/getSeq@5::.ctor(int32, int32)
IL_0007: ret
} // end of method Program::getSeq
.method public static
class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> getList () cil managed
{
// Method begins at RVA 0x2064
// Code size 12 (0xc)
.maxstack 8
IL_0000: ldc.i4.1
IL_0001: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_Empty()
IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0>)
IL_000b: ret
} // end of method Program::getList
.method public static
int32[] getArray () cil managed
{
// Method begins at RVA 0x2074
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldc.i4.1
IL_0001: newarr [mscorlib]System.Int32
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldc.i4.1
IL_0009: stelem.any [mscorlib]System.Int32
IL_000e: ret
} // end of method Program::getArray
.method public static
int32 main (
string[] argv
) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2084
// Code size 259 (0x103)
.maxstack 6
.entrypoint
.locals init (
[0] class [mscorlib]System.IDisposable,
[1] class [mscorlib]System.IDisposable,
[2] class [mscorlib]System.IDisposable,
[3] class [mscorlib]System.IDisposable,
[4] int32,
[5] class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>,
[6] class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>,
[7] class [FSharp.Core]Microsoft.FSharp.Core.Unit,
[8] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>,
[9] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>,
[10] int32,
[11] int32[]
)
IL_0000: call class [mscorlib]System.IDisposable Program::disposable()
IL_0005: stloc.1
.try
{
IL_0006: ldstr "Hello 1"
IL_000b: call void [mscorlib]System.Console::WriteLine(string)
IL_0010: call class [mscorlib]System.IDisposable Program::disposable()
IL_0015: stloc.2
IL_0016: leave.s IL_002e
} // end .try
finally
{
IL_0018: ldloc.1
IL_0019: isinst [mscorlib]System.IDisposable
IL_001e: stloc.3
IL_001f: ldloc.3
IL_0020: brfalse.s IL_002b
IL_0022: ldloc.3
IL_0023: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0028: ldnull
IL_0029: pop
IL_002a: endfinally
IL_002b: ldnull
IL_002c: pop
IL_002d: endfinally
} // end handler
IL_002e: ldloc.2
IL_002f: stloc.0
.try
{
IL_0030: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> Program::getSeq()
IL_0035: stloc.s 5
IL_0037: ldloc.s 5
IL_0039: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
IL_003e: stloc.s 6
.try
{
// loop start (head: IL_0040)
IL_0040: ldloc.s 6
IL_0042: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_0047: brfalse.s IL_0058
IL_0049: ldloc.s 6
IL_004b: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
IL_0050: call void [mscorlib]System.Console::WriteLine(int32)
IL_0055: nop
IL_0056: br.s IL_0040
// end loop
IL_0058: ldnull
IL_0059: stloc.s 7
IL_005b: leave.s IL_0074
} // end .try
finally
{
IL_005d: ldloc.s 6
IL_005f: isinst [mscorlib]System.IDisposable
IL_0064: stloc.1
IL_0065: ldloc.1
IL_0066: brfalse.s IL_0071
IL_0068: ldloc.1
IL_0069: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_006e: ldnull
IL_006f: pop
IL_0070: endfinally
IL_0071: ldnull
IL_0072: pop
IL_0073: endfinally
} // end handler
IL_0074: ldloc.s 7
IL_0076: pop
IL_0077: ldc.i4.1
IL_0078: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_Empty()
IL_007d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0>)
IL_0082: stloc.s 8
IL_0084: ldloc.s 8
IL_0086: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
IL_008b: stloc.s 9
// loop start (head: IL_008d)
IL_008d: ldloc.s 9
IL_008f: ldnull
IL_0090: cgt.un
IL_0092: brfalse.s IL_00b4
IL_0094: ldloc.s 8
IL_0096: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_HeadOrDefault()
IL_009b: stloc.s 10
IL_009d: ldloc.s 10
IL_009f: call void [mscorlib]System.Console::WriteLine(int32)
IL_00a4: ldloc.s 9
IL_00a6: stloc.s 8
IL_00a8: ldloc.s 8
IL_00aa: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_TailOrNull()
IL_00af: stloc.s 9
IL_00b1: nop
IL_00b2: br.s IL_008d
// end loop
IL_00b4: ldc.i4.1
IL_00b5: newarr [mscorlib]System.Int32
IL_00ba: dup
IL_00bb: ldc.i4.0
IL_00bc: ldc.i4.1
IL_00bd: stelem.any [mscorlib]System.Int32
IL_00c2: stloc.s 11
IL_00c4: ldc.i4.0
IL_00c5: stloc.s 10
IL_00c7: br.s IL_00dd
// loop start (head: IL_00dd)
IL_00c9: ldloc.s 11
IL_00cb: ldloc.s 10
IL_00cd: ldelem.any [mscorlib]System.Int32
IL_00d2: call void [mscorlib]System.Console::WriteLine(int32)
IL_00d7: ldloc.s 10
IL_00d9: ldc.i4.1
IL_00da: add
IL_00db: stloc.s 10
IL_00dd: ldloc.s 10
IL_00df: ldloc.s 11
IL_00e1: ldlen
IL_00e2: conv.i4
IL_00e3: blt.s IL_00c9
// end loop
IL_00e5: ldc.i4.0
IL_00e6: stloc.s 4
IL_00e8: leave.s IL_0100
} // end .try
finally
{
IL_00ea: ldloc.0
IL_00eb: isinst [mscorlib]System.IDisposable
IL_00f0: stloc.1
IL_00f1: ldloc.1
IL_00f2: brfalse.s IL_00fd
IL_00f4: ldloc.1
IL_00f5: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_00fa: ldnull
IL_00fb: pop
IL_00fc: endfinally
IL_00fd: ldnull
IL_00fe: pop
IL_00ff: endfinally
} // end handler
IL_0100: ldloc.s 4
IL_0102: ret
} // end of method Program::main
} // end of class Program
.class private auto ansi abstract sealed '<StartupCode$ConsoleApplication1>.$Program'
extends [mscorlib]System.Object
{
} // end of class <StartupCode$ConsoleApplication1>.$Program
.class private auto ansi abstract sealed '<StartupCode$ConsoleApplication1>.$AssemblyInfo'
extends [mscorlib]System.Object
{
} // end of class <StartupCode$ConsoleApplication1>.$AssemblyInfo
.class private auto ansi abstract sealed '<StartupCode$ConsoleApplication1>.$.NETFramework,Version=v4.6.1.AssemblyAttributes'
extends [mscorlib]System.Object
{
} // end of class <StartupCode$ConsoleApplication1>.$.NETFramework,Version=v4.6.1.AssemblyAttributes

0
ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpUsing.fs → ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing.fs

58
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
using System;
using System.IO;
public static class FSharpUsingPatterns
{
public static void sample1()
{
using (FileStream fileStream = File.Create("x.txt")) {
fileStream.WriteByte((byte)1);
}
}
public static void sample2()
{
Console.WriteLine("some text");
using (FileStream fileStream = File.Create("x.txt")) {
fileStream.WriteByte((byte)2);
Console.WriteLine("some text");
}
}
public static void sample3()
{
Console.WriteLine("some text");
using (FileStream fileStream = File.Create("x.txt")) {
fileStream.WriteByte((byte)3);
}
Console.WriteLine("some text");
}
public static void sample4()
{
Console.WriteLine("some text");
int num = default(int);
using (FileStream fileStream = File.OpenRead("x.txt")) {
num = fileStream.ReadByte();
}
int num2 = num;
Console.WriteLine("read:" + num2.ToString());
}
public static void sample5()
{
Console.WriteLine("some text");
int num = default(int);
using (FileStream fileStream = File.OpenRead("x.txt")) {
num = fileStream.ReadByte();
}
int num2 = num;
int num3 = default(int);
using (FileStream fileStream = File.OpenRead("x.txt")) {
fileStream.ReadByte();
num3 = fileStream.ReadByte();
}
int num4 = num3;
Console.WriteLine("read: {0}, {1}", num2, num4);
}
}

0
ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpUsing.fs.Debug.il → ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Debug.il

58
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
using System;
using System.IO;
public static class FSharpUsingPatterns
{
public static void sample1()
{
using (FileStream fileStream = File.Create("x.txt")) {
fileStream.WriteByte(1);
}
}
public static void sample2()
{
Console.WriteLine("some text");
using (FileStream fileStream = File.Create("x.txt")) {
fileStream.WriteByte(2);
Console.WriteLine("some text");
}
}
public static void sample3()
{
Console.WriteLine("some text");
using (FileStream fileStream = File.Create("x.txt")) {
fileStream.WriteByte(3);
}
Console.WriteLine("some text");
}
public static void sample4()
{
Console.WriteLine("some text");
int num = default(int);
using (FileStream fileStream = File.OpenRead("x.txt")) {
num = fileStream.ReadByte();
}
int num2 = num;
Console.WriteLine("read:" + num2.ToString());
}
public static void sample5()
{
Console.WriteLine("some text");
int num = default(int);
using (FileStream fileStream = File.OpenRead("x.txt")) {
num = fileStream.ReadByte();
}
int num2 = num;
int num3 = default(int);
using (FileStream fileStream = File.OpenRead("x.txt")) {
fileStream.ReadByte();
num3 = fileStream.ReadByte();
}
num = num3;
Console.WriteLine("read: {0}, {1}", num2, num);
}
}

0
ICSharpCode.Decompiler.Tests/FSharpPatterns/FSharpUsing.fs.Release.il → ICSharpCode.Decompiler.Tests/TestCases/ILPretty/FSharpUsing_Release.il

1
ICSharpCode.Decompiler.Tests/TestCases/Pretty/.gitignore vendored

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
/*.res
/*.dll
/*.exe
/*.pdb

11
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.cs

@ -27,6 +27,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -27,6 +27,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public abstract void B(bool b);
public abstract bool F(int i);
public abstract int GetInt(int i);
public abstract void M1();
public abstract void M2();
public abstract void E();
@ -91,6 +92,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -91,6 +92,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
this.E();
}
public void StmtOr4()
{
if (this.GetInt(0) != 0 || this.GetInt(1) != 0) {
this.M1();
} else {
this.M2();
}
this.E();
}
public void StmtComplex()
{
if (this.F(0) && this.F(1) && !this.F(2) && (this.F(3) || this.F(4))) {

60
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.il

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Copyright (c) Microsoft Corporation. All rights reserved.
@ -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 '0fqx5k1s'
.assembly bqtfnoxz
{
.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 '0fqx5k1s.dll'
// MVID: {40923C21-ED40-40E0-8D2A-58DE2CA84852}
.module bqtfnoxz.dll
// MVID: {E41D831E-089A-4F86-AA5D-FD2CB6D7C452}
.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: 0x031A0000
// Image base: 0x03120000
// =============== CLASS MEMBERS DECLARATION ===================
@ -46,6 +46,11 @@ @@ -46,6 +46,11 @@
{
} // end of method ShortCircuit::F
.method public hidebysig newslot abstract virtual
instance int32 GetInt(int32 i) cil managed
{
} // end of method ShortCircuit::GetInt
.method public hidebysig newslot abstract virtual
instance void M1() cil managed
{
@ -348,6 +353,49 @@ @@ -348,6 +353,49 @@
IL_0040: ret
} // end of method ShortCircuit::StmtOr3
.method public hidebysig instance void
StmtOr4() cil managed
{
// Code size 56 (0x38)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::GetInt(int32)
IL_0008: brtrue.s IL_0016
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::GetInt(int32)
IL_0011: ldc.i4.0
IL_0012: ceq
IL_0014: br.s IL_0017
IL_0016: ldc.i4.0
IL_0017: nop
IL_0018: stloc.0
IL_0019: ldloc.0
IL_001a: brtrue.s IL_0027
IL_001c: nop
IL_001d: ldarg.0
IL_001e: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0023: nop
IL_0024: nop
IL_0025: br.s IL_0030
IL_0027: nop
IL_0028: ldarg.0
IL_0029: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_002e: nop
IL_002f: nop
IL_0030: ldarg.0
IL_0031: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0036: nop
IL_0037: ret
} // end of method ShortCircuit::StmtOr4
.method public hidebysig instance void
StmtComplex() cil managed
{
@ -588,4 +636,4 @@ @@ -588,4 +636,4 @@
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\ShortCircuit.res
// WARNING: Created Win32 resource file ../../../TestCases/Pretty\ShortCircuit.res

43
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.opt.il

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Copyright (c) Microsoft Corporation. All rights reserved.
@ -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 gbge3vmw
.assembly '4yyrmwig'
{
.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 gbge3vmw.dll
// MVID: {39FE0BDC-C8CF-421C-936D-85782F68AEF4}
.module '4yyrmwig.dll'
// MVID: {A53FB590-72B6-46AB-809D-9F6F92B64475}
.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: 0x00C00000
// Image base: 0x015D0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -46,6 +46,11 @@ @@ -46,6 +46,11 @@
{
} // end of method ShortCircuit::F
.method public hidebysig newslot abstract virtual
instance int32 GetInt(int32 i) cil managed
{
} // end of method ShortCircuit::GetInt
.method public hidebysig newslot abstract virtual
instance void M1() cil managed
{
@ -268,6 +273,32 @@ @@ -268,6 +273,32 @@
IL_002f: ret
} // end of method ShortCircuit::StmtOr3
.method public hidebysig instance void
StmtOr4() cil managed
{
// Code size 39 (0x27)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::GetInt(int32)
IL_0007: brtrue.s IL_0012
IL_0009: ldarg.0
IL_000a: ldc.i4.1
IL_000b: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::GetInt(int32)
IL_0010: brfalse.s IL_001a
IL_0012: ldarg.0
IL_0013: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0018: br.s IL_0020
IL_001a: ldarg.0
IL_001b: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_0020: ldarg.0
IL_0021: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0026: ret
} // end of method ShortCircuit::StmtOr4
.method public hidebysig instance void
StmtComplex() cil managed
{
@ -433,4 +464,4 @@ @@ -433,4 +464,4 @@
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\ShortCircuit.opt.res
// WARNING: Created Win32 resource file ../../../TestCases/Pretty\ShortCircuit.opt.res

37
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.opt.roslyn.il

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Copyright (c) Microsoft Corporation. All rights reserved.
@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module ShortCircuit.dll
// MVID: {A27E149C-542B-41C0-AB29-FA01A65D43CB}
// MVID: {FAFDF41B-AD51-4575-890D-F2652CF85283}
.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: 0x02490000
// Image base: 0x00710000
// =============== CLASS MEMBERS DECLARATION ===================
@ -50,6 +50,11 @@ @@ -50,6 +50,11 @@
{
} // end of method ShortCircuit::F
.method public hidebysig newslot abstract virtual
instance int32 GetInt(int32 i) cil managed
{
} // end of method ShortCircuit::GetInt
.method public hidebysig newslot abstract virtual
instance void M1() cil managed
{
@ -272,6 +277,32 @@ @@ -272,6 +277,32 @@
IL_002f: ret
} // end of method ShortCircuit::StmtOr3
.method public hidebysig instance void
StmtOr4() cil managed
{
// Code size 39 (0x27)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::GetInt(int32)
IL_0007: brtrue.s IL_0012
IL_0009: ldarg.0
IL_000a: ldc.i4.1
IL_000b: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::GetInt(int32)
IL_0010: brfalse.s IL_001a
IL_0012: ldarg.0
IL_0013: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0018: br.s IL_0020
IL_001a: ldarg.0
IL_001b: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_0020: ldarg.0
IL_0021: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0026: ret
} // end of method ShortCircuit::StmtOr4
.method public hidebysig instance void
StmtComplex() cil managed
{

53
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ShortCircuit.roslyn.il

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929
// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Copyright (c) Microsoft Corporation. All rights reserved.
@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module ShortCircuit.dll
// MVID: {5FB25D31-D6C4-4D39-B72D-A6EBD832225B}
// MVID: {B0D8F5AF-A2A3-4091-846A-B19B13874A74}
.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: 0x00D60000
// Image base: 0x00AD0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -50,6 +50,11 @@ @@ -50,6 +50,11 @@
{
} // end of method ShortCircuit::F
.method public hidebysig newslot abstract virtual
instance int32 GetInt(int32 i) cil managed
{
} // end of method ShortCircuit::GetInt
.method public hidebysig newslot abstract virtual
instance void M1() cil managed
{
@ -336,6 +341,48 @@ @@ -336,6 +341,48 @@
IL_003c: ret
} // end of method ShortCircuit::StmtOr3
.method public hidebysig instance void
StmtOr4() cil managed
{
// Code size 55 (0x37)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::GetInt(int32)
IL_0008: brtrue.s IL_0016
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::GetInt(int32)
IL_0011: ldc.i4.0
IL_0012: cgt.un
IL_0014: br.s IL_0017
IL_0016: ldc.i4.1
IL_0017: stloc.0
IL_0018: ldloc.0
IL_0019: brfalse.s IL_0026
IL_001b: nop
IL_001c: ldarg.0
IL_001d: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0022: nop
IL_0023: nop
IL_0024: br.s IL_002f
IL_0026: nop
IL_0027: ldarg.0
IL_0028: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_002d: nop
IL_002e: nop
IL_002f: ldarg.0
IL_0030: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0035: nop
IL_0036: ret
} // end of method ShortCircuit::StmtOr4
.method public hidebysig instance void
StmtComplex() cil managed
{

288
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -0,0 +1,288 @@ @@ -0,0 +1,288 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// 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;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public class UnsafeCode
{
public struct SimpleStruct
{
public int X;
public double Y;
}
public struct StructWithFixedSizeMembers
{
public unsafe fixed int Integers[100];
public int NormalMember;
public unsafe fixed double Doubles[200];
[Obsolete("another attribute")]
public unsafe fixed byte Old[1];
}
public unsafe int* NullPointer {
get {
return null;
}
}
public unsafe int SizeOf()
{
return sizeof(SimpleStruct);
}
private static void UseBool(bool b)
{
}
public unsafe void PointerComparison(int* a, double* b)
{
UnsafeCode.UseBool(a == b);
UnsafeCode.UseBool(a != b);
UnsafeCode.UseBool(a < b);
UnsafeCode.UseBool(a > b);
UnsafeCode.UseBool(a <= b);
UnsafeCode.UseBool(a >= b);
}
public unsafe void PointerComparisonWithNull(int* a)
{
UnsafeCode.UseBool(a == null);
UnsafeCode.UseBool(a != null);
}
public unsafe int* PointerCast(long* p)
{
return (int*)p;
}
public unsafe long ConvertDoubleToLong(double d)
{
return *(long*)(&d);
}
public unsafe double ConvertLongToDouble(long d)
{
return *(double*)(&d);
}
public unsafe int ConvertFloatToInt(float d)
{
return *(int*)(&d);
}
public unsafe float ConvertIntToFloat(int d)
{
return *(float*)(&d);
}
public unsafe int PointerCasts()
{
int result = 0;
*(float*)(&result) = 0.5f;
((byte*)(&result))[3] = 3;
return result;
}
public unsafe void PassRefParameterAsPointer(ref int p)
{
fixed (int* p2 = &p) {
this.PassPointerAsRefParameter(p2);
}
}
public unsafe void PassPointerAsRefParameter(int* p)
{
this.PassRefParameterAsPointer(ref *p);
}
public unsafe void AddressInMultiDimensionalArray(double[,] matrix)
{
fixed (double* d = &matrix[1, 2]) {
this.PointerReferenceExpression(d);
this.PointerReferenceExpression(d);
}
}
public unsafe void FixedStringAccess(string text)
{
fixed (char* ptr = text) {
char* ptr2 = ptr;
while (*ptr2 == 'a') {
*ptr2 = 'A';
ptr2++;
}
}
}
public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val)
{
fixed (long* ptr = array) {
*(double*)(ptr + index) = val;
}
}
public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val)
{
fixed (long* ptr = &array[index]) {
*(double*)ptr = val;
}
}
public unsafe string PointerReferenceExpression(double* d)
{
return d->ToString();
}
public unsafe string PointerReferenceExpression2(long addr)
{
return ((int*)addr)->ToString();
}
public unsafe int* PointerArithmetic(int* p)
{
return p + 2;
}
public unsafe long* PointerArithmetic2(long* p)
{
return 3 + p;
}
public unsafe long* PointerArithmetic3(long* p)
{
return (long*)((byte*)p + 3);
}
public unsafe long* PointerArithmetic4(void* p)
{
return (long*)((byte*)p + 3);
}
public unsafe int PointerArithmetic5(void* p, byte* q, int i)
{
return q[i] + *(byte*)p;
}
public unsafe int PointerArithmetic6(SimpleStruct* p, int i)
{
return p[i].X;
}
public unsafe int* PointerArithmeticLong1(int* p, long offset)
{
return p + offset;
}
public unsafe int* PointerArithmeticLong2(int* p, long offset)
{
return offset + p;
}
public unsafe int* PointerArithmeticLong3(int* p, long offset)
{
return p - offset;
}
public unsafe SimpleStruct* PointerArithmeticLong1s(SimpleStruct* p, long offset)
{
return p + offset;
}
public unsafe SimpleStruct* PointerArithmeticLong2s(SimpleStruct* p, long offset)
{
return offset + p;
}
public unsafe SimpleStruct* PointerArithmeticLong3s(SimpleStruct* p, long offset)
{
return p - offset;
}
public unsafe int PointerSubtraction(long* p, long* q)
{
return (int)(p - q);
}
public unsafe long PointerSubtractionLong(long* p, long* q)
{
return p - q;
}
public unsafe int PointerSubtraction2(long* p, short* q)
{
return (int)((byte*)p - (byte*)q);
}
public unsafe int PointerSubtraction3(void* p, void* q)
{
return (int)((byte*)p - (byte*)q);
}
public unsafe long PointerSubtraction4(sbyte* p, sbyte* q)
{
return p - q;
}
public unsafe long PointerSubtraction5(SimpleStruct* p, SimpleStruct* q)
{
return p - q;
}
public unsafe double FixedMemberAccess(StructWithFixedSizeMembers* m, int i)
{
return (double)m->Integers[i] + m->Doubles[i];
}
public unsafe double* FixedMemberBasePointer(StructWithFixedSizeMembers* m)
{
return m->Doubles;
}
public unsafe string UsePointer(double* ptr)
{
return ptr->ToString();
}
public unsafe string StackAlloc(int count)
{
char* ptr = stackalloc char[count];
char* ptr2 = stackalloc char[100];
for (int i = 0; i < count; i++) {
ptr[i] = (char)i;
ptr2[i] = '\0';
}
return this.UsePointer((double*)ptr);
}
public unsafe string StackAllocStruct(int count)
{
SimpleStruct* ptr = stackalloc SimpleStruct[checked(count * 2)];
SimpleStruct* _ = stackalloc SimpleStruct[10];
return this.UsePointer(&ptr->Y);
}
unsafe ~UnsafeCode()
{
this.PassPointerAsRefParameter(this.NullPointer);
}
}
}

1149
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il

File diff suppressed because it is too large Load Diff

904
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il

@ -0,0 +1,904 @@ @@ -0,0 +1,904 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// 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 zuwavv1x
{
.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.
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module zuwavv1x.dll
// MVID: {4CC9FC6C-21CA-408A-ABC9-544A07D1E512}
.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: 0x01600000
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode
extends [mscorlib]System.Object
{
.class sequential ansi sealed nested public beforefieldinit SimpleStruct
extends [mscorlib]System.ValueType
{
.field public int32 X
.field public float64 Y
} // end of class SimpleStruct
.class sequential ansi sealed nested public beforefieldinit StructWithFixedSizeMembers
extends [mscorlib]System.ValueType
{
.class sequential ansi sealed nested public beforefieldinit '<Integers>e__FixedBuffer0'
extends [mscorlib]System.ValueType
{
.pack 0
.size 400
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 )
.field public int32 FixedElementField
} // end of class '<Integers>e__FixedBuffer0'
.class sequential ansi sealed nested public beforefieldinit '<Doubles>e__FixedBuffer1'
extends [mscorlib]System.ValueType
{
.pack 0
.size 1600
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 )
.field public float64 FixedElementField
} // end of class '<Doubles>e__FixedBuffer1'
.class sequential ansi sealed nested public beforefieldinit '<Old>e__FixedBuffer2'
extends [mscorlib]System.ValueType
{
.pack 0
.size 1
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 )
.field public uint8 FixedElementField
} // end of class '<Old>e__FixedBuffer2'
.field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer0' Integers
.custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type,
int32) = ( 01 00 59 53 79 73 74 65 6D 2E 49 6E 74 33 32 2C // ..YSystem.Int32,
20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 // mscorlib, Versi
6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 // on=4.0.0.0, Cult
75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 // ure=neutral, Pub
6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 // licKeyToken=b77a
35 63 35 36 31 39 33 34 65 30 38 39 64 00 00 00 // 5c561934e089d...
00 00 )
.field public int32 NormalMember
.field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer1' Doubles
.custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type,
int32) = ( 01 00 5A 53 79 73 74 65 6D 2E 44 6F 75 62 6C 65 // ..ZSystem.Double
2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 // , mscorlib, Vers
69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C // ion=4.0.0.0, Cul
74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 // ture=neutral, Pu
62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 // blicKeyToken=b77
61 35 63 35 36 31 39 33 34 65 30 38 39 C8 00 00 // a5c561934e089...
00 00 00 )
.field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Old>e__FixedBuffer2' Old
.custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type,
int32) = ( 01 00 58 53 79 73 74 65 6D 2E 42 79 74 65 2C 20 // ..XSystem.Byte,
6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F // mscorlib, Versio
6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 // n=4.0.0.0, Cultu
72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C // re=neutral, Publ
69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 // icKeyToken=b77a5
63 35 36 31 39 33 34 65 30 38 39 01 00 00 00 00 // c561934e089.....
00 )
.custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 11 61 6E 6F 74 68 65 72 20 61 74 74 72 69 // ...another attri
62 75 74 65 00 00 ) // bute..
} // end of class StructWithFixedSizeMembers
.method public hidebysig specialname instance int32*
get_NullPointer() cil managed
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: conv.u
IL_0002: ret
} // end of method UnsafeCode::get_NullPointer
.method public hidebysig instance int32
SizeOf() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0006: ret
} // end of method UnsafeCode::SizeOf
.method private hidebysig static void UseBool(bool b) cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method UnsafeCode::UseBool
.method public hidebysig instance void
PointerComparison(int32* a,
float64* b) cil managed
{
// Code size 64 (0x40)
.maxstack 2
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ceq
IL_0004: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0009: ldarg.1
IL_000a: ldarg.2
IL_000b: ceq
IL_000d: ldc.i4.0
IL_000e: ceq
IL_0010: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0015: ldarg.1
IL_0016: ldarg.2
IL_0017: clt.un
IL_0019: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_001e: ldarg.1
IL_001f: ldarg.2
IL_0020: cgt.un
IL_0022: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0027: ldarg.1
IL_0028: ldarg.2
IL_0029: cgt.un
IL_002b: ldc.i4.0
IL_002c: ceq
IL_002e: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0033: ldarg.1
IL_0034: ldarg.2
IL_0035: clt.un
IL_0037: ldc.i4.0
IL_0038: ceq
IL_003a: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_003f: ret
} // end of method UnsafeCode::PointerComparison
.method public hidebysig instance void
PointerComparisonWithNull(int32* a) cil managed
{
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: conv.u
IL_0003: ceq
IL_0005: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_000a: ldarg.1
IL_000b: ldc.i4.0
IL_000c: conv.u
IL_000d: ceq
IL_000f: ldc.i4.0
IL_0010: ceq
IL_0012: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0017: ret
} // end of method UnsafeCode::PointerComparisonWithNull
.method public hidebysig instance int32*
PointerCast(int64* p) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ret
} // end of method UnsafeCode::PointerCast
.method public hidebysig instance int64
ConvertDoubleToLong(float64 d) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarga.s d
IL_0002: conv.u
IL_0003: ldind.i8
IL_0004: ret
} // end of method UnsafeCode::ConvertDoubleToLong
.method public hidebysig instance float64
ConvertLongToDouble(int64 d) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarga.s d
IL_0002: conv.u
IL_0003: ldind.r8
IL_0004: ret
} // end of method UnsafeCode::ConvertLongToDouble
.method public hidebysig instance int32
ConvertFloatToInt(float32 d) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarga.s d
IL_0002: conv.u
IL_0003: ldind.i4
IL_0004: ret
} // end of method UnsafeCode::ConvertFloatToInt
.method public hidebysig instance float32
ConvertIntToFloat(int32 d) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarga.s d
IL_0002: conv.u
IL_0003: ldind.r4
IL_0004: ret
} // end of method UnsafeCode::ConvertIntToFloat
.method public hidebysig instance int32
PointerCasts() cil managed
{
// Code size 21 (0x15)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: conv.u
IL_0005: ldc.r4 0.5
IL_000a: stind.r4
IL_000b: ldloca.s V_0
IL_000d: conv.u
IL_000e: ldc.i4.3
IL_000f: conv.i
IL_0010: add
IL_0011: ldc.i4.3
IL_0012: stind.i1
IL_0013: ldloc.0
IL_0014: ret
} // end of method UnsafeCode::PointerCasts
.method public hidebysig instance void
PassRefParameterAsPointer(int32& p) cil managed
{
// Code size 14 (0xe)
.maxstack 2
.locals init (int32& pinned V_0)
IL_0000: ldarg.1
IL_0001: stloc.0
IL_0002: ldarg.0
IL_0003: ldloc.0
IL_0004: conv.i
IL_0005: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PassPointerAsRefParameter(int32*)
IL_000a: ldc.i4.0
IL_000b: conv.u
IL_000c: stloc.0
IL_000d: ret
} // end of method UnsafeCode::PassRefParameterAsPointer
.method public hidebysig instance void
PassPointerAsRefParameter(int32* p) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PassRefParameterAsPointer(int32&)
IL_0007: ret
} // end of method UnsafeCode::PassPointerAsRefParameter
.method public hidebysig instance void
AddressInMultiDimensionalArray(float64[0...,0...] matrix) cil managed
{
// Code size 31 (0x1f)
.maxstack 3
.locals init (float64& pinned V_0)
IL_0000: ldarg.1
IL_0001: ldc.i4.1
IL_0002: ldc.i4.2
IL_0003: call instance float64& float64[0...,0...]::Address(int32,
int32)
IL_0008: stloc.0
IL_0009: ldarg.0
IL_000a: ldloc.0
IL_000b: conv.i
IL_000c: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_0011: pop
IL_0012: ldarg.0
IL_0013: ldloc.0
IL_0014: conv.i
IL_0015: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_001a: pop
IL_001b: ldc.i4.0
IL_001c: conv.u
IL_001d: stloc.0
IL_001e: ret
} // end of method UnsafeCode::AddressInMultiDimensionalArray
.method public hidebysig instance void
FixedStringAccess(string text) cil managed
{
// Code size 36 (0x24)
.maxstack 2
.locals init (char* V_0,
char* V_1,
string pinned V_2)
IL_0000: ldarg.1
IL_0001: stloc.2
IL_0002: ldloc.2
IL_0003: conv.i
IL_0004: dup
IL_0005: brfalse.s IL_000d
IL_0007: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData()
IL_000c: add
IL_000d: stloc.0
IL_000e: ldloc.0
IL_000f: stloc.1
IL_0010: br.s IL_001b
IL_0012: ldloc.1
IL_0013: ldc.i4.s 65
IL_0015: stind.i2
IL_0016: ldloc.1
IL_0017: ldc.i4.2
IL_0018: conv.i
IL_0019: add
IL_001a: stloc.1
IL_001b: ldloc.1
IL_001c: ldind.u2
IL_001d: ldc.i4.s 97
IL_001f: beq.s IL_0012
IL_0021: ldnull
IL_0022: stloc.2
IL_0023: ret
} // end of method UnsafeCode::FixedStringAccess
.method public hidebysig instance void
PutDoubleIntoLongArray1(int64[] 'array',
int32 index,
float64 val) cil managed
{
// Code size 36 (0x24)
.maxstack 3
.locals init (int64& pinned V_0,
int64[] V_1)
IL_0000: ldarg.1
IL_0001: dup
IL_0002: stloc.1
IL_0003: brfalse.s IL_000a
IL_0005: ldloc.1
IL_0006: ldlen
IL_0007: conv.i4
IL_0008: brtrue.s IL_000f
IL_000a: ldc.i4.0
IL_000b: conv.u
IL_000c: stloc.0
IL_000d: br.s IL_0017
IL_000f: ldloc.1
IL_0010: ldc.i4.0
IL_0011: ldelema [mscorlib]System.Int64
IL_0016: stloc.0
IL_0017: ldloc.0
IL_0018: conv.i
IL_0019: ldarg.2
IL_001a: conv.i
IL_001b: ldc.i4.8
IL_001c: mul
IL_001d: add
IL_001e: ldarg.3
IL_001f: stind.r8
IL_0020: ldc.i4.0
IL_0021: conv.u
IL_0022: stloc.0
IL_0023: ret
} // end of method UnsafeCode::PutDoubleIntoLongArray1
.method public hidebysig instance void
PutDoubleIntoLongArray2(int64[] 'array',
int32 index,
float64 val) cil managed
{
// Code size 16 (0x10)
.maxstack 2
.locals init (int64& pinned V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int64
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: conv.i
IL_000a: ldarg.3
IL_000b: stind.r8
IL_000c: ldc.i4.0
IL_000d: conv.u
IL_000e: stloc.0
IL_000f: ret
} // end of method UnsafeCode::PutDoubleIntoLongArray2
.method public hidebysig instance string
PointerReferenceExpression(float64* d) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call instance string [mscorlib]System.Double::ToString()
IL_0006: ret
} // end of method UnsafeCode::PointerReferenceExpression
.method public hidebysig instance string
PointerReferenceExpression2(int64 addr) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: conv.u
IL_0002: call instance string [mscorlib]System.Int32::ToString()
IL_0007: ret
} // end of method UnsafeCode::PointerReferenceExpression2
.method public hidebysig instance int32*
PointerArithmetic(int32* p) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.8
IL_0002: conv.i
IL_0003: add
IL_0004: ret
} // end of method UnsafeCode::PointerArithmetic
.method public hidebysig instance int64*
PointerArithmetic2(int64* p) cil managed
{
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldc.i4.s 24
IL_0002: conv.i
IL_0003: ldarg.1
IL_0004: add
IL_0005: ret
} // end of method UnsafeCode::PointerArithmetic2
.method public hidebysig instance int64*
PointerArithmetic3(int64* p) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.3
IL_0002: conv.i
IL_0003: add
IL_0004: ret
} // end of method UnsafeCode::PointerArithmetic3
.method public hidebysig instance int64*
PointerArithmetic4(void* p) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.3
IL_0002: conv.i
IL_0003: add
IL_0004: ret
} // end of method UnsafeCode::PointerArithmetic4
.method public hidebysig instance int32
PointerArithmetic5(void* p,
uint8* q,
int32 i) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.2
IL_0001: ldarg.3
IL_0002: add
IL_0003: ldind.u1
IL_0004: ldarg.1
IL_0005: ldind.u1
IL_0006: add
IL_0007: ret
} // end of method UnsafeCode::PointerArithmetic5
.method public hidebysig instance int32
PointerArithmetic6(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
int32 i) cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: conv.i
IL_0003: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0009: mul
IL_000a: add
IL_000b: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_0010: ret
} // end of method UnsafeCode::PointerArithmetic6
.method public hidebysig instance int32*
PointerArithmeticLong1(int32* p,
int64 offset) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldc.i4.4
IL_0003: conv.i8
IL_0004: mul
IL_0005: conv.i
IL_0006: add
IL_0007: ret
} // end of method UnsafeCode::PointerArithmeticLong1
.method public hidebysig instance int32*
PointerArithmeticLong2(int32* p,
int64 offset) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.2
IL_0001: ldc.i4.4
IL_0002: conv.i8
IL_0003: mul
IL_0004: conv.i
IL_0005: ldarg.1
IL_0006: add
IL_0007: ret
} // end of method UnsafeCode::PointerArithmeticLong2
.method public hidebysig instance int32*
PointerArithmeticLong3(int32* p,
int64 offset) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldc.i4.4
IL_0003: conv.i8
IL_0004: mul
IL_0005: conv.i
IL_0006: sub
IL_0007: ret
} // end of method UnsafeCode::PointerArithmeticLong3
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct*
PointerArithmeticLong1s(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
int64 offset) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0008: conv.i8
IL_0009: mul
IL_000a: conv.i
IL_000b: add
IL_000c: ret
} // end of method UnsafeCode::PointerArithmeticLong1s
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct*
PointerArithmeticLong2s(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
int64 offset) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.2
IL_0001: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0007: conv.i8
IL_0008: mul
IL_0009: conv.i
IL_000a: ldarg.1
IL_000b: add
IL_000c: ret
} // end of method UnsafeCode::PointerArithmeticLong2s
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct*
PointerArithmeticLong3s(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
int64 offset) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0008: conv.i8
IL_0009: mul
IL_000a: conv.i
IL_000b: sub
IL_000c: ret
} // end of method UnsafeCode::PointerArithmeticLong3s
.method public hidebysig instance int32
PointerSubtraction(int64* p,
int64* q) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.8
IL_0004: div
IL_0005: conv.i8
IL_0006: conv.i4
IL_0007: ret
} // end of method UnsafeCode::PointerSubtraction
.method public hidebysig instance int64
PointerSubtractionLong(int64* p,
int64* q) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.8
IL_0004: div
IL_0005: conv.i8
IL_0006: ret
} // end of method UnsafeCode::PointerSubtractionLong
.method public hidebysig instance int32
PointerSubtraction2(int64* p,
int16* q) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.1
IL_0004: div
IL_0005: conv.i8
IL_0006: conv.i4
IL_0007: ret
} // end of method UnsafeCode::PointerSubtraction2
.method public hidebysig instance int32
PointerSubtraction3(void* p,
void* q) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.1
IL_0004: div
IL_0005: conv.i8
IL_0006: conv.i4
IL_0007: ret
} // end of method UnsafeCode::PointerSubtraction3
.method public hidebysig instance int64
PointerSubtraction4(int8* p,
int8* q) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.1
IL_0004: div
IL_0005: conv.i8
IL_0006: ret
} // end of method UnsafeCode::PointerSubtraction4
.method public hidebysig instance int64
PointerSubtraction5(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* q) cil managed
{
// Code size 12 (0xc)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0009: div
IL_000a: conv.i8
IL_000b: ret
} // end of method UnsafeCode::PointerSubtraction5
.method public hidebysig instance float64
FixedMemberAccess(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m,
int32 i) cil managed
{
// Code size 39 (0x27)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer0' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Integers
IL_0006: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer0'::FixedElementField
IL_000b: conv.u
IL_000c: ldarg.2
IL_000d: conv.i
IL_000e: ldc.i4.4
IL_000f: mul
IL_0010: add
IL_0011: ldind.i4
IL_0012: conv.r8
IL_0013: ldarg.1
IL_0014: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer1' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles
IL_0019: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer1'::FixedElementField
IL_001e: conv.u
IL_001f: ldarg.2
IL_0020: conv.i
IL_0021: ldc.i4.8
IL_0022: mul
IL_0023: add
IL_0024: ldind.r8
IL_0025: add
IL_0026: ret
} // end of method UnsafeCode::FixedMemberAccess
.method public hidebysig instance float64*
FixedMemberBasePointer(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer1' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles
IL_0006: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer1'::FixedElementField
IL_000b: conv.u
IL_000c: ret
} // end of method UnsafeCode::FixedMemberBasePointer
.method public hidebysig instance string
UsePointer(float64* ptr) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call instance string [mscorlib]System.Double::ToString()
IL_0006: ret
} // end of method UnsafeCode::UsePointer
.method public hidebysig instance string
StackAlloc(int32 count) cil managed
{
// Code size 52 (0x34)
.maxstack 3
.locals init (char* V_0,
char* V_1,
int32 V_2)
IL_0000: ldarg.1
IL_0001: conv.u
IL_0002: ldc.i4.2
IL_0003: mul.ovf.un
IL_0004: localloc
IL_0006: stloc.0
IL_0007: ldc.i4.s 100
IL_0009: conv.u
IL_000a: ldc.i4.2
IL_000b: mul.ovf.un
IL_000c: localloc
IL_000e: stloc.1
IL_000f: ldc.i4.0
IL_0010: stloc.2
IL_0011: br.s IL_0028
IL_0013: ldloc.0
IL_0014: ldloc.2
IL_0015: conv.i
IL_0016: ldc.i4.2
IL_0017: mul
IL_0018: add
IL_0019: ldloc.2
IL_001a: conv.u2
IL_001b: stind.i2
IL_001c: ldloc.1
IL_001d: ldloc.2
IL_001e: conv.i
IL_001f: ldc.i4.2
IL_0020: mul
IL_0021: add
IL_0022: ldc.i4.0
IL_0023: stind.i2
IL_0024: ldloc.2
IL_0025: ldc.i4.1
IL_0026: add
IL_0027: stloc.2
IL_0028: ldloc.2
IL_0029: ldarg.1
IL_002a: blt.s IL_0013
IL_002c: ldarg.0
IL_002d: ldloc.0
IL_002e: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_0033: ret
} // end of method UnsafeCode::StackAlloc
.method public hidebysig instance string
StackAllocStruct(int32 count) cil managed
{
// Code size 41 (0x29)
.maxstack 2
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0)
IL_0000: ldarg.1
IL_0001: ldc.i4.2
IL_0002: mul.ovf
IL_0003: conv.u
IL_0004: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_000a: mul.ovf.un
IL_000b: localloc
IL_000d: stloc.0
IL_000e: ldc.i4.s 10
IL_0010: conv.u
IL_0011: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0017: mul.ovf.un
IL_0018: localloc
IL_001a: pop
IL_001b: ldarg.0
IL_001c: ldloc.0
IL_001d: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
IL_0022: conv.u
IL_0023: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_0028: ret
} // end of method UnsafeCode::StackAllocStruct
.method family hidebysig virtual instance void
Finalize() cil managed
{
// Code size 22 (0x16)
.maxstack 2
.try
{
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call instance int32* ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::get_NullPointer()
IL_0007: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PassPointerAsRefParameter(int32*)
IL_000c: leave.s IL_0015
} // end .try
finally
{
IL_000e: ldarg.0
IL_000f: call instance void [mscorlib]System.Object::Finalize()
IL_0014: endfinally
} // end handler
IL_0015: ret
} // end of method UnsafeCode::Finalize
.method public 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 UnsafeCode::.ctor
.property instance int32* NullPointer()
{
.get instance int32* ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::get_NullPointer()
} // end of property UnsafeCode::NullPointer
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file ../../../TestCases/Pretty\UnsafeCode.opt.res

910
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il

@ -0,0 +1,910 @@ @@ -0,0 +1,910 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// 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 UnsafeCode
{
.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 UnsafeCode.dll
// MVID: {958D637E-F39D-447B-A248-B73AECEC847A}
.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: 0x007C0000
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode
extends [mscorlib]System.Object
{
.class sequential ansi sealed nested public beforefieldinit SimpleStruct
extends [mscorlib]System.ValueType
{
.field public int32 X
.field public float64 Y
} // end of class SimpleStruct
.class sequential ansi sealed nested public beforefieldinit StructWithFixedSizeMembers
extends [mscorlib]System.ValueType
{
.class sequential ansi sealed nested public beforefieldinit '<Integers>e__FixedBuffer'
extends [mscorlib]System.ValueType
{
.pack 0
.size 400
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 )
.field public int32 FixedElementField
} // end of class '<Integers>e__FixedBuffer'
.class sequential ansi sealed nested public beforefieldinit '<Doubles>e__FixedBuffer'
extends [mscorlib]System.ValueType
{
.pack 0
.size 1600
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 )
.field public float64 FixedElementField
} // end of class '<Doubles>e__FixedBuffer'
.class sequential ansi sealed nested public beforefieldinit '<Old>e__FixedBuffer'
extends [mscorlib]System.ValueType
{
.pack 0
.size 1
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 )
.field public uint8 FixedElementField
} // end of class '<Old>e__FixedBuffer'
.field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer' Integers
.custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type,
int32) = ( 01 00 59 53 79 73 74 65 6D 2E 49 6E 74 33 32 2C // ..YSystem.Int32,
20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 // mscorlib, Versi
6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 // on=4.0.0.0, Cult
75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 // ure=neutral, Pub
6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 // licKeyToken=b77a
35 63 35 36 31 39 33 34 65 30 38 39 64 00 00 00 // 5c561934e089d...
00 00 )
.field public int32 NormalMember
.field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer' Doubles
.custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type,
int32) = ( 01 00 5A 53 79 73 74 65 6D 2E 44 6F 75 62 6C 65 // ..ZSystem.Double
2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 // , mscorlib, Vers
69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C // ion=4.0.0.0, Cul
74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 // ture=neutral, Pu
62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 // blicKeyToken=b77
61 35 63 35 36 31 39 33 34 65 30 38 39 C8 00 00 // a5c561934e089...
00 00 00 )
.field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Old>e__FixedBuffer' Old
.custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type,
int32) = ( 01 00 58 53 79 73 74 65 6D 2E 42 79 74 65 2C 20 // ..XSystem.Byte,
6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F // mscorlib, Versio
6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 // n=4.0.0.0, Cultu
72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C // re=neutral, Publ
69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 // icKeyToken=b77a5
63 35 36 31 39 33 34 65 30 38 39 01 00 00 00 00 // c561934e089.....
00 )
.custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 11 61 6E 6F 74 68 65 72 20 61 74 74 72 69 // ...another attri
62 75 74 65 00 00 ) // bute..
} // end of class StructWithFixedSizeMembers
.method public hidebysig specialname instance int32*
get_NullPointer() cil managed
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: conv.u
IL_0002: ret
} // end of method UnsafeCode::get_NullPointer
.method public hidebysig instance int32
SizeOf() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0006: ret
} // end of method UnsafeCode::SizeOf
.method private hidebysig static void UseBool(bool b) cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method UnsafeCode::UseBool
.method public hidebysig instance void
PointerComparison(int32* a,
float64* b) cil managed
{
// Code size 64 (0x40)
.maxstack 2
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ceq
IL_0004: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0009: ldarg.1
IL_000a: ldarg.2
IL_000b: ceq
IL_000d: ldc.i4.0
IL_000e: ceq
IL_0010: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0015: ldarg.1
IL_0016: ldarg.2
IL_0017: clt.un
IL_0019: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_001e: ldarg.1
IL_001f: ldarg.2
IL_0020: cgt.un
IL_0022: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0027: ldarg.1
IL_0028: ldarg.2
IL_0029: cgt.un
IL_002b: ldc.i4.0
IL_002c: ceq
IL_002e: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0033: ldarg.1
IL_0034: ldarg.2
IL_0035: clt.un
IL_0037: ldc.i4.0
IL_0038: ceq
IL_003a: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_003f: ret
} // end of method UnsafeCode::PointerComparison
.method public hidebysig instance void
PointerComparisonWithNull(int32* a) cil managed
{
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: conv.u
IL_0003: ceq
IL_0005: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_000a: ldarg.1
IL_000b: ldc.i4.0
IL_000c: conv.u
IL_000d: ceq
IL_000f: ldc.i4.0
IL_0010: ceq
IL_0012: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0017: ret
} // end of method UnsafeCode::PointerComparisonWithNull
.method public hidebysig instance int32*
PointerCast(int64* p) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ret
} // end of method UnsafeCode::PointerCast
.method public hidebysig instance int64
ConvertDoubleToLong(float64 d) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarga.s d
IL_0002: conv.u
IL_0003: ldind.i8
IL_0004: ret
} // end of method UnsafeCode::ConvertDoubleToLong
.method public hidebysig instance float64
ConvertLongToDouble(int64 d) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarga.s d
IL_0002: conv.u
IL_0003: ldind.r8
IL_0004: ret
} // end of method UnsafeCode::ConvertLongToDouble
.method public hidebysig instance int32
ConvertFloatToInt(float32 d) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarga.s d
IL_0002: conv.u
IL_0003: ldind.i4
IL_0004: ret
} // end of method UnsafeCode::ConvertFloatToInt
.method public hidebysig instance float32
ConvertIntToFloat(int32 d) cil managed
{
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarga.s d
IL_0002: conv.u
IL_0003: ldind.r4
IL_0004: ret
} // end of method UnsafeCode::ConvertIntToFloat
.method public hidebysig instance int32
PointerCasts() cil managed
{
// Code size 20 (0x14)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: conv.u
IL_0005: ldc.r4 0.5
IL_000a: stind.r4
IL_000b: ldloca.s V_0
IL_000d: conv.u
IL_000e: ldc.i4.3
IL_000f: add
IL_0010: ldc.i4.3
IL_0011: stind.i1
IL_0012: ldloc.0
IL_0013: ret
} // end of method UnsafeCode::PointerCasts
.method public hidebysig instance void
PassRefParameterAsPointer(int32& p) cil managed
{
// Code size 14 (0xe)
.maxstack 2
.locals init (int32& pinned V_0)
IL_0000: ldarg.1
IL_0001: stloc.0
IL_0002: ldarg.0
IL_0003: ldloc.0
IL_0004: conv.i
IL_0005: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PassPointerAsRefParameter(int32*)
IL_000a: ldc.i4.0
IL_000b: conv.u
IL_000c: stloc.0
IL_000d: ret
} // end of method UnsafeCode::PassRefParameterAsPointer
.method public hidebysig instance void
PassPointerAsRefParameter(int32* p) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PassRefParameterAsPointer(int32&)
IL_0007: ret
} // end of method UnsafeCode::PassPointerAsRefParameter
.method public hidebysig instance void
AddressInMultiDimensionalArray(float64[0...,0...] matrix) cil managed
{
// Code size 31 (0x1f)
.maxstack 3
.locals init (float64& pinned V_0)
IL_0000: ldarg.1
IL_0001: ldc.i4.1
IL_0002: ldc.i4.2
IL_0003: call instance float64& float64[0...,0...]::Address(int32,
int32)
IL_0008: stloc.0
IL_0009: ldarg.0
IL_000a: ldloc.0
IL_000b: conv.i
IL_000c: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_0011: pop
IL_0012: ldarg.0
IL_0013: ldloc.0
IL_0014: conv.i
IL_0015: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_001a: pop
IL_001b: ldc.i4.0
IL_001c: conv.u
IL_001d: stloc.0
IL_001e: ret
} // end of method UnsafeCode::AddressInMultiDimensionalArray
.method public hidebysig instance void
FixedStringAccess(string text) cil managed
{
// Code size 37 (0x25)
.maxstack 2
.locals init (char* V_0,
string pinned V_1,
char* V_2)
IL_0000: ldarg.1
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: conv.i
IL_0004: stloc.0
IL_0005: ldloc.0
IL_0006: brfalse.s IL_0010
IL_0008: ldloc.0
IL_0009: call int32 [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData()
IL_000e: add
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: stloc.2
IL_0012: br.s IL_001c
IL_0014: ldloc.2
IL_0015: ldc.i4.s 65
IL_0017: stind.i2
IL_0018: ldloc.2
IL_0019: ldc.i4.2
IL_001a: add
IL_001b: stloc.2
IL_001c: ldloc.2
IL_001d: ldind.u2
IL_001e: ldc.i4.s 97
IL_0020: beq.s IL_0014
IL_0022: ldnull
IL_0023: stloc.1
IL_0024: ret
} // end of method UnsafeCode::FixedStringAccess
.method public hidebysig instance void
PutDoubleIntoLongArray1(int64[] 'array',
int32 index,
float64 val) cil managed
{
// Code size 36 (0x24)
.maxstack 3
.locals init (int64& pinned V_0,
int64[] V_1)
IL_0000: ldarg.1
IL_0001: dup
IL_0002: stloc.1
IL_0003: brfalse.s IL_000a
IL_0005: ldloc.1
IL_0006: ldlen
IL_0007: conv.i4
IL_0008: brtrue.s IL_000f
IL_000a: ldc.i4.0
IL_000b: conv.u
IL_000c: stloc.0
IL_000d: br.s IL_0017
IL_000f: ldloc.1
IL_0010: ldc.i4.0
IL_0011: ldelema [mscorlib]System.Int64
IL_0016: stloc.0
IL_0017: ldloc.0
IL_0018: conv.i
IL_0019: ldarg.2
IL_001a: conv.i
IL_001b: ldc.i4.8
IL_001c: mul
IL_001d: add
IL_001e: ldarg.3
IL_001f: stind.r8
IL_0020: ldc.i4.0
IL_0021: conv.u
IL_0022: stloc.0
IL_0023: ret
} // end of method UnsafeCode::PutDoubleIntoLongArray1
.method public hidebysig instance void
PutDoubleIntoLongArray2(int64[] 'array',
int32 index,
float64 val) cil managed
{
// Code size 16 (0x10)
.maxstack 2
.locals init (int64& pinned V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int64
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: conv.i
IL_000a: ldarg.3
IL_000b: stind.r8
IL_000c: ldc.i4.0
IL_000d: conv.u
IL_000e: stloc.0
IL_000f: ret
} // end of method UnsafeCode::PutDoubleIntoLongArray2
.method public hidebysig instance string
PointerReferenceExpression(float64* d) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call instance string [mscorlib]System.Double::ToString()
IL_0006: ret
} // end of method UnsafeCode::PointerReferenceExpression
.method public hidebysig instance string
PointerReferenceExpression2(int64 addr) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: conv.u
IL_0002: call instance string [mscorlib]System.Int32::ToString()
IL_0007: ret
} // end of method UnsafeCode::PointerReferenceExpression2
.method public hidebysig instance int32*
PointerArithmetic(int32* p) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.2
IL_0002: conv.i
IL_0003: ldc.i4.4
IL_0004: mul
IL_0005: add
IL_0006: ret
} // end of method UnsafeCode::PointerArithmetic
.method public hidebysig instance int64*
PointerArithmetic2(int64* p) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldc.i4.3
IL_0001: conv.i
IL_0002: ldc.i4.8
IL_0003: mul
IL_0004: ldarg.1
IL_0005: add
IL_0006: ret
} // end of method UnsafeCode::PointerArithmetic2
.method public hidebysig instance int64*
PointerArithmetic3(int64* p) cil managed
{
// Code size 4 (0x4)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.3
IL_0002: add
IL_0003: ret
} // end of method UnsafeCode::PointerArithmetic3
.method public hidebysig instance int64*
PointerArithmetic4(void* p) cil managed
{
// Code size 4 (0x4)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.3
IL_0002: add
IL_0003: ret
} // end of method UnsafeCode::PointerArithmetic4
.method public hidebysig instance int32
PointerArithmetic5(void* p,
uint8* q,
int32 i) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.2
IL_0001: ldarg.3
IL_0002: add
IL_0003: ldind.u1
IL_0004: ldarg.1
IL_0005: ldind.u1
IL_0006: add
IL_0007: ret
} // end of method UnsafeCode::PointerArithmetic5
.method public hidebysig instance int32
PointerArithmetic6(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
int32 i) cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: conv.i
IL_0003: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0009: mul
IL_000a: add
IL_000b: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_0010: ret
} // end of method UnsafeCode::PointerArithmetic6
.method public hidebysig instance int32*
PointerArithmeticLong1(int32* p,
int64 offset) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldc.i4.4
IL_0003: conv.i8
IL_0004: mul
IL_0005: conv.i
IL_0006: add
IL_0007: ret
} // end of method UnsafeCode::PointerArithmeticLong1
.method public hidebysig instance int32*
PointerArithmeticLong2(int32* p,
int64 offset) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.2
IL_0001: ldc.i4.4
IL_0002: conv.i8
IL_0003: mul
IL_0004: conv.i
IL_0005: ldarg.1
IL_0006: add
IL_0007: ret
} // end of method UnsafeCode::PointerArithmeticLong2
.method public hidebysig instance int32*
PointerArithmeticLong3(int32* p,
int64 offset) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldc.i4.4
IL_0003: conv.i8
IL_0004: mul
IL_0005: conv.i
IL_0006: sub
IL_0007: ret
} // end of method UnsafeCode::PointerArithmeticLong3
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct*
PointerArithmeticLong1s(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
int64 offset) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0008: conv.i8
IL_0009: mul
IL_000a: conv.i
IL_000b: add
IL_000c: ret
} // end of method UnsafeCode::PointerArithmeticLong1s
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct*
PointerArithmeticLong2s(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
int64 offset) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.2
IL_0001: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0007: conv.i8
IL_0008: mul
IL_0009: conv.i
IL_000a: ldarg.1
IL_000b: add
IL_000c: ret
} // end of method UnsafeCode::PointerArithmeticLong2s
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct*
PointerArithmeticLong3s(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
int64 offset) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0008: conv.i8
IL_0009: mul
IL_000a: conv.i
IL_000b: sub
IL_000c: ret
} // end of method UnsafeCode::PointerArithmeticLong3s
.method public hidebysig instance int32
PointerSubtraction(int64* p,
int64* q) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.8
IL_0004: div
IL_0005: conv.i8
IL_0006: conv.i4
IL_0007: ret
} // end of method UnsafeCode::PointerSubtraction
.method public hidebysig instance int64
PointerSubtractionLong(int64* p,
int64* q) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.8
IL_0004: div
IL_0005: conv.i8
IL_0006: ret
} // end of method UnsafeCode::PointerSubtractionLong
.method public hidebysig instance int32
PointerSubtraction2(int64* p,
int16* q) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.1
IL_0004: div
IL_0005: conv.i8
IL_0006: conv.i4
IL_0007: ret
} // end of method UnsafeCode::PointerSubtraction2
.method public hidebysig instance int32
PointerSubtraction3(void* p,
void* q) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.1
IL_0004: div
IL_0005: conv.i8
IL_0006: conv.i4
IL_0007: ret
} // end of method UnsafeCode::PointerSubtraction3
.method public hidebysig instance int64
PointerSubtraction4(int8* p,
int8* q) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: ldc.i4.1
IL_0004: div
IL_0005: conv.i8
IL_0006: ret
} // end of method UnsafeCode::PointerSubtraction4
.method public hidebysig instance int64
PointerSubtraction5(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* p,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* q) cil managed
{
// Code size 12 (0xc)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: sub
IL_0003: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0009: div
IL_000a: conv.i8
IL_000b: ret
} // end of method UnsafeCode::PointerSubtraction5
.method public hidebysig instance float64
FixedMemberAccess(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m,
int32 i) cil managed
{
// Code size 39 (0x27)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Integers
IL_0006: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer'::FixedElementField
IL_000b: conv.u
IL_000c: ldarg.2
IL_000d: conv.i
IL_000e: ldc.i4.4
IL_000f: mul
IL_0010: add
IL_0011: ldind.i4
IL_0012: conv.r8
IL_0013: ldarg.1
IL_0014: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles
IL_0019: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer'::FixedElementField
IL_001e: conv.u
IL_001f: ldarg.2
IL_0020: conv.i
IL_0021: ldc.i4.8
IL_0022: mul
IL_0023: add
IL_0024: ldind.r8
IL_0025: add
IL_0026: ret
} // end of method UnsafeCode::FixedMemberAccess
.method public hidebysig instance float64*
FixedMemberBasePointer(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles
IL_0006: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Doubles>e__FixedBuffer'::FixedElementField
IL_000b: conv.u
IL_000c: ret
} // end of method UnsafeCode::FixedMemberBasePointer
.method public hidebysig instance string
UsePointer(float64* ptr) cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call instance string [mscorlib]System.Double::ToString()
IL_0006: ret
} // end of method UnsafeCode::UsePointer
.method public hidebysig instance string
StackAlloc(int32 count) cil managed
{
// Code size 52 (0x34)
.maxstack 3
.locals init (char* V_0,
char* V_1,
int32 V_2)
IL_0000: ldarg.1
IL_0001: conv.u
IL_0002: ldc.i4.2
IL_0003: mul.ovf.un
IL_0004: localloc
IL_0006: stloc.0
IL_0007: ldc.i4.s 100
IL_0009: conv.u
IL_000a: ldc.i4.2
IL_000b: mul.ovf.un
IL_000c: localloc
IL_000e: stloc.1
IL_000f: ldc.i4.0
IL_0010: stloc.2
IL_0011: br.s IL_0028
IL_0013: ldloc.0
IL_0014: ldloc.2
IL_0015: conv.i
IL_0016: ldc.i4.2
IL_0017: mul
IL_0018: add
IL_0019: ldloc.2
IL_001a: conv.u2
IL_001b: stind.i2
IL_001c: ldloc.1
IL_001d: ldloc.2
IL_001e: conv.i
IL_001f: ldc.i4.2
IL_0020: mul
IL_0021: add
IL_0022: ldc.i4.0
IL_0023: stind.i2
IL_0024: ldloc.2
IL_0025: ldc.i4.1
IL_0026: add
IL_0027: stloc.2
IL_0028: ldloc.2
IL_0029: ldarg.1
IL_002a: blt.s IL_0013
IL_002c: ldarg.0
IL_002d: ldloc.0
IL_002e: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_0033: ret
} // end of method UnsafeCode::StackAlloc
.method public hidebysig instance string
StackAllocStruct(int32 count) cil managed
{
// Code size 41 (0x29)
.maxstack 2
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0)
IL_0000: ldarg.1
IL_0001: ldc.i4.2
IL_0002: mul.ovf
IL_0003: conv.u
IL_0004: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_000a: mul.ovf.un
IL_000b: localloc
IL_000d: stloc.0
IL_000e: ldc.i4.s 10
IL_0010: conv.u
IL_0011: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0017: mul.ovf.un
IL_0018: localloc
IL_001a: pop
IL_001b: ldarg.0
IL_001c: ldloc.0
IL_001d: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
IL_0022: conv.u
IL_0023: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_0028: ret
} // end of method UnsafeCode::StackAllocStruct
.method family hidebysig virtual instance void
Finalize() cil managed
{
.override [mscorlib]System.Object::Finalize
// Code size 22 (0x16)
.maxstack 2
.try
{
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call instance int32* ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::get_NullPointer()
IL_0007: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PassPointerAsRefParameter(int32*)
IL_000c: leave.s IL_0015
} // end .try
finally
{
IL_000e: ldarg.0
IL_000f: call instance void [mscorlib]System.Object::Finalize()
IL_0014: endfinally
} // end handler
IL_0015: ret
} // end of method UnsafeCode::Finalize
.method public 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 UnsafeCode::.ctor
.property instance int32* NullPointer()
{
.get instance int32* ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::get_NullPointer()
} // end of property UnsafeCode::NullPointer
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

1155
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il

File diff suppressed because it is too large Load Diff

192
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -30,7 +30,9 @@ using ICSharpCode.Decompiler.IL; @@ -30,7 +30,9 @@ using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.ControlFlow;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
using System.IO;
namespace ICSharpCode.Decompiler.CSharp
{
@ -168,6 +170,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -168,6 +170,11 @@ namespace ICSharpCode.Decompiler.CSharp
get { return astTransforms; }
}
public CSharpDecompiler(string fileName, DecompilerSettings settings)
: this(UniversalAssemblyResolver.LoadMainModule(fileName, settings.ThrowOnAssemblyResolveErrors, settings.LoadInMemory), settings)
{
}
public CSharpDecompiler(ModuleDefinition module, DecompilerSettings settings)
: this(new DecompilerTypeSystem(module), settings)
{
@ -180,7 +187,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -180,7 +187,7 @@ namespace ICSharpCode.Decompiler.CSharp
this.typeSystem = typeSystem;
this.settings = settings;
}
#region MemberIsHidden
public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings)
{
@ -201,6 +208,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -201,6 +208,8 @@ namespace ICSharpCode.Decompiler.CSharp
return true;
if (settings.AsyncAwait && AsyncAwaitDecompiler.IsCompilerGeneratedStateMachine(type))
return true;
if (settings.FixedBuffers && type.Name.StartsWith("<", StringComparison.Ordinal) && type.Name.Contains("__FixedBuffer"))
return true;
} else if (type.IsCompilerGenerated()) {
if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
return true;
@ -208,7 +217,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -208,7 +217,7 @@ namespace ICSharpCode.Decompiler.CSharp
return true;
}
}
FieldDefinition field = member as FieldDefinition;
if (field != null) {
if (field.IsCompilerGenerated()) {
@ -230,10 +239,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -230,10 +239,10 @@ namespace ICSharpCode.Decompiler.CSharp
return true;
}
}
return false;
}
static bool IsSwitchOnStringCache(FieldDefinition field)
{
return field.Name.StartsWith("<>f__switch", StringComparison.Ordinal);
@ -258,7 +267,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -258,7 +267,7 @@ namespace ICSharpCode.Decompiler.CSharp
return type.BaseType.FullName == "System.Object" && !type.HasInterfaces;
}
#endregion
TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext decompilationContext)
{
var typeSystemAstBuilder = new TypeSystemAstBuilder();
@ -267,7 +276,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -267,7 +276,7 @@ namespace ICSharpCode.Decompiler.CSharp
typeSystemAstBuilder.AddResolveResultAnnotations = true;
return typeSystemAstBuilder;
}
void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext)
{
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
@ -278,7 +287,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -278,7 +287,14 @@ namespace ICSharpCode.Decompiler.CSharp
}
rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
}
string SyntaxTreeToString(SyntaxTree syntaxTree)
{
StringWriter w = new StringWriter();
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, settings.CSharpFormattingOptions));
return w.ToString();
}
/// <summary>
/// Decompile assembly and module attributes.
/// </summary>
@ -292,6 +308,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -292,6 +308,14 @@ namespace ICSharpCode.Decompiler.CSharp
return syntaxTree;
}
/// <summary>
/// Decompile assembly and module attributes.
/// </summary>
public string DecompileModuleAndAssemblyAttributesToString()
{
return SyntaxTreeToString(DecompileModuleAndAssemblyAttributes());
}
void DoDecompileModuleAndAssemblyAttributes(ITypeResolveContext decompilationContext, SyntaxTree syntaxTree)
{
foreach (var a in typeSystem.Compilation.MainAssembly.AssemblyAttributes) {
@ -325,7 +349,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -325,7 +349,7 @@ namespace ICSharpCode.Decompiler.CSharp
groupNode.AddChild(typeDecl, SyntaxTree.MemberRole);
}
}
/// <summary>
/// Decompiles the whole module into a single syntax tree.
/// </summary>
@ -339,7 +363,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -339,7 +363,15 @@ namespace ICSharpCode.Decompiler.CSharp
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree;
}
/// <summary>
/// Decompiles the whole module into a single string.
/// </summary>
public string DecompileWholeModuleAsString()
{
return SyntaxTreeToString(DecompileWholeModuleAsSingleFile());
}
/// <summary>
/// Decompile the given types.
/// </summary>
@ -358,6 +390,47 @@ namespace ICSharpCode.Decompiler.CSharp @@ -358,6 +390,47 @@ namespace ICSharpCode.Decompiler.CSharp
return syntaxTree;
}
/// <summary>
/// Decompile the given types.
/// </summary>
/// <remarks>
/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definitions.
/// </remarks>
public string DecompileTypesAsString(IEnumerable<TypeDefinition> types)
{
return SyntaxTreeToString(DecompileTypes(types));
}
/// <summary>
/// Decompile the given type.
/// </summary>
/// <remarks>
/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definition.
/// </remarks>
public SyntaxTree DecompileType(FullTypeName fullTypeName)
{
var type = typeSystem.Compilation.FindType(fullTypeName).GetDefinition();
if (type == null)
throw new InvalidOperationException($"Could not find type definition {fullTypeName} in type system.");
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
DoDecompileTypes(new[] { typeSystem.GetCecil(type) }, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree;
}
/// <summary>
/// Decompile the given type.
/// </summary>
/// <remarks>
/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definition.
/// </remarks>
public string DecompileTypeAsString(FullTypeName fullTypeName)
{
return SyntaxTreeToString(DecompileType(fullTypeName));
}
/// <summary>
/// Decompile the specified types and/or members.
/// </summary>
@ -422,6 +495,22 @@ namespace ICSharpCode.Decompiler.CSharp @@ -422,6 +495,22 @@ namespace ICSharpCode.Decompiler.CSharp
return syntaxTree;
}
/// <summary>
/// Decompile the specified types and/or members.
/// </summary>
public string DecompileAsString(params IMemberDefinition[] definitions)
{
return SyntaxTreeToString(Decompile(definitions));
}
/// <summary>
/// Decompile the specified types and/or members.
/// </summary>
public string DecompileAsString(IList<IMemberDefinition> definitions)
{
return SyntaxTreeToString(Decompile(definitions));
}
IEnumerable<EntityDeclaration> AddInterfaceImplHelpers(EntityDeclaration memberDecl, MethodDefinition methodDef,
TypeSystemAstBuilder astBuilder)
{
@ -441,7 +530,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -441,7 +530,7 @@ namespace ICSharpCode.Decompiler.CSharp
methodDecl.Parameters.AddRange(memberDecl.GetChildrenByRole(Roles.Parameter).Select(n => n.Clone()));
methodDecl.Constraints.AddRange(memberDecl.GetChildrenByRole(Roles.Constraint)
.Select(n => (Constraint)n.Clone()));
methodDecl.Body = new BlockStatement();
methodDecl.Body.AddChild(new Comment(
"ILSpy generated this explicit interface implementation from .override directive in " + memberDecl.Name),
@ -458,7 +547,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -458,7 +547,7 @@ namespace ICSharpCode.Decompiler.CSharp
yield return methodDecl;
}
}
Expression ForwardParameter(ParameterDeclaration p)
{
switch (p.ParameterModifier) {
@ -470,7 +559,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -470,7 +559,7 @@ namespace ICSharpCode.Decompiler.CSharp
return new IdentifierExpression(p.Name);
}
}
/// <summary>
/// Sets new modifier if the member hides some other member from a base type.
/// </summary>
@ -480,7 +569,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -480,7 +569,7 @@ namespace ICSharpCode.Decompiler.CSharp
bool addNewModifier = false;
var entity = (IEntity)member.GetSymbol();
var lookup = new MemberLookup(entity.DeclaringTypeDefinition, entity.ParentAssembly);
var baseTypes = entity.DeclaringType.GetNonInterfaceBaseTypes().Where(t => entity.DeclaringType != t);
if (entity is ITypeDefinition) {
addNewModifier = baseTypes.SelectMany(b => b.GetNestedTypes(t => t.Name == entity.Name && lookup.IsAccessible(t, true))).Any();
@ -518,7 +607,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -518,7 +607,7 @@ namespace ICSharpCode.Decompiler.CSharp
i++;
}
}
EntityDeclaration DoDecompile(ITypeDefinition typeDef, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef);
@ -617,7 +706,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -617,7 +706,7 @@ namespace ICSharpCode.Decompiler.CSharp
};
return method;
}
EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentMember == method);
@ -656,7 +745,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -656,7 +745,7 @@ namespace ICSharpCode.Decompiler.CSharp
i++;
}
}
var context = new ILTransformContext(function, specializingTypeSystem, settings) {
CancellationToken = CancellationToken
};
@ -736,9 +825,37 @@ namespace ICSharpCode.Decompiler.CSharp @@ -736,9 +825,37 @@ namespace ICSharpCode.Decompiler.CSharp
}
var fieldDecl = typeSystemAstBuilder.ConvertEntity(field);
SetNewModifier(fieldDecl);
if (settings.FixedBuffers && IsFixedField(field, out var elementType, out var elementCount)) {
var fixedFieldDecl = new FixedFieldDeclaration();
fieldDecl.Attributes.MoveTo(fixedFieldDecl.Attributes);
fixedFieldDecl.Modifiers = fieldDecl.Modifiers;
fixedFieldDecl.ReturnType = typeSystemAstBuilder.ConvertType(elementType);
fixedFieldDecl.Variables.Add(new FixedVariableInitializer(field.Name, new PrimitiveExpression(elementCount)));
fixedFieldDecl.Variables.Single().CopyAnnotationsFrom(((FieldDeclaration)fieldDecl).Variables.Single());
fixedFieldDecl.CopyAnnotationsFrom(fieldDecl);
RemoveAttribute(fixedFieldDecl, fixedBufferAttributeTypeName);
return fixedFieldDecl;
}
return fieldDecl;
}
static readonly FullTypeName fixedBufferAttributeTypeName = new TopLevelTypeName("System.Runtime.CompilerServices", "FixedBufferAttribute");
internal static bool IsFixedField(IField field, out IType type, out int elementCount)
{
type = null;
elementCount = 0;
IAttribute attr = field.GetAttribute(fixedBufferAttributeTypeName, inherit: false);
if (attr != null && attr.PositionalArguments.Count == 2) {
if (attr.PositionalArguments[0] is TypeOfResolveResult trr && attr.PositionalArguments[1].ConstantValue is int length) {
type = trr.ReferencedType;
elementCount = length;
return true;
}
}
return false;
}
EntityDeclaration DoDecompile(PropertyDefinition propertyDefinition, IProperty property, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentMember == property);
@ -768,7 +885,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -768,7 +885,7 @@ namespace ICSharpCode.Decompiler.CSharp
SetNewModifier(propertyDecl);
return propertyDecl;
}
EntityDeclaration DoDecompile(EventDefinition eventDefinition, IEvent ev, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentMember == ev);
@ -848,13 +965,31 @@ namespace ICSharpCode.Decompiler.CSharp @@ -848,13 +965,31 @@ namespace ICSharpCode.Decompiler.CSharp
} else if (type is GenericParameter) {
return new SimpleType(type.Name);
} else if (type.IsNested) {
AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name);
MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart };
memberType.AddAnnotation(type);
AstType memberType;
if ((options & (ConvertTypeOptions.IncludeOuterTypeName | ConvertTypeOptions.IncludeNamespace)) != 0) {
AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
memberType = new MemberType { Target = typeRef, MemberName = namepart };
if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
AddTypeParameterDefininitionsTo(type, memberType);
}
} else {
memberType = new SimpleType(namepart);
if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
if (type.HasGenericParameters) {
List<AstType> typeArguments = new List<AstType>();
foreach (GenericParameter gp in type.GenericParameters) {
typeArguments.Add(new SimpleType(gp.Name));
}
ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out int typeParameterCount);
if (typeParameterCount > typeArguments.Count)
typeParameterCount = typeArguments.Count;
((SimpleType)memberType).TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount));
typeArguments.RemoveRange(typeArguments.Count - typeParameterCount, typeParameterCount);
}
}
}
memberType.AddAnnotation(type);
return memberType;
} else {
string ns = type.Namespace ?? string.Empty;
@ -943,14 +1078,22 @@ namespace ICSharpCode.Decompiler.CSharp @@ -943,14 +1078,22 @@ namespace ICSharpCode.Decompiler.CSharp
{
SimpleType st = baseType as SimpleType;
if (st != null) {
TypeReference type = st.Annotation<TypeReference>();
if (type != null) {
ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out int typeParameterCount);
if (typeParameterCount > typeArguments.Count)
typeParameterCount = typeArguments.Count;
st.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount));
} else {
st.TypeArguments.AddRange(typeArguments);
}
}
MemberType mt = baseType as MemberType;
if (mt != null) {
TypeReference type = mt.Annotation<TypeReference>();
if (type != null) {
int typeParameterCount;
ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out int typeParameterCount);
if (typeParameterCount > typeArguments.Count)
typeParameterCount = typeArguments.Count;
mt.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount));
@ -994,7 +1137,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -994,7 +1137,7 @@ namespace ICSharpCode.Decompiler.CSharp
SequencePointBuilder spb = new SequencePointBuilder();
syntaxTree.AcceptVisitor(spb);
return spb.GetSequencePoints();
}
}
#endregion
}
@ -1004,6 +1147,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1004,6 +1147,7 @@ namespace ICSharpCode.Decompiler.CSharp
None = 0,
IncludeNamespace = 1,
IncludeTypeParameterDefinitions = 2,
DoNotUsePrimitiveTypeNames = 4
DoNotUsePrimitiveTypeNames = 4,
IncludeOuterTypeName = 8,
}
}

428
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -229,55 +229,38 @@ namespace ICSharpCode.Decompiler.CSharp @@ -229,55 +229,38 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLocAlloc(LocAlloc inst, TranslationContext context)
{
IType elementType;
TranslatedExpression countExpression = TranslatePointerArgument(inst.Argument, context, out elementType);
TranslatedExpression countExpression;
PointerType pointerType;
if (inst.Argument.MatchBinaryNumericInstruction(BinaryNumericOperator.Mul, out var left, out var right)
&& right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend).MatchSizeOf(out var elementType))
{
// Determine the element type from the sizeof
countExpression = Translate(left.UnwrapConv(ConversionKind.ZeroExtend));
pointerType = new PointerType(elementType);
} else {
// Determine the element type from the expected pointer type in this context
pointerType = context.TypeHint as PointerType;
if (pointerType != null && GetPointerArithmeticOffset(
inst.Argument, Translate(inst.Argument),
pointerType, checkForOverflow: true,
unwrapZeroExtension: true
) is TranslatedExpression offset)
{
countExpression = offset;
elementType = pointerType.ElementType;
} else {
elementType = compilation.FindType(KnownTypeCode.Byte);
pointerType = new PointerType(elementType);
countExpression = Translate(inst.Argument);
}
}
countExpression = countExpression.ConvertTo(compilation.FindType(KnownTypeCode.Int32), this);
if (elementType == null)
elementType = compilation.FindType(KnownTypeCode.Byte);
return new StackAllocExpression {
Type = ConvertType(elementType),
CountExpression = countExpression
}.WithILInstruction(inst).WithRR(new ResolveResult(new PointerType(elementType)));
}
/// <summary>
/// Translate the argument of an operation that deals with pointers:
/// * undoes the implicit multiplication with `sizeof(elementType)` and returns `elementType`
/// * on failure, translates the whole expression and returns `elementType = null`.
/// </summary>
TranslatedExpression TranslatePointerArgument(ILInstruction countExpr, TranslationContext context, out IType elementType)
{
ILInstruction left;
ILInstruction right;
if (countExpr.MatchBinaryNumericInstruction(BinaryNumericOperator.Mul, out left, out right)
&& right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend).MatchSizeOf(out elementType))
{
return Translate(left);
}
var pointerTypeHint = context.TypeHint as PointerType;
if (pointerTypeHint == null) {
elementType = null;
return Translate(countExpr);
}
ResolveResult sizeofRR = resolver.ResolveSizeOf(pointerTypeHint.ElementType);
if (!(sizeofRR.IsCompileTimeConstant && sizeofRR.ConstantValue is int)) {
elementType = null;
return Translate(countExpr);
}
int typeSize = (int)sizeofRR.ConstantValue;
if (countExpr.MatchBinaryNumericInstruction(BinaryNumericOperator.Mul, out left, out right)
&& right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend).MatchLdcI4(typeSize))
{
elementType = pointerTypeHint.ElementType;
return Translate(left);
}
elementType = null;
return Translate(countExpr);
}
protected internal override TranslatedExpression VisitLdcI4(LdcI4 inst, TranslationContext context)
{
return new PrimitiveExpression(inst.Value)
@ -494,6 +477,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -494,6 +477,20 @@ namespace ICSharpCode.Decompiler.CSharp
return right;
}
}
// Handle comparisons between unsafe pointers and null:
if (left.Type.Kind == TypeKind.Pointer && inst.Right.MatchLdcI(0)) {
negateOutput = false;
right = new NullReferenceExpression().WithRR(new ConstantResolveResult(SpecialType.NullType, null))
.WithILInstruction(inst.Right);
return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right)
.WithILInstruction(inst);
} else if (right.Type.Kind == TypeKind.Pointer && inst.Left.MatchLdcI(0)) {
negateOutput = false;
left = new NullReferenceExpression().WithRR(new ConstantResolveResult(SpecialType.NullType, null))
.WithILInstruction(inst.Left);
return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right)
.WithILInstruction(inst);
}
// Special case comparisons with enum and char literals
left = AdjustConstantExpressionToType(left, right.Type);
@ -504,12 +501,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -504,12 +501,8 @@ namespace ICSharpCode.Decompiler.CSharp
{
// When comparing a delegate with null, the C# compiler generates a reference comparison.
negateOutput = false;
return new BinaryOperatorExpression(left.Expression, inst.Kind.ToBinaryOperatorType(), right.Expression)
.WithILInstruction(inst)
.WithRR(new OperatorResolveResult(
compilation.FindType(KnownTypeCode.Boolean),
inst.Kind == ComparisonKind.Equality ? ExpressionType.Equal : ExpressionType.NotEqual,
left.ResolveResult, right.ResolveResult));
return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right)
.WithILInstruction(inst);
}
var rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), left.ResolveResult, right.ResolveResult)
@ -521,7 +514,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -521,7 +514,15 @@ namespace ICSharpCode.Decompiler.CSharp
if (inst.InputType == StackType.O) {
targetType = compilation.FindType(KnownTypeCode.Object);
} else {
targetType = TypeUtils.GetLargerType(NullableType.GetUnderlyingType(left.Type), NullableType.GetUnderlyingType(right.Type));
var leftUType = NullableType.GetUnderlyingType(left.Type);
var rightUType = NullableType.GetUnderlyingType(right.Type);
if (leftUType.GetStackType() == inst.InputType && !leftUType.IsSmallIntegerType()) {
targetType = leftUType;
} else if (rightUType.GetStackType() == inst.InputType && !rightUType.IsSmallIntegerType()) {
targetType = rightUType;
} else {
targetType = compilation.FindType(inst.InputType.ToKnownTypeCode(leftUType.GetSign()));
}
}
if (inst.IsLifted) {
targetType = NullableType.Create(compilation, targetType);
@ -539,9 +540,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -539,9 +540,10 @@ namespace ICSharpCode.Decompiler.CSharp
// If converting one input wasn't sufficient, convert both:
left = left.ConvertTo(targetType, this);
right = right.ConvertTo(targetType, this);
rr = new OperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean),
BinaryOperatorExpression.GetLinqNodeType(BinaryOperatorType.Equality, false),
left.ResolveResult, right.ResolveResult);
rr = new OperatorResolveResult(
compilation.FindType(KnownTypeCode.Boolean),
BinaryOperatorExpression.GetLinqNodeType(inst.Kind.ToBinaryOperatorType(), false),
left.ResolveResult, right.ResolveResult);
}
}
negateOutput = false;
@ -549,6 +551,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -549,6 +551,17 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(inst)
.WithRR(rr);
}
ExpressionWithResolveResult CreateBuiltinBinaryOperator(
TranslatedExpression left, BinaryOperatorType type, TranslatedExpression right,
bool checkForOverflow = false)
{
return new BinaryOperatorExpression(left.Expression, type, right.Expression)
.WithRR(new OperatorResolveResult(
compilation.FindType(KnownTypeCode.Boolean),
BinaryOperatorExpression.GetLinqNodeType(type, checkForOverflow),
left.ResolveResult, right.ResolveResult));
}
/// <summary>
/// Handle Comp instruction, operators other than equality/inequality.
@ -558,6 +571,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -558,6 +571,12 @@ namespace ICSharpCode.Decompiler.CSharp
var op = inst.Kind.ToBinaryOperatorType();
var left = Translate(inst.Left);
var right = Translate(inst.Right);
if (left.Type.Kind == TypeKind.Pointer && right.Type.Kind == TypeKind.Pointer) {
return CreateBuiltinBinaryOperator(left, op, right)
.WithILInstruction(inst);
}
left = PrepareArithmeticArgument(left, inst.InputType, inst.Sign, inst.IsLifted);
right = PrepareArithmeticArgument(right, inst.InputType, inst.Sign, inst.IsLifted);
@ -652,7 +671,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -652,7 +671,8 @@ namespace ICSharpCode.Decompiler.CSharp
case BinaryNumericOperator.Mul:
return HandleBinaryNumeric(inst, BinaryOperatorType.Multiply);
case BinaryNumericOperator.Div:
return HandleBinaryNumeric(inst, BinaryOperatorType.Divide);
return HandlePointerSubtraction(inst)
?? HandleBinaryNumeric(inst, BinaryOperatorType.Divide);
case BinaryNumericOperator.Rem:
return HandleBinaryNumeric(inst, BinaryOperatorType.Modulus);
case BinaryNumericOperator.BitAnd:
@ -669,15 +689,202 @@ namespace ICSharpCode.Decompiler.CSharp @@ -669,15 +689,202 @@ namespace ICSharpCode.Decompiler.CSharp
throw new ArgumentOutOfRangeException();
}
}
/// <summary>
/// Translates pointer arithmetic:
/// ptr + int
/// int + ptr
/// ptr - int
/// Returns null if 'inst' is not performing pointer arithmetic.
/// This function not handle 'ptr - ptr'!
/// </summary>
TranslatedExpression? HandlePointerArithmetic(BinaryNumericInstruction inst, TranslatedExpression left, TranslatedExpression right)
{
if (!(inst.Operator == BinaryNumericOperator.Add || inst.Operator == BinaryNumericOperator.Sub))
return null;
if (inst.CheckForOverflow || inst.IsLifted)
return null;
if (!(inst.LeftInputType == StackType.I && inst.RightInputType == StackType.I))
return null;
PointerType pointerType;
ILInstruction byteOffsetInst;
TranslatedExpression byteOffsetExpr;
if (left.Type.Kind == TypeKind.Pointer) {
byteOffsetInst = inst.Right;
byteOffsetExpr = right;
pointerType = (PointerType)left.Type;
} else if (right.Type.Kind == TypeKind.Pointer) {
if (inst.Operator != BinaryNumericOperator.Add)
return null;
byteOffsetInst = inst.Left;
byteOffsetExpr = left;
pointerType = (PointerType)right.Type;
} else {
return null;
}
TranslatedExpression offsetExpr = GetPointerArithmeticOffset(byteOffsetInst, byteOffsetExpr, pointerType, inst.CheckForOverflow)
?? FallBackToBytePointer();
if (!offsetExpr.Type.IsCSharpPrimitiveIntegerType()) {
// pointer arithmetic accepts all primitive integer types, but no enums etc.
StackType targetType = offsetExpr.Type.GetStackType() == StackType.I4 ? StackType.I4 : StackType.I8;
offsetExpr = offsetExpr.ConvertTo(
compilation.FindType(targetType.ToKnownTypeCode(offsetExpr.Type.GetSign())),
this);
}
if (left.Type.Kind == TypeKind.Pointer) {
Debug.Assert(inst.Operator == BinaryNumericOperator.Add || inst.Operator == BinaryNumericOperator.Sub);
left = left.ConvertTo(pointerType, this);
right = offsetExpr;
} else {
Debug.Assert(inst.Operator == BinaryNumericOperator.Add);
Debug.Assert(right.Type.Kind == TypeKind.Pointer);
left = offsetExpr;
right = right.ConvertTo(pointerType, this);
}
var operatorType = inst.Operator == BinaryNumericOperator.Add ? BinaryOperatorType.Add : BinaryOperatorType.Subtract;
return new BinaryOperatorExpression(left, operatorType, right)
.WithILInstruction(inst)
.WithRR(new OperatorResolveResult(
pointerType, BinaryOperatorExpression.GetLinqNodeType(operatorType, inst.CheckForOverflow),
left.ResolveResult, right.ResolveResult));
TranslatedExpression FallBackToBytePointer()
{
pointerType = new PointerType(compilation.FindType(KnownTypeCode.Byte));
return byteOffsetExpr;
}
}
TranslatedExpression? GetPointerArithmeticOffset(ILInstruction byteOffsetInst, TranslatedExpression byteOffsetExpr,
PointerType pointerType, bool checkForOverflow, bool unwrapZeroExtension = false)
{
if (byteOffsetInst is Conv conv && conv.InputType == StackType.I8 && conv.ResultType == StackType.I) {
byteOffsetInst = conv.Argument;
}
int? elementSize = ComputeSizeOf(pointerType.ElementType);
if (elementSize == 1) {
return byteOffsetExpr;
} else if (byteOffsetInst is BinaryNumericInstruction mul && mul.Operator == BinaryNumericOperator.Mul) {
if (mul.CheckForOverflow != checkForOverflow)
return null;
if (mul.IsLifted)
return null;
if (elementSize > 0 && mul.Right.MatchLdcI(elementSize.Value)
|| mul.Right.UnwrapConv(ConversionKind.SignExtend) is SizeOf sizeOf && sizeOf.Type.Equals(pointerType.ElementType))
{
var countOffsetInst = mul.Left;
if (unwrapZeroExtension) {
countOffsetInst = countOffsetInst.UnwrapConv(ConversionKind.ZeroExtend);
}
return Translate(countOffsetInst);
}
} 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 PrimitiveExpression((int)val)
.WithILInstruction(byteOffsetInst)
.WithRR(new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), val));
}
}
}
return null;
}
/// <summary>
/// Called for divisions, detect and handles the code pattern:
/// div(sub(a, b), sizeof(T))
/// when a,b are of type T*.
/// This is what the C# compiler generates for pointer subtraction.
/// </summary>
TranslatedExpression? HandlePointerSubtraction(BinaryNumericInstruction inst)
{
Debug.Assert(inst.Operator == BinaryNumericOperator.Div);
if (inst.CheckForOverflow || inst.LeftInputType != StackType.I)
return null;
if (!(inst.Left is BinaryNumericInstruction sub && sub.Operator == BinaryNumericOperator.Sub))
return null;
if (sub.CheckForOverflow)
return null;
// First, attempt to parse the 'sizeof' on the RHS
IType elementType;
if (inst.Right.MatchLdcI(out long elementSize)) {
elementType = null;
// OK, might be pointer subtraction if the element size matches
} else if (inst.Right.UnwrapConv(ConversionKind.SignExtend).MatchSizeOf(out elementType)) {
// OK, might be pointer subtraction if the element type matches
} else {
return null;
}
var left = Translate(sub.Left);
var right = Translate(sub.Right);
IType pointerType;
if (IsMatchingPointerType(left.Type)) {
pointerType = left.Type;
} else if (IsMatchingPointerType(right.Type)) {
pointerType = right.Type;
} else if (elementSize == 1 && left.Type.Kind == TypeKind.Pointer && right.Type.Kind == TypeKind.Pointer) {
// two pointers (neither matching), we're dividing by 1 (debug builds only),
// -> subtract two byte pointers
pointerType = new PointerType(compilation.FindType(KnownTypeCode.Byte));
} else {
// neither is a matching pointer type
// -> not a pointer subtraction after all
return null;
}
// We got a pointer subtraction.
left = left.ConvertTo(pointerType, this);
right = right.ConvertTo(pointerType, this);
var rr = new OperatorResolveResult(
compilation.FindType(KnownTypeCode.Int64),
ExpressionType.Subtract,
left.ResolveResult, right.ResolveResult
);
var result = new BinaryOperatorExpression(
left.Expression, BinaryOperatorType.Subtract, right.Expression
).WithILInstruction(new[] { inst, sub })
.WithRR(rr);
return result;
bool IsMatchingPointerType(IType type)
{
if (type is PointerType pt) {
if (elementType != null)
return elementType.Equals(pt.ElementType);
else if (elementSize > 0)
return ComputeSizeOf(pt.ElementType) == elementSize;
}
return false;
}
}
int? ComputeSizeOf(IType type)
{
var rr = resolver.ResolveSizeOf(type);
if (rr.IsCompileTimeConstant && rr.ConstantValue is int size)
return size;
else
return null;
}
TranslatedExpression HandleBinaryNumeric(BinaryNumericInstruction inst, BinaryOperatorType op)
{
var resolverWithOverflowCheck = resolver.WithCheckForOverflow(inst.CheckForOverflow);
var left = Translate(inst.Left);
var right = Translate(inst.Right);
if (left.Type.Kind == TypeKind.Pointer || right.Type.Kind == TypeKind.Pointer) {
var ptrResult = HandlePointerArithmetic(inst, left, right);
if (ptrResult != null)
return ptrResult.Value;
}
left = PrepareArithmeticArgument(left, inst.LeftInputType, inst.Sign, inst.IsLifted);
right = PrepareArithmeticArgument(right, inst.RightInputType, inst.Sign, inst.IsLifted);
if (op == BinaryOperatorType.Subtract && inst.Left.MatchLdcI(0)) {
IType rightUType = NullableType.GetUnderlyingType(right.Type);
if (rightUType.IsKnownType(KnownTypeCode.Int32) || rightUType.IsKnownType(KnownTypeCode.Int64) || rightUType.IsCSharpSmallIntegerType()) {
@ -694,6 +901,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -694,6 +901,11 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
if (op.IsBitwise() && (left.Type.Kind == TypeKind.Enum || right.Type.Kind == TypeKind.Enum)) {
left = AdjustConstantExpressionToType(left, right.Type);
right = AdjustConstantExpressionToType(right, left.Type);
}
var rr = resolverWithOverflowCheck.ResolveBinaryOperator(op, left.ResolveResult, right.ResolveResult);
if (rr.IsError || NullableType.GetUnderlyingType(rr.Type).GetStackType() != inst.UnderlyingResultType
|| !IsCompatibleWithSign(left.Type, inst.Sign) || !IsCompatibleWithSign(right.Type, inst.Sign))
@ -726,6 +938,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -726,6 +938,7 @@ namespace ICSharpCode.Decompiler.CSharp
// If the argument is oversized (needs truncation to match stack size of its ILInstruction),
// perform the truncation now.
IType targetType = compilation.FindType(argStackType.ToKnownTypeCode(sign));
argUType = targetType;
if (isLifted)
targetType = NullableType.Create(compilation, targetType);
arg = arg.ConvertTo(targetType, this);
@ -974,7 +1187,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -974,7 +1187,7 @@ namespace ICSharpCode.Decompiler.CSharp
// We just need to ensure the input type before the conversion is signed.
// Also, if the argument was translated into an oversized C# type,
// we need to perform the truncatation to the input stack type.
if (inputType.GetSign() != Sign.Signed || inputType.GetSize() > inputStackType.GetSize()) {
if (inputType.GetSign() != Sign.Signed || ValueMightBeOversized(arg.ResolveResult, inputStackType)) {
// Note that an undersized C# type is handled just fine:
// If it is unsigned we'll zero-extend it to the width of the inputStackType here,
// and it is signed we just combine the two sign-extensions into a single sign-extending conversion.
@ -1030,12 +1243,48 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1030,12 +1243,48 @@ namespace ICSharpCode.Decompiler.CSharp
// Case 4 (left-over extension from implicit conversion) can also be handled by our caller.
return arg.WithILInstruction(inst);
}
default:
return arg.ConvertTo(GetType(inst.TargetType.ToKnownTypeCode()), this, inst.CheckForOverflow)
.WithILInstruction(inst);
default: {
// We need to convert to inst.TargetType, or to an equivalent type.
IType targetType;
if (inst.TargetType == NullableType.GetUnderlyingType(context.TypeHint).ToPrimitiveType()
&& NullableType.IsNullable(context.TypeHint) == inst.IsLifted)
{
targetType = context.TypeHint;
} else {
targetType = GetType(inst.TargetType.ToKnownTypeCode());
}
return arg.ConvertTo(targetType, this, inst.CheckForOverflow)
.WithILInstruction(inst);
}
}
}
/// <summary>
/// Gets whether the ResolveResult computes a value that might be oversized for the specified stack type.
/// </summary>
bool ValueMightBeOversized(ResolveResult rr, StackType stackType)
{
IType inputType = NullableType.GetUnderlyingType(rr.Type);
if (inputType.GetSize() <= stackType.GetSize()) {
// The input type is smaller or equal to the stack type,
// it can't be an oversized value.
return false;
}
if (rr is OperatorResolveResult orr) {
if (stackType == StackType.I && orr.OperatorType == ExpressionType.Subtract
&& orr.Operands.Count == 2
&& orr.Operands[0].Type.Kind == TypeKind.Pointer
&& orr.Operands[1].Type.Kind == TypeKind.Pointer)
{
// Even though a pointer subtraction produces a value of type long in C#,
// the value will always fit in a native int.
return false;
}
}
// We don't have any information about the value, so it might be oversized.
return true;
}
protected internal override TranslatedExpression VisitCall(Call inst, TranslationContext context)
{
return new CallBuilder(this, typeSystem, settings).Build(inst);
@ -1206,19 +1455,41 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1206,19 +1455,41 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLdObj(LdObj inst, TranslationContext context)
{
var target = Translate(inst.Target);
if (target.Expression is DirectionExpression && TypeUtils.IsCompatibleTypeForMemoryAccess(target.Type, inst.Type)) {
// we can dereference the managed reference by stripping away the 'ref'
var result = target.UnwrapChild(((DirectionExpression)target.Expression).Expression);
if (TypeUtils.IsCompatibleTypeForMemoryAccess(target.Type, inst.Type)) {
TranslatedExpression result;
if (target.Expression is DirectionExpression dirExpr) {
// we can dereference the managed reference by stripping away the 'ref'
result = target.UnwrapChild(dirExpr.Expression);
result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation
} else if (target.Type is PointerType pointerType) {
if (target.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.AddressOf) {
// We can dereference the pointer by stripping away the '&'
result = target.UnwrapChild(uoe.Expression);
result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation
} else {
// Dereference the existing pointer
result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
.WithILInstruction(inst)
.WithRR(new ResolveResult(pointerType.ElementType));
}
} else {
// reference type behind non-DirectionExpression?
// this case should be impossible, but we can use a pointer cast
// just to make sure
target = target.ConvertTo(new PointerType(inst.Type), this);
return new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
.WithILInstruction(inst)
.WithRR(new ResolveResult(inst.Type));
}
// we don't convert result to inst.Type, because the LdObj type
// might be inaccurate (it's often System.Object for all reference types),
// and our parent node should already insert casts where necessary
result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation
if (target.Type.IsSmallIntegerType() && inst.Type.IsSmallIntegerType() && target.Type.GetSign() != inst.Type.GetSign())
return result.ConvertTo(inst.Type, this);
return result;
} else {
// Cast pointer type if necessary:
// We need to cast the pointer type:
target = target.ConvertTo(new PointerType(inst.Type), this);
return new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
.WithILInstruction(inst)
@ -1265,14 +1536,30 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1265,14 +1536,30 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLdFlda(LdFlda inst, TranslationContext context)
{
var expr = ConvertField(inst.Field, inst.Target);
return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ResolveResult(new ByReferenceType(expr.Type)));
if (settings.FixedBuffers && inst.Field.Name == "FixedElementField"
&& inst.Target is LdFlda nestedLdFlda
&& CSharpDecompiler.IsFixedField(nestedLdFlda.Field, out var elementType, out _))
{
Expression result = ConvertField(nestedLdFlda.Field, nestedLdFlda.Target);
result.RemoveAnnotations<ResolveResult>();
return result.WithRR(new ResolveResult(new PointerType(elementType)))
.WithILInstruction(inst);
}
var expr = ConvertField(inst.Field, inst.Target).WithILInstruction(inst);
if (inst.ResultType == StackType.I) {
// ldflda producing native pointer
return new UnaryOperatorExpression(UnaryOperatorType.AddressOf, expr)
.WithoutILInstruction().WithRR(new ResolveResult(new PointerType(expr.Type)));
} else {
// ldflda producing managed pointer
return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ResolveResult(new ByReferenceType(expr.Type)));
}
}
protected internal override TranslatedExpression VisitLdsFlda(LdsFlda inst, TranslationContext context)
{
var expr = ConvertField(inst.Field);
var expr = ConvertField(inst.Field).WithILInstruction(inst);
return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ResolveResult(new ByReferenceType(expr.Type)));
}
@ -1667,7 +1954,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1667,7 +1954,8 @@ namespace ICSharpCode.Decompiler.CSharp
// ILAst LogicAnd/LogicOr can return a different value than 0 or 1
// if the rhs is evaluated.
// We can only correctly translate it to C# if the rhs is of type boolean:
if (op != BinaryOperatorType.Any && rhs.Type.IsKnownType(KnownTypeCode.Boolean)) {
if (op != BinaryOperatorType.Any && (rhs.Type.IsKnownType(KnownTypeCode.Boolean) || IfInstruction.IsInConditionSlot(inst))) {
rhs = rhs.ConvertToBoolean(this);
return new BinaryOperatorExpression(condition, op, rhs)
.WithILInstruction(inst)
.WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.Boolean)));

10
ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs

@ -99,5 +99,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -99,5 +99,15 @@ namespace ICSharpCode.Decompiler.CSharp
var simpleType = type as SimpleType;
return simpleType != null && simpleType.Identifier == "__arglist";
}
/// <summary>
/// Returns true if <paramref name="operatorType"/> is bitwise and, bitwise or, or exclusive or.
/// </summary>
public static bool IsBitwise(this BinaryOperatorType operatorType)
{
return operatorType == BinaryOperatorType.BitwiseAnd
|| operatorType == BinaryOperatorType.BitwiseOr
|| operatorType == BinaryOperatorType.ExclusiveOr;
}
}
}

36
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -278,6 +278,30 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -278,6 +278,30 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
isAtStartOfLine = true;
isAfterSpace = false;
}
int GetCallChainLengthLimited(MemberReferenceExpression expr)
{
int callChainLength = 0;
var node = expr;
while (node.Target is InvocationExpression invocation && invocation.Target is MemberReferenceExpression mre && callChainLength < 4) {
node = mre;
callChainLength++;
}
return callChainLength;
}
protected virtual void InsertNewLineWhenInMethodCallChain(MemberReferenceExpression expr)
{
int callChainLength = GetCallChainLengthLimited(expr);
if (callChainLength < 3) return;
if (callChainLength == 3)
writer.Indent();
writer.NewLine();
isAtStartOfLine = true;
isAfterSpace = false;
}
protected virtual void OpenBrace(BraceStyle style)
{
@ -810,6 +834,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -810,6 +834,12 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
invocationExpression.Target.AcceptVisitor(this);
Space(policy.SpaceBeforeMethodCallParentheses);
WriteCommaSeparatedListInParenthesis(invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses);
if (!(invocationExpression.Parent is MemberReferenceExpression)) {
if (invocationExpression.Target is MemberReferenceExpression mre) {
if (GetCallChainLengthLimited(mre) >= 3)
writer.Unindent();
}
}
EndNode(invocationExpression);
}
@ -859,6 +889,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -859,6 +889,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(memberReferenceExpression);
memberReferenceExpression.Target.AcceptVisitor(this);
InsertNewLineWhenInMethodCallChain(memberReferenceExpression);
WriteToken(Roles.Dot);
WriteIdentifier(memberReferenceExpression.MemberNameToken);
WriteTypeArguments(memberReferenceExpression.TypeArguments);
@ -890,6 +921,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -890,6 +921,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(nullReferenceExpression);
writer.WritePrimitiveValue(null);
isAfterSpace = false;
EndNode(nullReferenceExpression);
}
@ -1858,8 +1890,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1858,8 +1890,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
Space(policy.SpaceBeforeConstructorDeclarationParentheses);
WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses);
if (!constructorDeclaration.Initializer.IsNull) {
Space();
NewLine();
writer.Indent();
constructorDeclaration.Initializer.AcceptVisitor(this);
writer.Unindent();
}
WriteMethodBody(constructorDeclaration.Body, policy.ConstructorBraceStyle);
EndNode(constructorDeclaration);

0
ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterOutputFormatter.cs → ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs

29
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs

@ -16,17 +16,15 @@ @@ -16,17 +16,15 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Transforms
{
public class IntroduceUnsafeModifier : DepthFirstAstVisitor<bool>, IAstTransform
{
public static readonly object PointerArithmeticAnnotation = new PointerArithmetic();
sealed class PointerArithmetic {}
public void Run(AstNode compilationUnit, TransformContext context)
{
compilationUnit.AcceptVisitor(this);
@ -54,7 +52,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -54,7 +52,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
base.VisitPointerReferenceExpression(pointerReferenceExpression);
return true;
}
public override bool VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
{
// C# sizeof(MyStruct) requires unsafe{}
// (not for sizeof(int), but that gets constant-folded and thus decompiled to 4)
base.VisitSizeOfExpression(sizeOfExpression);
return true;
}
public override bool VisitComposedType(ComposedType composedType)
{
if (composedType.PointerRank > 0)
@ -67,8 +73,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -67,8 +73,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
bool result = base.VisitUnaryOperatorExpression(unaryOperatorExpression);
if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) {
BinaryOperatorExpression bop = unaryOperatorExpression.Expression as BinaryOperatorExpression;
if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.Annotation<PointerArithmetic>() != null) {
var bop = unaryOperatorExpression.Expression as BinaryOperatorExpression;
if (bop != null && bop.Operator == BinaryOperatorType.Add
&& bop.GetResolveResult() is OperatorResolveResult orr
&& orr.Operands.FirstOrDefault()?.Type.Kind == TypeKind.Pointer)
{
// transform "*(ptr + int)" to "ptr[int]"
IndexerExpression indexer = new IndexerExpression();
indexer.Target = bop.Left.Detach();
@ -118,5 +127,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -118,5 +127,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return true;
return result;
}
public override bool VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer)
{
base.VisitFixedVariableInitializer(fixedVariableInitializer);
return true;
}
}
}

9
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs

@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public FindRequiredImports(TransformContext context)
{
this.currentNamespace = context.DecompiledTypeDefinition != null ? context.DecompiledTypeDefinition.Namespace : string.Empty;
this.currentNamespace = context.DecompiledTypeDefinition?.Namespace ?? string.Empty;
}
bool IsParentOfCurrentNamespace(string ns)
@ -123,7 +123,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -123,7 +123,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public FullyQualifyAmbiguousTypeNamesVisitor(TransformContext context, UsingScope usingScope)
{
this.context = new Stack<CSharpTypeResolveContext>();
var currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainAssembly, usingScope.Resolve(context.TypeSystem.Compilation));
if (!string.IsNullOrEmpty(context.DecompiledTypeDefinition?.Namespace)) {
foreach (string ns in context.DecompiledTypeDefinition.Namespace.Split('.')) {
usingScope = new UsingScope(usingScope, ns);
}
}
var currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainAssembly, usingScope.Resolve(context.TypeSystem.Compilation), context.DecompiledTypeDefinition);
this.context.Push(currentContext);
this.astBuilder = CreateAstBuilder(currentContext);
}

4
ICSharpCode.Decompiler/CSharp/WholeProjectDecompiler.cs

@ -283,8 +283,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -283,8 +283,8 @@ namespace ICSharpCode.Decompiler.CSharp
const string prop = "Properties";
if (directories.Add(prop))
Directory.CreateDirectory(Path.Combine(targetDirectory, prop));
string assemblyInfo = Path.Combine(targetDirectory, prop, "AssemblyInfo.cs");
using (StreamWriter w = new StreamWriter(assemblyInfo)) {
string assemblyInfo = Path.Combine(prop, "AssemblyInfo.cs");
using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, assemblyInfo))) {
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, settings.CSharpFormattingOptions));
}
return new Tuple<string, string>[] { Tuple.Create("Compile", assemblyInfo) };

43
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -103,6 +103,21 @@ namespace ICSharpCode.Decompiler @@ -103,6 +103,21 @@ namespace ICSharpCode.Decompiler
}
}
bool fixedBuffers = true;
/// <summary>
/// Decompile C# 1.0 'public unsafe fixed int arr[10];' members.
/// </summary>
public bool FixedBuffers {
get { return fixedBuffers; }
set {
if (fixedBuffers != value) {
fixedBuffers = value;
OnPropertyChanged();
}
}
}
bool liftNullables = true;
/// <summary>
@ -375,6 +390,34 @@ namespace ICSharpCode.Decompiler @@ -375,6 +390,34 @@ namespace ICSharpCode.Decompiler
#endregion
#region Assembly Load and Resolve options
bool loadInMemory = false;
public bool LoadInMemory {
get { return loadInMemory; }
set {
if (loadInMemory != value) {
loadInMemory = value;
OnPropertyChanged();
}
}
}
bool throwOnAssemblyResolveErrors = false;
public bool ThrowOnAssemblyResolveErrors {
get { return throwOnAssemblyResolveErrors; }
set {
if (throwOnAssemblyResolveErrors != value) {
throwOnAssemblyResolveErrors = value;
OnPropertyChanged();
}
}
}
#endregion
CSharpFormattingOptions csharpFormattingOptions;
public CSharpFormattingOptions CSharpFormattingOptions {

2
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler @@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler
var depsJsonFileName = Path.Combine(basePath, $"{assemblyName}.deps.json");
if (!File.Exists(depsJsonFileName)) {
loadInfo.AddMessage(assemblyName, MessageKind.Error, $"{assemblyName}.deps.json could not be found!");
loadInfo.AddMessage(assemblyName, MessageKind.Warning, $"{assemblyName}.deps.json could not be found!");
return;
}

352
ICSharpCode.Decompiler/DotNetCore/UniversalAssemblyResolver.cs

@ -0,0 +1,352 @@ @@ -0,0 +1,352 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
namespace ICSharpCode.Decompiler
{
public class UniversalAssemblyResolver : IAssemblyResolver
{
DotNetCorePathFinder dotNetCorePathFinder;
readonly bool throwOnError;
readonly string mainAssemblyFileName;
readonly string baseDirectory;
readonly Dictionary<string, UnresolvedAssemblyNameReference> loadedAssemblyReferences;
readonly List<string> directories;
readonly List<string> gac_paths = GetGacPaths();
public static readonly bool OnMono = Type.GetType("Mono.Runtime") != null;
public event AssemblyResolveEventHandler ResolveFailed;
public void AddSearchDirectory(string directory)
{
directories.Add(directory);
}
public void RemoveSearchDirectory(string directory)
{
directories.Remove(directory);
}
public string[] GetSearchDirectories()
{
return directories.ToArray();
}
public string TargetFramework { get; set; }
private UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError)
{
this.mainAssemblyFileName = mainAssemblyFileName;
this.baseDirectory = Path.GetDirectoryName(mainAssemblyFileName);
this.throwOnError = throwOnError;
if (string.IsNullOrWhiteSpace(this.baseDirectory))
this.baseDirectory = Environment.CurrentDirectory;
AddSearchDirectory(baseDirectory);
}
public static ModuleDefinition LoadMainModule(string mainAssemblyFileName, bool throwOnError = true, bool inMemory = false)
{
var resolver = new UniversalAssemblyResolver(mainAssemblyFileName, throwOnError);
var module = ModuleDefinition.ReadModule(mainAssemblyFileName, new ReaderParameters {
AssemblyResolver = resolver,
InMemory = inMemory
});
resolver.TargetFramework = module.Assembly.DetectTargetFrameworkId();
return module;
}
public AssemblyDefinition Resolve(AssemblyNameReference name)
{
return Resolve(name, new ReaderParameters());
}
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
var targetFramework = TargetFramework.Split(new[] { ",Version=v" }, StringSplitOptions.None);
string file = null;
switch (targetFramework[0]) {
case ".NETCoreApp":
case ".NETStandard":
if (targetFramework.Length != 2) goto default;
if (dotNetCorePathFinder == null) {
var version = targetFramework[1].Length == 3 ? targetFramework[1] + ".0" : targetFramework[1];
dotNetCorePathFinder = new DotNetCorePathFinder(mainAssemblyFileName, TargetFramework, version, this.loadedAssemblyReferences);
}
file = dotNetCorePathFinder.TryResolveDotNetCore(name);
if (file == null)
goto default;
else {
var asm = ModuleDefinition.ReadModule(file, parameters).Assembly;
if (throwOnError && asm == null)
throw new AssemblyResolutionException(name);
return asm;
}
default:
return ResolveInternal(name, parameters);
}
}
AssemblyDefinition ResolveInternal(AssemblyNameReference name, ReaderParameters parameters)
{
if (name == null)
throw new ArgumentNullException(nameof(name));
if (parameters == null)
throw new ArgumentNullException(nameof(parameters));
var assembly = SearchDirectory(name, directories, parameters);
if (assembly != null)
return assembly;
if (name.IsRetargetable) {
// if the reference is retargetable, zero it
name = new AssemblyNameReference(name.Name, ZeroVersion) {
PublicKeyToken = Empty<byte>.Array,
};
}
var framework_dir = Path.GetDirectoryName(typeof(object).Module.FullyQualifiedName);
var framework_dirs = OnMono
? new[] { framework_dir, Path.Combine(framework_dir, "Facades") }
: new[] { framework_dir };
if (IsZero(name.Version)) {
assembly = SearchDirectory(name, framework_dirs, parameters);
if (assembly != null)
return assembly;
}
if (name.Name == "mscorlib") {
assembly = GetCorlib(name, parameters);
if (assembly != null)
return assembly;
}
assembly = GetAssemblyInGac(name, parameters);
if (assembly != null)
return assembly;
assembly = SearchDirectory(name, framework_dirs, parameters);
if (assembly != null)
return assembly;
if (ResolveFailed != null) {
assembly = ResolveFailed(this, name);
if (assembly != null)
return assembly;
}
if (throwOnError)
throw new AssemblyResolutionException(name);
return null;
}
#region .NET / mono GAC handling
AssemblyDefinition SearchDirectory(AssemblyNameReference name, IEnumerable<string> directories, ReaderParameters parameters)
{
var extensions = name.IsWindowsRuntime ? new[] { ".winmd", ".dll" } : new[] { ".exe", ".dll" };
foreach (var directory in directories) {
foreach (var extension in extensions) {
string file = Path.Combine(directory, name.Name + extension);
if (!File.Exists(file))
continue;
try {
return GetAssembly(file, parameters);
} catch (System.BadImageFormatException) {
continue;
}
}
}
return null;
}
static bool IsZero(Version version)
{
return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0;
}
static Version ZeroVersion = new Version(0, 0, 0, 0);
AssemblyDefinition GetCorlib(AssemblyNameReference reference, ReaderParameters parameters)
{
var version = reference.Version;
var corlib = typeof(object).Assembly.GetName();
if (corlib.Version == version || IsZero(version))
return GetAssembly(typeof(object).Module.FullyQualifiedName, parameters);
var path = Directory.GetParent(
Directory.GetParent(
typeof(object).Module.FullyQualifiedName).FullName
).FullName;
if (OnMono) {
if (version.Major == 1)
path = Path.Combine(path, "1.0");
else if (version.Major == 2) {
if (version.MajorRevision == 5)
path = Path.Combine(path, "2.1");
else
path = Path.Combine(path, "2.0");
} else if (version.Major == 4)
path = Path.Combine(path, "4.0");
else
throw new NotSupportedException("Version not supported: " + version);
} else {
switch (version.Major) {
case 1:
if (version.MajorRevision == 3300)
path = Path.Combine(path, "v1.0.3705");
else
path = Path.Combine(path, "v1.0.5000.0");
break;
case 2:
path = Path.Combine(path, "v2.0.50727");
break;
case 4:
path = Path.Combine(path, "v4.0.30319");
break;
default:
throw new NotSupportedException("Version not supported: " + version);
}
}
var file = Path.Combine(path, "mscorlib.dll");
if (File.Exists(file))
return GetAssembly(file, parameters);
return null;
}
static List<string> GetGacPaths()
{
if (OnMono)
return GetDefaultMonoGacPaths();
var paths = new List<string>(2);
var windir = Environment.GetEnvironmentVariable("WINDIR");
if (windir == null)
return paths;
paths.Add(Path.Combine(windir, "assembly"));
paths.Add(Path.Combine(windir, Path.Combine("Microsoft.NET", "assembly")));
return paths;
}
static List<string> GetDefaultMonoGacPaths()
{
var paths = new List<string>(1);
var gac = GetCurrentMonoGac();
if (gac != null)
paths.Add(gac);
var gac_paths_env = Environment.GetEnvironmentVariable("MONO_GAC_PREFIX");
if (string.IsNullOrEmpty(gac_paths_env))
return paths;
var prefixes = gac_paths_env.Split(Path.PathSeparator);
foreach (var prefix in prefixes) {
if (string.IsNullOrEmpty(prefix))
continue;
var gac_path = Path.Combine(Path.Combine(Path.Combine(prefix, "lib"), "mono"), "gac");
if (Directory.Exists(gac_path) && !paths.Contains(gac))
paths.Add(gac_path);
}
return paths;
}
static string GetCurrentMonoGac()
{
return Path.Combine(
Directory.GetParent(
Path.GetDirectoryName(typeof(object).Module.FullyQualifiedName)).FullName,
"gac");
}
AssemblyDefinition GetAssembly(string file, ReaderParameters parameters)
{
if (parameters.AssemblyResolver == null)
parameters.AssemblyResolver = this;
return ModuleDefinition.ReadModule(file, parameters).Assembly;
}
AssemblyDefinition GetAssemblyInGac(AssemblyNameReference reference, ReaderParameters parameters)
{
if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
return null;
if (OnMono)
return GetAssemblyInMonoGac(reference, parameters);
return GetAssemblyInNetGac(reference, parameters);
}
AssemblyDefinition GetAssemblyInMonoGac(AssemblyNameReference reference, ReaderParameters parameters)
{
for (int i = 0; i < gac_paths.Count; i++) {
var gac_path = gac_paths[i];
var file = GetAssemblyFile(reference, string.Empty, gac_path);
if (File.Exists(file))
return GetAssembly(file, parameters);
}
return null;
}
AssemblyDefinition GetAssemblyInNetGac(AssemblyNameReference reference, ReaderParameters parameters)
{
var gacs = new[] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" };
var prefixes = new[] { string.Empty, "v4.0_" };
for (int i = 0; i < 2; i++) {
for (int j = 0; j < gacs.Length; j++) {
var gac = Path.Combine(gac_paths[i], gacs[j]);
var file = GetAssemblyFile(reference, prefixes[i], gac);
if (Directory.Exists(gac) && File.Exists(file))
return GetAssembly(file, parameters);
}
}
return null;
}
static string GetAssemblyFile(AssemblyNameReference reference, string prefix, string gac)
{
var gac_folder = new StringBuilder()
.Append(prefix)
.Append(reference.Version)
.Append("__");
for (int i = 0; i < reference.PublicKeyToken.Length; i++)
gac_folder.Append(reference.PublicKeyToken[i].ToString("x2"));
return Path.Combine(
Path.Combine(
Path.Combine(gac, reference.Name), gac_folder.ToString()),
reference.Name + ".dll");
}
#endregion
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
}

18
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -24,21 +24,23 @@ @@ -24,21 +24,23 @@
<!-- HACK: Disable package generation on Unix due to tooling issues. -->
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<IncludeSymbolsInPackage>true</IncludeSymbolsInPackage>
<NuspecFile>ICSharpCode.Decompiler.nuspec</NuspecFile>
<NuspecProperties>Configuration=$(Configuration)</NuspecProperties>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DebugType>full</DebugType>
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
<EmbedSources>true</EmbedSources>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>$(DefineConstants);STEP</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>pdbonly</DebugType>
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
<EmbedSources>true</EmbedSources>
</PropertyGroup>
<PropertyGroup>
@ -203,7 +205,7 @@ @@ -203,7 +205,7 @@
<Compile Include="CSharp\OutputVisitor\InsertRequiredSpacesDecorator.cs" />
<Compile Include="CSharp\OutputVisitor\InsertSpecialsDecorator.cs" />
<Compile Include="CSharp\OutputVisitor\ITokenWriter.cs" />
<Compile Include="CSharp\OutputVisitor\TextWriterOutputFormatter.cs" />
<Compile Include="CSharp\OutputVisitor\TextWriterTokenWriter.cs" />
<Compile Include="CSharp\Resolver\AliasNamespaceResolveResult.cs" />
<Compile Include="CSharp\Resolver\AliasTypeResolveResult.cs" />
<Compile Include="CSharp\Resolver\AwaitResolveResult.cs" />
@ -272,6 +274,7 @@ @@ -272,6 +274,7 @@
<Compile Include="Documentation\XmlDocumentationProvider.cs" />
<Compile Include="DotNetCore\DotNetCorePathFinder.cs" />
<Compile Include="DotNetCore\DotNetCorePathFinderExtensions.cs" />
<Compile Include="DotNetCore\UniversalAssemblyResolver.cs" />
<Compile Include="DotNetCore\UnresolvedAssemblyNameReference.cs" />
<Compile Include="IL\ILAstWritingOptions.cs" />
<Compile Include="IL\SequencePoint.cs" />
@ -587,4 +590,11 @@ @@ -587,4 +590,11 @@
</PropertyGroup>
<Exec WorkingDirectory="$(SolutionDir)" Command="$(UpdateAssemblyInfo)" Timeout="60000" />
</Target>
<!-- Workaround for EmbedSources support, see https://github.com/dotnet/roslyn/issues/19127 -->
<Target Name="PopulateEmbeddedFiles" AfterTargets="BeforeCompile" BeforeTargets="CoreCompile">
<ItemGroup>
<EmbeddedFiles Include="@(Compile)" />
</ItemGroup>
</Target>
</Project>

15
ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec → ICSharpCode.Decompiler/ICSharpCode.Decompiler.nuspec.template

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>ICSharpCode.Decompiler</id>
<version>3.0.0-alpha3</version>
<version>$INSERTVERSION$$INSERTVERSIONNAMEPOSTFIX$</version>
<title>ILSpy Decompiler Engine</title>
<authors>Daniel Grunwald, David Srbecky, Ed Harvey, Siegfried Pammer</authors>
<owners>Daniel Grunwald, SharpDevelop</owners>
@ -12,12 +12,13 @@ @@ -12,12 +12,13 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>ICSharpCode.Decompiler is the decompiler engine used in ILSpy.</description>
<!--<releaseNotes></releaseNotes>-->
<copyright>Copyright 2011-2017 AlphaSierraPapa</copyright>
<copyright>Copyright 2011-$INSERTYEAR$ AlphaSierraPapa</copyright>
<tags>C# Decompiler ILSpy</tags>
<dependencies>
<dependency id="System.Collections.Immutable" version="1.3.0" />
<dependency id="System.ValueTuple" version="4.3.0" />
<dependency id="Newtonsoft.Json" version="10.0.3" />
<dependency id="Humanizer.Core" version="2.2.0" />
<dependency id="Newtonsoft.Json" version="10.0.3" />
<dependency id="System.Collections.Immutable" version="1.4.0" />
<dependency id="System.ValueTuple" version="4.4.0" />
</dependencies>
</metadata>
<files>
@ -30,9 +31,5 @@ @@ -30,9 +31,5 @@
<file src="bin\$Configuration$\netstandard2.0\ICSharpCode.Decompiler.pdb" target="lib\netstandard2.0" />
<file src="bin\$Configuration$\netstandard2.0\Mono.Cecil.dll" target="lib\netstandard2.0" />
<file src="bin\$Configuration$\netstandard2.0\Mono.Cecil.pdb" target="lib\netstandard2.0" />
<file src="**\*.cs" exclude="obj\**\*.cs" target="src\ICSharpCode.Decompiler" />
<file src="obj\$Configuration$\net461\**\*.cs" target="src\ICSharpCode.Decompiler\obj\$Configuration$\net461" />
<file src="obj\$Configuration$\netstandard2.0\**\*.cs" target="src\ICSharpCode.Decompiler\obj\$Configuration$\netstandard2.0" />
</files>
</package>

17
ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs

@ -172,10 +172,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -172,10 +172,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (DetectExitPoints.CompatibleExitInstruction(trueExitInst, falseExitInst)) {
// if (...) { ...; goto exitPoint; } goto nextBlock; nextBlock: ...; goto exitPoint;
// -> if (...) { ... } else { ... } goto exitPoint;
context.Step("Inline block as else-branch", ifInst);
targetBlock.Instructions.RemoveAt(targetBlock.Instructions.Count - 1);
targetBlock.Remove();
ifInst.FalseInst = targetBlock;
// the else block is not empty or nop-only:
if (targetBlock.Children.Any(inst => !(inst is Nop) && inst != falseExitInst)) {
context.Step("Inline block as else-branch", ifInst);
targetBlock.Instructions.RemoveAt(targetBlock.Instructions.Count - 1);
targetBlock.Remove();
ifInst.FalseInst = targetBlock;
} else {
// the else block is empty or nop-only and can be safely removed:
context.Step("Remove empty else-branch", ifInst);
targetBlock.Instructions.RemoveAt(targetBlock.Instructions.Count - 1);
targetBlock.Remove();
}
exitInst = block.Instructions[block.Instructions.Count - 1] = falseExitInst;
Block trueBlock = ifInst.TrueInst as Block;
if (trueBlock != null) {

2
ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

@ -337,6 +337,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -337,6 +337,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
new PointerType(((ByReferenceType)oldVar.Type).ElementType),
oldVar.Index);
newVar.Name = oldVar.Name;
newVar.HasGeneratedName = oldVar.HasGeneratedName;
oldVar.Function.Variables.Add(newVar);
ReplacePinnedVar(oldVar, newVar, pinnedRegion);
} else if (pinnedRegion.Variable.Type.IsKnownType(KnownTypeCode.String)) {
@ -383,6 +384,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -383,6 +384,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (nativeVar.Kind == VariableKind.Local) {
newVar = new ILVariable(VariableKind.PinnedLocal, nativeVar.Type, nativeVar.Index);
newVar.Name = nativeVar.Name;
newVar.HasGeneratedName = nativeVar.HasGeneratedName;
nativeVar.Function.Variables.Add(newVar);
ReplacePinnedVar(nativeVar, newVar, pinnedRegion);
} else {

2
ICSharpCode.Decompiler/IL/Instructions.cs

@ -3260,7 +3260,7 @@ namespace ICSharpCode.Decompiler.IL @@ -3260,7 +3260,7 @@ namespace ICSharpCode.Decompiler.IL
readonly IField field;
/// <summary>Returns the field operand.</summary>
public IField Field { get { return field; } }
public override StackType ResultType { get { return StackType.Ref; } }
public override StackType ResultType { get { return target.ResultType.IsIntegerType() ? StackType.I : StackType.Ref; } }
protected override InstructionFlags ComputeFlags()
{
return target.Flags | (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow);

3
ICSharpCode.Decompiler/IL/Instructions.tt

@ -192,7 +192,8 @@ @@ -192,7 +192,8 @@
SupportsVolatilePrefix, SupportsUnalignedPrefix, ResultType("Void")),
new OpCode("ldflda", "Load address of instance field",
CustomClassName("LdFlda"), CustomArguments("target"), MayThrowIfNotDelayed, HasFieldOperand, ResultType("Ref")),
CustomClassName("LdFlda"), CustomArguments("target"), MayThrowIfNotDelayed, HasFieldOperand,
ResultType("target.ResultType.IsIntegerType() ? StackType.I : StackType.Ref")),
new OpCode("ldsflda", "Load static field address",
CustomClassName("LdsFlda"), NoArguments, ResultType("Ref"), HasFieldOperand),

19
ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs

@ -107,5 +107,24 @@ namespace ICSharpCode.Decompiler.IL @@ -107,5 +107,24 @@ namespace ICSharpCode.Decompiler.IL
falseInst.WriteTo(output, options);
}
}
/// <summary>
/// Gets whether the input instruction occurs in a context where it is being compared with 0.
/// </summary>
internal static bool IsInConditionSlot(ILInstruction inst)
{
var slot = inst.SlotInfo;
if (slot == IfInstruction.ConditionSlot)
return true;
if (slot == IfInstruction.TrueInstSlot || slot == IfInstruction.FalseInstSlot || slot == NullCoalescingInstruction.FallbackInstSlot)
return IsInConditionSlot(inst.Parent);
if (inst.Parent is Comp comp) {
if (comp.Left == inst && comp.Right.MatchLdcI4(0))
return true;
if (comp.Right == inst && comp.Left.MatchLdcI4(0))
return true;
}
return false;
}
}
}

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

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.IL @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.IL
}
/// <summary>
/// Matches either LdcI4 or LdcI8.
/// Matches ldc.i4, ldc.i8, and extending conversions.
/// </summary>
public bool MatchLdcI(out long val)
{
@ -43,6 +43,17 @@ namespace ICSharpCode.Decompiler.IL @@ -43,6 +43,17 @@ namespace ICSharpCode.Decompiler.IL
val = intVal;
return true;
}
if (this is Conv conv) {
if (conv.Kind == ConversionKind.SignExtend) {
return conv.Argument.MatchLdcI(out val);
} else if (conv.Kind == ConversionKind.ZeroExtend && conv.InputType == StackType.I4) {
if (conv.Argument.MatchLdcI(out val)) {
// clear top 32 bits
val &= uint.MaxValue;
return true;
}
}
}
return false;
}

13
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -226,14 +226,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -226,14 +226,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
switch (inst) {
case LdObj ldobj:
IField field;
if (ldobj.Target is LdFlda ldflda)
field = ldflda.Field;
else if (ldobj.Target is LdsFlda ldsflda)
field = ldsflda.Field;
else
break;
return CleanUpVariableName(field.Name);
return GetNameFromInstruction(ldobj.Target);
case LdFlda ldflda:
return CleanUpVariableName(ldflda.Field.Name);
case LdsFlda ldsflda:
return CleanUpVariableName(ldsflda.Field.Name);
case CallInstruction call:
if (call is NewObj) break;
IMethod m = call.Method;

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

@ -49,9 +49,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -49,9 +49,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (block.Instructions[i].MatchStLoc(out v, out copiedExpr)) {
if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot) {
// dead store to stack
if (copiedExpr.Flags == InstructionFlags.None) {
if (SemanticHelper.IsPure(copiedExpr.Flags)) {
// no-op -> delete
context.Step("remove dead store to stack: no-op -> delete", block.Instructions[i - 1]);
context.Step("remove dead store to stack: no-op -> delete", block.Instructions[i]);
block.Instructions.RemoveAt(i--);
} else {
// evaluate the value for its side-effects

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

@ -54,18 +54,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -54,18 +54,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// we know those were already handled previously.
}
static bool IsInConditionSlot(ILInstruction inst)
{
var slot = inst.SlotInfo;
if (slot == IfInstruction.ConditionSlot)
return true;
if (slot == IfInstruction.TrueInstSlot || slot == IfInstruction.FalseInstSlot || slot == NullCoalescingInstruction.FallbackInstSlot)
return IsInConditionSlot(inst.Parent);
if (inst.Parent.MatchLogicNot(out _))
return true;
return false;
}
protected internal override void VisitComp(Comp inst)
{
// "logic.not(arg)" is sugar for "comp(arg != ldc.i4 0)"
@ -73,7 +61,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -73,7 +61,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
VisitLogicNot(inst, arg);
return;
} else if (inst.Kind == ComparisonKind.Inequality && inst.LiftingKind == ComparisonLiftingKind.None
&& inst.Right.MatchLdcI4(0) && (IsInConditionSlot(inst) || inst.Left is Comp)
&& inst.Right.MatchLdcI4(0) && (IfInstruction.IsInConditionSlot(inst) || inst.Left is Comp)
) {
// if (comp(x != 0)) ==> if (x)
// comp(comp(...) != 0) => comp(...)

28
ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Decompiler.FlowAnalysis;
namespace ICSharpCode.Decompiler.IL.Transforms
@ -37,13 +39,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -37,13 +39,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms
v.HasInitialValue = false;
}
}
if (function.IsIterator || function.IsAsync) {
// In yield return + async, the C# compiler tends to store null/default(T) to variables
// when the variable goes out of scope. Remove such useless stores.
foreach (var v in function.Variables) {
if (v.Kind == VariableKind.Local && v.StoreCount == 1 && v.LoadCount == 0 && v.AddressCount == 0) {
if (v.StoreInstructions[0] is StLoc stloc && (stloc.Value.MatchLdNull() || stloc.Value is DefaultValue) && stloc.Parent is Block block) {
// Remove dead stores to variables that are never read from.
// If the stored value has some side-effect, the value is unwrapped.
// This is necessary to remove useless stores generated by some compilers, e.g., the F# compiler.
// In yield return + async, the C# compiler tends to store null/default(T) to variables
// when the variable goes out of scope.
var variableQueue = new Queue<ILVariable>(function.Variables);
while (variableQueue.Count > 0) {
var v = variableQueue.Dequeue();
if (v.Kind != VariableKind.Local && v.Kind != VariableKind.StackSlot)
continue;
if (v.LoadCount != 0 || v.AddressCount != 0)
continue;
foreach (var stloc in v.StoreInstructions.OfType<StLoc>().ToArray()) {
if (stloc.Parent is Block block) {
if (SemanticHelper.IsPure(stloc.Value.Flags)) {
block.Instructions.Remove(stloc);
} else {
stloc.ReplaceWith(stloc.Value);
}
if (stloc.Value is LdLoc ldloc) {
variableQueue.Enqueue(ldloc.Variable);
}
}
}

14
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler @@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler
if (symbol == null && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) {
symbol = node.Parent.GetSymbol();
}
if (symbol != null && node.Parent is ObjectCreateExpression) {
if (symbol != null && node.Role == Roles.Type && node.Parent is ObjectCreateExpression) {
symbol = node.Parent.GetSymbol();
}
if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) {
@ -335,9 +335,15 @@ namespace ICSharpCode.Decompiler @@ -335,9 +335,15 @@ namespace ICSharpCode.Decompiler
case "char":
case "string":
case "object":
var typeSymbol = (nodeStack.Peek().GetSymbol() as IType)?.GetDefinition();
if (typeSymbol == null) goto default;
output.WriteReference(type, typeSystem.GetCecil(typeSymbol));
var node = nodeStack.Peek();
ISymbol symbol;
if (node.Role == Roles.Type && node.Parent is ObjectCreateExpression) {
symbol = node.Parent.GetSymbol();
} else {
symbol = nodeStack.Peek().GetSymbol();
}
if (symbol == null) goto default;
output.WriteReference(type, SymbolToCecil(symbol));
break;
default:
output.Write(type);

23
ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs

@ -127,6 +127,28 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -127,6 +127,28 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
/// <summary>
/// Gets whether the type is a C# primitive integer type: byte, sbyte, short, ushort, int, uint, long and ulong.
///
/// Unlike the ILAst, C# does not consider bool, enums, pointers or IntPtr to be integers.
/// </summary>
public static bool IsCSharpPrimitiveIntegerType(this IType type)
{
switch (type.GetDefinition()?.KnownTypeCode) {
case KnownTypeCode.Byte:
case KnownTypeCode.SByte:
case KnownTypeCode.Int16:
case KnownTypeCode.UInt16:
case KnownTypeCode.Int32:
case KnownTypeCode.UInt32:
case KnownTypeCode.Int64:
case KnownTypeCode.UInt64:
return true;
default:
return false;
}
}
/// <summary>
/// Gets whether the type is an IL integer type.
/// Returns true for I4, I, or I8.
@ -282,6 +304,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -282,6 +304,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
case KnownTypeCode.Byte:
return PrimitiveType.U1;
case KnownTypeCode.UInt16:
case KnownTypeCode.Char:
return PrimitiveType.U2;
case KnownTypeCode.UInt32:
return PrimitiveType.U4;

5
ICSharpCode.Decompiler/Util/EmptyList.cs

@ -111,4 +111,9 @@ namespace ICSharpCode.Decompiler.Util @@ -111,4 +111,9 @@ namespace ICSharpCode.Decompiler.Util
{
}
}
public static class Empty<T>
{
public static readonly T[] Array = new T[0];
}
}

24
ILSpy/Commands/SortAssemblyListCommand.cs

@ -18,12 +18,13 @@ @@ -18,12 +18,13 @@
using System;
using System.Collections.Generic;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_View", Header = "Sort assembly list by name", MenuIcon = "Images/Sort.png", MenuCategory = "View")]
[ExportToolbarCommand(ToolTip = "Sort assembly list by name", ToolbarIcon = "Images/Sort.png", ToolbarCategory = "View")]
class SortAssemblyListCommand : SimpleCommand, IComparer<LoadedAssembly>
sealed class SortAssemblyListCommand : SimpleCommand, IComparer<LoadedAssembly>
{
public override void Execute(object parameter)
{
@ -36,4 +37,25 @@ namespace ICSharpCode.ILSpy @@ -36,4 +37,25 @@ namespace ICSharpCode.ILSpy
return string.Compare(x.ShortName, y.ShortName, StringComparison.CurrentCulture);
}
}
[ExportMainMenuCommand(Menu = "_View", Header = "Collapse all tree nodes", MenuIcon = "Images/CollapseAll.png", MenuCategory = "View")]
[ExportToolbarCommand(ToolTip = "Collapse all tree nodes", ToolbarIcon = "Images/CollapseAll.png", ToolbarCategory = "View")]
sealed class CollapseAllCommand : SimpleCommand
{
public override void Execute(object parameter)
{
using (MainWindow.Instance.treeView.LockUpdates())
CollapseChildren(MainWindow.Instance.treeView.Root);
void CollapseChildren(SharpTreeNode node)
{
foreach (var child in node.Children) {
if (!child.IsExpanded)
continue;
CollapseChildren(child);
child.IsExpanded = false;
}
}
}
}
}

1
ILSpy/ILSpy.csproj

@ -346,6 +346,7 @@ @@ -346,6 +346,7 @@
<Resource Include="Images\PrivateInternal.png" />
<Resource Include="Images\Refresh.png" />
<Resource Include="Images\Constructor.png" />
<Resource Include="Images\CollapseAll.png" />
<Resource Include="Images\EnumValue.png" />
<Resource Include="Images\FieldReadOnly.png" />
<Resource Include="Images\OverlayInternal.png" />

BIN
ILSpy/Images/CollapseAll.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

7
ILSpy/Languages/CSharpHighlightingTokenWriter.cs

@ -127,9 +127,14 @@ namespace ICSharpCode.ILSpy @@ -127,9 +127,14 @@ namespace ICSharpCode.ILSpy
case "global":
case "dynamic":
case "await":
case "where":
color = structureKeywordsColor;
break;
case "where":
if (nodeStack.PeekOrDefault() is QueryClause)
color = queryKeywordsColor;
else
color = structureKeywordsColor;
break;
case "in":
if (nodeStack.PeekOrDefault() is ForeachStatement)
color = structureKeywordsColor;

2
ILSpy/Languages/CSharpLanguage.cs

@ -327,9 +327,9 @@ namespace ICSharpCode.ILSpy @@ -327,9 +327,9 @@ namespace ICSharpCode.ILSpy
decompiler.ProjectGuid = App.CommandLineArguments.FixedGuid;
decompiler.DecompileProject(assembly.ModuleDefinition, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken);
} else {
base.DecompileAssembly(assembly, output, options);
AddReferenceWarningMessage(assembly.AssemblyDefinition, output);
output.WriteLine();
base.DecompileAssembly(assembly, output, options);
ModuleDefinition mainModule = assembly.ModuleDefinition;
if (mainModule.Types.Count > 0) {
output.Write("// Global type: ");

10
ILSpy/OpenListDialog.xaml

@ -28,14 +28,14 @@ @@ -28,14 +28,14 @@
</ListView>
<DockPanel Grid.Row="2">
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right">
<Button IsDefault="True" Margin="2,0" IsEnabled="False" Name="okButton" Click="OKButton_Click">Open</Button>
<Button IsDefault="True" Margin="2,0" IsEnabled="False" Name="okButton" Click="OKButton_Click">_Open</Button>
<Button IsCancel="True" Margin="2,0">Cancel</Button>
</StackPanel>
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal" HorizontalAlignment="Left">
<Button Margin="2,0" Click="CreateButton_Click">Create</Button>
<Button Margin="2,0" IsEnabled="False" Name="removeButton" Click="RemoveButton_Click">Remove</Button>
<Button Margin="2,0" Click="ResetButton_Click">Reset</Button>
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal" HorizontalAlignment="Left">
<Button Margin="2,0" Click="CreateButton_Click">_Create</Button>
<Button Margin="2,0" IsEnabled="False" Name="deleteButton" Click="DeleteButton_Click">_Delete</Button>
<Button Margin="2,0" Click="ResetButton_Click">_Reset</Button>
</StackPanel>
</DockPanel>
</Grid>

13
ILSpy/OpenListDialog.xaml.cs

@ -20,6 +20,7 @@ using System.Windows; @@ -20,6 +20,7 @@ using System.Windows;
using System.Windows.Controls;
using Mono.Cecil;
using System.Windows.Input;
using System;
namespace ICSharpCode.ILSpy
{
@ -50,7 +51,7 @@ namespace ICSharpCode.ILSpy @@ -50,7 +51,7 @@ namespace ICSharpCode.ILSpy
void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
okButton.IsEnabled = listView.SelectedItem != null;
removeButton.IsEnabled = listView.SelectedItem != null;
deleteButton.IsEnabled = listView.SelectedItem != null;
}
void OKButton_Click(object sender, RoutedEventArgs e)
@ -174,10 +175,14 @@ namespace ICSharpCode.ILSpy @@ -174,10 +175,14 @@ namespace ICSharpCode.ILSpy
}
}
private void RemoveButton_Click(object sender, RoutedEventArgs e)
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
if (listView.SelectedItem != null)
manager.DeleteList(listView.SelectedItem.ToString());
if (listView.SelectedItem == null)
return;
if (MessageBox.Show(this, "Are you sure that you want to delete the selected assembly list?",
"ILSpy", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No, MessageBoxOptions.None) != MessageBoxResult.Yes)
return;
manager.DeleteList(listView.SelectedItem.ToString());
}
private void ResetButton_Click(object sender, RoutedEventArgs e)

2
ILSpy/Properties/AssemblyInfo.template.cs

@ -42,7 +42,7 @@ internal static class RevisionClass @@ -42,7 +42,7 @@ internal static class RevisionClass
public const string Minor = "0";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";
public const string VersionName = null;
public const string VersionName = "beta1";
public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$";
}

4
ILSpy/TreeNodes/TypeTreeNode.cs

@ -44,10 +44,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -44,10 +44,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
public AssemblyTreeNode ParentAssemblyNode { get; }
public string Name => TypeDefinition.Name;
public string Namespace => TypeDefinition.Namespace;
public override object Text => HighlightSearchMatch(this.Language.FormatTypeName(TypeDefinition), TypeDefinition.MetadataToken.ToSuffixString());
public override bool IsPublicAPI {

4
appveyor.yml

@ -20,4 +20,6 @@ after_test: @@ -20,4 +20,6 @@ after_test:
- python BuildTools\tidy.py
artifacts:
- path: ILSpy_binaries.zip
name: ILSpy %APPVEYOR_REPO_BRANCH% %ILSPY_VERSION_NUMBER% binaries
name: ILSpy %APPVEYOR_REPO_BRANCH% %ILSPY_VERSION_NUMBER% binaries
- path: '**\*.nupkg'
name: ICSharpCode.Decompiler %APPVEYOR_REPO_BRANCH% %ILSPY_VERSION_NUMBER% NuGet
Loading…
Cancel
Save