Browse Source

Merge pull request #960 from icsharpcode/increment

Improve handling of post-increment and compound assignments
pull/925/merge
Daniel Grunwald 8 years ago committed by GitHub
parent
commit
13140f60be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs
  2. 24
      ICSharpCode.Decompiler.Tests/Helpers/Tester.cs
  3. 4
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  4. 4
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  5. 21
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs
  6. 429
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il
  7. 236
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs
  8. 1008
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il
  9. 810
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il
  10. 806
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il
  11. 1014
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il
  12. 62
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs
  13. 285
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il
  14. 231
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il
  15. 431
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.roslyn.il
  16. 524
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.roslyn.il
  17. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs
  18. 10
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  19. 76
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  20. 19
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  21. 55
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  22. 4
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  23. 35
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  24. 15
      ICSharpCode.Decompiler/IL/ILVariable.cs
  25. 117
      ICSharpCode.Decompiler/IL/Instructions.cs
  26. 13
      ICSharpCode.Decompiler/IL/Instructions.tt
  27. 62
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  28. 14
      ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs
  29. 4
      ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs
  30. 8
      ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs
  31. 17
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
  32. 17
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  33. 567
      ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs
  34. 3
      ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs

31
ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using DiffLib; using DiffLib;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using NUnit.Framework; using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Helpers namespace ICSharpCode.Decompiler.Tests.Helpers
@ -115,24 +117,23 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
return NormalizeLine(line) == string.Empty; return NormalizeLine(line) == string.Empty;
} }
private static IEnumerable<string> NormalizeAndSplitCode(string input, string[] definedSymbols) class DeleteDisabledTextRewriter : CSharpSyntaxRewriter
{ {
bool include = true; public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
foreach (string line in input.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries)) { {
var temp = line.Trim(); if (trivia.IsKind(SyntaxKind.DisabledTextTrivia)) {
if (temp.StartsWith("#if !", StringComparison.Ordinal)) { return default(SyntaxTrivia); // delete
string symbol = temp.Substring(5);
if (definedSymbols.Contains(symbol))
include = false;
} else if (temp.StartsWith("#if ", StringComparison.Ordinal)) {
string symbol = temp.Substring(4);
if (!definedSymbols.Contains(symbol))
include = false;
} else if (temp.StartsWith("#endif", StringComparison.Ordinal)) {
include = true;
} }
if (include) yield return line; return base.VisitTrivia(trivia);
} }
} }
private static IEnumerable<string> NormalizeAndSplitCode(string input, IEnumerable<string> definedSymbols)
{
var syntaxTree = CSharpSyntaxTree.ParseText(input, new CSharpParseOptions(preprocessorSymbols: definedSymbols));
var result = new DeleteDisabledTextRewriter().Visit(syntaxTree.GetRoot());
input = result.ToFullString();
return input.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
}
} }
} }

24
ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

@ -158,6 +158,24 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
}; };
}); });
public static List<string> GetPreprocessorSymbols(CompilerOptions flags)
{
var preprocessorSymbols = new List<string>();
if (flags.HasFlag(CompilerOptions.UseDebug)) {
preprocessorSymbols.Add("DEBUG");
}
if (flags.HasFlag(CompilerOptions.Optimize)) {
preprocessorSymbols.Add("OPT");
}
if (flags.HasFlag(CompilerOptions.UseRoslyn)) {
preprocessorSymbols.Add("ROSLYN");
} else {
preprocessorSymbols.Add("LEGACY_CSC");
}
return preprocessorSymbols;
}
public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null) public static CompilerResults CompileCSharp(string sourceFileName, CompilerOptions flags = CompilerOptions.UseDebug, string outputFileName = null)
{ {
List<string> sourceFileNames = new List<string> { sourceFileName }; List<string> sourceFileNames = new List<string> { sourceFileName };
@ -165,10 +183,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value))); sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value)));
} }
var preprocessorSymbols = new List<string>(); var preprocessorSymbols = GetPreprocessorSymbols(flags);
if (flags.HasFlag(CompilerOptions.UseDebug)) {
preprocessorSymbols.Add("DEBUG");
}
if (flags.HasFlag(CompilerOptions.UseRoslyn)) { if (flags.HasFlag(CompilerOptions.UseRoslyn)) {
var parseOptions = new CSharpParseOptions(preprocessorSymbols: preprocessorSymbols.ToArray()); var parseOptions = new CSharpParseOptions(preprocessorSymbols: preprocessorSymbols.ToArray());
@ -194,7 +209,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
} }
return results; return results;
} else { } else {
preprocessorSymbols.Add("LEGACY_CSC");
var provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } }); var provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters(); CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library); options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);

4
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -32,8 +32,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DiffLib" Version="1.0.0.55" /> <PackageReference Include="DiffLib" Version="1.0.0.55" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.3.2" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.4.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" /> <PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="NUnit" Version="2.6.3" /> <PackageReference Include="NUnit" Version="2.6.3" />
<PackageReference Include="NUnitTestAdapter" Version="2.0.0" /> <PackageReference Include="NUnitTestAdapter" Version="2.0.0" />
</ItemGroup> </ItemGroup>

4
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -74,7 +74,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void InlineAssignmentTest([ValueSource("noRoslynOptions")] CompilerOptions cscOptions) public void InlineAssignmentTest([ValueSource("defaultOptions")] CompilerOptions cscOptions)
{ {
Run(cscOptions: cscOptions); Run(cscOptions: cscOptions);
} }
@ -226,7 +226,7 @@ namespace ICSharpCode.Decompiler.Tests
var executable = Tester.AssembleIL(ilFile, asmOptions | AssemblerOptions.Library); var executable = Tester.AssembleIL(ilFile, asmOptions | AssemblerOptions.Library);
var decompiled = Tester.DecompileCSharp(executable); var decompiled = Tester.DecompileCSharp(executable);
CodeAssert.FilesAreEqual(csFile, decompiled, cscOptions.HasFlag(CompilerOptions.UseRoslyn) ? null : new[] { "LEGACY_CSC" }); CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());
} }
} }
} }

21
ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs

@ -30,6 +30,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
CallTwice(); CallTwice();
UnsignedShiftRightInstanceField(); UnsignedShiftRightInstanceField();
UnsignedShiftRightStaticProperty(); UnsignedShiftRightStaticProperty();
DivideByBigValue();
} }
static void Test(int a, int b) static void Test(int a, int b)
@ -76,6 +77,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
} }
} }
static ushort shortField;
public static ushort ShortProperty {
get {
Console.WriteLine("In get_ShortProperty");
return shortField;
}
set {
Console.WriteLine("In set_ShortProperty, value={0}", value);
shortField = value;
}
}
public static Dictionary<string, int> GetDict() public static Dictionary<string, int> GetDict()
{ {
Console.WriteLine("In GetDict()"); Console.WriteLine("In GetDict()");
@ -133,5 +147,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
StaticProperty = -15; StaticProperty = -15;
Test(X(), StaticProperty = (int)((uint)StaticProperty >> 2)); Test(X(), StaticProperty = (int)((uint)StaticProperty >> 2));
} }
static void DivideByBigValue()
{
ShortProperty = 5;
// can't use "ShortProperty /= (ushort)(ushort.MaxValue + 3)" because that would be division by 2.
ShortProperty = (ushort)(ShortProperty / (ushort.MaxValue + 3));
}
} }
} }

429
ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il

@ -1,12 +1,12 @@
.assembly extern mscorlib .assembly extern mscorlib
{ {
.publickeytoken = ( b7 7a 5c 56 19 34 e0 89 ) .publickeytoken = ( b7 7a 5c 56 19 34 e0 89 )
.ver 4:0:0:0 .ver 4:0:0:0
} }
.assembly 'StackTypes' .assembly 'StackTypes'
{ {
.ver 0:0:0:0 .ver 0:0:0:0
} }
.module StackTypes.exe .module StackTypes.exe
@ -15,204 +15,227 @@
.class private auto ansi abstract sealed beforefieldinit Program .class private auto ansi abstract sealed beforefieldinit Program
extends [mscorlib]System.Object extends [mscorlib]System.Object
{ {
.method public hidebysig static void Main (string[] args) cil managed .method public hidebysig static void Main (string[] args) cil managed
{ {
.maxstack 8 .maxstack 8
.entrypoint .entrypoint
//call void Program::Int32OrNativeTests() call void Program::InlineAssignByte()
//call void Program::Int32OrNativeTests()
ret
} // end of method Main ret
} // end of method Main
/*
.method public static void Int32OrNativeTests() .method public static void InlineAssignByte()
{ {
ldstr "Int32OrNative(0x7fffffff, false) = {0}" .locals init (
ldc.i4 0x7fffffff int8 local
ldc.i4 0 )
call native int Program::Int32OrNative(int32, bool) ldstr "InlineAssignByte: WriteLine(local = {0})"
box native int ldc.i4 300
call void [mscorlib]System.Console::WriteLine(string, object) dup
br pointless // this pointless branch is a workaround for https://github.com/dotnet/coreclr/issues/14784
ldstr "Int32OrNative(0x7fffffff, true) = {0}" // it doesn't have any effect on ILSpy as TransformAssignment runs after control-flow reconstruction
ldc.i4 0x7fffffff pointless:
ldc.i4 1 // This assignment cannot be turned into a C# inline assignment, because doing so would truncate to 8 bits.
call native int Program::Int32OrNative(int32, bool) stloc.0
box native int box int32
call void [mscorlib]System.Console::WriteLine(string, object) call void [mscorlib]System.Console::WriteLine(string, object)
ldstr "InlineAssignByte: local is {0}"
ldstr "Int32OrNative(-1, false) = {0}" ldloc.0
ldc.i4.m1 box int32
ldc.i4 0 call void [mscorlib]System.Console::WriteLine(string, object)
call native int Program::Int32OrNative(int32, bool) ret
box native int }
call void [mscorlib]System.Console::WriteLine(string, object)
/*
ldstr "Int32OrNative(-1, true) = {0}" .method public static void Int32OrNativeTests()
ldc.i4.m1 {
ldc.i4 1 ldstr "Int32OrNative(0x7fffffff, false) = {0}"
call native int Program::Int32OrNative(int32, bool) ldc.i4 0x7fffffff
box native int ldc.i4 0
call void [mscorlib]System.Console::WriteLine(string, object) call native int Program::Int32OrNative(int32, bool)
box native int
ldstr "Int32OrNativeLoopStyle(0x7fffffff):" call void [mscorlib]System.Console::WriteLine(string, object)
call void [mscorlib]System.Console::WriteLine(string)
ldc.i4 0x7fffffff ldstr "Int32OrNative(0x7fffffff, true) = {0}"
call void Program::Int32OrNativeLoopStyle(int32) ldc.i4 0x7fffffff
ldc.i4 1
ldstr "Int32OrNativeLoopStyle(-1):" call native int Program::Int32OrNative(int32, bool)
call void [mscorlib]System.Console::WriteLine(string) box native int
ldc.i4.m1 call void [mscorlib]System.Console::WriteLine(string, object)
call void Program::Int32OrNativeLoopStyle(int32)
ldstr "Int32OrNative(-1, false) = {0}"
ldstr "Int32OrNativeDeadCode(0x7fffffff) = {0}" ldc.i4.m1
ldc.i4 0x7fffffff ldc.i4 0
call native int Program::Int32OrNativeDeadCode(int32) call native int Program::Int32OrNative(int32, bool)
box native int box native int
call void [mscorlib]System.Console::WriteLine(string, object) call void [mscorlib]System.Console::WriteLine(string, object)
ldstr "Int32OrNativeDeadCode(-1) = {0}" ldstr "Int32OrNative(-1, true) = {0}"
ldc.i4.m1 ldc.i4.m1
call native int Program::Int32OrNativeDeadCode(int32) ldc.i4 1
box native int call native int Program::Int32OrNative(int32, bool)
call void [mscorlib]System.Console::WriteLine(string, object) box native int
call void [mscorlib]System.Console::WriteLine(string, object)
ldc.i4 0x7fffffff
call void Program::RunInt32OrNativeMultiUse(int32) ldstr "Int32OrNativeLoopStyle(0x7fffffff):"
ldc.i4.m1 call void [mscorlib]System.Console::WriteLine(string)
call void Program::RunInt32OrNativeMultiUse(int32) ldc.i4 0x7fffffff
call void Program::Int32OrNativeLoopStyle(int32)
ret
} ldstr "Int32OrNativeLoopStyle(-1):"
.method public static native int Int32OrNative(int32 val, bool use_native) call void [mscorlib]System.Console::WriteLine(string)
{ ldc.i4.m1
ldarg.1 call void Program::Int32OrNativeLoopStyle(int32)
brtrue use_native_int
use_i4: ldstr "Int32OrNativeDeadCode(0x7fffffff) = {0}"
ldarg.0 ldc.i4 0x7fffffff
br after_if call native int Program::Int32OrNativeDeadCode(int32)
after_if: box native int
ldc.i4.1 call void [mscorlib]System.Console::WriteLine(string, object)
add
ret ldstr "Int32OrNativeDeadCode(-1) = {0}"
use_native_int: ldc.i4.m1
ldarg.0 call native int Program::Int32OrNativeDeadCode(int32)
conv.u box native int
br after_if call void [mscorlib]System.Console::WriteLine(string, object)
}
ldc.i4 0x7fffffff
.method public static void Int32OrNativeLoopStyle(int32 val) call void Program::RunInt32OrNativeMultiUse(int32)
{ ldc.i4.m1
.locals init ( call void Program::RunInt32OrNativeMultiUse(int32)
int32 i
) ret
ldarg.0 }
loop: .method public static native int Int32OrNative(int32 val, bool use_native)
ldc.i4.1 {
add ldarg.1
call void Program::Print(native int) brtrue use_native_int
ldloc.0 use_i4:
brtrue end ldarg.0
br after_if
ldc.i4.1 after_if:
stloc.0 ldc.i4.1
ldarg.0 add
conv.u ret
br loop use_native_int:
end: ldarg.0
ret conv.u
} br after_if
}
.method public static native int Int32OrNativeDeadCode(int32 val)
{ .method public static void Int32OrNativeLoopStyle(int32 val)
use_i4: {
ldarg.0 .locals init (
br after_if int32 i
after_if: )
ldc.i4.1 ldarg.0
add loop:
ret ldc.i4.1
use_native_int: // dead code add
ldarg.0 call void Program::Print(native int)
conv.u ldloc.0
br after_if brtrue end
}
ldc.i4.1
.method public static void RunInt32OrNativeMultiUse(int32 val) stloc.0
{ ldarg.0
ldstr "RunInt32OrNativeMultiUse({0}, push_i: false, use2: false) = {1}" conv.u
ldarg val br loop
box int32 end:
ldarg val ret
ldc.i4 0 // push_i }
ldc.i4 0 // use2
call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) .method public static native int Int32OrNativeDeadCode(int32 val)
box native int {
call void [mscorlib]System.Console::WriteLine(string, object, object) use_i4:
ldarg.0
ldstr "RunInt32OrNativeMultiUse({0}, push_i: false, use2: true) = {1}" br after_if
ldarg val after_if:
box int32 ldc.i4.1
ldarg val add
ldc.i4 0 // push_i ret
ldc.i4 1 // use2 use_native_int: // dead code
call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) ldarg.0
box native int conv.u
call void [mscorlib]System.Console::WriteLine(string, object, object) br after_if
}
ldstr "RunInt32OrNativeMultiUse({0}, push_i: true, use2: false) = {1}"
ldarg val .method public static void RunInt32OrNativeMultiUse(int32 val)
box int32 {
ldarg val ldstr "RunInt32OrNativeMultiUse({0}, push_i: false, use2: false) = {1}"
ldc.i4 1 // push_i ldarg val
ldc.i4 0 // use2 box int32
call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) ldarg val
box native int ldc.i4 0 // push_i
call void [mscorlib]System.Console::WriteLine(string, object, object) ldc.i4 0 // use2
call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2)
ldstr "RunInt32OrNativeMultiUse({0}, push_i: true, use2: true) = {1}" box native int
ldarg val call void [mscorlib]System.Console::WriteLine(string, object, object)
box int32
ldarg val ldstr "RunInt32OrNativeMultiUse({0}, push_i: false, use2: true) = {1}"
ldc.i4 1 // push_i ldarg val
ldc.i4 1 // use2 box int32
call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) ldarg val
box native int ldc.i4 0 // push_i
call void [mscorlib]System.Console::WriteLine(string, object, object) ldc.i4 1 // use2
ret call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2)
} box native int
call void [mscorlib]System.Console::WriteLine(string, object, object)
.method public static native int Int32OrNativeMultiUse(int32 val, bool push_i, bool use2)
{ ldstr "RunInt32OrNativeMultiUse({0}, push_i: true, use2: false) = {1}"
ldarg.1 ldarg val
brtrue push_i box int32
br push_i4 ldarg val
push_i4: ldc.i4 1 // push_i
ldarg.0 ldc.i4 0 // use2
ldarg.2 call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2)
brtrue use2 box native int
br use1 call void [mscorlib]System.Console::WriteLine(string, object, object)
push_i:
ldarg.0 ldstr "RunInt32OrNativeMultiUse({0}, push_i: true, use2: true) = {1}"
conv.u ldarg val
br use1 box int32
use1: ldarg val
ldc.i4.1 ldc.i4 1 // push_i
add ldc.i4 1 // use2
ret call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2)
use2: box native int
ldc.i4.2 call void [mscorlib]System.Console::WriteLine(string, object, object)
add ret
ret }
}
*/ .method public static native int Int32OrNativeMultiUse(int32 val, bool push_i, bool use2)
{
.method public static void Print(native int val) ldarg.1
{ brtrue push_i
ldarg.0 br push_i4
box native int push_i4:
call void [mscorlib]System.Console::WriteLine(object) ldarg.0
ret ldarg.2
} brtrue use2
br use1
push_i:
ldarg.0
conv.u
br use1
use1:
ldc.i4.1
add
ret
use2:
ldc.i4.2
add
ret
}
*/
.method public static void Print(native int val)
{
ldarg.0
box native int
call void [mscorlib]System.Console::WriteLine(object)
ret
}
} }

236
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
@ -31,6 +32,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Four = 4 Four = 4
} }
public enum ShortEnum : short
{
None = 0,
One = 1,
Two = 2,
Four = 4
}
private struct StructContainer private struct StructContainer
{ {
public bool HasIndex; public bool HasIndex;
@ -40,12 +49,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public class MutableClass public class MutableClass
{ {
public int Field; public int Field;
public short ShortField;
public int Property { public int Property {
get; get;
set; set;
} }
public byte ByteProperty {
get;
set;
}
public uint this[string name] { public uint this[string name] {
get { get {
return 0u; return 0u;
@ -64,13 +79,22 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private int[] array1; private int[] array1;
private StructContainer field1; private StructContainer field1;
private MyEnum enumField; private MyEnum enumField;
private Dictionary<ushort, ushort> ushortDict = new Dictionary<ushort, ushort>();
private ushort ushortField;
private ShortEnum shortEnumField;
public static int StaticField; public static int StaticField;
public static short StaticShortField;
public static int StaticProperty { public static int StaticProperty {
get; get;
set; set;
} }
public static ShortEnum StaticShortProperty {
get;
set;
}
private MutableClass M() private MutableClass M()
{ {
return new MutableClass(); return new MutableClass();
@ -200,6 +224,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void NestedField() public void NestedField()
{ {
if (this.field1.HasIndex) { if (this.field1.HasIndex) {
Console.WriteLine(this.field1.Field *= 2);
this.field1.Field++;
Console.WriteLine(this.field1.Field++); Console.WriteLine(this.field1.Field++);
} }
} }
@ -208,6 +234,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
this.enumField |= MyEnum.Two; this.enumField |= MyEnum.Two;
this.enumField &= ~MyEnum.Four; this.enumField &= ~MyEnum.Four;
this.enumField += 2;
this.enumField -= 3;
}
public void ShortEnumTest()
{
this.shortEnumField |= ShortEnum.Two;
this.shortEnumField &= ShortEnum.Four;
this.shortEnumField += 2;
this.shortEnumField -= 3;
} }
public int PreIncrementInAddition(int i, int j) public int PreIncrementInAddition(int i, int j)
@ -230,51 +266,146 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
array[pos]++; array[pos]++;
} }
public void DoubleArrayElement(int[] array, int pos)
{
array[pos] *= 2;
}
public int DoubleArrayElementAndReturn(int[] array, int pos)
{
return array[pos] *= 2;
}
public int PreIncrementArrayElementShort(short[] array, int pos)
{
return --array[pos];
}
public int PostIncrementArrayElementShort(short[] array, int pos)
{
return array[pos]++;
}
public void IncrementArrayElementShort(short[] array, int pos)
{
array[pos]++;
}
public void DoubleArrayElementShort(short[] array, int pos)
{
array[pos] *= 2;
}
public short DoubleArrayElementShortAndReturn(short[] array, int pos)
{
return array[pos] *= 2;
}
public int PreIncrementInstanceField() public int PreIncrementInstanceField()
{ {
return ++this.M().Field; return ++this.M().Field;
} }
//public int PostIncrementInstanceField() public int PostIncrementInstanceField()
//{ {
// return this.M().Field++; return this.M().Field++;
//} }
public void IncrementInstanceField() public void IncrementInstanceField()
{ {
this.M().Field++; this.M().Field++;
} }
public void DoubleInstanceField()
{
this.M().Field *= 2;
}
public int DoubleInstanceFieldAndReturn()
{
return this.M().Field *= 2;
}
public int PreIncrementInstanceField2(MutableClass m) public int PreIncrementInstanceField2(MutableClass m)
{ {
return ++m.Field; return ++m.Field;
} }
//public int PostIncrementInstanceField2(MutableClass m) public int PostIncrementInstanceField2(MutableClass m)
//{ {
// return m.Field++; return m.Field++;
//} }
public void IncrementInstanceField2(MutableClass m) public void IncrementInstanceField2(MutableClass m)
{ {
m.Field++; m.Field++;
} }
public int PreIncrementInstanceFieldShort()
{
return ++this.M().ShortField;
}
public int PostIncrementInstanceFieldShort()
{
return this.M().ShortField++;
}
public void IncrementInstanceFieldShort()
{
this.M().ShortField++;
}
public int PreIncrementInstanceProperty() public int PreIncrementInstanceProperty()
{ {
return ++this.M().Property; return ++this.M().Property;
} }
//public int PostIncrementInstanceProperty() public int PostIncrementInstanceProperty()
//{ {
// return this.M().Property++; return this.M().Property++;
//} }
public void IncrementInstanceProperty() public void IncrementInstanceProperty()
{ {
this.M().Property++; this.M().Property++;
} }
public void DoubleInstanceProperty()
{
this.M().Property *= 2;
}
public int DoubleInstancePropertyAndReturn()
{
return this.M().Property *= 2;
}
public int PreIncrementInstancePropertyByte()
{
return ++this.M().ByteProperty;
}
public int PostIncrementInstancePropertyByte()
{
return this.M().ByteProperty++;
}
public void IncrementInstancePropertyByte()
{
this.M().ByteProperty++;
}
public void DoubleInstancePropertyByte()
{
this.M().ByteProperty *= 2;
}
public int DoubleInstancePropertyByteAndReturn()
{
return this.M().ByteProperty *= 2;
}
public int PreIncrementStaticField() public int PreIncrementStaticField()
{ {
return ++CompoundAssignmentTest.StaticField; return ++CompoundAssignmentTest.StaticField;
@ -290,21 +421,81 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
CompoundAssignmentTest.StaticField++; CompoundAssignmentTest.StaticField++;
} }
public void DoubleStaticField()
{
CompoundAssignmentTest.StaticField *= 2;
}
public int DoubleStaticFieldAndReturn()
{
return CompoundAssignmentTest.StaticField *= 2;
}
public int PreIncrementStaticFieldShort()
{
return ++CompoundAssignmentTest.StaticShortField;
}
public int PostIncrementStaticFieldShort()
{
return CompoundAssignmentTest.StaticShortField++;
}
public void IncrementStaticFieldShort()
{
CompoundAssignmentTest.StaticShortField++;
}
public void DoubleStaticFieldShort()
{
CompoundAssignmentTest.StaticShortField *= 2;
}
public short DoubleStaticFieldAndReturnShort()
{
return CompoundAssignmentTest.StaticShortField *= 2;
}
public int PreIncrementStaticProperty() public int PreIncrementStaticProperty()
{ {
return ++CompoundAssignmentTest.StaticProperty; return ++CompoundAssignmentTest.StaticProperty;
} }
//public int PostIncrementStaticProperty() public int PostIncrementStaticProperty()
//{ {
// return CompoundAssignmentTest.StaticProperty++; return CompoundAssignmentTest.StaticProperty++;
//} }
public void IncrementStaticProperty() public void IncrementStaticProperty()
{ {
CompoundAssignmentTest.StaticProperty++; CompoundAssignmentTest.StaticProperty++;
} }
public void DoubleStaticProperty()
{
CompoundAssignmentTest.StaticProperty *= 2;
}
public int DoubleStaticPropertyAndReturn()
{
return CompoundAssignmentTest.StaticProperty *= 2;
}
public ShortEnum PreIncrementStaticPropertyShort()
{
return ++CompoundAssignmentTest.StaticShortProperty;
}
public ShortEnum PostIncrementStaticPropertyShort()
{
return CompoundAssignmentTest.StaticShortProperty++;
}
public void IncrementStaticPropertyShort()
{
CompoundAssignmentTest.StaticShortProperty++;
}
private static Item GetItem(object obj) private static Item GetItem(object obj)
{ {
return null; return null;
@ -315,5 +506,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Item item = CompoundAssignmentTest.GetItem(null); Item item = CompoundAssignmentTest.GetItem(null);
item.Self = item; item.Self = item;
} }
private void Issue954(ref MyEnum a, MyEnum b)
{
// cannot decompile to: "a %= b;", because the % operator does not apply to enums
a = (MyEnum)((int)a % (int)b);
// same with enum field:
this.enumField = (MyEnum)((int)this.enumField % (int)b);
}
private void Issue588(ushort val)
{
this.ushortDict.Add(this.ushortField++, val);
}
} }
} }

1008
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il

File diff suppressed because it is too large Load Diff

810
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il

@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.18020 // Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0 .ver 4:0:0:0
} }
.assembly d4bhqxbe .assembly '0ffxad1m'
{ {
.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.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 .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 @@
.hash algorithm 0x00008004 .hash algorithm 0x00008004
.ver 0:0:0:0 .ver 0:0:0:0
} }
.module d4bhqxbe.dll .module '0ffxad1m.dll'
// MVID: {B884BD61-6FE3-4893-B161-02EE675C0DF0} // MVID: {C53B3CFA-3FF4-4724-8DBE-8B180FA612BA}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000 .imagebase 0x10000000
.file alignment 0x00000200 .file alignment 0x00000200
.stackreserve 0x00100000 .stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI .subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY .corflags 0x00000001 // ILONLY
// Image base: 0x003A0000 // Image base: 0x028A0000
// =============== CLASS MEMBERS DECLARATION =================== // =============== CLASS MEMBERS DECLARATION ===================
@ -47,6 +47,16 @@
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum Four = int32(0x00000004) .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum Four = int32(0x00000004)
} // end of class MyEnum } // end of class MyEnum
.class auto ansi sealed nested public ShortEnum
extends [mscorlib]System.Enum
{
.field public specialname rtspecialname int16 value__
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum None = int16(0x0000)
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum One = int16(0x0001)
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum Two = int16(0x0002)
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum Four = int16(0x0004)
} // end of class ShortEnum
.class sequential ansi sealed nested private beforefieldinit StructContainer .class sequential ansi sealed nested private beforefieldinit StructContainer
extends [mscorlib]System.ValueType extends [mscorlib]System.ValueType
{ {
@ -59,8 +69,11 @@
{ {
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) // ...Item.. .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) // ...Item..
.field public int32 Field .field public int32 Field
.field public int16 ShortField
.field private int32 '<Property>k__BackingField' .field private int32 '<Property>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field private uint8 '<ByteProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname .method public hidebysig specialname
instance int32 get_Property() cil managed instance int32 get_Property() cil managed
{ {
@ -84,6 +97,29 @@
IL_0007: ret IL_0007: ret
} // end of method MutableClass::set_Property } // end of method MutableClass::set_Property
.method public hidebysig specialname
instance uint8 get_ByteProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::'<ByteProperty>k__BackingField'
IL_0006: ret
} // end of method MutableClass::get_ByteProperty
.method public hidebysig specialname
instance void set_ByteProperty(uint8 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::'<ByteProperty>k__BackingField'
IL_0007: ret
} // end of method MutableClass::set_ByteProperty
.method public hidebysig specialname .method public hidebysig specialname
instance uint32 get_Item(string name) cil managed instance uint32 get_Item(string name) cil managed
{ {
@ -117,6 +153,11 @@
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property() .get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32) .set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32)
} // end of property MutableClass::Property } // end of property MutableClass::Property
.property instance uint8 ByteProperty()
{
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
.get instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
} // end of property MutableClass::ByteProperty
.property instance uint32 Item(string) .property instance uint32 Item(string)
{ {
.get instance uint32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Item(string) .get instance uint32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Item(string)
@ -145,9 +186,15 @@
.field private int32[] array1 .field private int32[] array1
.field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1
.field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField
.field private class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16> ushortDict
.field private uint16 ushortField
.field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum shortEnumField
.field public static int32 StaticField .field public static int32 StaticField
.field public static int16 StaticShortField
.field private static int32 '<StaticProperty>k__BackingField' .field private static int32 '<StaticProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field private static valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum '<StaticShortProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname static .method public hidebysig specialname static
int32 get_StaticProperty() cil managed int32 get_StaticProperty() cil managed
{ {
@ -169,6 +216,28 @@
IL_0006: ret IL_0006: ret
} // end of method CompoundAssignmentTest::set_StaticProperty } // end of method CompoundAssignmentTest::set_StaticProperty
.method public hidebysig specialname static
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum
get_StaticShortProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldsfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::'<StaticShortProperty>k__BackingField'
IL_0005: ret
} // end of method CompoundAssignmentTest::get_StaticShortProperty
.method public hidebysig specialname static
void set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: stsfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::'<StaticShortProperty>k__BackingField'
IL_0006: ret
} // end of method CompoundAssignmentTest::set_StaticShortProperty
.method private hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass .method private hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass
M() cil managed M() cil managed
{ {
@ -568,32 +637,51 @@
.method public hidebysig instance void .method public hidebysig instance void
NestedField() cil managed NestedField() cil managed
{ {
// Code size 41 (0x29) // Code size 87 (0x57)
.maxstack 3 .maxstack 3
.locals init (int32 V_0) .locals init (int32 V_0,
int32 V_1)
IL_0000: ldarg.0 IL_0000: ldarg.0
IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1
IL_0006: ldfld bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::HasIndex IL_0006: ldfld bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::HasIndex
IL_000b: brfalse.s IL_0028 IL_000b: brfalse.s IL_0056
IL_000d: ldarg.0 IL_000d: ldarg.0
IL_000e: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 IL_000e: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1
IL_0013: dup IL_0013: dup
IL_0014: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field IL_0014: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_0019: dup IL_0019: ldc.i4.2
IL_001a: stloc.0 IL_001a: mul
IL_001b: ldc.i4.1 IL_001b: dup
IL_001c: add IL_001c: stloc.0
IL_001d: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field IL_001d: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_0022: ldloc.0 IL_0022: ldloc.0
IL_0023: call void [mscorlib]System.Console::WriteLine(int32) IL_0023: call void [mscorlib]System.Console::WriteLine(int32)
IL_0028: ret IL_0028: ldarg.0
IL_0029: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1
IL_002e: dup
IL_002f: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_0034: ldc.i4.1
IL_0035: add
IL_0036: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_003b: ldarg.0
IL_003c: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1
IL_0041: dup
IL_0042: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_0047: dup
IL_0048: stloc.1
IL_0049: ldc.i4.1
IL_004a: add
IL_004b: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_0050: ldloc.1
IL_0051: call void [mscorlib]System.Console::WriteLine(int32)
IL_0056: ret
} // end of method CompoundAssignmentTest::NestedField } // end of method CompoundAssignmentTest::NestedField
.method public hidebysig instance void .method public hidebysig instance void
Enum() cil managed Enum() cil managed
{ {
// Code size 30 (0x1e) // Code size 58 (0x3a)
.maxstack 8 .maxstack 8
IL_0000: ldarg.0 IL_0000: ldarg.0
IL_0001: dup IL_0001: dup
@ -607,9 +695,57 @@
IL_0015: ldc.i4.s -5 IL_0015: ldc.i4.s -5
IL_0017: and IL_0017: and
IL_0018: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField IL_0018: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_001d: ret IL_001d: ldarg.0
IL_001e: dup
IL_001f: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_0024: ldc.i4.2
IL_0025: add
IL_0026: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_002b: ldarg.0
IL_002c: dup
IL_002d: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_0032: ldc.i4.3
IL_0033: sub
IL_0034: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_0039: ret
} // end of method CompoundAssignmentTest::Enum } // end of method CompoundAssignmentTest::Enum
.method public hidebysig instance void
ShortEnumTest() cil managed
{
// Code size 61 (0x3d)
.maxstack 8
IL_0000: ldarg.0
IL_0001: dup
IL_0002: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_0007: ldc.i4.2
IL_0008: or
IL_0009: conv.i2
IL_000a: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_000f: ldarg.0
IL_0010: dup
IL_0011: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_0016: ldc.i4.4
IL_0017: and
IL_0018: conv.i2
IL_0019: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_001e: ldarg.0
IL_001f: dup
IL_0020: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_0025: ldc.i4.2
IL_0026: add
IL_0027: conv.i2
IL_0028: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_002d: ldarg.0
IL_002e: dup
IL_002f: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_0034: ldc.i4.3
IL_0035: sub
IL_0036: conv.i2
IL_0037: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_003c: ret
} // end of method CompoundAssignmentTest::ShortEnumTest
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementInAddition(int32 i, PreIncrementInAddition(int32 i,
int32 j) cil managed int32 j) cil managed
@ -685,6 +821,146 @@
IL_0014: ret IL_0014: ret
} // end of method CompoundAssignmentTest::IncrementArrayElement } // end of method CompoundAssignmentTest::IncrementArrayElement
.method public hidebysig instance void
DoubleArrayElement(int32[] 'array',
int32 pos) cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int32
IL_0007: dup
IL_0008: ldobj [mscorlib]System.Int32
IL_000d: ldc.i4.2
IL_000e: mul
IL_000f: stobj [mscorlib]System.Int32
IL_0014: ret
} // end of method CompoundAssignmentTest::DoubleArrayElement
.method public hidebysig instance int32
DoubleArrayElementAndReturn(int32[] 'array',
int32 pos) cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int32
IL_0007: dup
IL_0008: ldobj [mscorlib]System.Int32
IL_000d: ldc.i4.2
IL_000e: mul
IL_000f: dup
IL_0010: stloc.0
IL_0011: stobj [mscorlib]System.Int32
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::DoubleArrayElementAndReturn
.method public hidebysig instance int32
PreIncrementArrayElementShort(int16[] 'array',
int32 pos) cil managed
{
// Code size 25 (0x19)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldobj [mscorlib]System.Int16
IL_000d: ldc.i4.1
IL_000e: sub
IL_000f: conv.i2
IL_0010: dup
IL_0011: stloc.0
IL_0012: stobj [mscorlib]System.Int16
IL_0017: ldloc.0
IL_0018: ret
} // end of method CompoundAssignmentTest::PreIncrementArrayElementShort
.method public hidebysig instance int32
PostIncrementArrayElementShort(int16[] 'array',
int32 pos) cil managed
{
// Code size 25 (0x19)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldobj [mscorlib]System.Int16
IL_000d: dup
IL_000e: stloc.0
IL_000f: ldc.i4.1
IL_0010: add
IL_0011: conv.i2
IL_0012: stobj [mscorlib]System.Int16
IL_0017: ldloc.0
IL_0018: ret
} // end of method CompoundAssignmentTest::PostIncrementArrayElementShort
.method public hidebysig instance void
IncrementArrayElementShort(int16[] 'array',
int32 pos) cil managed
{
// Code size 22 (0x16)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldobj [mscorlib]System.Int16
IL_000d: ldc.i4.1
IL_000e: add
IL_000f: conv.i2
IL_0010: stobj [mscorlib]System.Int16
IL_0015: ret
} // end of method CompoundAssignmentTest::IncrementArrayElementShort
.method public hidebysig instance void
DoubleArrayElementShort(int16[] 'array',
int32 pos) cil managed
{
// Code size 22 (0x16)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldobj [mscorlib]System.Int16
IL_000d: ldc.i4.2
IL_000e: mul
IL_000f: conv.i2
IL_0010: stobj [mscorlib]System.Int16
IL_0015: ret
} // end of method CompoundAssignmentTest::DoubleArrayElementShort
.method public hidebysig instance int16
DoubleArrayElementShortAndReturn(int16[] 'array',
int32 pos) cil managed
{
// Code size 25 (0x19)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldobj [mscorlib]System.Int16
IL_000d: ldc.i4.2
IL_000e: mul
IL_000f: conv.i2
IL_0010: dup
IL_0011: stloc.0
IL_0012: stobj [mscorlib]System.Int16
IL_0017: ldloc.0
IL_0018: ret
} // end of method CompoundAssignmentTest::DoubleArrayElementShortAndReturn
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementInstanceField() cil managed PreIncrementInstanceField() cil managed
{ {
@ -704,6 +980,25 @@
IL_0016: ret IL_0016: ret
} // end of method CompoundAssignmentTest::PreIncrementInstanceField } // end of method CompoundAssignmentTest::PreIncrementInstanceField
.method public hidebysig instance int32
PostIncrementInstanceField() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_000c: dup
IL_000d: stloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0015: ldloc.0
IL_0016: ret
} // end of method CompoundAssignmentTest::PostIncrementInstanceField
.method public hidebysig instance void .method public hidebysig instance void
IncrementInstanceField() cil managed IncrementInstanceField() cil managed
{ {
@ -719,6 +1014,40 @@
IL_0013: ret IL_0013: ret
} // end of method CompoundAssignmentTest::IncrementInstanceField } // end of method CompoundAssignmentTest::IncrementInstanceField
.method public hidebysig instance void
DoubleInstanceField() cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0013: ret
} // end of method CompoundAssignmentTest::DoubleInstanceField
.method public hidebysig instance int32
DoubleInstanceFieldAndReturn() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: dup
IL_000f: stloc.0
IL_0010: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0015: ldloc.0
IL_0016: ret
} // end of method CompoundAssignmentTest::DoubleInstanceFieldAndReturn
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed PreIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed
{ {
@ -737,6 +1066,24 @@
IL_0011: ret IL_0011: ret
} // end of method CompoundAssignmentTest::PreIncrementInstanceField2 } // end of method CompoundAssignmentTest::PreIncrementInstanceField2
.method public hidebysig instance int32
PostIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed
{
// Code size 18 (0x12)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.1
IL_0001: dup
IL_0002: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0007: dup
IL_0008: stloc.0
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0010: ldloc.0
IL_0011: ret
} // end of method CompoundAssignmentTest::PostIncrementInstanceField2
.method public hidebysig instance void .method public hidebysig instance void
IncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed IncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed
{ {
@ -751,6 +1098,62 @@
IL_000e: ret IL_000e: ret
} // end of method CompoundAssignmentTest::IncrementInstanceField2 } // end of method CompoundAssignmentTest::IncrementInstanceField2
.method public hidebysig instance int32
PreIncrementInstanceFieldShort() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: conv.i2
IL_000f: dup
IL_0010: stloc.0
IL_0011: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::PreIncrementInstanceFieldShort
.method public hidebysig instance int32
PostIncrementInstanceFieldShort() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_000c: dup
IL_000d: stloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: conv.i2
IL_0011: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::PostIncrementInstanceFieldShort
.method public hidebysig instance void
IncrementInstanceFieldShort() cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: conv.i2
IL_000f: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_0014: ret
} // end of method CompoundAssignmentTest::IncrementInstanceFieldShort
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementInstanceProperty() cil managed PreIncrementInstanceProperty() cil managed
{ {
@ -770,6 +1173,25 @@
IL_0016: ret IL_0016: ret
} // end of method CompoundAssignmentTest::PreIncrementInstanceProperty } // end of method CompoundAssignmentTest::PreIncrementInstanceProperty
.method public hidebysig instance int32
PostIncrementInstanceProperty() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property()
IL_000c: dup
IL_000d: stloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32)
IL_0015: ldloc.0
IL_0016: ret
} // end of method CompoundAssignmentTest::PostIncrementInstanceProperty
.method public hidebysig instance void .method public hidebysig instance void
IncrementInstanceProperty() cil managed IncrementInstanceProperty() cil managed
{ {
@ -785,6 +1207,132 @@
IL_0013: ret IL_0013: ret
} // end of method CompoundAssignmentTest::IncrementInstanceProperty } // end of method CompoundAssignmentTest::IncrementInstanceProperty
.method public hidebysig instance void
DoubleInstanceProperty() cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property()
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32)
IL_0013: ret
} // end of method CompoundAssignmentTest::DoubleInstanceProperty
.method public hidebysig instance int32
DoubleInstancePropertyAndReturn() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property()
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: dup
IL_000f: stloc.0
IL_0010: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32)
IL_0015: ldloc.0
IL_0016: ret
} // end of method CompoundAssignmentTest::DoubleInstancePropertyAndReturn
.method public hidebysig instance int32
PreIncrementInstancePropertyByte() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (uint8 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: conv.u1
IL_000f: dup
IL_0010: stloc.0
IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::PreIncrementInstancePropertyByte
.method public hidebysig instance int32
PostIncrementInstancePropertyByte() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (uint8 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: dup
IL_000d: stloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: conv.u1
IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::PostIncrementInstancePropertyByte
.method public hidebysig instance void
IncrementInstancePropertyByte() cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: conv.u1
IL_000f: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0014: ret
} // end of method CompoundAssignmentTest::IncrementInstancePropertyByte
.method public hidebysig instance void
DoubleInstancePropertyByte() cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: conv.u1
IL_000f: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0014: ret
} // end of method CompoundAssignmentTest::DoubleInstancePropertyByte
.method public hidebysig instance int32
DoubleInstancePropertyByteAndReturn() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (uint8 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: conv.u1
IL_000f: dup
IL_0010: stloc.0
IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::DoubleInstancePropertyByteAndReturn
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementStaticField() cil managed PreIncrementStaticField() cil managed
{ {
@ -823,6 +1371,99 @@
IL_000c: ret IL_000c: ret
} // end of method CompoundAssignmentTest::IncrementStaticField } // end of method CompoundAssignmentTest::IncrementStaticField
.method public hidebysig instance void
DoubleStaticField() cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField
IL_000c: ret
} // end of method CompoundAssignmentTest::DoubleStaticField
.method public hidebysig instance int32
DoubleStaticFieldAndReturn() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: dup
IL_0008: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField
IL_000d: ret
} // end of method CompoundAssignmentTest::DoubleStaticFieldAndReturn
.method public hidebysig instance int32
PreIncrementStaticFieldShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: conv.i2
IL_0008: dup
IL_0009: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000e: ret
} // end of method CompoundAssignmentTest::PreIncrementStaticFieldShort
.method public hidebysig instance int32
PostIncrementStaticFieldShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: dup
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: conv.i2
IL_0009: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000e: ret
} // end of method CompoundAssignmentTest::PostIncrementStaticFieldShort
.method public hidebysig instance void
IncrementStaticFieldShort() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: conv.i2
IL_0008: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000d: ret
} // end of method CompoundAssignmentTest::IncrementStaticFieldShort
.method public hidebysig instance void
DoubleStaticFieldShort() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: conv.i2
IL_0008: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000d: ret
} // end of method CompoundAssignmentTest::DoubleStaticFieldShort
.method public hidebysig instance int16
DoubleStaticFieldAndReturnShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: conv.i2
IL_0008: dup
IL_0009: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000e: ret
} // end of method CompoundAssignmentTest::DoubleStaticFieldAndReturnShort
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementStaticProperty() cil managed PreIncrementStaticProperty() cil managed
{ {
@ -836,6 +1477,19 @@
IL_000d: ret IL_000d: ret
} // end of method CompoundAssignmentTest::PreIncrementStaticProperty } // end of method CompoundAssignmentTest::PreIncrementStaticProperty
.method public hidebysig instance int32
PostIncrementStaticProperty() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty()
IL_0005: dup
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32)
IL_000d: ret
} // end of method CompoundAssignmentTest::PostIncrementStaticProperty
.method public hidebysig instance void .method public hidebysig instance void
IncrementStaticProperty() cil managed IncrementStaticProperty() cil managed
{ {
@ -848,6 +1502,72 @@
IL_000c: ret IL_000c: ret
} // end of method CompoundAssignmentTest::IncrementStaticProperty } // end of method CompoundAssignmentTest::IncrementStaticProperty
.method public hidebysig instance void
DoubleStaticProperty() cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty()
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32)
IL_000c: ret
} // end of method CompoundAssignmentTest::DoubleStaticProperty
.method public hidebysig instance int32
DoubleStaticPropertyAndReturn() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty()
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: dup
IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32)
IL_000d: ret
} // end of method CompoundAssignmentTest::DoubleStaticPropertyAndReturn
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum
PreIncrementStaticPropertyShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty()
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: conv.i2
IL_0008: dup
IL_0009: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum)
IL_000e: ret
} // end of method CompoundAssignmentTest::PreIncrementStaticPropertyShort
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum
PostIncrementStaticPropertyShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty()
IL_0005: dup
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: conv.i2
IL_0009: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum)
IL_000e: ret
} // end of method CompoundAssignmentTest::PostIncrementStaticPropertyShort
.method public hidebysig instance void
IncrementStaticPropertyShort() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty()
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: conv.i2
IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum)
IL_000d: ret
} // end of method CompoundAssignmentTest::IncrementStaticPropertyShort
.method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/Item .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/Item
GetItem(object obj) cil managed GetItem(object obj) cil managed
{ {
@ -871,14 +1591,62 @@
IL_000e: ret IL_000e: ret
} // end of method CompoundAssignmentTest::Issue882 } // end of method CompoundAssignmentTest::Issue882
.method private hidebysig instance void
Issue954(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum& a,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum b) cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.1
IL_0002: ldind.i4
IL_0003: ldarg.2
IL_0004: rem
IL_0005: stind.i4
IL_0006: ldarg.0
IL_0007: ldarg.0
IL_0008: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_000d: ldarg.2
IL_000e: rem
IL_000f: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_0014: ret
} // end of method CompoundAssignmentTest::Issue954
.method private hidebysig instance void
Issue588(uint16 val) cil managed
{
// Code size 31 (0x1f)
.maxstack 4
.locals init (uint16 V_0)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16> ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortDict
IL_0006: ldarg.0
IL_0007: dup
IL_0008: ldfld uint16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortField
IL_000d: dup
IL_000e: stloc.0
IL_000f: ldc.i4.1
IL_0010: add
IL_0011: conv.u2
IL_0012: stfld uint16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortField
IL_0017: ldloc.0
IL_0018: ldarg.1
IL_0019: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16>::Add(!0,
!1)
IL_001e: ret
} // end of method CompoundAssignmentTest::Issue588
.method public hidebysig specialname rtspecialname .method public hidebysig specialname rtspecialname
instance void .ctor() cil managed instance void .ctor() cil managed
{ {
// Code size 7 (0x7) // Code size 18 (0x12)
.maxstack 8 .maxstack 8
IL_0000: ldarg.0 IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16>::.ctor()
IL_0006: ret IL_0006: stfld class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16> ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortDict
IL_000b: ldarg.0
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: ret
} // end of method CompoundAssignmentTest::.ctor } // end of method CompoundAssignmentTest::.ctor
.property int32 StaticProperty() .property int32 StaticProperty()
@ -886,6 +1654,12 @@
.get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() .get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty()
.set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) .set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32)
} // end of property CompoundAssignmentTest::StaticProperty } // end of property CompoundAssignmentTest::StaticProperty
.property valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum
StaticShortProperty()
{
.get valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty()
.set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum)
} // end of property CompoundAssignmentTest::StaticShortProperty
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest

806
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il

@ -1,5 +1,5 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.18020 // Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
@ -25,14 +25,14 @@
.ver 0:0:0:0 .ver 0:0:0:0
} }
.module CompoundAssignmentTest.dll .module CompoundAssignmentTest.dll
// MVID: {6E5749EE-F4C5-4B86-96FC-F4A665551BA6} // MVID: {EE880025-0C8C-414F-BD89-E5DB86D9B5FA}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000 .imagebase 0x10000000
.file alignment 0x00000200 .file alignment 0x00000200
.stackreserve 0x00100000 .stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI .subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY .corflags 0x00000001 // ILONLY
// Image base: 0x028A0000 // Image base: 0x016C0000
// =============== CLASS MEMBERS DECLARATION =================== // =============== CLASS MEMBERS DECLARATION ===================
@ -51,6 +51,16 @@
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum Four = int32(0x00000004) .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum Four = int32(0x00000004)
} // end of class MyEnum } // end of class MyEnum
.class auto ansi sealed nested public ShortEnum
extends [mscorlib]System.Enum
{
.field public specialname rtspecialname int16 value__
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum None = int16(0x0000)
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum One = int16(0x0001)
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum Two = int16(0x0002)
.field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum Four = int16(0x0004)
} // end of class ShortEnum
.class sequential ansi sealed nested private beforefieldinit StructContainer .class sequential ansi sealed nested private beforefieldinit StructContainer
extends [mscorlib]System.ValueType extends [mscorlib]System.ValueType
{ {
@ -63,8 +73,11 @@
{ {
.custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) // ...Item.. .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) // ...Item..
.field public int32 Field .field public int32 Field
.field public int16 ShortField
.field private int32 '<Property>k__BackingField' .field private int32 '<Property>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field private uint8 '<ByteProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname .method public hidebysig specialname
instance int32 get_Property() cil managed instance int32 get_Property() cil managed
{ {
@ -88,6 +101,29 @@
IL_0007: ret IL_0007: ret
} // end of method MutableClass::set_Property } // end of method MutableClass::set_Property
.method public hidebysig specialname
instance uint8 get_ByteProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::'<ByteProperty>k__BackingField'
IL_0006: ret
} // end of method MutableClass::get_ByteProperty
.method public hidebysig specialname
instance void set_ByteProperty(uint8 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::'<ByteProperty>k__BackingField'
IL_0007: ret
} // end of method MutableClass::set_ByteProperty
.method public hidebysig specialname .method public hidebysig specialname
instance uint32 get_Item(string name) cil managed instance uint32 get_Item(string name) cil managed
{ {
@ -121,6 +157,11 @@
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property() .get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32) .set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32)
} // end of property MutableClass::Property } // end of property MutableClass::Property
.property instance uint8 ByteProperty()
{
.get instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
} // end of property MutableClass::ByteProperty
.property instance uint32 Item(string) .property instance uint32 Item(string)
{ {
.get instance uint32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Item(string) .get instance uint32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Item(string)
@ -149,9 +190,15 @@
.field private int32[] array1 .field private int32[] array1
.field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1
.field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField
.field private class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16> ushortDict
.field private uint16 ushortField
.field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum shortEnumField
.field public static int32 StaticField .field public static int32 StaticField
.field public static int16 StaticShortField
.field private static int32 '<StaticProperty>k__BackingField' .field private static int32 '<StaticProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field private static valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum '<StaticShortProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname static .method public hidebysig specialname static
int32 get_StaticProperty() cil managed int32 get_StaticProperty() cil managed
{ {
@ -173,6 +220,28 @@
IL_0006: ret IL_0006: ret
} // end of method CompoundAssignmentTest::set_StaticProperty } // end of method CompoundAssignmentTest::set_StaticProperty
.method public hidebysig specialname static
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum
get_StaticShortProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldsfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::'<StaticShortProperty>k__BackingField'
IL_0005: ret
} // end of method CompoundAssignmentTest::get_StaticShortProperty
.method public hidebysig specialname static
void set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: stsfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::'<StaticShortProperty>k__BackingField'
IL_0006: ret
} // end of method CompoundAssignmentTest::set_StaticShortProperty
.method private hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass .method private hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass
M() cil managed M() cil managed
{ {
@ -570,33 +639,53 @@
.method public hidebysig instance void .method public hidebysig instance void
NestedField() cil managed NestedField() cil managed
{ {
// Code size 38 (0x26) // Code size 78 (0x4e)
.maxstack 3 .maxstack 3
.locals init (int32 V_0) .locals init (int32 V_0)
IL_0000: ldarg.0 IL_0000: ldarg.0
IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1
IL_0006: ldfld bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::HasIndex IL_0006: ldfld bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::HasIndex
IL_000b: brfalse.s IL_0025 IL_000b: brfalse.s IL_004d
IL_000d: ldarg.0 IL_000d: ldarg.0
IL_000e: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 IL_000e: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1
IL_0013: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field IL_0013: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_0018: dup IL_0018: dup
IL_0019: ldind.i4 IL_0019: ldind.i4
IL_001a: stloc.0 IL_001a: ldc.i4.2
IL_001b: ldloc.0 IL_001b: mul
IL_001c: ldc.i4.1 IL_001c: dup
IL_001d: add IL_001d: stloc.0
IL_001e: stind.i4 IL_001e: stind.i4
IL_001f: ldloc.0 IL_001f: ldloc.0
IL_0020: call void [mscorlib]System.Console::WriteLine(int32) IL_0020: call void [mscorlib]System.Console::WriteLine(int32)
IL_0025: ret IL_0025: ldarg.0
IL_0026: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1
IL_002b: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_0030: dup
IL_0031: ldind.i4
IL_0032: ldc.i4.1
IL_0033: add
IL_0034: stind.i4
IL_0035: ldarg.0
IL_0036: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1
IL_003b: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field
IL_0040: dup
IL_0041: ldind.i4
IL_0042: stloc.0
IL_0043: ldloc.0
IL_0044: ldc.i4.1
IL_0045: add
IL_0046: stind.i4
IL_0047: ldloc.0
IL_0048: call void [mscorlib]System.Console::WriteLine(int32)
IL_004d: ret
} // end of method CompoundAssignmentTest::NestedField } // end of method CompoundAssignmentTest::NestedField
.method public hidebysig instance void .method public hidebysig instance void
Enum() cil managed Enum() cil managed
{ {
// Code size 30 (0x1e) // Code size 58 (0x3a)
.maxstack 8 .maxstack 8
IL_0000: ldarg.0 IL_0000: ldarg.0
IL_0001: ldarg.0 IL_0001: ldarg.0
@ -610,9 +699,55 @@
IL_0015: ldc.i4.s -5 IL_0015: ldc.i4.s -5
IL_0017: and IL_0017: and
IL_0018: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField IL_0018: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_001d: ret IL_001d: ldarg.0
IL_001e: ldarg.0
IL_001f: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_0024: ldc.i4.2
IL_0025: add
IL_0026: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_002b: ldarg.0
IL_002c: ldarg.0
IL_002d: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_0032: ldc.i4.3
IL_0033: sub
IL_0034: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_0039: ret
} // end of method CompoundAssignmentTest::Enum } // end of method CompoundAssignmentTest::Enum
.method public hidebysig instance void
ShortEnumTest() cil managed
{
// Code size 59 (0x3b)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_0007: ldc.i4.2
IL_0008: or
IL_0009: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_000e: ldarg.0
IL_000f: ldarg.0
IL_0010: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_0015: ldc.i4.4
IL_0016: and
IL_0017: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_001c: ldarg.0
IL_001d: ldarg.0
IL_001e: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_0023: ldc.i4.2
IL_0024: add
IL_0025: conv.i2
IL_0026: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_002b: ldarg.0
IL_002c: ldarg.0
IL_002d: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_0032: ldc.i4.3
IL_0033: sub
IL_0034: conv.i2
IL_0035: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField
IL_003a: ret
} // end of method CompoundAssignmentTest::ShortEnumTest
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementInAddition(int32 i, PreIncrementInAddition(int32 i,
int32 j) cil managed int32 j) cil managed
@ -688,6 +823,146 @@
IL_000c: ret IL_000c: ret
} // end of method CompoundAssignmentTest::IncrementArrayElement } // end of method CompoundAssignmentTest::IncrementArrayElement
.method public hidebysig instance void
DoubleArrayElement(int32[] 'array',
int32 pos) cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int32
IL_0007: dup
IL_0008: ldind.i4
IL_0009: ldc.i4.2
IL_000a: mul
IL_000b: stind.i4
IL_000c: ret
} // end of method CompoundAssignmentTest::DoubleArrayElement
.method public hidebysig instance int32
DoubleArrayElementAndReturn(int32[] 'array',
int32 pos) cil managed
{
// Code size 16 (0x10)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int32
IL_0007: dup
IL_0008: ldind.i4
IL_0009: ldc.i4.2
IL_000a: mul
IL_000b: dup
IL_000c: stloc.0
IL_000d: stind.i4
IL_000e: ldloc.0
IL_000f: ret
} // end of method CompoundAssignmentTest::DoubleArrayElementAndReturn
.method public hidebysig instance int32
PreIncrementArrayElementShort(int16[] 'array',
int32 pos) cil managed
{
// Code size 17 (0x11)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldind.i2
IL_0009: ldc.i4.1
IL_000a: sub
IL_000b: conv.i2
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: stind.i2
IL_000f: ldloc.0
IL_0010: ret
} // end of method CompoundAssignmentTest::PreIncrementArrayElementShort
.method public hidebysig instance int32
PostIncrementArrayElementShort(int16[] 'array',
int32 pos) cil managed
{
// Code size 17 (0x11)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldind.i2
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: ldc.i4.1
IL_000c: add
IL_000d: conv.i2
IL_000e: stind.i2
IL_000f: ldloc.0
IL_0010: ret
} // end of method CompoundAssignmentTest::PostIncrementArrayElementShort
.method public hidebysig instance void
IncrementArrayElementShort(int16[] 'array',
int32 pos) cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldind.i2
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: conv.i2
IL_000c: stind.i2
IL_000d: ret
} // end of method CompoundAssignmentTest::IncrementArrayElementShort
.method public hidebysig instance void
DoubleArrayElementShort(int16[] 'array',
int32 pos) cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldind.i2
IL_0009: ldc.i4.2
IL_000a: mul
IL_000b: conv.i2
IL_000c: stind.i2
IL_000d: ret
} // end of method CompoundAssignmentTest::DoubleArrayElementShort
.method public hidebysig instance int16
DoubleArrayElementShortAndReturn(int16[] 'array',
int32 pos) cil managed
{
// Code size 17 (0x11)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldelema [mscorlib]System.Int16
IL_0007: dup
IL_0008: ldind.i2
IL_0009: ldc.i4.2
IL_000a: mul
IL_000b: conv.i2
IL_000c: dup
IL_000d: stloc.0
IL_000e: stind.i2
IL_000f: ldloc.0
IL_0010: ret
} // end of method CompoundAssignmentTest::DoubleArrayElementShortAndReturn
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementInstanceField() cil managed PreIncrementInstanceField() cil managed
{ {
@ -707,6 +982,25 @@
IL_0016: ret IL_0016: ret
} // end of method CompoundAssignmentTest::PreIncrementInstanceField } // end of method CompoundAssignmentTest::PreIncrementInstanceField
.method public hidebysig instance int32
PostIncrementInstanceField() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0015: ldloc.0
IL_0016: ret
} // end of method CompoundAssignmentTest::PostIncrementInstanceField
.method public hidebysig instance void .method public hidebysig instance void
IncrementInstanceField() cil managed IncrementInstanceField() cil managed
{ {
@ -722,6 +1016,40 @@
IL_0013: ret IL_0013: ret
} // end of method CompoundAssignmentTest::IncrementInstanceField } // end of method CompoundAssignmentTest::IncrementInstanceField
.method public hidebysig instance void
DoubleInstanceField() cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0013: ret
} // end of method CompoundAssignmentTest::DoubleInstanceField
.method public hidebysig instance int32
DoubleInstanceFieldAndReturn() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: dup
IL_000f: stloc.0
IL_0010: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0015: ldloc.0
IL_0016: ret
} // end of method CompoundAssignmentTest::DoubleInstanceFieldAndReturn
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed PreIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed
{ {
@ -740,6 +1068,24 @@
IL_0011: ret IL_0011: ret
} // end of method CompoundAssignmentTest::PreIncrementInstanceField2 } // end of method CompoundAssignmentTest::PreIncrementInstanceField2
.method public hidebysig instance int32
PostIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed
{
// Code size 18 (0x12)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.1
IL_0001: dup
IL_0002: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field
IL_0010: ldloc.0
IL_0011: ret
} // end of method CompoundAssignmentTest::PostIncrementInstanceField2
.method public hidebysig instance void .method public hidebysig instance void
IncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed IncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed
{ {
@ -754,6 +1100,62 @@
IL_000e: ret IL_000e: ret
} // end of method CompoundAssignmentTest::IncrementInstanceField2 } // end of method CompoundAssignmentTest::IncrementInstanceField2
.method public hidebysig instance int32
PreIncrementInstanceFieldShort() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: conv.i2
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::PreIncrementInstanceFieldShort
.method public hidebysig instance int32
PostIncrementInstanceFieldShort() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (int16 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: conv.i2
IL_0011: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::PostIncrementInstanceFieldShort
.method public hidebysig instance void
IncrementInstanceFieldShort() cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: conv.i2
IL_000f: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField
IL_0014: ret
} // end of method CompoundAssignmentTest::IncrementInstanceFieldShort
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementInstanceProperty() cil managed PreIncrementInstanceProperty() cil managed
{ {
@ -773,6 +1175,25 @@
IL_0016: ret IL_0016: ret
} // end of method CompoundAssignmentTest::PreIncrementInstanceProperty } // end of method CompoundAssignmentTest::PreIncrementInstanceProperty
.method public hidebysig instance int32
PostIncrementInstanceProperty() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property()
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32)
IL_0015: ldloc.0
IL_0016: ret
} // end of method CompoundAssignmentTest::PostIncrementInstanceProperty
.method public hidebysig instance void .method public hidebysig instance void
IncrementInstanceProperty() cil managed IncrementInstanceProperty() cil managed
{ {
@ -791,6 +1212,135 @@
IL_0015: ret IL_0015: ret
} // end of method CompoundAssignmentTest::IncrementInstanceProperty } // end of method CompoundAssignmentTest::IncrementInstanceProperty
.method public hidebysig instance void
DoubleInstanceProperty() cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property()
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32)
IL_0013: ret
} // end of method CompoundAssignmentTest::DoubleInstanceProperty
.method public hidebysig instance int32
DoubleInstancePropertyAndReturn() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property()
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: dup
IL_000f: stloc.0
IL_0010: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32)
IL_0015: ldloc.0
IL_0016: ret
} // end of method CompoundAssignmentTest::DoubleInstancePropertyAndReturn
.method public hidebysig instance int32
PreIncrementInstancePropertyByte() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (uint8 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: conv.u1
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::PreIncrementInstancePropertyByte
.method public hidebysig instance int32
PostIncrementInstancePropertyByte() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (uint8 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: conv.u1
IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::PostIncrementInstancePropertyByte
.method public hidebysig instance void
IncrementInstancePropertyByte() cil managed
{
// Code size 23 (0x17)
.maxstack 3
.locals init (uint8 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: conv.u1
IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0016: ret
} // end of method CompoundAssignmentTest::IncrementInstancePropertyByte
.method public hidebysig instance void
DoubleInstancePropertyByte() cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: conv.u1
IL_000f: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0014: ret
} // end of method CompoundAssignmentTest::DoubleInstancePropertyByte
.method public hidebysig instance int32
DoubleInstancePropertyByteAndReturn() cil managed
{
// Code size 24 (0x18)
.maxstack 3
.locals init (uint8 V_0)
IL_0000: ldarg.0
IL_0001: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M()
IL_0006: dup
IL_0007: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty()
IL_000c: ldc.i4.2
IL_000d: mul
IL_000e: conv.u1
IL_000f: dup
IL_0010: stloc.0
IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8)
IL_0016: ldloc.0
IL_0017: ret
} // end of method CompoundAssignmentTest::DoubleInstancePropertyByteAndReturn
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementStaticField() cil managed PreIncrementStaticField() cil managed
{ {
@ -829,6 +1379,99 @@
IL_000c: ret IL_000c: ret
} // end of method CompoundAssignmentTest::IncrementStaticField } // end of method CompoundAssignmentTest::IncrementStaticField
.method public hidebysig instance void
DoubleStaticField() cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField
IL_000c: ret
} // end of method CompoundAssignmentTest::DoubleStaticField
.method public hidebysig instance int32
DoubleStaticFieldAndReturn() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: dup
IL_0008: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField
IL_000d: ret
} // end of method CompoundAssignmentTest::DoubleStaticFieldAndReturn
.method public hidebysig instance int32
PreIncrementStaticFieldShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: conv.i2
IL_0008: dup
IL_0009: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000e: ret
} // end of method CompoundAssignmentTest::PreIncrementStaticFieldShort
.method public hidebysig instance int32
PostIncrementStaticFieldShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: dup
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: conv.i2
IL_0009: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000e: ret
} // end of method CompoundAssignmentTest::PostIncrementStaticFieldShort
.method public hidebysig instance void
IncrementStaticFieldShort() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: conv.i2
IL_0008: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000d: ret
} // end of method CompoundAssignmentTest::IncrementStaticFieldShort
.method public hidebysig instance void
DoubleStaticFieldShort() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: conv.i2
IL_0008: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000d: ret
} // end of method CompoundAssignmentTest::DoubleStaticFieldShort
.method public hidebysig instance int16
DoubleStaticFieldAndReturnShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: conv.i2
IL_0008: dup
IL_0009: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField
IL_000e: ret
} // end of method CompoundAssignmentTest::DoubleStaticFieldAndReturnShort
.method public hidebysig instance int32 .method public hidebysig instance int32
PreIncrementStaticProperty() cil managed PreIncrementStaticProperty() cil managed
{ {
@ -842,6 +1485,19 @@
IL_000d: ret IL_000d: ret
} // end of method CompoundAssignmentTest::PreIncrementStaticProperty } // end of method CompoundAssignmentTest::PreIncrementStaticProperty
.method public hidebysig instance int32
PostIncrementStaticProperty() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty()
IL_0005: dup
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32)
IL_000d: ret
} // end of method CompoundAssignmentTest::PostIncrementStaticProperty
.method public hidebysig instance void .method public hidebysig instance void
IncrementStaticProperty() cil managed IncrementStaticProperty() cil managed
{ {
@ -854,6 +1510,72 @@
IL_000c: ret IL_000c: ret
} // end of method CompoundAssignmentTest::IncrementStaticProperty } // end of method CompoundAssignmentTest::IncrementStaticProperty
.method public hidebysig instance void
DoubleStaticProperty() cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty()
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32)
IL_000c: ret
} // end of method CompoundAssignmentTest::DoubleStaticProperty
.method public hidebysig instance int32
DoubleStaticPropertyAndReturn() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty()
IL_0005: ldc.i4.2
IL_0006: mul
IL_0007: dup
IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32)
IL_000d: ret
} // end of method CompoundAssignmentTest::DoubleStaticPropertyAndReturn
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum
PreIncrementStaticPropertyShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty()
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: conv.i2
IL_0008: dup
IL_0009: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum)
IL_000e: ret
} // end of method CompoundAssignmentTest::PreIncrementStaticPropertyShort
.method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum
PostIncrementStaticPropertyShort() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty()
IL_0005: dup
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: conv.i2
IL_0009: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum)
IL_000e: ret
} // end of method CompoundAssignmentTest::PostIncrementStaticPropertyShort
.method public hidebysig instance void
IncrementStaticPropertyShort() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty()
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: conv.i2
IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum)
IL_000d: ret
} // end of method CompoundAssignmentTest::IncrementStaticPropertyShort
.method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/Item .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/Item
GetItem(object obj) cil managed GetItem(object obj) cil managed
{ {
@ -874,14 +1596,62 @@
IL_000c: ret IL_000c: ret
} // end of method CompoundAssignmentTest::Issue882 } // end of method CompoundAssignmentTest::Issue882
.method private hidebysig instance void
Issue954(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum& a,
valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum b) cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldarg.1
IL_0002: ldind.i4
IL_0003: ldarg.2
IL_0004: rem
IL_0005: stind.i4
IL_0006: ldarg.0
IL_0007: ldarg.0
IL_0008: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_000d: ldarg.2
IL_000e: rem
IL_000f: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField
IL_0014: ret
} // end of method CompoundAssignmentTest::Issue954
.method private hidebysig instance void
Issue588(uint16 val) cil managed
{
// Code size 31 (0x1f)
.maxstack 4
.locals init (uint16 V_0)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16> ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortDict
IL_0006: ldarg.0
IL_0007: ldarg.0
IL_0008: ldfld uint16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortField
IL_000d: stloc.0
IL_000e: ldloc.0
IL_000f: ldc.i4.1
IL_0010: add
IL_0011: conv.u2
IL_0012: stfld uint16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortField
IL_0017: ldloc.0
IL_0018: ldarg.1
IL_0019: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16>::Add(!0,
!1)
IL_001e: ret
} // end of method CompoundAssignmentTest::Issue588
.method public hidebysig specialname rtspecialname .method public hidebysig specialname rtspecialname
instance void .ctor() cil managed instance void .ctor() cil managed
{ {
// Code size 7 (0x7) // Code size 18 (0x12)
.maxstack 8 .maxstack 8
IL_0000: ldarg.0 IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16>::.ctor()
IL_0006: ret IL_0006: stfld class [mscorlib]System.Collections.Generic.Dictionary`2<uint16,uint16> ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortDict
IL_000b: ldarg.0
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: ret
} // end of method CompoundAssignmentTest::.ctor } // end of method CompoundAssignmentTest::.ctor
.property int32 StaticProperty() .property int32 StaticProperty()
@ -889,6 +1659,12 @@
.get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() .get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty()
.set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) .set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32)
} // end of property CompoundAssignmentTest::StaticProperty } // end of property CompoundAssignmentTest::StaticProperty
.property valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum
StaticShortProperty()
{
.get valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty()
.set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum)
} // end of property CompoundAssignmentTest::StaticShortProperty
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest

1014
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il

File diff suppressed because it is too large Load Diff

62
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.IO;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
@ -25,15 +26,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private int field1; private int field1;
private static InlineAssignmentTest field2; private static InlineAssignmentTest field2;
private int[] field3; private int[] field3;
private short field4;
public int InstanceProperty {
get;
set;
}
public static int StaticProperty {
get;
set;
}
public void SimpleInlineWithLocals() public void SimpleInlineWithLocals()
{ {
int value; int index;
Console.WriteLine(value = 5); Console.WriteLine(this.GetFormat(), index = this.GetIndex());
Console.WriteLine(index);
InlineAssignmentTest value;
Console.WriteLine(this.GetFormat(), value = new InlineAssignmentTest());
Console.WriteLine(value); Console.WriteLine(value);
InlineAssignmentTest value2;
Console.WriteLine(value2 = new InlineAssignmentTest());
Console.WriteLine(value2);
} }
public void SimpleInlineWithFields() public void SimpleInlineWithFields()
@ -48,16 +59,26 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(this.field1); Console.WriteLine(this.field1);
Console.WriteLine(InlineAssignmentTest.field2 = new InlineAssignmentTest()); Console.WriteLine(InlineAssignmentTest.field2 = new InlineAssignmentTest());
Console.WriteLine(InlineAssignmentTest.field2); Console.WriteLine(InlineAssignmentTest.field2);
this.UseShort(this.field4 = 6);
this.UseShort(this.field4 = -10000);
this.UseShort(this.field4 = (short)this.field1);
this.UseShort(this.field4 = this.UseShort(0));
Console.WriteLine(this.field4);
} }
// public void ReadLoop1(TextReader r) public short UseShort(short s)
// { {
// string V_0; Console.WriteLine(s);
// while ((V_0 = r.ReadLine()) != null) return s;
// { }
// Console.WriteLine(V_0);
// } public void ReadLoop1(TextReader r)
// } {
string value;
while ((value = r.ReadLine()) != null) {
Console.WriteLine(value);
}
}
public void AccessArray(int[] a) public void AccessArray(int[] a)
{ {
@ -91,6 +112,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
throw new NotImplementedException(); throw new NotImplementedException();
} }
public string GetFormat()
{
return "{0}";
}
public int GetValue(int value) public int GetValue(int value)
{ {
return value; return value;
@ -100,5 +126,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
return this.GetArray()[this.GetIndex()] = this.GetValue(this.GetIndex()); return this.GetArray()[this.GetIndex()] = this.GetValue(this.GetIndex());
} }
public int StaticPropertyTest()
{
return InlineAssignmentTest.StaticProperty = this.GetIndex();
}
public int InstancePropertyTest()
{
return this.InstanceProperty = this.GetIndex();
}
} }
} }

285
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il

@ -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. // Copyright (c) Microsoft Corporation. All rights reserved.
@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0 .ver 4:0:0:0
} }
.assembly xh5er5kd .assembly cljdpn4p
{ {
.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.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 .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 @@
.hash algorithm 0x00008004 .hash algorithm 0x00008004
.ver 0:0:0:0 .ver 0:0:0:0
} }
.module xh5er5kd.dll .module cljdpn4p.dll
// MVID: {9DBFA28B-BEE8-4796-A203-E73267B1357D} // MVID: {4E91830C-4968-4AA2-B516-7FDA32452515}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000 .imagebase 0x10000000
.file alignment 0x00000200 .file alignment 0x00000200
.stackreserve 0x00100000 .stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI .subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY .corflags 0x00000001 // ILONLY
// Image base: 0x023E0000 // Image base: 0x006A0000
// =============== CLASS MEMBERS DECLARATION =================== // =============== CLASS MEMBERS DECLARATION ===================
@ -39,31 +39,98 @@
.field private int32 field1 .field private int32 field1
.field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2 .field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2
.field private int32[] field3 .field private int32[] field3
.field private int16 field4
.field private int32 '<InstanceProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field private static int32 '<StaticProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname instance int32
get_InstanceProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 11 (0xb)
.maxstack 1
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<InstanceProperty>k__BackingField'
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method InlineAssignmentTest::get_InstanceProperty
.method public hidebysig specialname instance void
set_InstanceProperty(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<InstanceProperty>k__BackingField'
IL_0007: ret
} // end of method InlineAssignmentTest::set_InstanceProperty
.method public hidebysig specialname static
int32 get_StaticProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 10 (0xa)
.maxstack 1
.locals init (int32 V_0)
IL_0000: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<StaticProperty>k__BackingField'
IL_0005: stloc.0
IL_0006: br.s IL_0008
IL_0008: ldloc.0
IL_0009: ret
} // end of method InlineAssignmentTest::get_StaticProperty
.method public hidebysig specialname static
void set_StaticProperty(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<StaticProperty>k__BackingField'
IL_0006: ret
} // end of method InlineAssignmentTest::set_StaticProperty
.method public hidebysig instance void .method public hidebysig instance void
SimpleInlineWithLocals() cil managed SimpleInlineWithLocals() cil managed
{ {
// Code size 38 (0x26) // Code size 60 (0x3c)
.maxstack 2 .maxstack 3
.locals init (int32 V_0, .locals init (int32 V_0,
class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1) class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1)
IL_0000: nop IL_0000: nop
IL_0001: ldc.i4.5 IL_0001: ldarg.0
IL_0002: dup IL_0002: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetFormat()
IL_0003: stloc.0 IL_0007: ldarg.0
IL_0004: call void [mscorlib]System.Console::WriteLine(int32) IL_0008: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0009: nop IL_000d: dup
IL_000a: ldloc.0 IL_000e: stloc.0
IL_000b: call void [mscorlib]System.Console::WriteLine(int32) IL_000f: box [mscorlib]System.Int32
IL_0010: nop IL_0014: call void [mscorlib]System.Console::WriteLine(string,
IL_0011: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor() object)
IL_0016: dup IL_0019: nop
IL_0017: stloc.1 IL_001a: ldloc.0
IL_0018: call void [mscorlib]System.Console::WriteLine(object) IL_001b: call void [mscorlib]System.Console::WriteLine(int32)
IL_001d: nop IL_0020: nop
IL_001e: ldloc.1 IL_0021: ldarg.0
IL_001f: call void [mscorlib]System.Console::WriteLine(object) IL_0022: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetFormat()
IL_0024: nop IL_0027: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0025: ret IL_002c: dup
IL_002d: stloc.1
IL_002e: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_0033: nop
IL_0034: ldloc.1
IL_0035: call void [mscorlib]System.Console::WriteLine(object)
IL_003a: nop
IL_003b: ret
} // end of method InlineAssignmentTest::SimpleInlineWithLocals } // end of method InlineAssignmentTest::SimpleInlineWithLocals
.method public hidebysig instance void .method public hidebysig instance void
@ -92,9 +159,10 @@
.method public hidebysig instance void .method public hidebysig instance void
SimpleInlineWithFields2() cil managed SimpleInlineWithFields2() cil managed
{ {
// Code size 58 (0x3a) // Code size 154 (0x9a)
.maxstack 3 .maxstack 4
.locals init (int32 V_0) .locals init (int32 V_0,
int16 V_1)
IL_0000: nop IL_0000: nop
IL_0001: ldarg.0 IL_0001: ldarg.0
IL_0002: ldc.i4.5 IL_0002: ldc.i4.5
@ -116,9 +184,101 @@
IL_002e: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2 IL_002e: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_0033: call void [mscorlib]System.Console::WriteLine(object) IL_0033: call void [mscorlib]System.Console::WriteLine(object)
IL_0038: nop IL_0038: nop
IL_0039: ret IL_0039: ldarg.0
IL_003a: ldarg.0
IL_003b: ldc.i4.6
IL_003c: dup
IL_003d: stloc.1
IL_003e: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0043: ldloc.1
IL_0044: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0049: pop
IL_004a: ldarg.0
IL_004b: ldarg.0
IL_004c: ldc.i4 0xffffd8f0
IL_0051: dup
IL_0052: stloc.1
IL_0053: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0058: ldloc.1
IL_0059: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_005e: pop
IL_005f: ldarg.0
IL_0060: ldarg.0
IL_0061: ldarg.0
IL_0062: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0067: conv.i2
IL_0068: dup
IL_0069: stloc.1
IL_006a: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_006f: ldloc.1
IL_0070: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0075: pop
IL_0076: ldarg.0
IL_0077: ldarg.0
IL_0078: ldarg.0
IL_0079: ldc.i4.0
IL_007a: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_007f: dup
IL_0080: stloc.1
IL_0081: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0086: ldloc.1
IL_0087: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_008c: pop
IL_008d: ldarg.0
IL_008e: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0093: call void [mscorlib]System.Console::WriteLine(int32)
IL_0098: nop
IL_0099: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields2 } // end of method InlineAssignmentTest::SimpleInlineWithFields2
.method public hidebysig instance int16
UseShort(int16 s) cil managed
{
// Code size 14 (0xe)
.maxstack 1
.locals init (int16 V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call void [mscorlib]System.Console::WriteLine(int32)
IL_0007: nop
IL_0008: ldarg.1
IL_0009: stloc.0
IL_000a: br.s IL_000c
IL_000c: ldloc.0
IL_000d: ret
} // end of method InlineAssignmentTest::UseShort
.method public hidebysig instance void
ReadLoop1(class [mscorlib]System.IO.TextReader r) cil managed
{
// Code size 31 (0x1f)
.maxstack 2
.locals init (string V_0,
bool V_1)
IL_0000: nop
IL_0001: br.s IL_000c
IL_0003: nop
IL_0004: ldloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: nop
IL_000b: nop
IL_000c: ldarg.1
IL_000d: callvirt instance string [mscorlib]System.IO.TextReader::ReadLine()
IL_0012: dup
IL_0013: stloc.0
IL_0014: ldnull
IL_0015: ceq
IL_0017: ldc.i4.0
IL_0018: ceq
IL_001a: stloc.1
IL_001b: ldloc.1
IL_001c: brtrue.s IL_0003
IL_001e: ret
} // end of method InlineAssignmentTest::ReadLoop1
.method public hidebysig instance void .method public hidebysig instance void
AccessArray(int32[] a) cil managed AccessArray(int32[] a) cil managed
{ {
@ -242,6 +402,21 @@
IL_0006: throw IL_0006: throw
} // end of method InlineAssignmentTest::GetArray } // end of method InlineAssignmentTest::GetArray
.method public hidebysig instance string
GetFormat() cil managed
{
// Code size 11 (0xb)
.maxstack 1
.locals init (string V_0)
IL_0000: nop
IL_0001: ldstr "{0}"
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method InlineAssignmentTest::GetFormat
.method public hidebysig instance int32 .method public hidebysig instance int32
GetValue(int32 'value') cil managed GetValue(int32 'value') cil managed
{ {
@ -284,6 +459,48 @@
IL_0021: ret IL_0021: ret
} // end of method InlineAssignmentTest::ArrayUsageWithMethods } // end of method InlineAssignmentTest::ArrayUsageWithMethods
.method public hidebysig instance int32
StaticPropertyTest() cil managed
{
// Code size 19 (0x13)
.maxstack 2
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0007: dup
IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_StaticProperty(int32)
IL_000d: nop
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
} // end of method InlineAssignmentTest::StaticPropertyTest
.method public hidebysig instance int32
InstancePropertyTest() cil managed
{
// Code size 22 (0x16)
.maxstack 3
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0008: dup
IL_0009: stloc.1
IL_000a: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_InstanceProperty(int32)
IL_000f: nop
IL_0010: ldloc.1
IL_0011: stloc.0
IL_0012: br.s IL_0014
IL_0014: ldloc.0
IL_0015: ret
} // end of method InlineAssignmentTest::InstancePropertyTest
.method public hidebysig specialname rtspecialname .method public hidebysig specialname rtspecialname
instance void .ctor() cil managed instance void .ctor() cil managed
{ {
@ -294,10 +511,20 @@
IL_0006: ret IL_0006: ret
} // end of method InlineAssignmentTest::.ctor } // end of method InlineAssignmentTest::.ctor
.property instance int32 InstanceProperty()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::get_InstanceProperty()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_InstanceProperty(int32)
} // end of property InlineAssignmentTest::InstanceProperty
.property int32 StaticProperty()
{
.get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::get_StaticProperty()
.set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_StaticProperty(int32)
} // end of property InlineAssignmentTest::StaticProperty
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest
// ============================================================= // =============================================================
// *********** DISASSEMBLY COMPLETE *********************** // *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\InlineAssignmentTest.res // WARNING: Created Win32 resource file ../../../TestCases/Pretty\InlineAssignmentTest.res

231
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il

@ -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. // Copyright (c) Microsoft Corporation. All rights reserved.
@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0 .ver 4:0:0:0
} }
.assembly b1jpssom .assembly jfxjxuqt
{ {
.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.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 .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 @@
.hash algorithm 0x00008004 .hash algorithm 0x00008004
.ver 0:0:0:0 .ver 0:0:0:0
} }
.module b1jpssom.dll .module jfxjxuqt.dll
// MVID: {7C6502B0-8536-4BED-9395-765EB2F77653} // MVID: {862986C8-F9C1-4FF3-8646-A3CA63D29744}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000 .imagebase 0x10000000
.file alignment 0x00000200 .file alignment 0x00000200
.stackreserve 0x00100000 .stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI .subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY .corflags 0x00000001 // ILONLY
// Image base: 0x02B00000 // Image base: 0x010B0000
// =============== CLASS MEMBERS DECLARATION =================== // =============== CLASS MEMBERS DECLARATION ===================
@ -39,26 +39,83 @@
.field private int32 field1 .field private int32 field1
.field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2 .field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2
.field private int32[] field3 .field private int32[] field3
.field private int16 field4
.field private int32 '<InstanceProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field private static int32 '<StaticProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname instance int32
get_InstanceProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<InstanceProperty>k__BackingField'
IL_0006: ret
} // end of method InlineAssignmentTest::get_InstanceProperty
.method public hidebysig specialname instance void
set_InstanceProperty(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<InstanceProperty>k__BackingField'
IL_0007: ret
} // end of method InlineAssignmentTest::set_InstanceProperty
.method public hidebysig specialname static
int32 get_StaticProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<StaticProperty>k__BackingField'
IL_0005: ret
} // end of method InlineAssignmentTest::get_StaticProperty
.method public hidebysig specialname static
void set_StaticProperty(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<StaticProperty>k__BackingField'
IL_0006: ret
} // end of method InlineAssignmentTest::set_StaticProperty
.method public hidebysig instance void .method public hidebysig instance void
SimpleInlineWithLocals() cil managed SimpleInlineWithLocals() cil managed
{ {
// Code size 33 (0x21) // Code size 55 (0x37)
.maxstack 2 .maxstack 3
.locals init (int32 V_0, .locals init (int32 V_0,
class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1) class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1)
IL_0000: ldc.i4.5 IL_0000: ldarg.0
IL_0001: dup IL_0001: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetFormat()
IL_0002: stloc.0 IL_0006: ldarg.0
IL_0003: call void [mscorlib]System.Console::WriteLine(int32) IL_0007: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0008: ldloc.0 IL_000c: dup
IL_0009: call void [mscorlib]System.Console::WriteLine(int32) IL_000d: stloc.0
IL_000e: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor() IL_000e: box [mscorlib]System.Int32
IL_0013: dup IL_0013: call void [mscorlib]System.Console::WriteLine(string,
IL_0014: stloc.1 object)
IL_0015: call void [mscorlib]System.Console::WriteLine(object) IL_0018: ldloc.0
IL_001a: ldloc.1 IL_0019: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: call void [mscorlib]System.Console::WriteLine(object) IL_001e: ldarg.0
IL_0020: ret IL_001f: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetFormat()
IL_0024: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0029: dup
IL_002a: stloc.1
IL_002b: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_0030: ldloc.1
IL_0031: call void [mscorlib]System.Console::WriteLine(object)
IL_0036: ret
} // end of method InlineAssignmentTest::SimpleInlineWithLocals } // end of method InlineAssignmentTest::SimpleInlineWithLocals
.method public hidebysig instance void .method public hidebysig instance void
@ -84,9 +141,13 @@
.method public hidebysig instance void .method public hidebysig instance void
SimpleInlineWithFields2() cil managed SimpleInlineWithFields2() cil managed
{ {
// Code size 53 (0x35) // Code size 150 (0x96)
.maxstack 3 .maxstack 4
.locals init (int32 V_0) .locals init (int32 V_0,
int16 V_1,
int16 V_2,
int16 V_3,
int16 V_4)
IL_0000: ldarg.0 IL_0000: ldarg.0
IL_0001: ldc.i4.5 IL_0001: ldc.i4.5
IL_0002: dup IL_0002: dup
@ -103,9 +164,82 @@
IL_0025: call void [mscorlib]System.Console::WriteLine(object) IL_0025: call void [mscorlib]System.Console::WriteLine(object)
IL_002a: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2 IL_002a: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_002f: call void [mscorlib]System.Console::WriteLine(object) IL_002f: call void [mscorlib]System.Console::WriteLine(object)
IL_0034: ret IL_0034: ldarg.0
IL_0035: ldarg.0
IL_0036: ldc.i4.6
IL_0037: dup
IL_0038: stloc.1
IL_0039: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_003e: ldloc.1
IL_003f: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0044: pop
IL_0045: ldarg.0
IL_0046: ldarg.0
IL_0047: ldc.i4 0xffffd8f0
IL_004c: dup
IL_004d: stloc.2
IL_004e: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0053: ldloc.2
IL_0054: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0059: pop
IL_005a: ldarg.0
IL_005b: ldarg.0
IL_005c: ldarg.0
IL_005d: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0062: conv.i2
IL_0063: dup
IL_0064: stloc.3
IL_0065: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_006a: ldloc.3
IL_006b: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0070: pop
IL_0071: ldarg.0
IL_0072: ldarg.0
IL_0073: ldarg.0
IL_0074: ldc.i4.0
IL_0075: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_007a: dup
IL_007b: stloc.s V_4
IL_007d: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0082: ldloc.s V_4
IL_0084: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0089: pop
IL_008a: ldarg.0
IL_008b: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0090: call void [mscorlib]System.Console::WriteLine(int32)
IL_0095: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields2 } // end of method InlineAssignmentTest::SimpleInlineWithFields2
.method public hidebysig instance int16
UseShort(int16 s) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call void [mscorlib]System.Console::WriteLine(int32)
IL_0006: ldarg.1
IL_0007: ret
} // end of method InlineAssignmentTest::UseShort
.method public hidebysig instance void
ReadLoop1(class [mscorlib]System.IO.TextReader r) cil managed
{
// Code size 19 (0x13)
.maxstack 2
.locals init (string V_0)
IL_0000: br.s IL_0008
IL_0002: ldloc.0
IL_0003: call void [mscorlib]System.Console::WriteLine(string)
IL_0008: ldarg.1
IL_0009: callvirt instance string [mscorlib]System.IO.TextReader::ReadLine()
IL_000e: dup
IL_000f: stloc.0
IL_0010: brtrue.s IL_0002
IL_0012: ret
} // end of method InlineAssignmentTest::ReadLoop1
.method public hidebysig instance void .method public hidebysig instance void
AccessArray(int32[] a) cil managed AccessArray(int32[] a) cil managed
{ {
@ -201,6 +335,15 @@
IL_0005: throw IL_0005: throw
} // end of method InlineAssignmentTest::GetArray } // end of method InlineAssignmentTest::GetArray
.method public hidebysig instance string
GetFormat() cil managed
{
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldstr "{0}"
IL_0005: ret
} // end of method InlineAssignmentTest::GetFormat
.method public hidebysig instance int32 .method public hidebysig instance int32
GetValue(int32 'value') cil managed GetValue(int32 'value') cil managed
{ {
@ -231,6 +374,34 @@
IL_001c: ret IL_001c: ret
} // end of method InlineAssignmentTest::ArrayUsageWithMethods } // end of method InlineAssignmentTest::ArrayUsageWithMethods
.method public hidebysig instance int32
StaticPropertyTest() cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0006: dup
IL_0007: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_StaticProperty(int32)
IL_000c: ret
} // end of method InlineAssignmentTest::StaticPropertyTest
.method public hidebysig instance int32
InstancePropertyTest() cil managed
{
// Code size 16 (0x10)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0007: dup
IL_0008: stloc.0
IL_0009: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_InstanceProperty(int32)
IL_000e: ldloc.0
IL_000f: ret
} // end of method InlineAssignmentTest::InstancePropertyTest
.method public hidebysig specialname rtspecialname .method public hidebysig specialname rtspecialname
instance void .ctor() cil managed instance void .ctor() cil managed
{ {
@ -241,10 +412,20 @@
IL_0006: ret IL_0006: ret
} // end of method InlineAssignmentTest::.ctor } // end of method InlineAssignmentTest::.ctor
.property instance int32 InstanceProperty()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::get_InstanceProperty()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_InstanceProperty(int32)
} // end of property InlineAssignmentTest::InstanceProperty
.property int32 StaticProperty()
{
.get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::get_StaticProperty()
.set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_StaticProperty(int32)
} // end of property InlineAssignmentTest::StaticProperty
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest
// ============================================================= // =============================================================
// *********** DISASSEMBLY COMPLETE *********************** // *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\InlineAssignmentTest.opt.res // WARNING: Created Win32 resource file ../../../TestCases/Pretty\InlineAssignmentTest.opt.res

431
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.roslyn.il

@ -0,0 +1,431 @@
// 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 InlineAssignmentTest
{
.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 InlineAssignmentTest.dll
// MVID: {2D549318-D869-4294-BA40-CB6EEA5D9CE2}
.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: 0x02CB0000
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest
extends [mscorlib]System.Object
{
.field private int32 field1
.field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2
.field private int32[] field3
.field private int16 field4
.field private int32 '<InstanceProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.field private static int32 '<StaticProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname instance int32
get_InstanceProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<InstanceProperty>k__BackingField'
IL_0006: ret
} // end of method InlineAssignmentTest::get_InstanceProperty
.method public hidebysig specialname instance void
set_InstanceProperty(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<InstanceProperty>k__BackingField'
IL_0007: ret
} // end of method InlineAssignmentTest::set_InstanceProperty
.method public hidebysig specialname static
int32 get_StaticProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<StaticProperty>k__BackingField'
IL_0005: ret
} // end of method InlineAssignmentTest::get_StaticProperty
.method public hidebysig specialname static
void set_StaticProperty(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<StaticProperty>k__BackingField'
IL_0006: ret
} // end of method InlineAssignmentTest::set_StaticProperty
.method public hidebysig instance void
SimpleInlineWithLocals() cil managed
{
// Code size 55 (0x37)
.maxstack 3
.locals init (int32 V_0,
class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1)
IL_0000: ldarg.0
IL_0001: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetFormat()
IL_0006: ldarg.0
IL_0007: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_000c: dup
IL_000d: stloc.0
IL_000e: box [mscorlib]System.Int32
IL_0013: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_0018: ldloc.0
IL_0019: call void [mscorlib]System.Console::WriteLine(int32)
IL_001e: ldarg.0
IL_001f: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetFormat()
IL_0024: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0029: dup
IL_002a: stloc.1
IL_002b: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_0030: ldloc.1
IL_0031: call void [mscorlib]System.Console::WriteLine(object)
IL_0036: ret
} // end of method InlineAssignmentTest::SimpleInlineWithLocals
.method public hidebysig instance void
SimpleInlineWithFields() cil managed
{
// Code size 32 (0x20)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: dup
IL_0003: stloc.0
IL_0004: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0009: ldloc.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0014: dup
IL_0015: stsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_001a: call void [mscorlib]System.Console::WriteLine(object)
IL_001f: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields
.method public hidebysig instance void
SimpleInlineWithFields2() cil managed
{
// Code size 148 (0x94)
.maxstack 4
.locals init (int32 V_0,
int16 V_1)
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: dup
IL_0003: stloc.0
IL_0004: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0009: ldloc.0
IL_000a: call void [mscorlib]System.Console::WriteLine(int32)
IL_000f: ldarg.0
IL_0010: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0015: call void [mscorlib]System.Console::WriteLine(int32)
IL_001a: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_001f: dup
IL_0020: stsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_0025: call void [mscorlib]System.Console::WriteLine(object)
IL_002a: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_002f: call void [mscorlib]System.Console::WriteLine(object)
IL_0034: ldarg.0
IL_0035: ldarg.0
IL_0036: ldc.i4.6
IL_0037: dup
IL_0038: stloc.1
IL_0039: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_003e: ldloc.1
IL_003f: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0044: pop
IL_0045: ldarg.0
IL_0046: ldarg.0
IL_0047: ldc.i4 0xffffd8f0
IL_004c: dup
IL_004d: stloc.1
IL_004e: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0053: ldloc.1
IL_0054: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0059: pop
IL_005a: ldarg.0
IL_005b: ldarg.0
IL_005c: ldarg.0
IL_005d: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0062: conv.i2
IL_0063: dup
IL_0064: stloc.1
IL_0065: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_006a: ldloc.1
IL_006b: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0070: pop
IL_0071: ldarg.0
IL_0072: ldarg.0
IL_0073: ldarg.0
IL_0074: ldc.i4.0
IL_0075: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_007a: dup
IL_007b: stloc.1
IL_007c: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0081: ldloc.1
IL_0082: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0087: pop
IL_0088: ldarg.0
IL_0089: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_008e: call void [mscorlib]System.Console::WriteLine(int32)
IL_0093: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields2
.method public hidebysig instance int16
UseShort(int16 s) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call void [mscorlib]System.Console::WriteLine(int32)
IL_0006: ldarg.1
IL_0007: ret
} // end of method InlineAssignmentTest::UseShort
.method public hidebysig instance void
ReadLoop1(class [mscorlib]System.IO.TextReader r) cil managed
{
// Code size 19 (0x13)
.maxstack 2
.locals init (string V_0)
IL_0000: br.s IL_0008
IL_0002: ldloc.0
IL_0003: call void [mscorlib]System.Console::WriteLine(string)
IL_0008: ldarg.1
IL_0009: callvirt instance string [mscorlib]System.IO.TextReader::ReadLine()
IL_000e: dup
IL_000f: stloc.0
IL_0010: brtrue.s IL_0002
IL_0012: ret
} // end of method InlineAssignmentTest::ReadLoop1
.method public hidebysig instance void
AccessArray(int32[] a) cil managed
{
// Code size 23 (0x17)
.maxstack 4
.locals init (int32 V_0,
int32 V_1)
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: ldelem.i4
IL_0003: dup
IL_0004: stloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(int32)
IL_000a: ldarg.1
IL_000b: ldloc.0
IL_000c: ldloc.0
IL_000d: dup
IL_000e: stloc.1
IL_000f: stelem.i4
IL_0010: ldloc.1
IL_0011: call void [mscorlib]System.Console::WriteLine(int32)
IL_0016: ret
} // end of method InlineAssignmentTest::AccessArray
.method public hidebysig instance int32
Return(int32& a) cil managed
{
// Code size 7 (0x7)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.1
IL_0001: ldc.i4.3
IL_0002: dup
IL_0003: stloc.0
IL_0004: stind.i4
IL_0005: ldloc.0
IL_0006: ret
} // end of method InlineAssignmentTest::Return
.method public hidebysig instance int32
Array(int32[] a,
int32 i) cil managed
{
// Code size 8 (0x8)
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ldarg.2
IL_0003: dup
IL_0004: stloc.0
IL_0005: stelem.i4
IL_0006: ldloc.0
IL_0007: ret
} // end of method InlineAssignmentTest::Array
.method public hidebysig instance int32
Array2(int32 i) cil managed
{
// Code size 13 (0xd)
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldfld int32[] ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field3
IL_0006: ldarg.1
IL_0007: ldc.i4.1
IL_0008: dup
IL_0009: stloc.0
IL_000a: stelem.i4
IL_000b: ldloc.0
IL_000c: ret
} // end of method InlineAssignmentTest::Array2
.method public hidebysig instance int32
GetIndex() cil managed
{
// Code size 14 (0xe)
.maxstack 8
IL_0000: newobj instance void [mscorlib]System.Random::.ctor()
IL_0005: ldc.i4.0
IL_0006: ldc.i4.s 100
IL_0008: callvirt instance int32 [mscorlib]System.Random::Next(int32,
int32)
IL_000d: ret
} // end of method InlineAssignmentTest::GetIndex
.method public hidebysig instance int32[]
GetArray() cil managed
{
// Code size 6 (0x6)
.maxstack 8
IL_0000: newobj instance void [mscorlib]System.NotImplementedException::.ctor()
IL_0005: throw
} // end of method InlineAssignmentTest::GetArray
.method public hidebysig instance string
GetFormat() cil managed
{
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldstr "{0}"
IL_0005: ret
} // end of method InlineAssignmentTest::GetFormat
.method public hidebysig instance int32
GetValue(int32 'value') cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ret
} // end of method InlineAssignmentTest::GetValue
.method public hidebysig instance int32
ArrayUsageWithMethods() cil managed
{
// Code size 29 (0x1d)
.maxstack 4
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: call instance int32[] ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetArray()
IL_0006: ldarg.0
IL_0007: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_000c: ldarg.0
IL_000d: ldarg.0
IL_000e: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0013: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetValue(int32)
IL_0018: dup
IL_0019: stloc.0
IL_001a: stelem.i4
IL_001b: ldloc.0
IL_001c: ret
} // end of method InlineAssignmentTest::ArrayUsageWithMethods
.method public hidebysig instance int32
StaticPropertyTest() cil managed
{
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0006: dup
IL_0007: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_StaticProperty(int32)
IL_000c: ret
} // end of method InlineAssignmentTest::StaticPropertyTest
.method public hidebysig instance int32
InstancePropertyTest() cil managed
{
// Code size 16 (0x10)
.maxstack 3
.locals init (int32 V_0)
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0007: dup
IL_0008: stloc.0
IL_0009: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_InstanceProperty(int32)
IL_000e: ldloc.0
IL_000f: ret
} // end of method InlineAssignmentTest::InstancePropertyTest
.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 InlineAssignmentTest::.ctor
.property instance int32 InstanceProperty()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::get_InstanceProperty()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_InstanceProperty(int32)
} // end of property InlineAssignmentTest::InstanceProperty
.property int32 StaticProperty()
{
.get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::get_StaticProperty()
.set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_StaticProperty(int32)
} // end of property InlineAssignmentTest::StaticProperty
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

524
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.roslyn.il

@ -0,0 +1,524 @@
// 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 InlineAssignmentTest
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module InlineAssignmentTest.dll
// MVID: {370735A1-C3D5-4BD3-8F9B-CC3F81FB734E}
.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: 0x00BE0000
// =============== CLASS MEMBERS DECLARATION ===================
.class public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest
extends [mscorlib]System.Object
{
.field private int32 field1
.field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2
.field private int32[] field3
.field private int16 field4
.field private int32 '<InstanceProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
.field private static int32 '<StaticProperty>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 )
.method public hidebysig specialname instance int32
get_InstanceProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<InstanceProperty>k__BackingField'
IL_0006: ret
} // end of method InlineAssignmentTest::get_InstanceProperty
.method public hidebysig specialname instance void
set_InstanceProperty(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<InstanceProperty>k__BackingField'
IL_0007: ret
} // end of method InlineAssignmentTest::set_InstanceProperty
.method public hidebysig specialname static
int32 get_StaticProperty() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<StaticProperty>k__BackingField'
IL_0005: ret
} // end of method InlineAssignmentTest::get_StaticProperty
.method public hidebysig specialname static
void set_StaticProperty(int32 'value') cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::'<StaticProperty>k__BackingField'
IL_0006: ret
} // end of method InlineAssignmentTest::set_StaticProperty
.method public hidebysig instance void
SimpleInlineWithLocals() cil managed
{
// Code size 60 (0x3c)
.maxstack 3
.locals init (int32 V_0,
class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetFormat()
IL_0007: ldarg.0
IL_0008: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_000d: dup
IL_000e: stloc.0
IL_000f: box [mscorlib]System.Int32
IL_0014: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_0019: nop
IL_001a: ldloc.0
IL_001b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0020: nop
IL_0021: ldarg.0
IL_0022: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetFormat()
IL_0027: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_002c: dup
IL_002d: stloc.1
IL_002e: call void [mscorlib]System.Console::WriteLine(string,
object)
IL_0033: nop
IL_0034: ldloc.1
IL_0035: call void [mscorlib]System.Console::WriteLine(object)
IL_003a: nop
IL_003b: ret
} // end of method InlineAssignmentTest::SimpleInlineWithLocals
.method public hidebysig instance void
SimpleInlineWithFields() cil managed
{
// Code size 35 (0x23)
.maxstack 3
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.5
IL_0003: dup
IL_0004: stloc.0
IL_0005: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_000a: ldloc.0
IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0010: nop
IL_0011: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0016: dup
IL_0017: stsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_001c: call void [mscorlib]System.Console::WriteLine(object)
IL_0021: nop
IL_0022: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields
.method public hidebysig instance void
SimpleInlineWithFields2() cil managed
{
// Code size 154 (0x9a)
.maxstack 4
.locals init (int32 V_0,
int16 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.5
IL_0003: dup
IL_0004: stloc.0
IL_0005: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_000a: ldloc.0
IL_000b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0010: nop
IL_0011: ldarg.0
IL_0012: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0017: call void [mscorlib]System.Console::WriteLine(int32)
IL_001c: nop
IL_001d: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor()
IL_0022: dup
IL_0023: stsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_0028: call void [mscorlib]System.Console::WriteLine(object)
IL_002d: nop
IL_002e: ldsfld class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field2
IL_0033: call void [mscorlib]System.Console::WriteLine(object)
IL_0038: nop
IL_0039: ldarg.0
IL_003a: ldarg.0
IL_003b: ldc.i4.6
IL_003c: dup
IL_003d: stloc.1
IL_003e: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0043: ldloc.1
IL_0044: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0049: pop
IL_004a: ldarg.0
IL_004b: ldarg.0
IL_004c: ldc.i4 0xffffd8f0
IL_0051: dup
IL_0052: stloc.1
IL_0053: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0058: ldloc.1
IL_0059: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_005e: pop
IL_005f: ldarg.0
IL_0060: ldarg.0
IL_0061: ldarg.0
IL_0062: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0067: conv.i2
IL_0068: dup
IL_0069: stloc.1
IL_006a: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_006f: ldloc.1
IL_0070: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0075: pop
IL_0076: ldarg.0
IL_0077: ldarg.0
IL_0078: ldarg.0
IL_0079: ldc.i4.0
IL_007a: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_007f: dup
IL_0080: stloc.1
IL_0081: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0086: ldloc.1
IL_0087: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_008c: pop
IL_008d: ldarg.0
IL_008e: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0093: call void [mscorlib]System.Console::WriteLine(int32)
IL_0098: nop
IL_0099: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields2
.method public hidebysig instance int16
UseShort(int16 s) cil managed
{
// Code size 14 (0xe)
.maxstack 1
.locals init (int16 V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call void [mscorlib]System.Console::WriteLine(int32)
IL_0007: nop
IL_0008: ldarg.1
IL_0009: stloc.0
IL_000a: br.s IL_000c
IL_000c: ldloc.0
IL_000d: ret
} // end of method InlineAssignmentTest::UseShort
.method public hidebysig instance void
ReadLoop1(class [mscorlib]System.IO.TextReader r) cil managed
{
// Code size 28 (0x1c)
.maxstack 2
.locals init (string V_0,
bool V_1)
IL_0000: nop
IL_0001: br.s IL_000c
IL_0003: nop
IL_0004: ldloc.0
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: nop
IL_000b: nop
IL_000c: ldarg.1
IL_000d: callvirt instance string [mscorlib]System.IO.TextReader::ReadLine()
IL_0012: dup
IL_0013: stloc.0
IL_0014: ldnull
IL_0015: cgt.un
IL_0017: stloc.1
IL_0018: ldloc.1
IL_0019: brtrue.s IL_0003
IL_001b: ret
} // end of method InlineAssignmentTest::ReadLoop1
.method public hidebysig instance void
AccessArray(int32[] a) cil managed
{
// Code size 26 (0x1a)
.maxstack 4
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.0
IL_0003: ldelem.i4
IL_0004: dup
IL_0005: stloc.0
IL_0006: call void [mscorlib]System.Console::WriteLine(int32)
IL_000b: nop
IL_000c: ldarg.1
IL_000d: ldloc.0
IL_000e: ldloc.0
IL_000f: dup
IL_0010: stloc.1
IL_0011: stelem.i4
IL_0012: ldloc.1
IL_0013: call void [mscorlib]System.Console::WriteLine(int32)
IL_0018: nop
IL_0019: ret
} // end of method InlineAssignmentTest::AccessArray
.method public hidebysig instance int32
Return(int32& a) cil managed
{
// Code size 12 (0xc)
.maxstack 3
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.3
IL_0003: dup
IL_0004: stloc.0
IL_0005: stind.i4
IL_0006: ldloc.0
IL_0007: stloc.1
IL_0008: br.s IL_000a
IL_000a: ldloc.1
IL_000b: ret
} // end of method InlineAssignmentTest::Return
.method public hidebysig instance int32
Array(int32[] a,
int32 i) cil managed
{
// Code size 13 (0xd)
.maxstack 4
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: ldarg.2
IL_0004: dup
IL_0005: stloc.0
IL_0006: stelem.i4
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: br.s IL_000b
IL_000b: ldloc.1
IL_000c: ret
} // end of method InlineAssignmentTest::Array
.method public hidebysig instance int32
Array2(int32 i) cil managed
{
// Code size 18 (0x12)
.maxstack 4
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32[] ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field3
IL_0007: ldarg.1
IL_0008: ldc.i4.1
IL_0009: dup
IL_000a: stloc.0
IL_000b: stelem.i4
IL_000c: ldloc.0
IL_000d: stloc.1
IL_000e: br.s IL_0010
IL_0010: ldloc.1
IL_0011: ret
} // end of method InlineAssignmentTest::Array2
.method public hidebysig instance int32
GetIndex() cil managed
{
// Code size 19 (0x13)
.maxstack 3
.locals init (int32 V_0)
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.Random::.ctor()
IL_0006: ldc.i4.0
IL_0007: ldc.i4.s 100
IL_0009: callvirt instance int32 [mscorlib]System.Random::Next(int32,
int32)
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
} // end of method InlineAssignmentTest::GetIndex
.method public hidebysig instance int32[]
GetArray() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.NotImplementedException::.ctor()
IL_0006: throw
} // end of method InlineAssignmentTest::GetArray
.method public hidebysig instance string
GetFormat() cil managed
{
// Code size 11 (0xb)
.maxstack 1
.locals init (string V_0)
IL_0000: nop
IL_0001: ldstr "{0}"
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method InlineAssignmentTest::GetFormat
.method public hidebysig instance int32
GetValue(int32 'value') cil managed
{
// Code size 7 (0x7)
.maxstack 1
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: stloc.0
IL_0003: br.s IL_0005
IL_0005: ldloc.0
IL_0006: ret
} // end of method InlineAssignmentTest::GetValue
.method public hidebysig instance int32
ArrayUsageWithMethods() cil managed
{
// Code size 34 (0x22)
.maxstack 4
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance int32[] ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetArray()
IL_0007: ldarg.0
IL_0008: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_000d: ldarg.0
IL_000e: ldarg.0
IL_000f: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0014: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetValue(int32)
IL_0019: dup
IL_001a: stloc.0
IL_001b: stelem.i4
IL_001c: ldloc.0
IL_001d: stloc.1
IL_001e: br.s IL_0020
IL_0020: ldloc.1
IL_0021: ret
} // end of method InlineAssignmentTest::ArrayUsageWithMethods
.method public hidebysig instance int32
StaticPropertyTest() cil managed
{
// Code size 19 (0x13)
.maxstack 2
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0007: dup
IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_StaticProperty(int32)
IL_000d: nop
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
} // end of method InlineAssignmentTest::StaticPropertyTest
.method public hidebysig instance int32
InstancePropertyTest() cil managed
{
// Code size 22 (0x16)
.maxstack 3
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: call instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::GetIndex()
IL_0008: dup
IL_0009: stloc.0
IL_000a: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_InstanceProperty(int32)
IL_000f: nop
IL_0010: ldloc.0
IL_0011: stloc.1
IL_0012: br.s IL_0014
IL_0014: ldloc.1
IL_0015: ret
} // end of method InlineAssignmentTest::InstancePropertyTest
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method InlineAssignmentTest::.ctor
.property instance int32 InstanceProperty()
{
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::get_InstanceProperty()
.set instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_InstanceProperty(int32)
} // end of property InlineAssignmentTest::InstanceProperty
.property int32 StaticProperty()
{
.get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::get_StaticProperty()
.set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::set_StaticProperty(int32)
} // end of property InlineAssignmentTest::StaticProperty
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

6
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs

@ -388,8 +388,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void ForeachWithRefUsage(List<int> items) public static void ForeachWithRefUsage(List<int> items)
{ {
foreach (int item in items) { foreach (int item in items) {
#if ROSLYN && OPT
// The variable names differs based on whether roslyn optimizes out the 'item' variable
int current = item; int current = item;
Loops.Operation(ref current); Loops.Operation(ref current);
#else
int num = item;
Loops.Operation(ref num);
#endif
} }
} }

10
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -109,8 +109,11 @@ namespace ICSharpCode.Decompiler.CSharp
// CachedDelegateInitialization must run after ConditionDetection and before/in LoopingBlockTransform // CachedDelegateInitialization must run after ConditionDetection and before/in LoopingBlockTransform
// and must run before NullCoalescingTransform // and must run before NullCoalescingTransform
new CachedDelegateInitialization(), new CachedDelegateInitialization(),
new ILInlining(), // Run the assignment transform both before and after copy propagation.
new TransformAssignment(), // must run before CopyPropagation // Before is necessary because inline assignments of constants are otherwise
// copy-propated (turned into two separate assignments of the constant).
// After is necessary because the assigned value might involve null coalescing/etc.
new StatementTransform(new ILInlining(), new TransformAssignment()),
new CopyPropagation(), new CopyPropagation(),
new StatementTransform( new StatementTransform(
// per-block transforms that depend on each other, and thus need to // per-block transforms that depend on each other, and thus need to
@ -121,11 +124,12 @@ namespace ICSharpCode.Decompiler.CSharp
// Inlining must be first, because it doesn't trigger re-runs. // Inlining must be first, because it doesn't trigger re-runs.
// Any other transform that opens up new inlining opportunities should call RequestRerun(). // Any other transform that opens up new inlining opportunities should call RequestRerun().
new ExpressionTransforms(), new ExpressionTransforms(),
new TransformAssignment(), // inline and compound assignments
new NullCoalescingTransform(), new NullCoalescingTransform(),
new NullableLiftingStatementTransform(), new NullableLiftingStatementTransform(),
new TransformArrayInitializers(), new TransformArrayInitializers(),
new TransformCollectionAndObjectInitializers() new TransformCollectionAndObjectInitializers()
) ),
} }
}, },
new ProxyCallReplacer(), new ProxyCallReplacer(),

76
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -47,28 +47,32 @@ namespace ICSharpCode.Decompiler.CSharp
public TranslatedExpression Build(CallInstruction inst) public TranslatedExpression Build(CallInstruction inst)
{ {
IMethod method = inst.Method; if (inst is NewObj newobj && IL.Transforms.DelegateConstruction.IsDelegateConstruction(newobj, true)) {
return HandleDelegateConstruction(newobj);
}
return Build(inst.OpCode, inst.Method, inst.Arguments).WithILInstruction(inst);
}
public ExpressionWithResolveResult Build(OpCode callOpCode, IMethod method, IReadOnlyList<ILInstruction> callArguments)
{
// Used for Call, CallVirt and NewObj // Used for Call, CallVirt and NewObj
TranslatedExpression target; TranslatedExpression target;
if (inst.OpCode == OpCode.NewObj) { if (callOpCode == OpCode.NewObj) {
if (IL.Transforms.DelegateConstruction.IsDelegateConstruction((NewObj)inst, true)) {
return HandleDelegateConstruction(inst);
}
target = default(TranslatedExpression); // no target target = default(TranslatedExpression); // no target
} else { } else {
target = expressionBuilder.TranslateTarget(method, inst.Arguments.FirstOrDefault(), inst.OpCode == OpCode.Call); target = expressionBuilder.TranslateTarget(method, callArguments.FirstOrDefault(), callOpCode == OpCode.Call);
} }
int firstParamIndex = (method.IsStatic || inst.OpCode == OpCode.NewObj) ? 0 : 1; int firstParamIndex = (method.IsStatic || callOpCode == OpCode.NewObj) ? 0 : 1;
// Translate arguments to the expected parameter types // Translate arguments to the expected parameter types
var arguments = new List<TranslatedExpression>(method.Parameters.Count); var arguments = new List<TranslatedExpression>(method.Parameters.Count);
Debug.Assert(inst.Arguments.Count == firstParamIndex + method.Parameters.Count); Debug.Assert(callArguments.Count == firstParamIndex + method.Parameters.Count);
var expectedParameters = method.Parameters.ToList(); var expectedParameters = method.Parameters.ToList();
bool isExpandedForm = false; bool isExpandedForm = false;
for (int i = 0; i < method.Parameters.Count; i++) { for (int i = 0; i < method.Parameters.Count; i++) {
var parameter = expectedParameters[i]; var parameter = expectedParameters[i];
var arg = expressionBuilder.Translate(inst.Arguments[firstParamIndex + i]); var arg = expressionBuilder.Translate(callArguments[firstParamIndex + i]);
if (parameter.IsParams && i + 1 == method.Parameters.Count) { if (parameter.IsParams && i + 1 == method.Parameters.Count) {
// Parameter is marked params // Parameter is marked params
// If the argument is an array creation, inline all elements into the call and add missing default values. // If the argument is an array creation, inline all elements into the call and add missing default values.
@ -90,7 +94,7 @@ namespace ICSharpCode.Decompiler.CSharp
expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction()); expandedArguments.Add(expressionBuilder.GetDefaultValueExpression(elementType).WithoutILInstruction());
} }
} }
if (IsUnambiguousCall(inst, target, method, Array.Empty<IType>(), expandedArguments) == OverloadResolutionErrors.None) { if (IsUnambiguousCall(callOpCode, target, method, Array.Empty<IType>(), expandedArguments) == OverloadResolutionErrors.None) {
isExpandedForm = true; isExpandedForm = true;
expectedParameters = expandedParameters; expectedParameters = expandedParameters;
arguments = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach())); arguments = expandedArguments.SelectList(a => new TranslatedExpression(a.Expression.Detach()));
@ -124,7 +128,7 @@ namespace ICSharpCode.Decompiler.CSharp
ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm); ResolveResult rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults, isExpandedForm: isExpandedForm);
if (inst.OpCode == OpCode.NewObj) { if (callOpCode == OpCode.NewObj) {
if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) { if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) {
var argumentExpressions = arguments.SelectArray(arg => arg.Expression); var argumentExpressions = arguments.SelectArray(arg => arg.Expression);
AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
@ -140,11 +144,10 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
return atce return atce
.WithILInstruction(inst)
.WithRR(rr); .WithRR(rr);
} else { } else {
if (IsUnambiguousCall(inst, target, method, Array.Empty<IType>(), arguments) != OverloadResolutionErrors.None) { if (IsUnambiguousCall(callOpCode, target, method, Array.Empty<IType>(), arguments) != OverloadResolutionErrors.None) {
for (int i = 0; i < arguments.Count; i++) { for (int i = 0; i < arguments.Count; i++) {
if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) {
if (arguments[i].Expression is LambdaExpression lambda) { if (arguments[i].Expression is LambdaExpression lambda) {
@ -155,20 +158,20 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
} }
return new ObjectCreateExpression(expressionBuilder.ConvertType(inst.Method.DeclaringType), arguments.SelectArray(arg => arg.Expression)) return new ObjectCreateExpression(expressionBuilder.ConvertType(method.DeclaringType), arguments.SelectArray(arg => arg.Expression))
.WithILInstruction(inst).WithRR(rr); .WithRR(rr);
} }
} else { } else {
int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0); int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0);
if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expectedParameters.Count == allowedParamCount)) { if (method.IsAccessor && (method.AccessorOwner.SymbolKind == SymbolKind.Indexer || expectedParameters.Count == allowedParamCount)) {
return HandleAccessorCall(inst, target, method, arguments.ToList()); return HandleAccessorCall(callOpCode == OpCode.CallVirt, target, method, arguments.ToList());
} else if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate) { } else if (method.Name == "Invoke" && method.DeclaringType.Kind == TypeKind.Delegate) {
return new InvocationExpression(target, arguments.Select(arg => arg.Expression)).WithILInstruction(inst).WithRR(rr); return new InvocationExpression(target, arguments.Select(arg => arg.Expression)).WithRR(rr);
} else if (IsDelegateEqualityComparison(method, arguments)) { } else if (IsDelegateEqualityComparison(method, arguments)) {
return HandleDelegateEqualityComparison(method, arguments) return HandleDelegateEqualityComparison(method, arguments)
.WithILInstruction(inst).WithRR(rr); .WithRR(rr);
} else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1) { } else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1) {
return HandleImplicitConversion(inst, arguments[0]); return HandleImplicitConversion(method, arguments[0]);
} else { } else {
bool requireTypeArguments = false; bool requireTypeArguments = false;
bool targetCasted = false; bool targetCasted = false;
@ -176,7 +179,7 @@ namespace ICSharpCode.Decompiler.CSharp
IType[] typeArguments = Array.Empty<IType>(); IType[] typeArguments = Array.Empty<IType>();
OverloadResolutionErrors errors; OverloadResolutionErrors errors;
while ((errors = IsUnambiguousCall(inst, target, method, typeArguments, arguments)) != OverloadResolutionErrors.None) { while ((errors = IsUnambiguousCall(callOpCode, target, method, typeArguments, arguments)) != OverloadResolutionErrors.None) {
switch (errors) { switch (errors) {
case OverloadResolutionErrors.TypeInferenceFailed: case OverloadResolutionErrors.TypeInferenceFailed:
case OverloadResolutionErrors.WrongNumberOfTypeArguments: case OverloadResolutionErrors.WrongNumberOfTypeArguments:
@ -213,7 +216,7 @@ namespace ICSharpCode.Decompiler.CSharp
Expression targetExpr = target.Expression; Expression targetExpr = target.Expression;
string methodName = method.Name; string methodName = method.Name;
// HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method. // HACK : convert this.Dispose() to ((IDisposable)this).Dispose(), if Dispose is an explicitly implemented interface method.
if (inst.Method.IsExplicitInterfaceImplementation && targetExpr is ThisReferenceExpression) { if (method.IsExplicitInterfaceImplementation && targetExpr is ThisReferenceExpression) {
targetExpr = new CastExpression(expressionBuilder.ConvertType(method.ImplementedInterfaceMembers[0].DeclaringType), targetExpr); targetExpr = new CastExpression(expressionBuilder.ConvertType(method.ImplementedInterfaceMembers[0].DeclaringType), targetExpr);
methodName = method.ImplementedInterfaceMembers[0].Name; methodName = method.ImplementedInterfaceMembers[0].Name;
} }
@ -221,7 +224,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType()))) if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType())))
mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType));
var argumentExpressions = arguments.Select(arg => arg.Expression); var argumentExpressions = arguments.Select(arg => arg.Expression);
return new InvocationExpression(mre, argumentExpressions).WithILInstruction(inst).WithRR(rr); return new InvocationExpression(mre, argumentExpressions).WithRR(rr);
} }
} }
} }
@ -271,28 +274,27 @@ namespace ICSharpCode.Decompiler.CSharp
); );
} }
private TranslatedExpression HandleImplicitConversion(CallInstruction call, TranslatedExpression argument) private ExpressionWithResolveResult HandleImplicitConversion(IMethod method, TranslatedExpression argument)
{ {
var conversions = CSharpConversions.Get(expressionBuilder.compilation); var conversions = CSharpConversions.Get(expressionBuilder.compilation);
IType targetType = call.Method.ReturnType; IType targetType = method.ReturnType;
var conv = conversions.ImplicitConversion(argument.Type, targetType); var conv = conversions.ImplicitConversion(argument.Type, targetType);
if (!(conv.IsUserDefined && conv.Method.Equals(call.Method))) { if (!(conv.IsUserDefined && conv.Method.Equals(method))) {
// implicit conversion to targetType isn't directly possible, so first insert a cast to the argument type // implicit conversion to targetType isn't directly possible, so first insert a cast to the argument type
argument = argument.ConvertTo(call.Method.Parameters[0].Type, expressionBuilder); argument = argument.ConvertTo(method.Parameters[0].Type, expressionBuilder);
conv = conversions.ImplicitConversion(argument.Type, targetType); conv = conversions.ImplicitConversion(argument.Type, targetType);
} }
return new CastExpression(expressionBuilder.ConvertType(targetType), argument.Expression) return new CastExpression(expressionBuilder.ConvertType(targetType), argument.Expression)
.WithILInstruction(call)
.WithRR(new ConversionResolveResult(targetType, argument.ResolveResult, conv)); .WithRR(new ConversionResolveResult(targetType, argument.ResolveResult, conv));
} }
OverloadResolutionErrors IsUnambiguousCall(ILInstruction inst, TranslatedExpression target, IMethod method, IType[] typeArguments, IList<TranslatedExpression> arguments) OverloadResolutionErrors IsUnambiguousCall(OpCode callOpCode, TranslatedExpression target, IMethod method, IType[] typeArguments, IList<TranslatedExpression> arguments)
{ {
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
var or = new OverloadResolution(resolver.Compilation, arguments.SelectArray(a => a.ResolveResult), typeArguments: typeArguments); var or = new OverloadResolution(resolver.Compilation, arguments.SelectArray(a => a.ResolveResult), typeArguments: typeArguments);
if (inst is NewObj newObj) { if (callOpCode == OpCode.NewObj) {
foreach (IMethod ctor in newObj.Method.DeclaringType.GetConstructors()) { foreach (IMethod ctor in method.DeclaringType.GetConstructors()) {
if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == newObj.Method.DeclaringTypeDefinition)) { if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition)) {
or.AddCandidate(ctor); or.AddCandidate(ctor);
} }
} }
@ -304,7 +306,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
if (or.BestCandidateErrors != OverloadResolutionErrors.None) if (or.BestCandidateErrors != OverloadResolutionErrors.None)
return or.BestCandidateErrors; return or.BestCandidateErrors;
if (!IsAppropriateCallTarget(method, or.GetBestCandidateWithSubstitutedTypeArguments(), inst.OpCode == OpCode.CallVirt)) if (!IsAppropriateCallTarget(method, or.GetBestCandidateWithSubstitutedTypeArguments(), callOpCode == OpCode.CallVirt))
return OverloadResolutionErrors.AmbiguousMatch; return OverloadResolutionErrors.AmbiguousMatch;
return OverloadResolutionErrors.None; return OverloadResolutionErrors.None;
} }
@ -327,12 +329,12 @@ namespace ICSharpCode.Decompiler.CSharp
return true; return true;
} }
TranslatedExpression HandleAccessorCall(ILInstruction inst, TranslatedExpression target, IMethod method, IList<TranslatedExpression> arguments) ExpressionWithResolveResult HandleAccessorCall(bool isVirtCall, TranslatedExpression target, IMethod method, IList<TranslatedExpression> arguments)
{ {
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
var result = lookup.Lookup(target.ResolveResult, method.AccessorOwner.Name, EmptyList<IType>.Instance, isInvocation: false); var result = lookup.Lookup(target.ResolveResult, method.AccessorOwner.Name, EmptyList<IType>.Instance, isInvocation: false);
if (result.IsError || (result is MemberResolveResult && !IsAppropriateCallTarget(method.AccessorOwner, ((MemberResolveResult)result).Member, inst.OpCode == OpCode.CallVirt))) if (result.IsError || (result is MemberResolveResult && !IsAppropriateCallTarget(method.AccessorOwner, ((MemberResolveResult)result).Member, isVirtCall)))
target = target.ConvertTo(method.AccessorOwner.DeclaringType, expressionBuilder); target = target.ConvertTo(method.AccessorOwner.DeclaringType, expressionBuilder);
var rr = new MemberResolveResult(target.ResolveResult, method.AccessorOwner); var rr = new MemberResolveResult(target.ResolveResult, method.AccessorOwner);
@ -356,12 +358,12 @@ namespace ICSharpCode.Decompiler.CSharp
op = AssignmentOperatorType.Subtract; op = AssignmentOperatorType.Subtract;
} }
} }
return new AssignmentExpression(expr, op, value.Expression).WithILInstruction(inst).WithRR(new TypeResolveResult(method.AccessorOwner.ReturnType)); return new AssignmentExpression(expr, op, value.Expression).WithRR(new TypeResolveResult(method.AccessorOwner.ReturnType));
} else { } else {
if (arguments.Count == 0) if (arguments.Count == 0)
return new MemberReferenceExpression(target.Expression, method.AccessorOwner.Name).WithILInstruction(inst).WithRR(rr); return new MemberReferenceExpression(target.Expression, method.AccessorOwner.Name).WithRR(rr);
else else
return new IndexerExpression(target.Expression, arguments.Select(a => a.Expression)).WithILInstruction(inst).WithRR(rr); return new IndexerExpression(target.Expression, arguments.Select(a => a.Expression)).WithRR(rr);
} }
} }

19
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1078,7 +1078,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (NullableType.IsNullable(value.Type)) { if (NullableType.IsNullable(value.Type)) {
targetType = NullableType.Create(compilation, targetType); targetType = NullableType.Create(compilation, targetType);
} }
value = value.ConvertTo(targetType, this, inst.CheckForOverflow); value = value.ConvertTo(targetType, this, inst.CheckForOverflow, allowImplicitConversion: true);
break; break;
} }
case AssignmentOperatorType.Multiply: case AssignmentOperatorType.Multiply:
@ -1091,7 +1091,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (NullableType.IsNullable(value.Type)) { if (NullableType.IsNullable(value.Type)) {
targetType = NullableType.Create(compilation, targetType); targetType = NullableType.Create(compilation, targetType);
} }
value = value.ConvertTo(targetType, this, inst.CheckForOverflow); value = value.ConvertTo(targetType, this, inst.CheckForOverflow, allowImplicitConversion: true);
break; break;
} }
} }
@ -1694,11 +1694,26 @@ namespace ICSharpCode.Decompiler.CSharp
return TranslateObjectAndCollectionInitializer(block); return TranslateObjectAndCollectionInitializer(block);
case BlockType.PostfixOperator: case BlockType.PostfixOperator:
return TranslatePostfixOperator(block); return TranslatePostfixOperator(block);
case BlockType.CallInlineAssign:
return TranslateSetterCallAssignment(block);
default: default:
return ErrorExpression("Unknown block type: " + block.Type); return ErrorExpression("Unknown block type: " + block.Type);
} }
} }
private TranslatedExpression TranslateSetterCallAssignment(Block block)
{
if (!block.MatchInlineAssignBlock(out var call, out var value)) {
// should never happen unless the ILAst is invalid
return ErrorExpression("Error: MatchInlineAssignBlock() returned false");
}
var arguments = call.Arguments.ToList();
arguments[arguments.Count - 1] = value;
return new CallBuilder(this, typeSystem, settings)
.Build(call.OpCode, call.Method, arguments)
.WithILInstruction(call);
}
TranslatedExpression TranslateObjectAndCollectionInitializer(Block block) TranslatedExpression TranslateObjectAndCollectionInitializer(Block block)
{ {
var stloc = block.Instructions.FirstOrDefault() as StLoc; var stloc = block.Instructions.FirstOrDefault() as StLoc;

55
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -463,26 +463,6 @@ namespace ICSharpCode.Decompiler.CSharp
foreachVariable.Kind = VariableKind.ForeachLocal; foreachVariable.Kind = VariableKind.ForeachLocal;
foreachVariable.Name = AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>(), foreachVariable); foreachVariable.Name = AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>(), foreachVariable);
break; break;
case RequiredGetCurrentTransformation.UninlineAndUseExistingVariable:
// Unwrap stloc chain.
var nestedStores = new Stack<ILVariable>();
var currentInst = instToReplace; // instToReplace is the innermost value of the stloc chain.
while (currentInst.Parent is StLoc stloc) {
// Exclude nested stores to foreachVariable
// we'll insert one store at the beginning of the block.
if (stloc.Variable != foreachVariable && stloc.Parent is StLoc)
nestedStores.Push(stloc.Variable);
currentInst = stloc;
}
// Rebuild the nested store instructions:
ILInstruction reorderedStores = new LdLoc(foreachVariable);
while (nestedStores.Count > 0) {
reorderedStores = new StLoc(nestedStores.Pop(), reorderedStores);
}
currentInst.ReplaceWith(reorderedStores);
body.Instructions.Insert(0, new StLoc(foreachVariable, instToReplace));
// Adjust variable type, kind and name.
goto case RequiredGetCurrentTransformation.UseExistingVariable;
case RequiredGetCurrentTransformation.IntroduceNewVariable: case RequiredGetCurrentTransformation.IntroduceNewVariable:
foreachVariable = currentFunction.RegisterVariable( foreachVariable = currentFunction.RegisterVariable(
VariableKind.ForeachLocal, type, VariableKind.ForeachLocal, type,
@ -567,16 +547,6 @@ namespace ICSharpCode.Decompiler.CSharp
/// </summary> /// </summary>
UseExistingVariable, UseExistingVariable,
/// <summary> /// <summary>
/// Uninline (and possibly reorder) multiple stloc instructions and insert stloc foreachVar(call get_Current()) as first statement in the loop body.
/// <code>
/// ... (stloc foreachVar(stloc otherVar(call get_Current())) ...
/// =>
/// stloc foreachVar(call get_Current())
/// ... (stloc otherVar(ldloc foreachVar)) ...
/// </code>
/// </summary>
UninlineAndUseExistingVariable,
/// <summary>
/// No store was found, thus create a new variable and use it as foreach variable. /// No store was found, thus create a new variable and use it as foreach variable.
/// <code> /// <code>
/// ... (call get_Current()) ... /// ... (call get_Current()) ...
@ -617,32 +587,15 @@ namespace ICSharpCode.Decompiler.CSharp
// the result of call get_Current is casted. // the result of call get_Current is casted.
while (inst.Parent is UnboxAny || inst.Parent is CastClass) while (inst.Parent is UnboxAny || inst.Parent is CastClass)
inst = inst.Parent; inst = inst.Parent;
// Gather all nested assignments to determine the foreach variable.
List<StLoc> nestedStores = new List<StLoc>();
while (inst.Parent is StLoc stloc) {
nestedStores.Add(stloc);
inst = stloc;
}
// No variable was found: we need a new one.
if (nestedStores.Count == 0)
return RequiredGetCurrentTransformation.IntroduceNewVariable;
// One variable was found. // One variable was found.
if (nestedStores.Count == 1) { if (inst.Parent is StLoc stloc) {
// Must be a plain assignment expression and variable must only be used in 'body' + only assigned once. // Must be a plain assignment expression and variable must only be used in 'body' + only assigned once.
if (nestedStores[0].Parent == loopBody && VariableIsOnlyUsedInBlock(nestedStores[0], usingContainer)) { if (stloc.Parent == loopBody && VariableIsOnlyUsedInBlock(stloc, usingContainer)) {
foreachVariable = nestedStores[0].Variable; foreachVariable = stloc.Variable;
return RequiredGetCurrentTransformation.UseExistingVariable; return RequiredGetCurrentTransformation.UseExistingVariable;
} }
} else {
// Check if any of the variables is usable as foreach variable.
foreach (var store in nestedStores) {
if (VariableIsOnlyUsedInBlock(store, usingContainer)) {
foreachVariable = store.Variable;
return RequiredGetCurrentTransformation.UninlineAndUseExistingVariable;
}
}
} }
// No suitable variable found. // No suitable variable was found: we need a new one.
return RequiredGetCurrentTransformation.IntroduceNewVariable; return RequiredGetCurrentTransformation.IntroduceNewVariable;
} }

4
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -51,8 +51,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.2.0" /> <PackageReference Include="Humanizer.Core" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" /> <PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="System.ValueTuple" Version="4.4.0" /> <PackageReference Include="System.ValueTuple" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

35
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -127,5 +127,40 @@ namespace ICSharpCode.Decompiler.IL
{ {
return primitiveType.GetStackType().IsIntegerType(); return primitiveType.GetStackType().IsIntegerType();
} }
/// <summary>
/// Infers the C# type for an IL instruction.
///
/// Returns SpecialType.UnknownType for unsupported instructions.
/// </summary>
public static IType InferType(this ILInstruction inst)
{
switch (inst) {
case NewObj newObj:
return newObj.Method.DeclaringType;
case Call call:
return call.Method.ReturnType;
case CallVirt callVirt:
return callVirt.Method.ReturnType;
case CallIndirect calli:
return calli.ReturnType;
case LdObj ldobj:
return ldobj.Type;
case StObj stobj:
return stobj.Type;
case LdLoc ldloc:
return ldloc.Variable.Type;
case StLoc stloc:
return stloc.Variable.Type;
case LdLoca ldloca:
return new TypeSystem.ByReferenceType(ldloca.Variable.Type);
case LdFlda ldflda:
return new TypeSystem.ByReferenceType(ldflda.Field.Type);
case LdsFlda ldsflda:
return new TypeSystem.ByReferenceType(ldsflda.Field.Type);
default:
return SpecialType.UnknownType;
}
}
} }
} }

15
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -335,6 +335,21 @@ namespace ICSharpCode.Decompiler.IL
{ {
output.WriteReference(this.Name, this, isLocal: true); output.WriteReference(this.Name, this, isLocal: true);
} }
/// <summary>
/// Gets whether this variable occurs within the specified instruction.
/// </summary>
internal bool IsUsedWithin(ILInstruction inst)
{
if (inst is IInstructionWithVariableOperand iwvo && iwvo.Variable == this) {
return true;
}
foreach (var child in inst.Children) {
if (IsUsedWithin(child))
return true;
}
return false;
}
} }
public interface IInstructionWithVariableOperand public interface IInstructionWithVariableOperand

117
ICSharpCode.Decompiler/IL/Instructions.cs

@ -93,7 +93,8 @@ namespace ICSharpCode.Decompiler.IL
LdLoc, LdLoc,
/// <summary>Loads the address of a local variable. (ldarga/ldloca)</summary> /// <summary>Loads the address of a local variable. (ldarga/ldloca)</summary>
LdLoca, LdLoca,
/// <summary>Stores a value into a local variable. (starg/stloc)</summary> /// <summary>Stores a value into a local variable. (IL: starg/stloc)
/// Evaluates to the value that was stored (for byte/short variables: evaluates to the truncated value, sign/zero extended back to I4 based on variable.Type.GetSign())</summary>
StLoc, StLoc,
/// <summary>Stores the value into an anonymous temporary variable, and returns the address of that variable.</summary> /// <summary>Stores the value into an anonymous temporary variable, and returns the address of that variable.</summary>
AddressOf, AddressOf,
@ -137,7 +138,8 @@ namespace ICSharpCode.Decompiler.IL
IsInst, IsInst,
/// <summary>Indirect load (ref/pointer dereference).</summary> /// <summary>Indirect load (ref/pointer dereference).</summary>
LdObj, LdObj,
/// <summary>Indirect store (store to ref/pointer).</summary> /// <summary>Indirect store (store to ref/pointer).
/// Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value, sign/zero extended back to I4 based on type.GetSign())</summary>
StObj, StObj,
/// <summary>Boxes a value.</summary> /// <summary>Boxes a value.</summary>
Box, Box,
@ -941,9 +943,12 @@ namespace ICSharpCode.Decompiler.IL
clone.Value = this.value.Clone(); clone.Value = this.value.Clone();
return clone; return clone;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return type.GetStackType(); } } public override StackType ResultType { get { return type.GetStackType(); } }
public override void AcceptVisitor(ILVisitor visitor) public override void AcceptVisitor(ILVisitor visitor)
{ {
@ -2217,7 +2222,8 @@ namespace ICSharpCode.Decompiler.IL
} }
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
/// <summary>Stores a value into a local variable. (starg/stloc)</summary> /// <summary>Stores a value into a local variable. (IL: starg/stloc)
/// Evaluates to the value that was stored (for byte/short variables: evaluates to the truncated value, sign/zero extended back to I4 based on variable.Type.GetSign())</summary>
public sealed partial class StLoc : ILInstruction, IStoreInstruction public sealed partial class StLoc : ILInstruction, IStoreInstruction
{ {
public StLoc(ILVariable variable, ILInstruction value) : base(OpCode.StLoc) public StLoc(ILVariable variable, ILInstruction value) : base(OpCode.StLoc)
@ -2811,9 +2817,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.O; } } public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{ {
@ -3347,9 +3356,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return type.GetStackType(); } } public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -3398,9 +3410,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.O; } } public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{ {
@ -3488,9 +3503,12 @@ namespace ICSharpCode.Decompiler.IL
clone.Target = this.target.Clone(); clone.Target = this.target.Clone();
return clone; return clone;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
/// <summary>Gets/Sets whether the memory access is volatile.</summary> /// <summary>Gets/Sets whether the memory access is volatile.</summary>
public bool IsVolatile { get; set; } public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> /// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
@ -3540,7 +3558,8 @@ namespace ICSharpCode.Decompiler.IL
} }
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
/// <summary>Indirect store (store to ref/pointer).</summary> /// <summary>Indirect store (store to ref/pointer).
/// Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value, sign/zero extended back to I4 based on type.GetSign())</summary>
public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
public StObj(ILInstruction target, ILInstruction value, IType type) : base(OpCode.StObj) public StObj(ILInstruction target, ILInstruction value, IType type) : base(OpCode.StObj)
@ -3613,9 +3632,12 @@ namespace ICSharpCode.Decompiler.IL
clone.Value = this.value.Clone(); clone.Value = this.value.Clone();
return clone; return clone;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
/// <summary>Gets/Sets whether the memory access is volatile.</summary> /// <summary>Gets/Sets whether the memory access is volatile.</summary>
public bool IsVolatile { get; set; } public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> /// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
@ -3674,9 +3696,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.O; } } public override StackType ResultType { get { return StackType.O; } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -3725,9 +3750,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.Ref; } } public override StackType ResultType { get { return StackType.Ref; } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -3776,9 +3804,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return type.GetStackType(); } } public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -3852,9 +3883,12 @@ namespace ICSharpCode.Decompiler.IL
this.Indices = new InstructionCollection<ILInstruction>(this, 0); this.Indices = new InstructionCollection<ILInstruction>(this, 0);
this.Indices.AddRange(indices); this.Indices.AddRange(indices);
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public static readonly SlotInfo IndicesSlot = new SlotInfo("Indices", canInlineInto: true); public static readonly SlotInfo IndicesSlot = new SlotInfo("Indices", canInlineInto: true);
public InstructionCollection<ILInstruction> Indices { get; private set; } public InstructionCollection<ILInstruction> Indices { get; private set; }
protected sealed override int GetChildCount() protected sealed override int GetChildCount()
@ -3942,9 +3976,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return type.GetStackType(); } } public override StackType ResultType { get { return type.GetStackType(); } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{ {
@ -4055,9 +4092,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.I4; } } public override StackType ResultType { get { return StackType.I4; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{ {
@ -4177,9 +4217,12 @@ namespace ICSharpCode.Decompiler.IL
this.Indices = new InstructionCollection<ILInstruction>(this, 1); this.Indices = new InstructionCollection<ILInstruction>(this, 1);
this.Indices.AddRange(indices); this.Indices.AddRange(indices);
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public static readonly SlotInfo ArraySlot = new SlotInfo("Array", canInlineInto: true); public static readonly SlotInfo ArraySlot = new SlotInfo("Array", canInlineInto: true);
ILInstruction array; ILInstruction array;
public ILInstruction Array { public ILInstruction Array {
@ -4464,9 +4507,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.O; } } public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options) public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{ {
@ -4534,9 +4580,12 @@ namespace ICSharpCode.Decompiler.IL
{ {
this.type = type; this.type = type;
} }
readonly IType type; IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } } public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.Ref; } } public override StackType ResultType { get { return StackType.Ref; } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {

13
ICSharpCode.Decompiler/IL/Instructions.tt

@ -150,7 +150,8 @@
CustomClassName("LdLoc"), NoArguments, HasVariableOperand("Load"), ResultType("variable.StackType")), CustomClassName("LdLoc"), NoArguments, HasVariableOperand("Load"), ResultType("variable.StackType")),
new OpCode("ldloca", "Loads the address of a local variable. (ldarga/ldloca)", new OpCode("ldloca", "Loads the address of a local variable. (ldarga/ldloca)",
CustomClassName("LdLoca"), NoArguments, ResultType("Ref"), HasVariableOperand("Address")), CustomClassName("LdLoca"), NoArguments, ResultType("Ref"), HasVariableOperand("Address")),
new OpCode("stloc", "Stores a value into a local variable. (starg/stloc)", new OpCode("stloc", "Stores a value into a local variable. (IL: starg/stloc)" + Environment.NewLine
+ "Evaluates to the value that was stored (for byte/short variables: evaluates to the truncated value, sign/zero extended back to I4 based on variable.Type.GetSign())",
CustomClassName("StLoc"), HasVariableOperand("Store"), CustomArguments("value"), CustomClassName("StLoc"), HasVariableOperand("Store"), CustomArguments("value"),
ResultType("variable.StackType")), ResultType("variable.StackType")),
new OpCode("addressof", "Stores the value into an anonymous temporary variable, and returns the address of that variable.", new OpCode("addressof", "Stores the value into an anonymous temporary variable, and returns the address of that variable.",
@ -204,7 +205,8 @@
new OpCode("ldobj", "Indirect load (ref/pointer dereference).", new OpCode("ldobj", "Indirect load (ref/pointer dereference).",
CustomClassName("LdObj"), CustomArguments("target"), HasTypeOperand, MemoryAccess, CustomWriteToButKeepOriginal, CustomClassName("LdObj"), CustomArguments("target"), HasTypeOperand, MemoryAccess, CustomWriteToButKeepOriginal,
SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, ResultType("type.GetStackType()")), SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, ResultType("type.GetStackType()")),
new OpCode("stobj", "Indirect store (store to ref/pointer).", new OpCode("stobj", "Indirect store (store to ref/pointer)." + Environment.NewLine
+ "Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value, sign/zero extended back to I4 based on type.GetSign())",
CustomClassName("StObj"), CustomArguments("target", "value"), HasTypeOperand, MemoryAccess, CustomWriteToButKeepOriginal, CustomClassName("StObj"), CustomArguments("target", "value"), HasTypeOperand, MemoryAccess, CustomWriteToButKeepOriginal,
SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, ResultType("type.GetStackType()")), SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, ResultType("type.GetStackType()")),
@ -937,12 +939,15 @@ protected override void Disconnected()
static Action<OpCode> HasTypeOperand = opCode => { static Action<OpCode> HasTypeOperand = opCode => {
opCode.ConstructorParameters.Add("IType type"); opCode.ConstructorParameters.Add("IType type");
opCode.Members.Add("readonly IType type;"); opCode.Members.Add("IType type;");
opCode.ConstructorBody.Add("this.type = type;"); opCode.ConstructorBody.Add("this.type = type;");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "IType", Name = "type", FieldName = "Type" }); opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "IType", Name = "type", FieldName = "Type" });
opCode.PerformMatchConditions.Add("type.Equals(o.type)"); opCode.PerformMatchConditions.Add("type.Equals(o.type)");
opCode.Members.Add("/// <summary>Returns the type operand.</summary>" + Environment.NewLine opCode.Members.Add("/// <summary>Returns the type operand.</summary>" + Environment.NewLine
+ "public IType Type { get { return type; } }"); + "public IType Type {" + Environment.NewLine
+ "\tget { return type; }" + Environment.NewLine
+ "\tset { type = value; InvalidateFlags(); }" + Environment.NewLine
+ "}");
opCode.GenerateWriteTo = true; opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');"); opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("type.WriteTo(output);"); opCode.WriteOperand.Add("type.WriteTo(output);");

62
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -108,8 +108,13 @@ namespace ICSharpCode.Decompiler.IL
// only the last instruction may have an unreachable endpoint // only the last instruction may have an unreachable endpoint
Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable)); Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable));
} }
if (this.Type == BlockType.ControlFlow) { switch (this.Type) {
Debug.Assert(finalInstruction.OpCode == OpCode.Nop); case BlockType.ControlFlow:
Debug.Assert(finalInstruction.OpCode == OpCode.Nop);
break;
case BlockType.CallInlineAssign:
Debug.Assert(MatchInlineAssignBlock(out _, out _));
break;
} }
} }
@ -251,13 +256,62 @@ namespace ICSharpCode.Decompiler.IL
} }
return inst; return inst;
} }
public bool MatchInlineAssignBlock(out CallInstruction call, out ILInstruction value)
{
call = null;
value = null;
if (this.Type != BlockType.CallInlineAssign)
return false;
if (this.Instructions.Count != 1)
return false;
call = this.Instructions[0] as CallInstruction;
if (call == null || call.Arguments.Count == 0)
return false;
if (!call.Arguments.Last().MatchStLoc(out var tmp, out value))
return false;
if (!(tmp.IsSingleDefinition && tmp.LoadCount == 1))
return false;
return this.FinalInstruction.MatchLdLoc(tmp);
}
} }
public enum BlockType { public enum BlockType
{
/// <summary>
/// Block is used for control flow.
/// All blocks in block containers must have this type.
/// Control flow blocks cannot evaluate to a value (FinalInstruction must be Nop).
/// </summary>
ControlFlow, ControlFlow,
/// <summary>
/// Block is used for array initializers, e.g. `new int[] { expr1, expr2 }`.
/// </summary>
ArrayInitializer, ArrayInitializer,
CollectionInitializer, CollectionInitializer,
ObjectInitializer, ObjectInitializer,
PostfixOperator /// <summary>
/// Block is used for postfix operator on local variable.
/// </summary>
/// <remarks>
/// Postfix operators on non-locals use CompoundAssignmentInstruction with CompoundAssignmentType.EvaluatesToOldValue.
/// </remarks>
PostfixOperator,
/// <summary>
/// Block is used for using the result of a property setter inline.
/// Example: <code>Use(this.Property = value);</code>
/// This is only for inline assignments to property or indexers; other inline assignments work
/// by using the result value of the stloc/stobj instructions.
///
/// Constructed by TransformAssignment.
/// Can be deconstructed using Block.MatchInlineAssignBlock().
/// </summary>
/// <example>
/// Block {
/// call setter(..., stloc s(...))
/// final: ldloc s
/// }
/// </example>
CallInlineAssign
} }
} }

14
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs

@ -85,6 +85,18 @@ namespace ICSharpCode.Decompiler.IL
return false; return false;
type = NullableType.GetUnderlyingType(type); type = NullableType.GetUnderlyingType(type);
} }
if (type.Kind == TypeKind.Enum) {
switch (binary.Operator) {
case BinaryNumericOperator.Add:
case BinaryNumericOperator.Sub:
case BinaryNumericOperator.BitAnd:
case BinaryNumericOperator.BitOr:
case BinaryNumericOperator.BitXor:
break; // OK
default:
return false; // operator not supported on enum types
}
}
if (binary.Sign != Sign.None) { if (binary.Sign != Sign.None) {
if (type.GetSign() != binary.Sign) if (type.GetSign() != binary.Sign)
return false; return false;
@ -95,7 +107,7 @@ namespace ICSharpCode.Decompiler.IL
internal static bool IsValidCompoundAssignmentTarget(ILInstruction inst) internal static bool IsValidCompoundAssignmentTarget(ILInstruction inst)
{ {
switch (inst.OpCode) { switch (inst.OpCode) {
case OpCode.LdLoc: // case OpCode.LdLoc: -- not valid -- does not mark the variable as written to
case OpCode.LdObj: case OpCode.LdObj:
return true; return true;
case OpCode.Call: case OpCode.Call:

4
ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs

@ -140,6 +140,10 @@ namespace ICSharpCode.Decompiler.IL
/// </remarks> /// </remarks>
public int IndexOf(T item) public int IndexOf(T item)
{ {
if (item == null) {
// InstructionCollection can't contain nulls
return -1;
}
// If this collection is the item's primary position, we can use ChildIndex: // If this collection is the item's primary position, we can use ChildIndex:
int index = item.ChildIndex - firstChildIndex; int index = item.ChildIndex - firstChildIndex;
if (index >= 0 && index < list.Count && list[index] == item) if (index >= 0 && index < list.Count && list[index] == item)

8
ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.IL
if (this.MatchLdFld(out var target, out var field)) { if (this.MatchLdFld(out var target, out var field)) {
ILRange.WriteTo(output, options); ILRange.WriteTo(output, options);
output.Write("ldfld "); output.Write("ldfld ");
Disassembler.DisassemblerHelpers.WriteOperand(output, field); field.WriteTo(output);
output.Write('('); output.Write('(');
target.WriteTo(output, options); target.WriteTo(output, options);
output.Write(')'); output.Write(')');
@ -51,7 +51,7 @@ namespace ICSharpCode.Decompiler.IL
} else if (this.MatchLdsFld(out field)) { } else if (this.MatchLdsFld(out field)) {
ILRange.WriteTo(output, options); ILRange.WriteTo(output, options);
output.Write("ldsfld "); output.Write("ldsfld ");
Disassembler.DisassemblerHelpers.WriteOperand(output, field); field.WriteTo(output);
return; return;
} }
} }
@ -67,7 +67,7 @@ namespace ICSharpCode.Decompiler.IL
if (this.MatchStFld(out var target, out var field, out var value)) { if (this.MatchStFld(out var target, out var field, out var value)) {
ILRange.WriteTo(output, options); ILRange.WriteTo(output, options);
output.Write("stfld "); output.Write("stfld ");
Disassembler.DisassemblerHelpers.WriteOperand(output, field); field.WriteTo(output);
output.Write('('); output.Write('(');
target.WriteTo(output, options); target.WriteTo(output, options);
output.Write(", "); output.Write(", ");
@ -77,7 +77,7 @@ namespace ICSharpCode.Decompiler.IL
} else if (this.MatchStsFld(out field, out value)) { } else if (this.MatchStsFld(out field, out value)) {
ILRange.WriteTo(output, options); ILRange.WriteTo(output, options);
output.Write("stsfld "); output.Write("stsfld ");
Disassembler.DisassemblerHelpers.WriteOperand(output, field); field.WriteTo(output);
output.Write('('); output.Write('(');
value.WriteTo(output, options); value.WriteTo(output, options);
output.Write(')'); output.Write(')');

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

@ -359,18 +359,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (!variableType.IsKnownType(KnownTypeCode.Object)) if (!variableType.IsKnownType(KnownTypeCode.Object))
return variableType; return variableType;
switch (inst) { IType inferredType = inst.InferType();
case NewObj newObj: if (inferredType.Kind != TypeKind.Unknown)
return newObj.Method.DeclaringType; return inferredType;
case Call call: else
return call.Method.ReturnType; return variableType;
case CallVirt callVirt:
return callVirt.Method.ReturnType;
case CallIndirect calli:
return calli.ReturnType;
default:
return context.TypeSystem.Compilation.FindType(inst.ResultType.ToKnownTypeCode());
}
} }
internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, ILVariable existingVariable = null) internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, ILVariable existingVariable = null)

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

@ -16,9 +16,11 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.IL.Transforms namespace ICSharpCode.Decompiler.IL.Transforms
{ {
@ -277,20 +279,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.RequestRerun(); context.RequestRerun();
return; return;
} }
TransformAssignment.HandleStObjCompoundAssign(inst, context);
if (inst.Value is BinaryNumericInstruction binary
&& binary.Left.MatchLdObj(out ILInstruction target, out IType t)
&& inst.Target.Match(target).Success
&& SemanticHelper.IsPure(target.Flags)
&& CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, t))
{
context.Step("compound assignment", inst);
// stobj(target, binary.op(ldobj(target), ...))
// => compound.op(target, ...)
inst.ReplaceWith(new CompoundAssignmentInstruction(
binary, binary.Left, binary.Right,
t, CompoundAssignmentType.EvaluatesToNewValue));
}
} }
protected internal override void VisitIfInstruction(IfInstruction inst) protected internal override void VisitIfInstruction(IfInstruction inst)

567
ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

@ -17,38 +17,36 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL.Transforms namespace ICSharpCode.Decompiler.IL.Transforms
{ {
/// <summary> /// <summary>
/// Constructs compound assignments and inline assignments. /// Constructs compound assignments and inline assignments.
/// </summary> /// </summary>
public class TransformAssignment : IBlockTransform public class TransformAssignment : IStatementTransform
{ {
BlockTransformContext context; StatementTransformContext context;
void IBlockTransform.Run(Block block, BlockTransformContext context) void IStatementTransform.Run(Block block, int pos, StatementTransformContext context)
{ {
this.context = context; this.context = context;
for (int i = block.Instructions.Count - 1; i >= 0; i--) { if (TransformInlineAssignmentStObjOrCall(block, pos) || TransformInlineAssignmentLocal(block, pos)) {
if (TransformPostIncDecOperatorOnAddress(block, i) || TransformPostIncDecOnStaticField(block, i) || TransformCSharp4PostIncDecOperatorOnAddress(block, i)) { // both inline assignments create a top-level stloc which might affect inlining
block.Instructions.RemoveAt(i); context.RequestRerun();
continue; return;
} }
if (TransformPostIncDecOperator(block, i)) { if (TransformPostIncDecOperatorWithInlineStore(block, pos)
block.Instructions.RemoveAt(i); || TransformPostIncDecOperator(block, pos)
continue; || TransformPostIncDecOperatorLocal(block, pos))
} {
if (TransformInlineAssignmentStObj(block, i)) // again, new top-level stloc might need inlining:
continue; context.RequestRerun();
if (TransformInlineCompoundAssignmentCall(block, i)) return;
continue;
if (TransformRoslynCompoundAssignmentCall(block, i))
continue;
if (TransformRoslynPostIncDecOperatorOnAddress(block, i))
continue;
} }
} }
@ -56,124 +54,135 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// stloc s(value) /// stloc s(value)
/// stloc l(ldloc s) /// stloc l(ldloc s)
/// stobj(..., ldloc s) /// stobj(..., ldloc s)
/// where ... is pure and does not use s or l,
/// and where neither the 'stloc s' nor the 'stobj' truncates
/// --> /// -->
/// stloc l(stobj (..., value)) /// stloc l(stobj (..., value))
/// </code> /// </code>
/// e.g. used for inline assignment to instance field
///
/// -or- /// -or-
///
/// <code> /// <code>
/// stloc s(value) /// stloc s(value)
/// stobj (..., ldloc s) /// stobj (..., ldloc s)
/// where ... is pure and does not use s, and where the 'stobj' does not truncate
/// --> /// -->
/// stloc s(stobj (..., value)) /// stloc s(stobj (..., value))
/// </code> /// </code>
bool TransformInlineAssignmentStObj(Block block, int i) /// e.g. used for inline assignment to static field
///
/// -or-
///
/// <code>
/// stloc s(value)
/// call set_Property(..., ldloc s)
/// where the '...' arguments are pure and not using 's'
/// -->
/// stloc s(Block InlineAssign { call set_Property(..., stloc i(value)); final: ldloc i })
/// new temporary 'i' has type of the property; transform only valid if 'stloc i' doesn't truncate
/// </code>
bool TransformInlineAssignmentStObjOrCall(Block block, int pos)
{ {
var inst = block.Instructions[i] as StLoc; var inst = block.Instructions[pos] as StLoc;
// in some cases it can be a compiler-generated local // in some cases it can be a compiler-generated local
if (inst == null || (inst.Variable.Kind != VariableKind.StackSlot && inst.Variable.Kind != VariableKind.Local)) if (inst == null || (inst.Variable.Kind != VariableKind.StackSlot && inst.Variable.Kind != VariableKind.Local))
return false; return false;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1); if (IsImplicitTruncation(inst.Value, inst.Variable.Type)) {
ILInstruction replacement; // 'stloc s' is implicitly truncating the value
StObj fieldStore; return false;
}
ILVariable local; ILVariable local;
if (nextInst is StLoc) { // instance fields int nextPos;
var localStore = (StLoc)nextInst; if (block.Instructions[pos + 1] is StLoc localStore) { // with extra local
if (localStore.Variable.Kind == VariableKind.StackSlot || !localStore.Value.MatchLdLoc(inst.Variable)) if (localStore.Variable.Kind != VariableKind.Local || !localStore.Value.MatchLdLoc(inst.Variable))
return false;
// if we're using an extra local, we'll delete "s", so check that that doesn't have any additional uses
if (!(inst.Variable.IsSingleDefinition && inst.Variable.LoadCount == 2))
return false;
local = localStore.Variable;
nextPos = pos + 2;
} else {
local = inst.Variable;
localStore = null;
nextPos = pos + 1;
}
if (block.Instructions[nextPos] is StObj stobj) {
if (!stobj.Value.MatchLdLoc(inst.Variable))
return false;
if (!SemanticHelper.IsPure(stobj.Target.Flags) || inst.Variable.IsUsedWithin(stobj.Target))
return false;
if (IsImplicitTruncation(inst.Value, stobj.Type)) {
// 'stobj' is implicitly truncating the value
return false; return false;
var memberStore = block.Instructions.ElementAtOrDefault(i + 2); }
if (memberStore is StObj) { context.Step("Inline assignment stobj", stobj);
fieldStore = memberStore as StObj; block.Instructions.Remove(localStore);
if (!fieldStore.Value.MatchLdLoc(inst.Variable)) block.Instructions.Remove(stobj);
stobj.Value = inst.Value;
inst.ReplaceWith(new StLoc(local, stobj));
// note: our caller will trigger a re-run, which will call HandleStObjCompoundAssign if applicable
return true;
} else if (block.Instructions[nextPos] is CallInstruction call) {
// call must be a setter call:
if (!(call.OpCode == OpCode.Call || call.OpCode == OpCode.CallVirt))
return false;
if (call.ResultType != StackType.Void || call.Arguments.Count == 0)
return false;
if (!call.Method.Equals((call.Method.AccessorOwner as IProperty)?.Setter))
return false;
if (!call.Arguments.Last().MatchLdLoc(inst.Variable))
return false;
foreach (var arg in call.Arguments.SkipLast(1)) {
if (!SemanticHelper.IsPure(arg.Flags) || inst.Variable.IsUsedWithin(arg))
return false; return false;
replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type);
} else { // otherwise it must be local
return TransformInlineAssignmentLocal(block, i);
} }
context.Step("Inline assignment to instance field", fieldStore); if (IsImplicitTruncation(inst.Value, call.Method.Parameters.Last().Type)) {
local = localStore.Variable; // setter call is implicitly truncating the value
block.Instructions.RemoveAt(i + 1);
} else if (nextInst is StObj) { // static fields
fieldStore = (StObj)nextInst;
if (!fieldStore.Value.MatchLdLoc(inst.Variable) || (fieldStore.Target.MatchLdFlda(out var target, out _) && target.MatchLdLoc(inst.Variable)))
return false; return false;
context.Step("Inline assignment to static field", fieldStore); }
local = inst.Variable; // stloc s(Block InlineAssign { call set_Property(..., stloc i(value)); final: ldloc i })
replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); context.Step("Inline assignment call", call);
block.Instructions.Remove(localStore);
block.Instructions.Remove(call);
var newVar = context.Function.RegisterVariable(VariableKind.StackSlot, call.Method.Parameters.Last().Type);
call.Arguments[call.Arguments.Count - 1] = new StLoc(newVar, inst.Value);
var inlineBlock = new Block(BlockType.CallInlineAssign) {
Instructions = { call },
FinalInstruction = new LdLoc(newVar)
};
inst.ReplaceWith(new StLoc(local, inlineBlock));
// because the ExpressionTransforms don't look into inline blocks, manually trigger HandleCallCompoundAssign
if (HandleCallCompoundAssign(call, context)) {
// if we did construct a compound assignment, it should have made our inline block redundant:
if (inlineBlock.Instructions.Single().MatchStLoc(newVar, out var compoundAssign)) {
Debug.Assert(newVar.IsSingleDefinition && newVar.LoadCount == 1);
inlineBlock.ReplaceWith(compoundAssign);
}
}
return true;
} else { } else {
return false; return false;
} }
block.Instructions.RemoveAt(i + 1);
inst.ReplaceWith(new StLoc(local, replacement));
return true;
} }
/// <code> static ILInstruction UnwrapSmallIntegerConv(ILInstruction inst, out Conv conv)
/// stloc s(binary(callvirt(getter), value))
/// callvirt (setter, ldloc s)
/// (followed by single usage of s in next instruction)
/// -->
/// stloc s(compound.op.new(callvirt(getter), value))
/// </code>
bool TransformInlineCompoundAssignmentCall(Block block, int i)
{ {
var mainStLoc = block.Instructions[i] as StLoc; conv = inst as Conv;
// in some cases it can be a compiler-generated local if (conv != null && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) {
if (mainStLoc == null || (mainStLoc.Variable.Kind != VariableKind.StackSlot && mainStLoc.Variable.Kind != VariableKind.Local)) // for compound assignments to small integers, the compiler emits a "conv" instruction
return false; return conv.Argument;
BinaryNumericInstruction binary = mainStLoc.Value as BinaryNumericInstruction; } else {
ILVariable localVariable = mainStLoc.Variable; return inst;
if (!localVariable.IsSingleDefinition) }
return false;
if (localVariable.LoadCount != 2)
return false;
var getterCall = binary?.Left as CallInstruction;
var setterCall = block.Instructions.ElementAtOrDefault(i + 1) as CallInstruction;
if (!MatchingGetterAndSetterCalls(getterCall, setterCall))
return false;
if (!setterCall.Arguments.Last().MatchLdLoc(localVariable))
return false;
var next = block.Instructions.ElementAtOrDefault(i + 2);
if (next == null)
return false;
if (next.Descendants.Where(d => d.MatchLdLoc(localVariable)).Count() != 1)
return false;
if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, getterCall.Method.ReturnType))
return false;
context.Step($"Inline compound assignment to '{getterCall.Method.AccessorOwner.Name}'", setterCall);
block.Instructions.RemoveAt(i + 1); // remove setter call
binary.ReplaceWith(new CompoundAssignmentInstruction(
binary, getterCall, binary.Right,
getterCall.Method.ReturnType, CompoundAssignmentType.EvaluatesToNewValue));
return true;
} }
/// <summary> static bool ValidateCompoundAssign(BinaryNumericInstruction binary, Conv conv, IType targetType)
/// Roslyn compound assignment that's not inline within another instruction.
/// </summary>
bool TransformRoslynCompoundAssignmentCall(Block block, int i)
{ {
// stloc variable(callvirt get_Property(ldloc obj)) if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType))
// callvirt set_Property(ldloc obj, binary.op(ldloc variable, ldc.i4 1))
// => compound.op.new(callvirt get_Property(ldloc obj), ldc.i4 1)
if (!(block.Instructions[i] is StLoc stloc))
return false;
if (!(stloc.Variable.IsSingleDefinition && stloc.Variable.LoadCount == 1))
return false;
var getterCall = stloc.Value as CallInstruction;
var setterCall = block.Instructions[i + 1] as CallInstruction;
if (!(MatchingGetterAndSetterCalls(getterCall, setterCall)))
return false;
var binary = setterCall.Arguments.Last() as BinaryNumericInstruction;
if (binary == null || !binary.Left.MatchLdLoc(stloc.Variable))
return false; return false;
if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, getterCall.Method.ReturnType)) if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow))
return false; return false; // conv does not match binary operation
context.Step($"Compound assignment to '{getterCall.Method.AccessorOwner.Name}'", setterCall);
block.Instructions.RemoveAt(i + 1); // remove setter call
stloc.ReplaceWith(new CompoundAssignmentInstruction(
binary, getterCall, binary.Right,
getterCall.Method.ReturnType, CompoundAssignmentType.EvaluatesToNewValue));
return true; return true;
} }
@ -206,21 +215,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms
internal static bool HandleCallCompoundAssign(CallInstruction setterCall, StatementTransformContext context) internal static bool HandleCallCompoundAssign(CallInstruction setterCall, StatementTransformContext context)
{ {
// callvirt set_Property(ldloc S_1, binary.op(callvirt get_Property(ldloc S_1), value)) // callvirt set_Property(ldloc S_1, binary.op(callvirt get_Property(ldloc S_1), value))
// ==> compound.op.new(callvirt(callvirt get_Property(ldloc S_1)), value) // ==> compound.op.new(callvirt get_Property(ldloc S_1), value)
var setterValue = setterCall.Arguments.LastOrDefault(); var setterValue = setterCall.Arguments.LastOrDefault();
var storeInSetter = setterValue as StLoc; var storeInSetter = setterValue as StLoc;
if (storeInSetter != null) { if (storeInSetter != null) {
// callvirt set_Property(ldloc S_1, stloc v(binary.op(callvirt get_Property(ldloc S_1), value))) // callvirt set_Property(ldloc S_1, stloc v(binary.op(callvirt get_Property(ldloc S_1), value)))
// ==> stloc v(compound.op.new(callvirt(callvirt get_Property(ldloc S_1)), value)) // ==> stloc v(compound.op.new(callvirt get_Property(ldloc S_1), value))
setterValue = storeInSetter.Value; setterValue = storeInSetter.Value;
} }
setterValue = UnwrapSmallIntegerConv(setterValue, out var conv);
if (!(setterValue is BinaryNumericInstruction binary)) if (!(setterValue is BinaryNumericInstruction binary))
return false; return false;
var getterCall = binary.Left as CallInstruction; var getterCall = binary.Left as CallInstruction;
if (!MatchingGetterAndSetterCalls(getterCall, setterCall)) if (!MatchingGetterAndSetterCalls(getterCall, setterCall))
return false; return false;
if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, getterCall.Method.ReturnType)) IType targetType = getterCall.Method.ReturnType;
if (!ValidateCompoundAssign(binary, conv, targetType))
return false; return false;
if (storeInSetter != null && storeInSetter.Variable.Type.IsSmallIntegerType()) {
// 'stloc v' implicitly truncates.
// Ensure that type of 'v' must match type of the property:
if (storeInSetter.Variable.Type.GetSize() != targetType.GetSize())
return false;
if (storeInSetter.Variable.Type.GetSign() != targetType.GetSign())
return false;
}
context.Step($"Compound assignment to '{getterCall.Method.AccessorOwner.Name}'", setterCall); context.Step($"Compound assignment to '{getterCall.Method.AccessorOwner.Name}'", setterCall);
ILInstruction newInst = new CompoundAssignmentInstruction( ILInstruction newInst = new CompoundAssignmentInstruction(
binary, getterCall, binary.Right, binary, getterCall, binary.Right,
@ -234,29 +253,123 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true; return true;
} }
/// <summary>
/// stobj(target, binary.op(ldobj(target), ...))
/// where target is pure
/// => compound.op(target, ...)
/// </summary>
/// <remarks>
/// Called by ExpressionTransforms.
/// </remarks>
internal static bool HandleStObjCompoundAssign(StObj inst, ILTransformContext context)
{
if (!(UnwrapSmallIntegerConv(inst.Value, out var conv) is BinaryNumericInstruction binary))
return false;
if (!(binary.Left is LdObj ldobj))
return false;
if (!inst.Target.Match(ldobj.Target).Success)
return false;
if (!SemanticHelper.IsPure(ldobj.Target.Flags))
return false;
// ldobj.Type may just be 'int' (due to ldind.i4) when we're actually operating on a 'ref MyEnum'.
// Try to determine the real type of the object we're modifying:
IType targetType = ldobj.Target.InferType();
if (targetType.Kind == TypeKind.Pointer || targetType.Kind == TypeKind.ByReference) {
targetType = ((TypeWithElementType)targetType).ElementType;
if (targetType.Kind == TypeKind.Unknown || targetType.GetSize() != ldobj.Type.GetSize()) {
targetType = ldobj.Type;
}
} else {
targetType = ldobj.Type;
}
if (!ValidateCompoundAssign(binary, conv, targetType))
return false;
context.Step("compound assignment", inst);
inst.ReplaceWith(new CompoundAssignmentInstruction(
binary, binary.Left, binary.Right,
targetType, CompoundAssignmentType.EvaluatesToNewValue));
return true;
}
/// <code> /// <code>
/// stloc s(value) /// stloc s(value)
/// stloc l(ldloc s) /// stloc l(ldloc s)
/// where neither 'stloc s' nor 'stloc l' truncates the value
/// --> /// -->
/// stloc s(stloc l(value)) /// stloc s(stloc l(value))
/// </code> /// </code>
bool TransformInlineAssignmentLocal(Block block, int i) bool TransformInlineAssignmentLocal(Block block, int pos)
{ {
var inst = block.Instructions[i] as StLoc; var inst = block.Instructions[pos] as StLoc;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; var nextInst = block.Instructions.ElementAtOrDefault(pos + 1) as StLoc;
if (inst == null || nextInst == null) if (inst == null || nextInst == null)
return false; return false;
if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable)) if (inst.Variable.Kind != VariableKind.StackSlot)
return false;
Debug.Assert(!inst.Variable.Type.IsSmallIntegerType());
if (!(nextInst.Variable.Kind == VariableKind.Local || nextInst.Variable.Kind == VariableKind.Parameter))
return false;
if (!nextInst.Value.MatchLdLoc(inst.Variable))
return false;
if (IsImplicitTruncation(inst.Value, inst.Variable.Type)) {
// 'stloc s' is implicitly truncating the stack value
return false; return false;
}
if (IsImplicitTruncation(inst.Value, nextInst.Variable.Type)) {
// 'stloc l' is implicitly truncating the stack value
return false;
}
context.Step("Inline assignment to local variable", inst); context.Step("Inline assignment to local variable", inst);
var value = inst.Value; var value = inst.Value;
var var = nextInst.Variable; var var = nextInst.Variable;
var stackVar = inst.Variable; var stackVar = inst.Variable;
block.Instructions.RemoveAt(i); block.Instructions.RemoveAt(pos);
nextInst.ReplaceWith(new StLoc(stackVar, new StLoc(var, value))); nextInst.ReplaceWith(new StLoc(stackVar, new StLoc(var, value)));
return true; return true;
} }
/// <summary>
/// Gets whether 'stobj type(..., value)' would evaluate to a different value than 'value'
/// due to implicit truncation.
/// </summary>
bool IsImplicitTruncation(ILInstruction value, IType type)
{
if (!type.IsSmallIntegerType()) {
// Implicit truncation in ILAst only happens for small integer types;
// other types of implicit truncation in IL cause the ILReader to insert
// conv instructions.
return false;
}
// With small integer types, test whether the value might be changed by
// truncation (based on type.GetSize()) followed by sign/zero extension (based on type.GetSign()).
// (it's OK to have false-positives here if we're unsure)
if (value.MatchLdcI4(out int val)) {
switch (type.GetEnumUnderlyingType().GetDefinition()?.KnownTypeCode) {
case KnownTypeCode.Boolean:
return !(val == 0 || val == 1);
case KnownTypeCode.Byte:
return !(val >= byte.MinValue && val <= byte.MaxValue);
case KnownTypeCode.SByte:
return !(val >= sbyte.MinValue && val <= sbyte.MaxValue);
case KnownTypeCode.Int16:
return !(val >= short.MinValue && val <= short.MaxValue);
case KnownTypeCode.UInt16:
case KnownTypeCode.Char:
return !(val >= ushort.MinValue && val <= ushort.MaxValue);
}
} else if (value is Conv conv) {
return conv.TargetType != type.ToPrimitiveType();
} else if (value is Comp) {
return false; // comp returns 0 or 1, which always fits
} else {
IType inferredType = value.InferType();
if (inferredType.Kind != TypeKind.Unknown) {
return !(inferredType.GetSize() <= type.GetSize() && inferredType.GetSign() == type.GetSign());
}
}
return true;
}
/// <code> /// <code>
/// stloc s(ldloc l) /// stloc s(ldloc l)
/// stloc l(binary.op(ldloc s, ldc.i4 1)) /// stloc l(binary.op(ldloc s, ldc.i4 1))
@ -267,10 +380,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// final: ldloc s2 /// final: ldloc s2
/// }) /// })
/// </code> /// </code>
bool TransformPostIncDecOperator(Block block, int i) bool TransformPostIncDecOperatorLocal(Block block, int pos)
{ {
var inst = block.Instructions[i] as StLoc; var inst = block.Instructions[pos] as StLoc;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; var nextInst = block.Instructions.ElementAtOrDefault(pos + 1) as StLoc;
if (inst == null || nextInst == null || !inst.Value.MatchLdLoc(out var l) || !ILVariableEqualityComparer.Instance.Equals(l, nextInst.Variable)) if (inst == null || nextInst == null || !inst.Value.MatchLdLoc(out var l) || !ILVariableEqualityComparer.Instance.Equals(l, nextInst.Variable))
return false; return false;
var binary = nextInst.Value as BinaryNumericInstruction; var binary = nextInst.Value as BinaryNumericInstruction;
@ -280,158 +393,142 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false; return false;
if ((binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub) || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1)) if ((binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub) || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1))
return false; return false;
context.Step($"TransformPostIncDecOperator", inst); context.Step($"TransformPostIncDecOperatorLocal", inst);
var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, inst.Variable.Type); var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, inst.Variable.Type);
var assignment = new Block(BlockType.PostfixOperator); var assignment = new Block(BlockType.PostfixOperator);
assignment.Instructions.Add(new StLoc(tempStore, new LdLoc(nextInst.Variable))); assignment.Instructions.Add(new StLoc(tempStore, new LdLoc(nextInst.Variable)));
assignment.Instructions.Add(new StLoc(nextInst.Variable, new BinaryNumericInstruction(binary.Operator, new LdLoc(tempStore), new LdcI4(1), binary.CheckForOverflow, binary.Sign))); assignment.Instructions.Add(new StLoc(nextInst.Variable, new BinaryNumericInstruction(binary.Operator, new LdLoc(tempStore), new LdcI4(1), binary.CheckForOverflow, binary.Sign)));
assignment.FinalInstruction = new LdLoc(tempStore); assignment.FinalInstruction = new LdLoc(tempStore);
nextInst.ReplaceWith(new StLoc(inst.Variable, assignment)); inst.Value = assignment;
block.Instructions.RemoveAt(pos + 1); // remove nextInst
return true; return true;
} }
/// ldaddress ::= ldelema | ldflda | ldsflda; /// <summary>
/// <code> /// Gets whether 'inst' is a possible store for use as a compound store.
/// stloc s(ldaddress) /// </summary>
/// stloc l(ldobj(ldloc s)) bool IsCompoundStore(ILInstruction inst, out IType storeType, out ILInstruction value)
/// stobj(ldloc s, binary.op(ldloc l, ldc.i4 1))
/// -->
/// stloc l(compound.op.old(ldobj(ldaddress), ldc.i4 1))
/// </code>
bool TransformPostIncDecOperatorOnAddress(Block block, int i)
{ {
var inst = block.Instructions[i] as StLoc; value = null;
var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; storeType = null;
var stobj = block.Instructions.ElementAtOrDefault(i + 2) as StObj; if (inst is StObj stobj) {
if (inst == null || nextInst == null || stobj == null) storeType = stobj.Type;
return false; value = stobj.Value;
if (!inst.Variable.IsSingleDefinition || inst.Variable.LoadCount != 2) return SemanticHelper.IsPure(stobj.Target.Flags);
return false; } else if (inst is CallInstruction call && (call.OpCode == OpCode.Call || call.OpCode == OpCode.CallVirt)) {
if (!(inst.Value is LdElema || inst.Value is LdFlda || inst.Value is LdsFlda)) if (call.Method.Parameters.Count == 0) {
return false; return false;
ILInstruction target; }
IType targetType; foreach (var arg in call.Arguments.SkipLast(1)) {
if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdObj(out target, out targetType) || !target.MatchLdLoc(inst.Variable)) if (!SemanticHelper.IsPure(arg.Flags)) {
return false; return false;
if (!stobj.Target.MatchLdLoc(inst.Variable)) }
}
storeType = call.Method.Parameters.Last().Type;
value = call.Arguments.Last();
return IsSameMember(call.Method, (call.Method.AccessorOwner as IProperty)?.Setter);
} else {
return false; return false;
var binary = stobj.Value as BinaryNumericInstruction; }
if (binary == null || !binary.Left.MatchLdLoc(nextInst.Variable) || !binary.Right.MatchLdcI4(1) }
|| (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub))
bool IsMatchingCompoundLoad(ILInstruction load, ILInstruction store, ILVariable forbiddenVariable)
{
if (load is LdObj ldobj && store is StObj stobj) {
Debug.Assert(SemanticHelper.IsPure(stobj.Target.Flags));
if (!SemanticHelper.IsPure(ldobj.Target.Flags))
return false;
if (forbiddenVariable.IsUsedWithin(ldobj.Target))
return false;
return ldobj.Target.Match(stobj.Target).Success;
} else if (MatchingGetterAndSetterCalls(load as CallInstruction, store as CallInstruction)) {
if (forbiddenVariable.IsUsedWithin(load))
return false;
return true;
} else {
return false; return false;
context.Step($"TransformPostIncDecOperator", inst); }
var assignment = new CompoundAssignmentInstruction(binary, new LdObj(inst.Value, targetType), binary.Right, targetType, CompoundAssignmentType.EvaluatesToOldValue);
stobj.ReplaceWith(new StLoc(nextInst.Variable, assignment));
block.Instructions.RemoveAt(i + 1);
return true;
} }
/// <code> /// <code>
/// stloc l(ldobj(ldflda(target))) /// stobj(target, binary.add(stloc l(ldobj(target)), ldc.i4 1))
/// stobj(ldflda(target), binary.op(ldloc l, ldc.i4 1)) /// where target is pure and does not use 'l', and the 'stloc l' does not truncate
/// -->
/// stloc l(compound.op.old(ldobj(target), ldc.i4 1))
///
/// -or-
///
/// call set_Prop(args..., binary.add(stloc l(call get_Prop(args...)), ldc.i4 1))
/// where args.. are pure and do not use 'l', and the 'stloc l' does not truncate
/// --> /// -->
/// compound.op.old(ldobj(ldflda(target)), ldc.i4 1) /// stloc l(compound.op.old(call get_Prop(target), ldc.i4 1))
/// </code> /// </code>
bool TransformRoslynPostIncDecOperatorOnAddress(Block block, int i) /// <remarks>
/// Even though this transform operates only on a single expression, it's not an expression transform
/// as the result value of the expression changes (this is OK only for statements in a block).
/// </remarks>
bool TransformPostIncDecOperatorWithInlineStore(Block block, int pos)
{ {
var inst = block.Instructions[i] as StLoc; var store = block.Instructions[pos];
var stobj = block.Instructions.ElementAtOrDefault(i + 1) as StObj; if (!IsCompoundStore(store, out var targetType, out var value))
if (inst == null || stobj == null)
return false; return false;
if (!inst.Variable.IsSingleDefinition || inst.Variable.LoadCount != 1) var binary = UnwrapSmallIntegerConv(value, out var conv) as BinaryNumericInstruction;
if (binary == null || !binary.Right.MatchLdcI4(1))
return false; return false;
if (!inst.Value.MatchLdObj(out var loadTarget, out var loadType) || !loadTarget.MatchLdFlda(out var fieldTarget, out var field)) if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub))
return false; return false;
if (!stobj.Target.MatchLdFlda(out var fieldTarget2, out var field2)) if (!(binary.Left is StLoc stloc))
return false; return false;
if (!fieldTarget.Match(fieldTarget2).Success || !field.Equals(field2)) if (!(stloc.Variable.Kind == VariableKind.Local || stloc.Variable.Kind == VariableKind.StackSlot))
return false; return false;
var binary = stobj.Value as BinaryNumericInstruction; if (!IsMatchingCompoundLoad(stloc.Value, store, stloc.Variable))
if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1)
|| (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub))
return false; return false;
context.Step("TransformRoslynPostIncDecOperator", inst); if (!ValidateCompoundAssign(binary, conv, targetType))
stobj.ReplaceWith(new CompoundAssignmentInstruction(binary, inst.Value, binary.Right, loadType, CompoundAssignmentType.EvaluatesToOldValue));
block.Instructions.RemoveAt(i);
return true;
}
/// <code>
/// stloc s(ldflda)
/// stloc s2(ldobj(ldflda(ldloc s)))
/// stloc l(ldloc s2)
/// stobj (ldflda(ldloc s), binary.add(ldloc s2, ldc.i4 1))
/// -->
/// stloc l(compound.op.old(ldobj(ldflda(ldflda)), ldc.i4 1))
/// </code>
bool TransformCSharp4PostIncDecOperatorOnAddress(Block block, int i)
{
var baseFieldAddress = block.Instructions[i] as StLoc;
var fieldValue = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
var fieldValueCopyToLocal = block.Instructions.ElementAtOrDefault(i + 2) as StLoc;
var stobj = block.Instructions.ElementAtOrDefault(i + 3) as StObj;
if (baseFieldAddress == null || fieldValue == null || fieldValueCopyToLocal == null || stobj == null)
return false;
if (baseFieldAddress.Variable.Kind != VariableKind.StackSlot || fieldValue.Variable.Kind != VariableKind.StackSlot || fieldValueCopyToLocal.Variable.Kind != VariableKind.Local)
return false;
IType t;
IField targetField;
ILInstruction targetFieldLoad, baseFieldAddressLoad2;
if (!fieldValue.Value.MatchLdObj(out targetFieldLoad, out t))
return false;
ILInstruction baseAddress;
if (baseFieldAddress.Value is LdFlda) {
IField targetField2;
ILInstruction baseFieldAddressLoad3;
if (!targetFieldLoad.MatchLdFlda(out baseFieldAddressLoad2, out targetField) || !baseFieldAddressLoad2.MatchLdLoc(baseFieldAddress.Variable))
return false;
if (!stobj.Target.MatchLdFlda(out baseFieldAddressLoad3, out targetField2) || !baseFieldAddressLoad3.MatchLdLoc(baseFieldAddress.Variable) || !IsSameMember(targetField, targetField2))
return false;
baseAddress = new LdFlda(baseFieldAddress.Value, targetField);
} else if (baseFieldAddress.Value is LdElema) {
if (!targetFieldLoad.MatchLdLoc(baseFieldAddress.Variable) || !stobj.Target.MatchLdLoc(baseFieldAddress.Variable))
return false;
baseAddress = baseFieldAddress.Value;
} else {
return false; return false;
} if (IsImplicitTruncation(stloc.Value, stloc.Variable.Type))
BinaryNumericInstruction binary = stobj.Value as BinaryNumericInstruction; return false;
if (binary == null || !binary.Left.MatchLdLoc(fieldValue.Variable) || !binary.Right.MatchLdcI4(1) context.Step("TransformPostIncDecOperatorWithInlineStore", store);
|| (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub)) block.Instructions[pos] = new StLoc(stloc.Variable, new CompoundAssignmentInstruction(
return false; binary, stloc.Value, binary.Right, targetType, CompoundAssignmentType.EvaluatesToOldValue));
context.Step($"TransformCSharp4PostIncDecOperatorOnAddress", baseFieldAddress);
var assignment = new CompoundAssignmentInstruction(binary, new LdObj(baseAddress, t), binary.Right, t, CompoundAssignmentType.EvaluatesToOldValue);
stobj.ReplaceWith(new StLoc(fieldValueCopyToLocal.Variable, assignment));
block.Instructions.RemoveAt(i + 2);
block.Instructions.RemoveAt(i + 1);
return true; return true;
} }
/// <code> /// <code>
/// stloc s(ldobj(ldsflda)) /// stloc l(ldobj(target))
/// stobj (ldsflda, binary.op(ldloc s, ldc.i4 1)) /// stobj(target, binary.op(ldloc l, ldc.i4 1))
/// target is pure and does not use 'l', 'stloc does not truncate'
/// --> /// -->
/// stloc s(compound.op.old(ldobj(ldsflda), ldc.i4 1)) /// stloc l(compound.op.old(ldobj(target), ldc.i4 1))
/// </code> /// </code>
bool TransformPostIncDecOnStaticField(Block block, int i) /// <remarks>
/// This pattern occurs with legacy csc for static fields, and with Roslyn for most post-increments.
/// </remarks>
bool TransformPostIncDecOperator(Block block, int i)
{ {
var inst = block.Instructions[i] as StLoc; var inst = block.Instructions[i] as StLoc;
var stobj = block.Instructions.ElementAtOrDefault(i + 1) as StObj; var store = block.Instructions.ElementAtOrDefault(i + 1);
if (inst == null || stobj == null) if (inst == null || store == null)
return false; return false;
ILInstruction target; if (!IsCompoundStore(store, out var targetType, out var value))
IType type;
IField field, field2;
if (inst.Variable.Kind != VariableKind.StackSlot || !inst.Value.MatchLdObj(out target, out type) || !target.MatchLdsFlda(out field))
return false; return false;
if (!stobj.Target.MatchLdsFlda(out field2) || !IsSameMember(field, field2)) if (!IsMatchingCompoundLoad(inst.Value, store, inst.Variable))
return false; return false;
var binary = stobj.Value as BinaryNumericInstruction; var binary = UnwrapSmallIntegerConv(value, out var conv) as BinaryNumericInstruction;
if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1)) if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1))
return false; return false;
context.Step($"TransformPostIncDecOnStaticField", inst); if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub))
var assignment = new CompoundAssignmentInstruction(binary, inst.Value, binary.Right, type, CompoundAssignmentType.EvaluatesToOldValue); return false;
stobj.ReplaceWith(new StLoc(inst.Variable, assignment)); if (!ValidateCompoundAssign(binary, conv, targetType))
return false;
if (IsImplicitTruncation(value, targetType))
return false;
context.Step("TransformPostIncDecOperator", inst);
inst.Value = new CompoundAssignmentInstruction(binary, inst.Value, binary.Right, targetType, CompoundAssignmentType.EvaluatesToOldValue);
block.Instructions.RemoveAt(i + 1);
if (inst.Variable.IsSingleDefinition && inst.Variable.LoadCount == 0) {
// dead store -> it was a statement-level post-increment
inst.ReplaceWith(inst.Value);
}
return true; return true;
} }

3
ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs

@ -106,7 +106,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
public static bool IsSmallIntegerType(this IType type) public static bool IsSmallIntegerType(this IType type)
{ {
return GetSize(type) < 4; int size = GetSize(type);
return size > 0 && size < 4;
} }
/// <summary> /// <summary>

Loading…
Cancel
Save