From 89963ff8a50f67eec4201e187e5933344ea8bcdf Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 31 Oct 2017 22:44:28 +0100 Subject: [PATCH 01/15] Add a whole bunch of (failing) tests for post-increments. --- .../Pretty/CompoundAssignmentTest.cs | 135 ++++- .../Pretty/CompoundAssignmentTest.il | 514 +++++++++++++++++- .../Pretty/CompoundAssignmentTest.opt.il | 407 +++++++++++++- .../CompoundAssignmentTest.opt.roslyn.il | 406 +++++++++++++- .../Pretty/CompoundAssignmentTest.roslyn.il | 505 ++++++++++++++++- .../TestCases/Pretty/InlineAssignmentTest.cs | 32 +- .../TestCases/Pretty/InlineAssignmentTest.il | 77 ++- .../Pretty/InlineAssignmentTest.opt.il | 62 ++- 8 files changed, 2070 insertions(+), 68 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index 4730703aa..e09609a66 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs @@ -30,7 +30,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Two = 2, Four = 4 } - + + public enum ShortEnum : short + { + None = 0, + One = 1, + Two = 2, + Four = 4 + } + private struct StructContainer { public bool HasIndex; @@ -40,11 +48,17 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public class MutableClass { public int Field; + public short ShortField; public int Property { get; set; } + + public byte ByteProperty { + get; + set; + } public uint this[string name] { get { @@ -65,12 +79,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private StructContainer field1; private MyEnum enumField; public static int StaticField; - + public static short StaticShortField; + public static int StaticProperty { get; set; } - + + public static ShortEnum StaticShortProperty { + get; + set; + } + private MutableClass M() { return new MutableClass(); @@ -230,15 +250,30 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty array[pos]++; } + public int PreIncrementShortArrayElement(short[] array, int pos) + { + return --array[pos]; + } + + public int PostIncrementShortArrayElement(short[] array, int pos) + { + return array[pos]++; + } + + public void IncrementShortArrayElement(short[] array, int pos) + { + array[pos]++; + } + public int PreIncrementInstanceField() { return ++this.M().Field; } - //public int PostIncrementInstanceField() - //{ - // return this.M().Field++; - //} + public int PostIncrementInstanceField() + { + return this.M().Field++; + } public void IncrementInstanceField() { @@ -250,31 +285,61 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return ++m.Field; } - //public int PostIncrementInstanceField2(MutableClass m) - //{ - // return m.Field++; - //} + public int PostIncrementInstanceField2(MutableClass m) + { + return m.Field++; + } public void IncrementInstanceField2(MutableClass m) { 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() { return ++this.M().Property; } - //public int PostIncrementInstanceProperty() - //{ - // return this.M().Property++; - //} + public int PostIncrementInstanceProperty() + { + return this.M().Property++; + } public void IncrementInstanceProperty() { this.M().Property++; } + public int PreIncrementInstancePropertyByte() + { + return ++this.M().ByteProperty; + } + + public int PostIncrementInstancePropertyByte() + { + return this.M().ByteProperty++; + } + + public void IncrementInstancePropertyByte() + { + this.M().ByteProperty++; + } + public int PreIncrementStaticField() { return ++CompoundAssignmentTest.StaticField; @@ -290,21 +355,51 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty CompoundAssignmentTest.StaticField++; } + public int PreIncrementStaticFieldShort() + { + return ++CompoundAssignmentTest.StaticShortField; + } + + public int PostIncrementStaticFieldShort() + { + return CompoundAssignmentTest.StaticShortField++; + } + + public void IncrementStaticFieldShort() + { + CompoundAssignmentTest.StaticShortField++; + } + public int PreIncrementStaticProperty() { return ++CompoundAssignmentTest.StaticProperty; } - //public int PostIncrementStaticProperty() - //{ - // return CompoundAssignmentTest.StaticProperty++; - //} + public int PostIncrementStaticProperty() + { + return CompoundAssignmentTest.StaticProperty++; + } public void IncrementStaticProperty() { CompoundAssignmentTest.StaticProperty++; } - + + public ShortEnum PreIncrementStaticPropertyShort() + { + return ++CompoundAssignmentTest.StaticShortProperty; + } + + public ShortEnum PostIncrementStaticPropertyShort() + { + return CompoundAssignmentTest.StaticShortProperty++; + } + + public void IncrementStaticPropertyShort() + { + CompoundAssignmentTest.StaticShortProperty++; + } + private static Item GetItem(object obj) { return null; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il index dfc206ce2..5d1d21eda 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.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. @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly kiryblux +.assembly w1xcwa3w { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module kiryblux.dll -// MVID: {34EC794D-1FFD-488F-9BDC-2D5D9C15854D} +.module w1xcwa3w.dll +// MVID: {FAFFB825-2101-4417-8C03-0E0B083653E5} .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: 0x02A30000 +// Image base: 0x00D60000 // =============== CLASS MEMBERS DECLARATION =================== @@ -47,6 +47,16 @@ .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum Four = int32(0x00000004) } // 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 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.. .field public int32 Field + .field public int16 ShortField .field private int32 'k__BackingField' .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private uint8 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .method public hidebysig specialname instance int32 get_Property() cil managed { @@ -89,6 +102,34 @@ IL_0007: ret } // 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 11 (0xb) + .maxstack 1 + .locals init (uint8 V_0) + IL_0000: ldarg.0 + IL_0001: ldfld uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::'k__BackingField' + IL_0006: stloc.0 + IL_0007: br.s IL_0009 + + IL_0009: ldloc.0 + IL_000a: 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::'k__BackingField' + IL_0007: ret + } // end of method MutableClass::set_ByteProperty + .method public hidebysig specialname instance uint32 get_Item(string name) cil managed { @@ -129,6 +170,11 @@ .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) } // 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) { .get instance uint32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Item(string) @@ -158,8 +204,11 @@ .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField .field public static int32 StaticField + .field public static int16 StaticShortField .field private static int32 'k__BackingField' .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private static valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .method public hidebysig specialname static int32 get_StaticProperty() cil managed { @@ -186,6 +235,33 @@ IL_0006: ret } // 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 10 (0xa) + .maxstack 1 + .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum V_0) + IL_0000: ldsfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::'k__BackingField' + IL_0005: stloc.0 + IL_0006: br.s IL_0008 + + IL_0008: ldloc.0 + IL_0009: 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::'k__BackingField' + IL_0006: ret + } // end of method CompoundAssignmentTest::set_StaticShortProperty + .method private hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass M() cil managed { @@ -807,6 +883,81 @@ IL_0015: ret } // end of method CompoundAssignmentTest::IncrementArrayElement + .method public hidebysig instance int32 + PreIncrementShortArrayElement(int16[] 'array', + int32 pos) cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (int32 V_0, + int16 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldobj [mscorlib]System.Int16 + IL_000e: ldc.i4.1 + IL_000f: sub + IL_0010: conv.i2 + IL_0011: dup + IL_0012: stloc.1 + IL_0013: stobj [mscorlib]System.Int16 + IL_0018: ldloc.1 + IL_0019: stloc.0 + IL_001a: br.s IL_001c + + IL_001c: ldloc.0 + IL_001d: ret + } // end of method CompoundAssignmentTest::PreIncrementShortArrayElement + + .method public hidebysig instance int32 + PostIncrementShortArrayElement(int16[] 'array', + int32 pos) cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (int32 V_0, + int16 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldobj [mscorlib]System.Int16 + IL_000e: dup + IL_000f: stloc.1 + IL_0010: ldc.i4.1 + IL_0011: add + IL_0012: conv.i2 + IL_0013: stobj [mscorlib]System.Int16 + IL_0018: ldloc.1 + IL_0019: stloc.0 + IL_001a: br.s IL_001c + + IL_001c: ldloc.0 + IL_001d: ret + } // end of method CompoundAssignmentTest::PostIncrementShortArrayElement + + .method public hidebysig instance void + IncrementShortArrayElement(int16[] 'array', + int32 pos) cil managed + { + // Code size 23 (0x17) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldobj [mscorlib]System.Int16 + IL_000e: ldc.i4.1 + IL_000f: add + IL_0010: conv.i2 + IL_0011: stobj [mscorlib]System.Int16 + IL_0016: ret + } // end of method CompoundAssignmentTest::IncrementShortArrayElement + .method public hidebysig instance int32 PreIncrementInstanceField() cil managed { @@ -832,6 +983,31 @@ IL_001b: ret } // end of method CompoundAssignmentTest::PreIncrementInstanceField + .method public hidebysig instance int32 + PostIncrementInstanceField() cil managed + { + // Code size 28 (0x1c) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_000d: dup + IL_000e: stloc.1 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0016: ldloc.1 + IL_0017: stloc.0 + IL_0018: br.s IL_001a + + IL_001a: ldloc.0 + IL_001b: ret + } // end of method CompoundAssignmentTest::PostIncrementInstanceField + .method public hidebysig instance void IncrementInstanceField() cil managed { @@ -872,6 +1048,30 @@ IL_0016: ret } // end of method CompoundAssignmentTest::PreIncrementInstanceField2 + .method public hidebysig instance int32 + PostIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed + { + // Code size 23 (0x17) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: dup + IL_0003: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0008: dup + IL_0009: stloc.1 + IL_000a: ldc.i4.1 + IL_000b: add + IL_000c: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0011: ldloc.1 + IL_0012: stloc.0 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.0 + IL_0016: ret + } // end of method CompoundAssignmentTest::PostIncrementInstanceField2 + .method public hidebysig instance void IncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed { @@ -887,6 +1087,75 @@ IL_000f: ret } // end of method CompoundAssignmentTest::IncrementInstanceField2 + .method public hidebysig instance int32 + PreIncrementInstanceFieldShort() cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int32 V_0, + int16 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: conv.i2 + IL_0010: dup + IL_0011: stloc.1 + IL_0012: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_0017: ldloc.1 + IL_0018: stloc.0 + IL_0019: br.s IL_001b + + IL_001b: ldloc.0 + IL_001c: ret + } // end of method CompoundAssignmentTest::PreIncrementInstanceFieldShort + + .method public hidebysig instance int32 + PostIncrementInstanceFieldShort() cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int32 V_0, + int16 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_000d: dup + IL_000e: stloc.1 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: conv.i2 + IL_0012: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_0017: ldloc.1 + IL_0018: stloc.0 + IL_0019: br.s IL_001b + + IL_001b: ldloc.0 + IL_001c: ret + } // end of method CompoundAssignmentTest::PostIncrementInstanceFieldShort + + .method public hidebysig instance void + IncrementInstanceFieldShort() cil managed + { + // Code size 22 (0x16) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: conv.i2 + IL_0010: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_0015: ret + } // end of method CompoundAssignmentTest::IncrementInstanceFieldShort + .method public hidebysig instance int32 PreIncrementInstanceProperty() cil managed { @@ -913,6 +1182,32 @@ IL_001c: ret } // end of method CompoundAssignmentTest::PreIncrementInstanceProperty + .method public hidebysig instance int32 + PostIncrementInstanceProperty() cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property() + IL_000d: dup + IL_000e: stloc.1 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32) + IL_0016: nop + IL_0017: ldloc.1 + IL_0018: stloc.0 + IL_0019: br.s IL_001b + + IL_001b: ldloc.0 + IL_001c: ret + } // end of method CompoundAssignmentTest::PostIncrementInstanceProperty + .method public hidebysig instance void IncrementInstanceProperty() cil managed { @@ -930,6 +1225,78 @@ IL_0015: ret } // end of method CompoundAssignmentTest::IncrementInstanceProperty + .method public hidebysig instance int32 + PreIncrementInstancePropertyByte() cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (int32 V_0, + uint8 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: conv.u1 + IL_0010: dup + IL_0011: stloc.1 + IL_0012: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0017: nop + IL_0018: ldloc.1 + IL_0019: stloc.0 + IL_001a: br.s IL_001c + + IL_001c: ldloc.0 + IL_001d: ret + } // end of method CompoundAssignmentTest::PreIncrementInstancePropertyByte + + .method public hidebysig instance int32 + PostIncrementInstancePropertyByte() cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (int32 V_0, + uint8 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: dup + IL_000e: stloc.1 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: conv.u1 + IL_0012: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0017: nop + IL_0018: ldloc.1 + IL_0019: stloc.0 + IL_001a: br.s IL_001c + + IL_001c: ldloc.0 + IL_001d: ret + } // end of method CompoundAssignmentTest::PostIncrementInstancePropertyByte + + .method public hidebysig instance void + IncrementInstancePropertyByte() cil managed + { + // Code size 23 (0x17) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: conv.u1 + IL_0010: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0015: nop + IL_0016: ret + } // end of method CompoundAssignmentTest::IncrementInstancePropertyByte + .method public hidebysig instance int32 PreIncrementStaticField() cil managed { @@ -981,6 +1348,60 @@ IL_000d: ret } // end of method CompoundAssignmentTest::IncrementStaticField + .method public hidebysig instance int32 + PreIncrementStaticFieldShort() cil managed + { + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_0006: ldc.i4.1 + IL_0007: add + IL_0008: conv.i2 + IL_0009: dup + IL_000a: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::PreIncrementStaticFieldShort + + .method public hidebysig instance int32 + PostIncrementStaticFieldShort() cil managed + { + // Code size 20 (0x14) + .maxstack 3 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_0006: dup + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: conv.i2 + IL_000a: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::PostIncrementStaticFieldShort + + .method public hidebysig instance void + IncrementStaticFieldShort() cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + 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::IncrementStaticFieldShort + .method public hidebysig instance int32 PreIncrementStaticProperty() cil managed { @@ -1001,6 +1422,26 @@ IL_0013: ret } // end of method CompoundAssignmentTest::PreIncrementStaticProperty + .method public hidebysig instance int32 + PostIncrementStaticProperty() cil managed + { + // Code size 20 (0x14) + .maxstack 3 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() + IL_0006: dup + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) + IL_000e: nop + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::PostIncrementStaticProperty + .method public hidebysig instance void IncrementStaticProperty() cil managed { @@ -1015,6 +1456,63 @@ IL_000e: ret } // end of method CompoundAssignmentTest::IncrementStaticProperty + .method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum + PreIncrementStaticPropertyShort() cil managed + { + // Code size 21 (0x15) + .maxstack 2 + .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum V_0) + IL_0000: nop + IL_0001: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty() + IL_0006: ldc.i4.1 + IL_0007: add + IL_0008: conv.i2 + IL_0009: dup + IL_000a: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum) + IL_000f: nop + IL_0010: stloc.0 + IL_0011: br.s IL_0013 + + IL_0013: ldloc.0 + IL_0014: ret + } // end of method CompoundAssignmentTest::PreIncrementStaticPropertyShort + + .method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum + PostIncrementStaticPropertyShort() cil managed + { + // Code size 21 (0x15) + .maxstack 3 + .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum V_0) + IL_0000: nop + IL_0001: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty() + IL_0006: dup + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: conv.i2 + IL_000a: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum) + IL_000f: nop + IL_0010: stloc.0 + IL_0011: br.s IL_0013 + + IL_0013: ldloc.0 + IL_0014: ret + } // end of method CompoundAssignmentTest::PostIncrementStaticPropertyShort + + .method public hidebysig instance void + IncrementStaticPropertyShort() cil managed + { + // Code size 16 (0x10) + .maxstack 8 + IL_0000: nop + IL_0001: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty() + 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: nop + IL_000f: ret + } // end of method CompoundAssignmentTest::IncrementStaticPropertyShort + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/Item GetItem(object obj) cil managed { @@ -1060,6 +1558,12 @@ .get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() .set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) } // 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 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il index 2dea51f56..09d5a0a91 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il +++ b/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. @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly d4bhqxbe +.assembly pbv15mad { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module d4bhqxbe.dll -// MVID: {B884BD61-6FE3-4893-B161-02EE675C0DF0} +.module pbv15mad.dll +// MVID: {7F137601-6720-4272-9855-AEC542FD460D} .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: 0x003A0000 +// Image base: 0x01300000 // =============== CLASS MEMBERS DECLARATION =================== @@ -47,6 +47,16 @@ .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum Four = int32(0x00000004) } // 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 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.. .field public int32 Field + .field public int16 ShortField .field private int32 'k__BackingField' .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private uint8 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .method public hidebysig specialname instance int32 get_Property() cil managed { @@ -84,6 +97,29 @@ IL_0007: ret } // 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::'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::'k__BackingField' + IL_0007: ret + } // end of method MutableClass::set_ByteProperty + .method public hidebysig specialname instance uint32 get_Item(string name) cil managed { @@ -117,6 +153,11 @@ .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) } // 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) { .get instance uint32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Item(string) @@ -146,8 +187,11 @@ .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField .field public static int32 StaticField + .field public static int16 StaticShortField .field private static int32 'k__BackingField' .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private static valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .method public hidebysig specialname static int32 get_StaticProperty() cil managed { @@ -169,6 +213,28 @@ IL_0006: ret } // 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::'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::'k__BackingField' + IL_0006: ret + } // end of method CompoundAssignmentTest::set_StaticShortProperty + .method private hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass M() cil managed { @@ -685,6 +751,68 @@ IL_0014: ret } // end of method CompoundAssignmentTest::IncrementArrayElement + .method public hidebysig instance int32 + PreIncrementShortArrayElement(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::PreIncrementShortArrayElement + + .method public hidebysig instance int32 + PostIncrementShortArrayElement(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::PostIncrementShortArrayElement + + .method public hidebysig instance void + IncrementShortArrayElement(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::IncrementShortArrayElement + .method public hidebysig instance int32 PreIncrementInstanceField() cil managed { @@ -704,6 +832,25 @@ IL_0016: ret } // 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 IncrementInstanceField() cil managed { @@ -737,6 +884,24 @@ IL_0011: ret } // 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 IncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed { @@ -751,6 +916,62 @@ IL_000e: ret } // 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 PreIncrementInstanceProperty() cil managed { @@ -770,6 +991,25 @@ IL_0016: ret } // 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 IncrementInstanceProperty() cil managed { @@ -785,6 +1025,62 @@ IL_0013: ret } // end of method CompoundAssignmentTest::IncrementInstanceProperty + .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 int32 PreIncrementStaticField() cil managed { @@ -823,6 +1119,47 @@ IL_000c: ret } // end of method CompoundAssignmentTest::IncrementStaticField + .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 int32 PreIncrementStaticProperty() cil managed { @@ -836,6 +1173,19 @@ IL_000d: ret } // 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 IncrementStaticProperty() cil managed { @@ -848,6 +1198,47 @@ IL_000c: ret } // end of method CompoundAssignmentTest::IncrementStaticProperty + .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 GetItem(object obj) cil managed { @@ -886,6 +1277,12 @@ .get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() .set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) } // 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 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il index 36f83b082..feb9ee854 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il +++ b/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. @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {6E5749EE-F4C5-4B86-96FC-F4A665551BA6} +// MVID: {7FF443A1-4D5C-4B6C-ABE8-2BE60079524D} .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: 0x028A0000 +// Image base: 0x02DC0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -51,6 +51,16 @@ .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum Four = int32(0x00000004) } // 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 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.. .field public int32 Field + .field public int16 ShortField .field private int32 'k__BackingField' .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private uint8 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .method public hidebysig specialname instance int32 get_Property() cil managed { @@ -88,6 +101,29 @@ IL_0007: ret } // 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::'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::'k__BackingField' + IL_0007: ret + } // end of method MutableClass::set_ByteProperty + .method public hidebysig specialname instance uint32 get_Item(string name) cil managed { @@ -121,6 +157,11 @@ .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) } // 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) { .get instance uint32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Item(string) @@ -150,8 +191,11 @@ .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField .field public static int32 StaticField + .field public static int16 StaticShortField .field private static int32 'k__BackingField' .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private static valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .method public hidebysig specialname static int32 get_StaticProperty() cil managed { @@ -173,6 +217,28 @@ IL_0006: ret } // 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::'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::'k__BackingField' + IL_0006: ret + } // end of method CompoundAssignmentTest::set_StaticShortProperty + .method private hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass M() cil managed { @@ -688,6 +754,68 @@ IL_000c: ret } // end of method CompoundAssignmentTest::IncrementArrayElement + .method public hidebysig instance int32 + PreIncrementShortArrayElement(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::PreIncrementShortArrayElement + + .method public hidebysig instance int32 + PostIncrementShortArrayElement(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::PostIncrementShortArrayElement + + .method public hidebysig instance void + IncrementShortArrayElement(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::IncrementShortArrayElement + .method public hidebysig instance int32 PreIncrementInstanceField() cil managed { @@ -707,6 +835,25 @@ IL_0016: ret } // 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 IncrementInstanceField() cil managed { @@ -740,6 +887,24 @@ IL_0011: ret } // 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 IncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed { @@ -754,6 +919,62 @@ IL_000e: ret } // 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 PreIncrementInstanceProperty() cil managed { @@ -773,6 +994,25 @@ IL_0016: ret } // 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 IncrementInstanceProperty() cil managed { @@ -791,6 +1031,65 @@ IL_0015: ret } // end of method CompoundAssignmentTest::IncrementInstanceProperty + .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 int32 PreIncrementStaticField() cil managed { @@ -829,6 +1128,47 @@ IL_000c: ret } // end of method CompoundAssignmentTest::IncrementStaticField + .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 int32 PreIncrementStaticProperty() cil managed { @@ -842,6 +1182,19 @@ IL_000d: ret } // 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 IncrementStaticProperty() cil managed { @@ -854,6 +1207,47 @@ IL_000c: ret } // end of method CompoundAssignmentTest::IncrementStaticProperty + .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 GetItem(object obj) cil managed { @@ -889,6 +1283,12 @@ .get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() .set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) } // 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 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il index 1404a451f..1e7a12bce 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.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. @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {391C1968-5381-4AC7-9C19-7B5F6ED36AF8} +// MVID: {514BA798-3837-4D3D-8485-D675114840C6} .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: 0x003D0000 +// Image base: 0x01590000 // =============== CLASS MEMBERS DECLARATION =================== @@ -51,6 +51,16 @@ .field public static literal valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum Four = int32(0x00000004) } // 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 extends [mscorlib]System.ValueType { @@ -63,9 +73,13 @@ { .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 int16 ShortField .field private int32 '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 uint8 '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_Property() cil managed { @@ -89,6 +103,29 @@ IL_0007: ret } // 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::'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::'k__BackingField' + IL_0007: ret + } // end of method MutableClass::set_ByteProperty + .method public hidebysig specialname instance uint32 get_Item(string name) cil managed { @@ -130,6 +167,11 @@ .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) } // 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) { .get instance uint32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Item(string) @@ -160,9 +202,13 @@ .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField .field public static int32 StaticField + .field public static int16 StaticShortField .field private static int32 '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 valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum '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 static int32 get_StaticProperty() cil managed { @@ -184,6 +230,28 @@ IL_0006: ret } // 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::'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::'k__BackingField' + IL_0006: ret + } // end of method CompoundAssignmentTest::set_StaticShortProperty + .method private hidebysig instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass M() cil managed { @@ -804,6 +872,81 @@ IL_000d: ret } // end of method CompoundAssignmentTest::IncrementArrayElement + .method public hidebysig instance int32 + PreIncrementShortArrayElement(int16[] 'array', + int32 pos) cil managed + { + // Code size 22 (0x16) + .maxstack 3 + .locals init (int16 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldind.i2 + IL_000a: ldc.i4.1 + IL_000b: sub + IL_000c: conv.i2 + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: stind.i2 + IL_0010: ldloc.0 + IL_0011: stloc.1 + IL_0012: br.s IL_0014 + + IL_0014: ldloc.1 + IL_0015: ret + } // end of method CompoundAssignmentTest::PreIncrementShortArrayElement + + .method public hidebysig instance int32 + PostIncrementShortArrayElement(int16[] 'array', + int32 pos) cil managed + { + // Code size 22 (0x16) + .maxstack 3 + .locals init (int16 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldind.i2 + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: ldc.i4.1 + IL_000d: add + IL_000e: conv.i2 + IL_000f: stind.i2 + IL_0010: ldloc.0 + IL_0011: stloc.1 + IL_0012: br.s IL_0014 + + IL_0014: ldloc.1 + IL_0015: ret + } // end of method CompoundAssignmentTest::PostIncrementShortArrayElement + + .method public hidebysig instance void + IncrementShortArrayElement(int16[] 'array', + int32 pos) cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldind.i2 + IL_000a: ldc.i4.1 + IL_000b: add + IL_000c: conv.i2 + IL_000d: stind.i2 + IL_000e: ret + } // end of method CompoundAssignmentTest::IncrementShortArrayElement + .method public hidebysig instance int32 PreIncrementInstanceField() cil managed { @@ -829,6 +972,31 @@ IL_001b: ret } // end of method CompoundAssignmentTest::PreIncrementInstanceField + .method public hidebysig instance int32 + PostIncrementInstanceField() cil managed + { + // Code size 28 (0x1c) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0016: ldloc.0 + IL_0017: stloc.1 + IL_0018: br.s IL_001a + + IL_001a: ldloc.1 + IL_001b: ret + } // end of method CompoundAssignmentTest::PostIncrementInstanceField + .method public hidebysig instance void IncrementInstanceField() cil managed { @@ -869,6 +1037,30 @@ IL_0016: ret } // end of method CompoundAssignmentTest::PreIncrementInstanceField2 + .method public hidebysig instance int32 + PostIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed + { + // Code size 23 (0x17) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: dup + IL_0003: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: ldc.i4.1 + IL_000b: add + IL_000c: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0011: ldloc.0 + IL_0012: stloc.1 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.1 + IL_0016: ret + } // end of method CompoundAssignmentTest::PostIncrementInstanceField2 + .method public hidebysig instance void IncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed { @@ -884,6 +1076,75 @@ IL_000f: ret } // end of method CompoundAssignmentTest::IncrementInstanceField2 + .method public hidebysig instance int32 + PreIncrementInstanceFieldShort() cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int16 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: conv.i2 + IL_0010: stloc.0 + IL_0011: ldloc.0 + IL_0012: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_0017: ldloc.0 + IL_0018: stloc.1 + IL_0019: br.s IL_001b + + IL_001b: ldloc.1 + IL_001c: ret + } // end of method CompoundAssignmentTest::PreIncrementInstanceFieldShort + + .method public hidebysig instance int32 + PostIncrementInstanceFieldShort() cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int16 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: conv.i2 + IL_0012: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_0017: ldloc.0 + IL_0018: stloc.1 + IL_0019: br.s IL_001b + + IL_001b: ldloc.1 + IL_001c: ret + } // end of method CompoundAssignmentTest::PostIncrementInstanceFieldShort + + .method public hidebysig instance void + IncrementInstanceFieldShort() cil managed + { + // Code size 22 (0x16) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: conv.i2 + IL_0010: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::ShortField + IL_0015: ret + } // end of method CompoundAssignmentTest::IncrementInstanceFieldShort + .method public hidebysig instance int32 PreIncrementInstanceProperty() cil managed { @@ -910,6 +1171,32 @@ IL_001c: ret } // end of method CompoundAssignmentTest::PreIncrementInstanceProperty + .method public hidebysig instance int32 + PostIncrementInstanceProperty() cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property() + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32) + IL_0016: nop + IL_0017: ldloc.0 + IL_0018: stloc.1 + IL_0019: br.s IL_001b + + IL_001b: ldloc.1 + IL_001c: ret + } // end of method CompoundAssignmentTest::PostIncrementInstanceProperty + .method public hidebysig instance void IncrementInstanceProperty() cil managed { @@ -930,6 +1217,81 @@ IL_0017: ret } // end of method CompoundAssignmentTest::IncrementInstanceProperty + .method public hidebysig instance int32 + PreIncrementInstancePropertyByte() cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (uint8 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: conv.u1 + IL_0010: stloc.0 + IL_0011: ldloc.0 + IL_0012: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0017: nop + IL_0018: ldloc.0 + IL_0019: stloc.1 + IL_001a: br.s IL_001c + + IL_001c: ldloc.1 + IL_001d: ret + } // end of method CompoundAssignmentTest::PreIncrementInstancePropertyByte + + .method public hidebysig instance int32 + PostIncrementInstancePropertyByte() cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (uint8 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: conv.u1 + IL_0012: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0017: nop + IL_0018: ldloc.0 + IL_0019: stloc.1 + IL_001a: br.s IL_001c + + IL_001c: ldloc.1 + IL_001d: ret + } // end of method CompoundAssignmentTest::PostIncrementInstancePropertyByte + + .method public hidebysig instance void + IncrementInstancePropertyByte() cil managed + { + // Code size 25 (0x19) + .maxstack 3 + .locals init (uint8 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: ldc.i4.1 + IL_0010: add + IL_0011: conv.u1 + IL_0012: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0017: nop + IL_0018: ret + } // end of method CompoundAssignmentTest::IncrementInstancePropertyByte + .method public hidebysig instance int32 PreIncrementStaticField() cil managed { @@ -981,6 +1343,60 @@ IL_000d: ret } // end of method CompoundAssignmentTest::IncrementStaticField + .method public hidebysig instance int32 + PreIncrementStaticFieldShort() cil managed + { + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_0006: ldc.i4.1 + IL_0007: add + IL_0008: conv.i2 + IL_0009: dup + IL_000a: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::PreIncrementStaticFieldShort + + .method public hidebysig instance int32 + PostIncrementStaticFieldShort() cil managed + { + // Code size 20 (0x14) + .maxstack 3 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_0006: dup + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: conv.i2 + IL_000a: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::PostIncrementStaticFieldShort + + .method public hidebysig instance void + IncrementStaticFieldShort() cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + 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::IncrementStaticFieldShort + .method public hidebysig instance int32 PreIncrementStaticProperty() cil managed { @@ -1001,6 +1417,26 @@ IL_0013: ret } // end of method CompoundAssignmentTest::PreIncrementStaticProperty + .method public hidebysig instance int32 + PostIncrementStaticProperty() cil managed + { + // Code size 20 (0x14) + .maxstack 3 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() + IL_0006: dup + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) + IL_000e: nop + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::PostIncrementStaticProperty + .method public hidebysig instance void IncrementStaticProperty() cil managed { @@ -1015,6 +1451,63 @@ IL_000e: ret } // end of method CompoundAssignmentTest::IncrementStaticProperty + .method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum + PreIncrementStaticPropertyShort() cil managed + { + // Code size 21 (0x15) + .maxstack 2 + .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum V_0) + IL_0000: nop + IL_0001: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty() + IL_0006: ldc.i4.1 + IL_0007: add + IL_0008: conv.i2 + IL_0009: dup + IL_000a: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum) + IL_000f: nop + IL_0010: stloc.0 + IL_0011: br.s IL_0013 + + IL_0013: ldloc.0 + IL_0014: ret + } // end of method CompoundAssignmentTest::PreIncrementStaticPropertyShort + + .method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum + PostIncrementStaticPropertyShort() cil managed + { + // Code size 21 (0x15) + .maxstack 3 + .locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum V_0) + IL_0000: nop + IL_0001: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty() + IL_0006: dup + IL_0007: ldc.i4.1 + IL_0008: add + IL_0009: conv.i2 + IL_000a: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticShortProperty(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum) + IL_000f: nop + IL_0010: stloc.0 + IL_0011: br.s IL_0013 + + IL_0013: ldloc.0 + IL_0014: ret + } // end of method CompoundAssignmentTest::PostIncrementStaticPropertyShort + + .method public hidebysig instance void + IncrementStaticPropertyShort() cil managed + { + // Code size 16 (0x10) + .maxstack 8 + IL_0000: nop + IL_0001: call valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticShortProperty() + 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: nop + IL_000f: ret + } // end of method CompoundAssignmentTest::IncrementStaticPropertyShort + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/Item GetItem(object obj) cil managed { @@ -1061,6 +1554,12 @@ .get int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() .set void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) } // 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 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs index 98426bca0..cc0887987 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.IO; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { @@ -25,7 +26,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private int field1; private static InlineAssignmentTest field2; private int[] field3; - + private short field4; + public void SimpleInlineWithLocals() { int value; @@ -41,24 +43,30 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(this.field1 = 5); Console.WriteLine(InlineAssignmentTest.field2 = new InlineAssignmentTest()); } - + public void SimpleInlineWithFields2() { Console.WriteLine(this.field1 = 5); Console.WriteLine(this.field1); Console.WriteLine(InlineAssignmentTest.field2 = new InlineAssignmentTest()); Console.WriteLine(InlineAssignmentTest.field2); + this.UseShort(this.field4 = 6); + Console.WriteLine(this.field4); } - -// public void ReadLoop1(TextReader r) -// { -// string V_0; -// while ((V_0 = r.ReadLine()) != null) -// { -// Console.WriteLine(V_0); -// } -// } - + + public void UseShort(short s) + { + Console.WriteLine(s); + } + + public void ReadLoop1(TextReader r) + { + string value; + while ((value = r.ReadLine()) != null) { + Console.WriteLine(value); + } + } + public void AccessArray(int[] a) { int num; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il index e0920cdba..ec2d0ea7e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il +++ b/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. @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly xh5er5kd +.assembly uq03kalt { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module xh5er5kd.dll -// MVID: {9DBFA28B-BEE8-4796-A203-E73267B1357D} +.module uq03kalt.dll +// MVID: {D636DE2E-D2CD-4EDF-B87B-0B0985C6C0B8} .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: 0x023E0000 +// Image base: 0x018D0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -39,6 +39,7 @@ .field private int32 field1 .field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2 .field private int32[] field3 + .field private int16 field4 .method public hidebysig instance void SimpleInlineWithLocals() cil managed { @@ -92,9 +93,10 @@ .method public hidebysig instance void SimpleInlineWithFields2() cil managed { - // Code size 58 (0x3a) - .maxstack 3 - .locals init (int32 V_0) + // Code size 87 (0x57) + .maxstack 4 + .locals init (int32 V_0, + int16 V_1) IL_0000: nop IL_0001: ldarg.0 IL_0002: ldc.i4.5 @@ -116,9 +118,64 @@ 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: 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 void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16) + IL_0049: nop + IL_004a: ldarg.0 + IL_004b: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4 + IL_0050: call void [mscorlib]System.Console::WriteLine(int32) + IL_0055: nop + IL_0056: ret } // end of method InlineAssignmentTest::SimpleInlineWithFields2 + .method public hidebysig instance void + UseShort(int16 s) cil managed + { + // Code size 9 (0x9) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: call void [mscorlib]System.Console::WriteLine(int32) + IL_0007: nop + IL_0008: 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 AccessArray(int32[] a) cil managed { @@ -300,4 +357,4 @@ // ============================================================= // *********** DISASSEMBLY COMPLETE *********************** -// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\InlineAssignmentTest.res +// WARNING: Created Win32 resource file ../../../TestCases/Pretty\InlineAssignmentTest.res diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il index da60ad226..f98d18c87 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il +++ b/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. @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly b1jpssom +.assembly zztqnmi4 { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module b1jpssom.dll -// MVID: {7C6502B0-8536-4BED-9395-765EB2F77653} +.module zztqnmi4.dll +// MVID: {038F2DF5-AE7B-4B0A-B846-AC254CE46038} .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: 0x02B00000 +// Image base: 0x006A0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -39,6 +39,7 @@ .field private int32 field1 .field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2 .field private int32[] field3 + .field private int16 field4 .method public hidebysig instance void SimpleInlineWithLocals() cil managed { @@ -84,9 +85,10 @@ .method public hidebysig instance void SimpleInlineWithFields2() cil managed { - // Code size 53 (0x35) - .maxstack 3 - .locals init (int32 V_0) + // Code size 80 (0x50) + .maxstack 4 + .locals init (int32 V_0, + int16 V_1) IL_0000: ldarg.0 IL_0001: ldc.i4.5 IL_0002: dup @@ -103,9 +105,49 @@ 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: 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 void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16) + IL_0044: ldarg.0 + IL_0045: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4 + IL_004a: call void [mscorlib]System.Console::WriteLine(int32) + IL_004f: ret } // end of method InlineAssignmentTest::SimpleInlineWithFields2 + .method public hidebysig instance void + UseShort(int16 s) cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: call void [mscorlib]System.Console::WriteLine(int32) + IL_0006: 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 { @@ -247,4 +289,4 @@ // ============================================================= // *********** DISASSEMBLY COMPLETE *********************** -// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\InlineAssignmentTest.opt.res +// WARNING: Created Win32 resource file ../../../TestCases/Pretty\InlineAssignmentTest.opt.res From 385005b2e5b7c232452e5bc147e84d0326791b36 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 00:03:36 +0100 Subject: [PATCH 02/15] More strictly test the inline assignment pattern. --- ICSharpCode.Decompiler/IL/ILVariable.cs | 17 +++++++++- ICSharpCode.Decompiler/IL/Instructions.cs | 12 ++++--- ICSharpCode.Decompiler/IL/Instructions.tt | 8 +++-- .../IL/Transforms/TransformAssignment.cs | 31 ++++++++++++------- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ILVariable.cs b/ICSharpCode.Decompiler/IL/ILVariable.cs index 8f6ec5e08..c89821c5c 100644 --- a/ICSharpCode.Decompiler/IL/ILVariable.cs +++ b/ICSharpCode.Decompiler/IL/ILVariable.cs @@ -335,8 +335,23 @@ namespace ICSharpCode.Decompiler.IL { output.WriteReference(this.Name, this, isLocal: true); } + + /// + /// Gets whether this variable occurs within the specified instruction. + /// + 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 { ILVariable Variable { get; set; } diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index c5d4786c5..809aabafe 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -93,7 +93,8 @@ namespace ICSharpCode.Decompiler.IL LdLoc, /// Loads the address of a local variable. (ldarga/ldloca) LdLoca, - /// Stores a value into a local variable. (starg/stloc) + /// 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) StLoc, /// Stores the value into an anonymous temporary variable, and returns the address of that variable. AddressOf, @@ -137,7 +138,8 @@ namespace ICSharpCode.Decompiler.IL IsInst, /// Indirect load (ref/pointer dereference). LdObj, - /// Indirect store (store to ref/pointer). + /// Indirect store (store to ref/pointer). + /// Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value) StObj, /// Boxes a value. Box, @@ -2217,7 +2219,8 @@ namespace ICSharpCode.Decompiler.IL } namespace ICSharpCode.Decompiler.IL { - /// Stores a value into a local variable. (starg/stloc) + /// 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) public sealed partial class StLoc : ILInstruction, IStoreInstruction { public StLoc(ILVariable variable, ILInstruction value) : base(OpCode.StLoc) @@ -3540,7 +3543,8 @@ namespace ICSharpCode.Decompiler.IL } namespace ICSharpCode.Decompiler.IL { - /// Indirect store (store to ref/pointer). + /// Indirect store (store to ref/pointer). + /// Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value) public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix { public StObj(ILInstruction target, ILInstruction value, IType type) : base(OpCode.StObj) diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index cab30f507..126b9c795 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -150,7 +150,8 @@ CustomClassName("LdLoc"), NoArguments, HasVariableOperand("Load"), ResultType("variable.StackType")), new OpCode("ldloca", "Loads the address of a local variable. (ldarga/ldloca)", 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)", CustomClassName("StLoc"), HasVariableOperand("Store"), CustomArguments("value"), ResultType("variable.StackType")), new OpCode("addressof", "Stores the value into an anonymous temporary variable, and returns the address of that variable.", @@ -204,10 +205,11 @@ new OpCode("ldobj", "Indirect load (ref/pointer dereference).", CustomClassName("LdObj"), CustomArguments("target"), HasTypeOperand, MemoryAccess, CustomWriteToButKeepOriginal, 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)", CustomClassName("StObj"), CustomArguments("target", "value"), HasTypeOperand, MemoryAccess, CustomWriteToButKeepOriginal, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, ResultType("type.GetStackType()")), - + new OpCode("box", "Boxes a value.", Unary, HasTypeOperand, MemoryAccess, MayThrow, ResultType("O")), new OpCode("unbox", "Compute address inside box.", diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index a1de1bf3e..c18d1ed96 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms block.Instructions.RemoveAt(i); continue; } - if (TransformInlineAssignmentStObj(block, i)) + if (TransformInlineAssignmentStObj(block, i) || TransformInlineAssignmentLocal(block, i)) continue; if (TransformInlineCompoundAssignmentCall(block, i)) continue; @@ -59,13 +59,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// --> /// stloc l(stobj (..., value)) /// + /// e.g. used for inline assignment to instance field + /// /// -or- + /// /// /// stloc s(value) /// stobj (..., ldloc s) /// --> /// stloc s(stobj (..., value)) /// + /// e.g. used for inline assignment to static field bool TransformInlineAssignmentStObj(Block block, int i) { var inst = block.Instructions[i] as StLoc; @@ -76,27 +80,28 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILInstruction replacement; StObj fieldStore; ILVariable local; - if (nextInst is StLoc) { // instance fields - var localStore = (StLoc)nextInst; - if (localStore.Variable.Kind == VariableKind.StackSlot || !localStore.Value.MatchLdLoc(inst.Variable)) + if (nextInst is StLoc localStore) { // with extra local + if (localStore.Variable.Kind != VariableKind.Local || !localStore.Value.MatchLdLoc(inst.Variable)) + return false; + if (!(inst.Variable.IsSingleDefinition && inst.Variable.LoadCount == 2)) return false; var memberStore = block.Instructions.ElementAtOrDefault(i + 2); if (memberStore is StObj) { fieldStore = memberStore as StObj; - if (!fieldStore.Value.MatchLdLoc(inst.Variable)) + if (!fieldStore.Value.MatchLdLoc(inst.Variable) || localStore.Variable.IsUsedWithin(fieldStore.Target)) return false; replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); - } else { // otherwise it must be local - return TransformInlineAssignmentLocal(block, i); + } else { + return false; } - context.Step("Inline assignment to instance field", fieldStore); + context.Step("Inline assignment stobj (with extra local)", fieldStore); local = localStore.Variable; block.Instructions.RemoveAt(i + 1); - } else if (nextInst is StObj) { // static fields + } else if (nextInst is StObj) { // without extra local fieldStore = (StObj)nextInst; - if (!fieldStore.Value.MatchLdLoc(inst.Variable) || (fieldStore.Target.MatchLdFlda(out var target, out _) && target.MatchLdLoc(inst.Variable))) + if (!fieldStore.Value.MatchLdLoc(inst.Variable) || inst.Variable.IsUsedWithin(fieldStore.Target)) return false; - context.Step("Inline assignment to static field", fieldStore); + context.Step("Inline assignment stobj", fieldStore); local = inst.Variable; replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); } else { @@ -246,7 +251,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; if (inst == null || nextInst == null) return false; - if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdLoc(inst.Variable)) + if (inst.Variable.Kind != VariableKind.StackSlot) + return false; + if (nextInst.Variable.Kind != VariableKind.Local || !nextInst.Value.MatchLdLoc(inst.Variable)) return false; context.Step("Inline assignment to local variable", inst); var value = inst.Value; From c7e60a9b3c10cb5bd6ff4119521cde452b3d7233 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 02:01:06 +0100 Subject: [PATCH 03/15] Avoid using inline assignments if they truncate the input value. --- .../TestCases/Correctness/StackTypes.il | 427 +++++++++--------- .../IL/Instructions/InstructionCollection.cs | 4 + .../IL/Transforms/TransformAssignment.cs | 63 +-- .../TypeSystem/TypeUtils.cs | 3 +- 4 files changed, 267 insertions(+), 230 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il index bb66d1596..338a9cbce 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/StackTypes.il @@ -1,12 +1,12 @@ .assembly extern mscorlib { - .publickeytoken = ( b7 7a 5c 56 19 34 e0 89 ) - .ver 4:0:0:0 + .publickeytoken = ( b7 7a 5c 56 19 34 e0 89 ) + .ver 4:0:0:0 } .assembly 'StackTypes' { - .ver 0:0:0:0 + .ver 0:0:0:0 } .module StackTypes.exe @@ -15,204 +15,227 @@ .class private auto ansi abstract sealed beforefieldinit Program extends [mscorlib]System.Object { - .method public hidebysig static void Main (string[] args) cil managed - { - .maxstack 8 - .entrypoint - - //call void Program::Int32OrNativeTests() - - ret - } // end of method Main - - /* - .method public static void Int32OrNativeTests() - { - ldstr "Int32OrNative(0x7fffffff, false) = {0}" - ldc.i4 0x7fffffff - ldc.i4 0 - call native int Program::Int32OrNative(int32, bool) - box native int - call void [mscorlib]System.Console::WriteLine(string, object) - - ldstr "Int32OrNative(0x7fffffff, true) = {0}" - ldc.i4 0x7fffffff - ldc.i4 1 - call native int Program::Int32OrNative(int32, bool) - box native int - call void [mscorlib]System.Console::WriteLine(string, object) - - ldstr "Int32OrNative(-1, false) = {0}" - ldc.i4.m1 - ldc.i4 0 - call native int Program::Int32OrNative(int32, bool) - box native int - call void [mscorlib]System.Console::WriteLine(string, object) - - ldstr "Int32OrNative(-1, true) = {0}" - ldc.i4.m1 - ldc.i4 1 - call native int Program::Int32OrNative(int32, bool) - box native int - call void [mscorlib]System.Console::WriteLine(string, object) - - ldstr "Int32OrNativeLoopStyle(0x7fffffff):" - call void [mscorlib]System.Console::WriteLine(string) - ldc.i4 0x7fffffff - call void Program::Int32OrNativeLoopStyle(int32) - - ldstr "Int32OrNativeLoopStyle(-1):" - call void [mscorlib]System.Console::WriteLine(string) - ldc.i4.m1 - call void Program::Int32OrNativeLoopStyle(int32) - - ldstr "Int32OrNativeDeadCode(0x7fffffff) = {0}" - ldc.i4 0x7fffffff - call native int Program::Int32OrNativeDeadCode(int32) - box native int - call void [mscorlib]System.Console::WriteLine(string, object) - - ldstr "Int32OrNativeDeadCode(-1) = {0}" - ldc.i4.m1 - call native int Program::Int32OrNativeDeadCode(int32) - box native int - call void [mscorlib]System.Console::WriteLine(string, object) - - ldc.i4 0x7fffffff - call void Program::RunInt32OrNativeMultiUse(int32) - ldc.i4.m1 - call void Program::RunInt32OrNativeMultiUse(int32) - - ret - } - .method public static native int Int32OrNative(int32 val, bool use_native) - { - ldarg.1 - brtrue use_native_int - use_i4: - ldarg.0 - br after_if - after_if: - ldc.i4.1 - add - ret - use_native_int: - ldarg.0 - conv.u - br after_if - } - - .method public static void Int32OrNativeLoopStyle(int32 val) - { - .locals init ( - int32 i - ) - ldarg.0 - loop: - ldc.i4.1 - add - call void Program::Print(native int) - ldloc.0 - brtrue end - - ldc.i4.1 - stloc.0 - ldarg.0 - conv.u - br loop - end: - ret - } - - .method public static native int Int32OrNativeDeadCode(int32 val) - { - use_i4: - ldarg.0 - br after_if - after_if: - ldc.i4.1 - add - ret - use_native_int: // dead code - ldarg.0 - conv.u - br after_if - } - - .method public static void RunInt32OrNativeMultiUse(int32 val) - { - ldstr "RunInt32OrNativeMultiUse({0}, push_i: false, use2: false) = {1}" - ldarg val - box int32 - ldarg val - ldc.i4 0 // push_i - ldc.i4 0 // use2 - call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) - box native int - call void [mscorlib]System.Console::WriteLine(string, object, object) - - ldstr "RunInt32OrNativeMultiUse({0}, push_i: false, use2: true) = {1}" - ldarg val - box int32 - ldarg val - ldc.i4 0 // push_i - ldc.i4 1 // use2 - call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) - box native int - call void [mscorlib]System.Console::WriteLine(string, object, object) - - ldstr "RunInt32OrNativeMultiUse({0}, push_i: true, use2: false) = {1}" - ldarg val - box int32 - ldarg val - ldc.i4 1 // push_i - ldc.i4 0 // use2 - call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) - box native int - call void [mscorlib]System.Console::WriteLine(string, object, object) - - ldstr "RunInt32OrNativeMultiUse({0}, push_i: true, use2: true) = {1}" - ldarg val - box int32 - ldarg val - ldc.i4 1 // push_i - ldc.i4 1 // use2 - call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) - box native int - call void [mscorlib]System.Console::WriteLine(string, object, object) - ret - } - - .method public static native int Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) - { - ldarg.1 - brtrue push_i - br push_i4 - push_i4: - ldarg.0 - 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 hidebysig static void Main (string[] args) cil managed + { + .maxstack 8 + .entrypoint + + call void Program::InlineAssignByte() + //call void Program::Int32OrNativeTests() + + ret + } // end of method Main + + .method public static void InlineAssignByte() + { + .locals init ( + int8 local + ) + ldstr "InlineAssignByte: WriteLine(local = {0})" + ldc.i4 300 + dup + br pointless // this pointless branch is a workaround for https://github.com/dotnet/coreclr/issues/14784 + // it doesn't have any effect on ILSpy as TransformAssignment runs after control-flow reconstruction +pointless: + // This assignment cannot be turned into a C# inline assignment, because doing so would truncate to 8 bits. + stloc.0 + box int32 + call void [mscorlib]System.Console::WriteLine(string, object) + ldstr "InlineAssignByte: local is {0}" + ldloc.0 + box int32 + call void [mscorlib]System.Console::WriteLine(string, object) + ret + } + + /* + .method public static void Int32OrNativeTests() + { + ldstr "Int32OrNative(0x7fffffff, false) = {0}" + ldc.i4 0x7fffffff + ldc.i4 0 + call native int Program::Int32OrNative(int32, bool) + box native int + call void [mscorlib]System.Console::WriteLine(string, object) + + ldstr "Int32OrNative(0x7fffffff, true) = {0}" + ldc.i4 0x7fffffff + ldc.i4 1 + call native int Program::Int32OrNative(int32, bool) + box native int + call void [mscorlib]System.Console::WriteLine(string, object) + + ldstr "Int32OrNative(-1, false) = {0}" + ldc.i4.m1 + ldc.i4 0 + call native int Program::Int32OrNative(int32, bool) + box native int + call void [mscorlib]System.Console::WriteLine(string, object) + + ldstr "Int32OrNative(-1, true) = {0}" + ldc.i4.m1 + ldc.i4 1 + call native int Program::Int32OrNative(int32, bool) + box native int + call void [mscorlib]System.Console::WriteLine(string, object) + + ldstr "Int32OrNativeLoopStyle(0x7fffffff):" + call void [mscorlib]System.Console::WriteLine(string) + ldc.i4 0x7fffffff + call void Program::Int32OrNativeLoopStyle(int32) + + ldstr "Int32OrNativeLoopStyle(-1):" + call void [mscorlib]System.Console::WriteLine(string) + ldc.i4.m1 + call void Program::Int32OrNativeLoopStyle(int32) + + ldstr "Int32OrNativeDeadCode(0x7fffffff) = {0}" + ldc.i4 0x7fffffff + call native int Program::Int32OrNativeDeadCode(int32) + box native int + call void [mscorlib]System.Console::WriteLine(string, object) + + ldstr "Int32OrNativeDeadCode(-1) = {0}" + ldc.i4.m1 + call native int Program::Int32OrNativeDeadCode(int32) + box native int + call void [mscorlib]System.Console::WriteLine(string, object) + + ldc.i4 0x7fffffff + call void Program::RunInt32OrNativeMultiUse(int32) + ldc.i4.m1 + call void Program::RunInt32OrNativeMultiUse(int32) + + ret + } + .method public static native int Int32OrNative(int32 val, bool use_native) + { + ldarg.1 + brtrue use_native_int + use_i4: + ldarg.0 + br after_if + after_if: + ldc.i4.1 + add + ret + use_native_int: + ldarg.0 + conv.u + br after_if + } + + .method public static void Int32OrNativeLoopStyle(int32 val) + { + .locals init ( + int32 i + ) + ldarg.0 + loop: + ldc.i4.1 + add + call void Program::Print(native int) + ldloc.0 + brtrue end + + ldc.i4.1 + stloc.0 + ldarg.0 + conv.u + br loop + end: + ret + } + + .method public static native int Int32OrNativeDeadCode(int32 val) + { + use_i4: + ldarg.0 + br after_if + after_if: + ldc.i4.1 + add + ret + use_native_int: // dead code + ldarg.0 + conv.u + br after_if + } + + .method public static void RunInt32OrNativeMultiUse(int32 val) + { + ldstr "RunInt32OrNativeMultiUse({0}, push_i: false, use2: false) = {1}" + ldarg val + box int32 + ldarg val + ldc.i4 0 // push_i + ldc.i4 0 // use2 + call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) + box native int + call void [mscorlib]System.Console::WriteLine(string, object, object) + + ldstr "RunInt32OrNativeMultiUse({0}, push_i: false, use2: true) = {1}" + ldarg val + box int32 + ldarg val + ldc.i4 0 // push_i + ldc.i4 1 // use2 + call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) + box native int + call void [mscorlib]System.Console::WriteLine(string, object, object) + + ldstr "RunInt32OrNativeMultiUse({0}, push_i: true, use2: false) = {1}" + ldarg val + box int32 + ldarg val + ldc.i4 1 // push_i + ldc.i4 0 // use2 + call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) + box native int + call void [mscorlib]System.Console::WriteLine(string, object, object) + + ldstr "RunInt32OrNativeMultiUse({0}, push_i: true, use2: true) = {1}" + ldarg val + box int32 + ldarg val + ldc.i4 1 // push_i + ldc.i4 1 // use2 + call native int Program::Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) + box native int + call void [mscorlib]System.Console::WriteLine(string, object, object) + ret + } + + .method public static native int Int32OrNativeMultiUse(int32 val, bool push_i, bool use2) + { + ldarg.1 + brtrue push_i + br push_i4 + push_i4: + ldarg.0 + 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 - } + .method public static void Print(native int val) + { + ldarg.0 + box native int + call void [mscorlib]System.Console::WriteLine(object) + ret + } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs b/ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs index eb44716a8..c6c05fdd6 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs @@ -140,6 +140,10 @@ namespace ICSharpCode.Decompiler.IL /// 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: int index = item.ChildIndex - firstChildIndex; if (index >= 0 && index < list.Count && list[index] == item) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index c18d1ed96..f631b5312 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; @@ -70,45 +71,43 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// stloc s(stobj (..., value)) /// /// e.g. used for inline assignment to static field - bool TransformInlineAssignmentStObj(Block block, int i) + bool TransformInlineAssignmentStObj(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 if (inst == null || (inst.Variable.Kind != VariableKind.StackSlot && inst.Variable.Kind != VariableKind.Local)) return false; - var nextInst = block.Instructions.ElementAtOrDefault(i + 1); - ILInstruction replacement; - StObj fieldStore; + if (IsImplicitTruncation(inst.Value, inst.Variable.Type)) { + // 'stloc s' is implicitly truncating the value + return false; + } ILVariable local; - if (nextInst is StLoc localStore) { // with extra local + int nextPos; + if (block.Instructions[pos + 1] is StLoc localStore) { // with extra local if (localStore.Variable.Kind != VariableKind.Local || !localStore.Value.MatchLdLoc(inst.Variable)) return false; if (!(inst.Variable.IsSingleDefinition && inst.Variable.LoadCount == 2)) return false; - var memberStore = block.Instructions.ElementAtOrDefault(i + 2); - if (memberStore is StObj) { - fieldStore = memberStore as StObj; - if (!fieldStore.Value.MatchLdLoc(inst.Variable) || localStore.Variable.IsUsedWithin(fieldStore.Target)) - return false; - replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); - } else { - return false; - } - context.Step("Inline assignment stobj (with extra local)", fieldStore); local = localStore.Variable; - block.Instructions.RemoveAt(i + 1); - } else if (nextInst is StObj) { // without extra local - fieldStore = (StObj)nextInst; - if (!fieldStore.Value.MatchLdLoc(inst.Variable) || inst.Variable.IsUsedWithin(fieldStore.Target)) - return false; - context.Step("Inline assignment stobj", fieldStore); - local = inst.Variable; - replacement = new StObj(fieldStore.Target, inst.Value, fieldStore.Type); + nextPos = pos + 2; } else { + local = inst.Variable; + localStore = null; + nextPos = pos + 1; + } + if (!(block.Instructions[nextPos] is StObj stobj)) + return false; + if (!stobj.Value.MatchLdLoc(inst.Variable) || inst.Variable.IsUsedWithin(stobj.Target)) + return false; + if (IsImplicitTruncation(inst.Value, stobj.Type)) { + // 'stloc s' is implicitly truncating the value return false; } - block.Instructions.RemoveAt(i + 1); - inst.ReplaceWith(new StLoc(local, replacement)); + context.Step("Inline assignment stobj", stobj); + block.Instructions.Remove(localStore); + block.Instructions.Remove(stobj); + stobj.Value = inst.Value; + inst.ReplaceWith(new StLoc(local, stobj)); return true; } @@ -253,8 +252,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (inst.Variable.Kind != VariableKind.StackSlot) return false; + Debug.Assert(!inst.Variable.Type.IsSmallIntegerType()); if (nextInst.Variable.Kind != VariableKind.Local || !nextInst.Value.MatchLdLoc(inst.Variable)) 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); var value = inst.Value; var var = nextInst.Variable; @@ -263,7 +267,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms nextInst.ReplaceWith(new StLoc(stackVar, new StLoc(var, value))); return true; } - + + bool IsImplicitTruncation(ILInstruction value, IType type) + { + return type.IsSmallIntegerType(); + } + /// /// stloc s(ldloc l) /// stloc l(binary.op(ldloc s, ldc.i4 1)) diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs b/ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs index 808285a09..8ef073fa4 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeUtils.cs @@ -106,7 +106,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static bool IsSmallIntegerType(this IType type) { - return GetSize(type) < 4; + int size = GetSize(type); + return size > 0 && size < 4; } /// From b0bf6326ad99db3ceea48db024745dbdfe8b87b3 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 02:51:23 +0100 Subject: [PATCH 04/15] Allow inline assignments to short integers when we can tell that there's no truncation. --- .../TestCases/Pretty/InlineAssignmentTest.cs | 6 +- .../TestCases/Pretty/InlineAssignmentTest.il | 67 ++++++++++++++----- .../Pretty/InlineAssignmentTest.opt.il | 64 ++++++++++++++---- .../IL/Transforms/TransformAssignment.cs | 48 ++++++++++++- 4 files changed, 154 insertions(+), 31 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs index cc0887987..f32d2fb6b 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs @@ -51,12 +51,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine(InlineAssignmentTest.field2 = new InlineAssignmentTest()); 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 UseShort(short s) + public short UseShort(short s) { Console.WriteLine(s); + return s; } public void ReadLoop1(TextReader r) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il index ec2d0ea7e..9a1797896 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly uq03kalt +.assembly w1xqybg1 { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module uq03kalt.dll -// MVID: {D636DE2E-D2CD-4EDF-B87B-0B0985C6C0B8} +.module w1xqybg1.dll +// MVID: {1BE5829A-0D5E-43DC-8C02-E3012B1780A2} .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: 0x018D0000 +// Image base: 0x033B0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -93,7 +93,7 @@ .method public hidebysig instance void SimpleInlineWithFields2() cil managed { - // Code size 87 (0x57) + // Code size 154 (0x9a) .maxstack 4 .locals init (int32 V_0, int16 V_1) @@ -125,25 +125,62 @@ IL_003d: stloc.1 IL_003e: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4 IL_0043: ldloc.1 - IL_0044: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16) - IL_0049: nop + IL_0044: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16) + IL_0049: pop IL_004a: ldarg.0 - IL_004b: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4 - IL_0050: call void [mscorlib]System.Console::WriteLine(int32) - IL_0055: nop - IL_0056: ret + 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 void + .method public hidebysig instance int16 UseShort(int16 s) cil managed { - // Code size 9 (0x9) - .maxstack 8 + // 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: ret + 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 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il index f98d18c87..2f944dee2 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly zztqnmi4 +.assembly f1ibwsev { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module zztqnmi4.dll -// MVID: {038F2DF5-AE7B-4B0A-B846-AC254CE46038} +.module f1ibwsev.dll +// MVID: {8DB4E6AA-A0C2-49F3-8E9C-A28CE30F145A} .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: 0x006A0000 +// Image base: 0x01400000 // =============== CLASS MEMBERS DECLARATION =================== @@ -85,10 +85,13 @@ .method public hidebysig instance void SimpleInlineWithFields2() cil managed { - // Code size 80 (0x50) + // Code size 150 (0x96) .maxstack 4 .locals init (int32 V_0, - int16 V_1) + int16 V_1, + int16 V_2, + int16 V_3, + int16 V_4) IL_0000: ldarg.0 IL_0001: ldc.i4.5 IL_0002: dup @@ -112,21 +115,54 @@ IL_0038: stloc.1 IL_0039: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4 IL_003e: ldloc.1 - IL_003f: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16) - IL_0044: ldarg.0 - IL_0045: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4 - IL_004a: call void [mscorlib]System.Console::WriteLine(int32) - IL_004f: ret + 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 - .method public hidebysig instance void + .method public hidebysig instance int16 UseShort(int16 s) cil managed { - // Code size 7 (0x7) + // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.1 IL_0001: call void [mscorlib]System.Console::WriteLine(int32) - IL_0006: ret + IL_0006: ldarg.1 + IL_0007: ret } // end of method InlineAssignmentTest::UseShort .method public hidebysig instance void diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index f631b5312..00542ee18 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -268,9 +268,55 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } + /// + /// Gets whether 'stobj type(..., value)' would evaluate to a different value than 'value' + /// due to implicit truncation. + /// bool IsImplicitTruncation(ILInstruction value, IType type) { - return type.IsSmallIntegerType(); + 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 being stored + // is being truncated: + 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 LdObj ldobj) { + return IsImplicitTruncation(ldobj.Type, type); + } else if (value is StObj stobj) { + return IsImplicitTruncation(stobj.Type, type); + } else if (value is LdLoc ldloc) { + return IsImplicitTruncation(ldloc.Variable.Type, type); + } else if (value is StLoc stloc) { + return IsImplicitTruncation(stloc.Variable.Type, type); + } else if (value is CallInstruction call) { + return IsImplicitTruncation(call.Method.ReturnType, type); + } 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 + } + return true; + } + + bool IsImplicitTruncation(IType fromType, IType toType) + { + return !(fromType.GetSize() <= toType.GetSize() && fromType.GetSign() == toType.GetSign()); } /// From 248a9ad76fd7975e4f1bb06e958ed7518659ebbb Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 03:31:19 +0100 Subject: [PATCH 05/15] Fix #954: don't use invalid compound assignments on enums --- .../Pretty/CompoundAssignmentTest.cs | 6 + .../Pretty/CompoundAssignmentTest.il | 24 +++- .../Pretty/CompoundAssignmentTest.opt.il | 23 +++- .../CompoundAssignmentTest.opt.roslyn.il | 19 +++- .../Pretty/CompoundAssignmentTest.roslyn.il | 20 +++- ICSharpCode.Decompiler/IL/ILTypeExtensions.cs | 35 ++++++ ICSharpCode.Decompiler/IL/Instructions.cs | 105 +++++++++++++----- ICSharpCode.Decompiler/IL/Instructions.tt | 7 +- .../CompoundAssignmentInstruction.cs | 4 + .../IL/Transforms/AssignVariableNames.cs | 17 +-- .../IL/Transforms/ExpressionTransforms.cs | 34 ++++-- .../IL/Transforms/TransformAssignment.cs | 22 +--- 12 files changed, 234 insertions(+), 82 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index e09609a66..b23995d57 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs @@ -410,5 +410,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Item item = CompoundAssignmentTest.GetItem(null); item.Self = item; } + + 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); + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il index 5d1d21eda..d1f7743a6 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly w1xcwa3w +.assembly gvvksqgl { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module w1xcwa3w.dll -// MVID: {FAFFB825-2101-4417-8C03-0E0B083653E5} +.module gvvksqgl.dll +// MVID: {50934C05-8B92-4905-A41A-146C5F2392BA} .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .imagebase 0x10000000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00D60000 +// Image base: 0x00410000 // =============== CLASS MEMBERS DECLARATION =================== @@ -1543,6 +1543,22 @@ IL_000f: ret } // 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 8 (0x8) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.1 + IL_0003: ldind.i4 + IL_0004: ldarg.2 + IL_0005: rem + IL_0006: stind.i4 + IL_0007: ret + } // end of method CompoundAssignmentTest::Issue954 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il index 09d5a0a91..81274b1ee 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly pbv15mad +.assembly '20aqunvz' { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module pbv15mad.dll -// MVID: {7F137601-6720-4272-9855-AEC542FD460D} +.module '20aqunvz.dll' +// MVID: {3A9D60C3-9668-4C33-85C8-329DB1EEECE6} .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: 0x01300000 +// Image base: 0x029E0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -1262,6 +1262,21 @@ IL_000e: ret } // 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 7 (0x7) + .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: ret + } // end of method CompoundAssignmentTest::Issue954 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il index feb9ee854..6f4cc80e5 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {7FF443A1-4D5C-4B6C-ABE8-2BE60079524D} +// MVID: {8664D95A-CCCF-4302-9678-AEB0491B7A00} .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: 0x02DC0000 +// Image base: 0x02D20000 // =============== CLASS MEMBERS DECLARATION =================== @@ -1268,6 +1268,21 @@ IL_000c: ret } // 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 7 (0x7) + .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: ret + } // end of method CompoundAssignmentTest::Issue954 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il index 1e7a12bce..23b86054a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {514BA798-3837-4D3D-8485-D675114840C6} +// MVID: {9D118C00-E9E9-446E-9B2F-0C32732A9171} .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: 0x01590000 +// Image base: 0x02BF0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -1538,6 +1538,22 @@ IL_000f: ret } // 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 8 (0x8) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.1 + IL_0003: ldind.i4 + IL_0004: ldarg.2 + IL_0005: rem + IL_0006: stind.i4 + IL_0007: ret + } // end of method CompoundAssignmentTest::Issue954 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { diff --git a/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs b/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs index 89f998823..739c8b62a 100644 --- a/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs +++ b/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs @@ -127,5 +127,40 @@ namespace ICSharpCode.Decompiler.IL { return primitiveType.GetStackType().IsIntegerType(); } + + /// + /// Infers the C# type for an IL instruction. + /// + /// Returns SpecialType.UnknownType for unsupported instructions. + /// + 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; + } + } } } diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 809aabafe..280b21190 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -943,9 +943,12 @@ namespace ICSharpCode.Decompiler.IL clone.Value = this.value.Clone(); return clone; } - readonly IType type; + IType type; /// Returns the type operand. - 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 void AcceptVisitor(ILVisitor visitor) { @@ -2814,9 +2817,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - 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 void WriteTo(ITextOutput output, ILAstWritingOptions options) { @@ -3350,9 +3356,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - public IType Type { get { return type; } } + public IType Type { + get { return type; } + set { type = value; InvalidateFlags(); } + } public override StackType ResultType { get { return type.GetStackType(); } } protected override InstructionFlags ComputeFlags() { @@ -3401,9 +3410,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - 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 void WriteTo(ITextOutput output, ILAstWritingOptions options) { @@ -3491,9 +3503,12 @@ namespace ICSharpCode.Decompiler.IL clone.Target = this.target.Clone(); return clone; } - readonly IType type; + IType type; /// Returns the type operand. - public IType Type { get { return type; } } + public IType Type { + get { return type; } + set { type = value; InvalidateFlags(); } + } /// Gets/Sets whether the memory access is volatile. public bool IsVolatile { get; set; } /// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix. @@ -3617,9 +3632,12 @@ namespace ICSharpCode.Decompiler.IL clone.Value = this.value.Clone(); return clone; } - readonly IType type; + IType type; /// Returns the type operand. - public IType Type { get { return type; } } + public IType Type { + get { return type; } + set { type = value; InvalidateFlags(); } + } /// Gets/Sets whether the memory access is volatile. public bool IsVolatile { get; set; } /// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix. @@ -3678,9 +3696,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - public IType Type { get { return type; } } + public IType Type { + get { return type; } + set { type = value; InvalidateFlags(); } + } public override StackType ResultType { get { return StackType.O; } } protected override InstructionFlags ComputeFlags() { @@ -3729,9 +3750,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - public IType Type { get { return type; } } + public IType Type { + get { return type; } + set { type = value; InvalidateFlags(); } + } public override StackType ResultType { get { return StackType.Ref; } } protected override InstructionFlags ComputeFlags() { @@ -3780,9 +3804,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - public IType Type { get { return type; } } + public IType Type { + get { return type; } + set { type = value; InvalidateFlags(); } + } public override StackType ResultType { get { return type.GetStackType(); } } protected override InstructionFlags ComputeFlags() { @@ -3856,9 +3883,12 @@ namespace ICSharpCode.Decompiler.IL this.Indices = new InstructionCollection(this, 0); this.Indices.AddRange(indices); } - readonly IType type; + IType type; /// Returns the type operand. - 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 InstructionCollection Indices { get; private set; } protected sealed override int GetChildCount() @@ -3946,9 +3976,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - 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 void WriteTo(ITextOutput output, ILAstWritingOptions options) { @@ -4059,9 +4092,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - 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 void WriteTo(ITextOutput output, ILAstWritingOptions options) { @@ -4181,9 +4217,12 @@ namespace ICSharpCode.Decompiler.IL this.Indices = new InstructionCollection(this, 1); this.Indices.AddRange(indices); } - readonly IType type; + IType type; /// Returns the type operand. - 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); ILInstruction array; public ILInstruction Array { @@ -4468,9 +4507,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - 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 void WriteTo(ITextOutput output, ILAstWritingOptions options) { @@ -4538,9 +4580,12 @@ namespace ICSharpCode.Decompiler.IL { this.type = type; } - readonly IType type; + IType type; /// Returns the type operand. - public IType Type { get { return type; } } + public IType Type { + get { return type; } + set { type = value; InvalidateFlags(); } + } public override StackType ResultType { get { return StackType.Ref; } } protected override InstructionFlags ComputeFlags() { diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 126b9c795..ccb17d8d6 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -939,12 +939,15 @@ protected override void Disconnected() static Action HasTypeOperand = opCode => { opCode.ConstructorParameters.Add("IType type"); - opCode.Members.Add("readonly IType type;"); + opCode.Members.Add("IType type;"); opCode.ConstructorBody.Add("this.type = type;"); opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "IType", Name = "type", FieldName = "Type" }); opCode.PerformMatchConditions.Add("type.Equals(o.type)"); opCode.Members.Add("/// Returns the type operand." + 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.WriteOperand.Add("output.Write(' ');"); opCode.WriteOperand.Add("type.WriteTo(output);"); diff --git a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs index 2b7f34e40..ad6c46560 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs @@ -85,6 +85,10 @@ namespace ICSharpCode.Decompiler.IL return false; type = NullableType.GetUnderlyingType(type); } + if (type.Kind == TypeKind.Enum) { + if (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub) + return false; + } if (binary.Sign != Sign.None) { if (type.GetSign() != binary.Sign) return false; diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs index bd39b6c1a..e7967e44e 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs @@ -359,18 +359,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (!variableType.IsKnownType(KnownTypeCode.Object)) return variableType; - 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; - default: - return context.TypeSystem.Compilation.FindType(inst.ResultType.ToKnownTypeCode()); - } + IType inferredType = inst.InferType(); + if (inferredType.Kind != TypeKind.Unknown) + return inferredType; + else + return variableType; } internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, ILVariable existingVariable = null) diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index 7471059e3..673cdba25 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/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 // DEALINGS IN THE SOFTWARE. +using System; using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.IL.Transforms { @@ -279,17 +281,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms } 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)) + && binary.Left is LdObj ldobj + && inst.Target.Match(ldobj.Target).Success + && SemanticHelper.IsPure(ldobj.Target.Flags)) { - 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)); + // 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 (CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) { + context.Step("compound assignment", inst); + // stobj(target, binary.op(ldobj(target), ...)) + // => compound.op(target, ...) + inst.ReplaceWith(new CompoundAssignmentInstruction( + binary, binary.Left, binary.Right, + targetType, CompoundAssignmentType.EvaluatesToNewValue)); + } } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index 00542ee18..df8c2ea45 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -296,29 +296,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms case KnownTypeCode.Char: return !(val >= ushort.MinValue && val <= ushort.MaxValue); } - } else if (value is LdObj ldobj) { - return IsImplicitTruncation(ldobj.Type, type); - } else if (value is StObj stobj) { - return IsImplicitTruncation(stobj.Type, type); - } else if (value is LdLoc ldloc) { - return IsImplicitTruncation(ldloc.Variable.Type, type); - } else if (value is StLoc stloc) { - return IsImplicitTruncation(stloc.Variable.Type, type); - } else if (value is CallInstruction call) { - return IsImplicitTruncation(call.Method.ReturnType, type); } 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; } - - bool IsImplicitTruncation(IType fromType, IType toType) - { - return !(fromType.GetSize() <= toType.GetSize() && fromType.GetSign() == toType.GetSign()); - } - + /// /// stloc s(ldloc l) /// stloc l(binary.op(ldloc s, ldc.i4 1)) From 40a4f08a8d14840a1244d3080dc4c62540b2719d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 13:49:55 +0100 Subject: [PATCH 06/15] Add support for compound assignment of short integers. --- .../Correctness/CompoundAssignment.cs | 21 + .../Pretty/CompoundAssignmentTest.cs | 105 ++++- .../Pretty/CompoundAssignmentTest.il | 405 +++++++++++++++++- .../Pretty/CompoundAssignmentTest.opt.il | 342 ++++++++++++++- .../CompoundAssignmentTest.opt.roslyn.il | 336 ++++++++++++++- .../Pretty/CompoundAssignmentTest.roslyn.il | 399 ++++++++++++++++- .../CSharp/ExpressionBuilder.cs | 4 +- ICSharpCode.Decompiler/IL/Instructions.cs | 8 +- ICSharpCode.Decompiler/IL/Instructions.tt | 4 +- .../CompoundAssignmentInstruction.cs | 12 +- .../IL/Transforms/ExpressionTransforms.cs | 27 +- .../IL/Transforms/TransformAssignment.cs | 81 +++- 12 files changed, 1643 insertions(+), 101 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs index 096ae9b17..7893c9e0a 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/CompoundAssignment.cs @@ -30,6 +30,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness CallTwice(); UnsignedShiftRightInstanceField(); UnsignedShiftRightStaticProperty(); + DivideByBigValue(); } 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 GetDict() { Console.WriteLine("In GetDict()"); @@ -133,5 +147,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness StaticProperty = -15; 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)); + } } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index b23995d57..e0d9ec95e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs @@ -78,6 +78,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private int[] array1; private StructContainer field1; private MyEnum enumField; + private ShortEnum shortEnumField; public static int StaticField; public static short StaticShortField; @@ -228,8 +229,18 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { this.enumField |= MyEnum.Two; 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) { return i + ++j; @@ -250,21 +261,41 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty array[pos]++; } - public int PreIncrementShortArrayElement(short[] array, int 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 PostIncrementShortArrayElement(short[] array, int pos) + public int PostIncrementArrayElementShort(short[] array, int pos) { return array[pos]++; } - public void IncrementShortArrayElement(short[] array, int 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() { return ++this.M().Field; @@ -280,6 +311,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty this.M().Field++; } + public void DoubleInstanceField() + { + this.M().Field *= 2; + } + + public int DoubleInstanceFieldAndReturn() + { + return this.M().Field *= 2; + } + public int PreIncrementInstanceField2(MutableClass m) { return ++m.Field; @@ -325,6 +366,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty 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; @@ -340,6 +391,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty this.M().ByteProperty++; } + public void DoubleInstancePropertyByte() + { + this.M().ByteProperty *= 2; + } + + public int DoubleInstancePropertyByteAndReturn() + { + return this.M().ByteProperty *= 2; + } + public int PreIncrementStaticField() { return ++CompoundAssignmentTest.StaticField; @@ -355,6 +416,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty CompoundAssignmentTest.StaticField++; } + public void DoubleStaticField() + { + CompoundAssignmentTest.StaticField *= 2; + } + + public int DoubleStaticFieldAndReturn() + { + return CompoundAssignmentTest.StaticField *= 2; + } + public int PreIncrementStaticFieldShort() { return ++CompoundAssignmentTest.StaticShortField; @@ -370,6 +441,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty CompoundAssignmentTest.StaticShortField++; } + public void DoubleStaticFieldShort() + { + CompoundAssignmentTest.StaticShortField *= 2; + } + + public short DoubleStaticFieldAndReturnShort() + { + return CompoundAssignmentTest.StaticShortField *= 2; + } + public int PreIncrementStaticProperty() { return ++CompoundAssignmentTest.StaticProperty; @@ -385,6 +466,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty CompoundAssignmentTest.StaticProperty++; } + public void DoubleStaticProperty() + { + CompoundAssignmentTest.StaticProperty *= 2; + } + + public int DoubleStaticPropertyAndReturn() + { + return CompoundAssignmentTest.StaticProperty *= 2; + } + public ShortEnum PreIncrementStaticPropertyShort() { return ++CompoundAssignmentTest.StaticShortProperty; @@ -399,7 +490,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { CompoundAssignmentTest.StaticShortProperty++; } - + private static Item GetItem(object obj) { return null; @@ -411,10 +502,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty item.Self = item; } - void Issue954(ref MyEnum a, MyEnum b) + 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); } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il index d1f7743a6..c1e975417 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly gvvksqgl +.assembly oguadjyn { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module gvvksqgl.dll -// MVID: {50934C05-8B92-4905-A41A-146C5F2392BA} +.module oguadjyn.dll +// MVID: {7DE8C1A3-5051-43F6-ACDA-EFB9A52251C4} .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: 0x00410000 +// Image base: 0x019F0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -203,6 +203,7 @@ .field private int32[] array1 .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/ShortEnum shortEnumField .field public static int32 StaticField .field public static int16 StaticShortField .field private static int32 'k__BackingField' @@ -771,7 +772,7 @@ .method public hidebysig instance void Enum() cil managed { - // Code size 31 (0x1f) + // Code size 59 (0x3b) .maxstack 8 IL_0000: nop IL_0001: ldarg.0 @@ -786,9 +787,58 @@ IL_0016: ldc.i4.s -5 IL_0018: and IL_0019: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField - IL_001e: ret + IL_001e: ldarg.0 + IL_001f: dup + IL_0020: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_0025: ldc.i4.2 + IL_0026: add + IL_0027: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_002c: ldarg.0 + IL_002d: dup + IL_002e: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_0033: ldc.i4.3 + IL_0034: sub + IL_0035: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_003a: ret } // end of method CompoundAssignmentTest::Enum + .method public hidebysig instance void + ShortEnumTest() cil managed + { + // Code size 63 (0x3f) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: dup + IL_0003: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0008: ldc.i4.2 + IL_0009: or + IL_000a: conv.i2 + IL_000b: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0010: ldarg.0 + IL_0011: dup + IL_0012: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0017: ldc.i4.s -5 + IL_0019: and + IL_001a: conv.i2 + IL_001b: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0020: ldarg.0 + IL_0021: dup + IL_0022: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0027: ldc.i4.2 + IL_0028: add + IL_0029: conv.i2 + IL_002a: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_002f: ldarg.0 + IL_0030: dup + IL_0031: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0036: ldc.i4.3 + IL_0037: sub + IL_0038: conv.i2 + IL_0039: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_003e: ret + } // end of method CompoundAssignmentTest::ShortEnumTest + .method public hidebysig instance int32 PreIncrementInAddition(int32 i, int32 j) cil managed @@ -883,8 +933,53 @@ IL_0015: ret } // end of method CompoundAssignmentTest::IncrementArrayElement + .method public hidebysig instance void + DoubleArrayElement(int32[] 'array', + int32 pos) cil managed + { + // Code size 22 (0x16) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int32 + IL_0008: dup + IL_0009: ldobj [mscorlib]System.Int32 + IL_000e: ldc.i4.2 + IL_000f: mul + IL_0010: stobj [mscorlib]System.Int32 + IL_0015: ret + } // end of method CompoundAssignmentTest::DoubleArrayElement + .method public hidebysig instance int32 - PreIncrementShortArrayElement(int16[] 'array', + DoubleArrayElementAndReturn(int32[] 'array', + int32 pos) cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int32 + IL_0008: dup + IL_0009: ldobj [mscorlib]System.Int32 + IL_000e: ldc.i4.2 + IL_000f: mul + IL_0010: dup + IL_0011: stloc.1 + IL_0012: stobj [mscorlib]System.Int32 + IL_0017: ldloc.1 + IL_0018: stloc.0 + IL_0019: br.s IL_001b + + IL_001b: ldloc.0 + IL_001c: ret + } // end of method CompoundAssignmentTest::DoubleArrayElementAndReturn + + .method public hidebysig instance int32 + PreIncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 30 (0x1e) @@ -909,10 +1004,10 @@ IL_001c: ldloc.0 IL_001d: ret - } // end of method CompoundAssignmentTest::PreIncrementShortArrayElement + } // end of method CompoundAssignmentTest::PreIncrementArrayElementShort .method public hidebysig instance int32 - PostIncrementShortArrayElement(int16[] 'array', + PostIncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 30 (0x1e) @@ -937,10 +1032,10 @@ IL_001c: ldloc.0 IL_001d: ret - } // end of method CompoundAssignmentTest::PostIncrementShortArrayElement + } // end of method CompoundAssignmentTest::PostIncrementArrayElementShort .method public hidebysig instance void - IncrementShortArrayElement(int16[] 'array', + IncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 23 (0x17) @@ -956,7 +1051,54 @@ IL_0010: conv.i2 IL_0011: stobj [mscorlib]System.Int16 IL_0016: ret - } // end of method CompoundAssignmentTest::IncrementShortArrayElement + } // end of method CompoundAssignmentTest::IncrementArrayElementShort + + .method public hidebysig instance void + DoubleArrayElementShort(int16[] 'array', + int32 pos) cil managed + { + // Code size 23 (0x17) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldobj [mscorlib]System.Int16 + IL_000e: ldc.i4.2 + IL_000f: mul + IL_0010: conv.i2 + IL_0011: stobj [mscorlib]System.Int16 + IL_0016: ret + } // end of method CompoundAssignmentTest::DoubleArrayElementShort + + .method public hidebysig instance int16 + DoubleArrayElementShortAndReturn(int16[] 'array', + int32 pos) cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (int16 V_0, + int16 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldobj [mscorlib]System.Int16 + IL_000e: ldc.i4.2 + IL_000f: mul + IL_0010: conv.i2 + IL_0011: dup + IL_0012: stloc.1 + IL_0013: stobj [mscorlib]System.Int16 + IL_0018: ldloc.1 + IL_0019: stloc.0 + IL_001a: br.s IL_001c + + IL_001c: ldloc.0 + IL_001d: ret + } // end of method CompoundAssignmentTest::DoubleArrayElementShortAndReturn .method public hidebysig instance int32 PreIncrementInstanceField() cil managed @@ -1024,6 +1166,47 @@ IL_0014: ret } // end of method CompoundAssignmentTest::IncrementInstanceField + .method public hidebysig instance void + DoubleInstanceField() cil managed + { + // Code size 21 (0x15) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0014: ret + } // end of method CompoundAssignmentTest::DoubleInstanceField + + .method public hidebysig instance int32 + DoubleInstanceFieldAndReturn() cil managed + { + // Code size 28 (0x1c) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: dup + IL_0010: stloc.1 + IL_0011: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0016: ldloc.1 + IL_0017: stloc.0 + IL_0018: br.s IL_001a + + IL_001a: ldloc.0 + IL_001b: ret + } // end of method CompoundAssignmentTest::DoubleInstanceFieldAndReturn + .method public hidebysig instance int32 PreIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed { @@ -1225,6 +1408,49 @@ IL_0015: ret } // end of method CompoundAssignmentTest::IncrementInstanceProperty + .method public hidebysig instance void + DoubleInstanceProperty() cil managed + { + // Code size 22 (0x16) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property() + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32) + IL_0014: nop + IL_0015: ret + } // end of method CompoundAssignmentTest::DoubleInstanceProperty + + .method public hidebysig instance int32 + DoubleInstancePropertyAndReturn() cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property() + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: dup + IL_0010: stloc.1 + IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32) + IL_0016: nop + IL_0017: ldloc.1 + IL_0018: stloc.0 + IL_0019: br.s IL_001b + + IL_001b: ldloc.0 + IL_001c: ret + } // end of method CompoundAssignmentTest::DoubleInstancePropertyAndReturn + .method public hidebysig instance int32 PreIncrementInstancePropertyByte() cil managed { @@ -1297,6 +1523,51 @@ IL_0016: ret } // end of method CompoundAssignmentTest::IncrementInstancePropertyByte + .method public hidebysig instance void + DoubleInstancePropertyByte() cil managed + { + // Code size 23 (0x17) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: conv.u1 + IL_0010: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0015: nop + IL_0016: ret + } // end of method CompoundAssignmentTest::DoubleInstancePropertyByte + + .method public hidebysig instance int32 + DoubleInstancePropertyByteAndReturn() cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (int32 V_0, + uint8 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: conv.u1 + IL_0010: dup + IL_0011: stloc.1 + IL_0012: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0017: nop + IL_0018: ldloc.1 + IL_0019: stloc.0 + IL_001a: br.s IL_001c + + IL_001c: ldloc.0 + IL_001d: ret + } // end of method CompoundAssignmentTest::DoubleInstancePropertyByteAndReturn + .method public hidebysig instance int32 PreIncrementStaticField() cil managed { @@ -1348,6 +1619,38 @@ IL_000d: ret } // end of method CompoundAssignmentTest::IncrementStaticField + .method public hidebysig instance void + DoubleStaticField() cil managed + { + // Code size 14 (0xe) + .maxstack 8 + IL_0000: nop + IL_0001: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField + IL_000d: ret + } // end of method CompoundAssignmentTest::DoubleStaticField + + .method public hidebysig instance int32 + DoubleStaticFieldAndReturn() cil managed + { + // Code size 19 (0x13) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: dup + IL_0009: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method CompoundAssignmentTest::DoubleStaticFieldAndReturn + .method public hidebysig instance int32 PreIncrementStaticFieldShort() cil managed { @@ -1402,6 +1705,40 @@ IL_000e: ret } // end of method CompoundAssignmentTest::IncrementStaticFieldShort + .method public hidebysig instance void + DoubleStaticFieldShort() cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: conv.i2 + IL_0009: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_000e: ret + } // end of method CompoundAssignmentTest::DoubleStaticFieldShort + + .method public hidebysig instance int16 + DoubleStaticFieldAndReturnShort() cil managed + { + // Code size 20 (0x14) + .maxstack 2 + .locals init (int16 V_0) + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: conv.i2 + IL_0009: dup + IL_000a: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::DoubleStaticFieldAndReturnShort + .method public hidebysig instance int32 PreIncrementStaticProperty() cil managed { @@ -1456,6 +1793,40 @@ IL_000e: ret } // end of method CompoundAssignmentTest::IncrementStaticProperty + .method public hidebysig instance void + DoubleStaticProperty() cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: nop + IL_0001: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) + IL_000d: nop + IL_000e: ret + } // end of method CompoundAssignmentTest::DoubleStaticProperty + + .method public hidebysig instance int32 + DoubleStaticPropertyAndReturn() cil managed + { + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: dup + IL_0009: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) + IL_000e: nop + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::DoubleStaticPropertyAndReturn + .method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum PreIncrementStaticPropertyShort() cil managed { @@ -1547,7 +1918,7 @@ Issue954(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum& a, valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum b) cil managed { - // Code size 8 (0x8) + // Code size 22 (0x16) .maxstack 8 IL_0000: nop IL_0001: ldarg.1 @@ -1556,7 +1927,13 @@ IL_0004: ldarg.2 IL_0005: rem IL_0006: stind.i4 - IL_0007: ret + IL_0007: ldarg.0 + IL_0008: ldarg.0 + IL_0009: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_000e: ldarg.2 + IL_000f: rem + IL_0010: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_0015: ret } // end of method CompoundAssignmentTest::Issue954 .method public hidebysig specialname rtspecialname diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il index 81274b1ee..f318769c5 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly '20aqunvz' +.assembly vm2ov5l1 { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module '20aqunvz.dll' -// MVID: {3A9D60C3-9668-4C33-85C8-329DB1EEECE6} +.module vm2ov5l1.dll +// MVID: {F7BCAA28-E619-40E7-921D-149FF48046FD} .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: 0x029E0000 +// Image base: 0x052F0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -186,6 +186,7 @@ .field private int32[] array1 .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/ShortEnum shortEnumField .field public static int32 StaticField .field public static int16 StaticShortField .field private static int32 'k__BackingField' @@ -659,7 +660,7 @@ .method public hidebysig instance void Enum() cil managed { - // Code size 30 (0x1e) + // Code size 58 (0x3a) .maxstack 8 IL_0000: ldarg.0 IL_0001: dup @@ -673,9 +674,57 @@ IL_0015: ldc.i4.s -5 IL_0017: and 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 + .method public hidebysig instance void + ShortEnumTest() cil managed + { + // Code size 62 (0x3e) + .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.s -5 + IL_0018: and + IL_0019: conv.i2 + IL_001a: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_001f: ldarg.0 + IL_0020: dup + IL_0021: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0026: ldc.i4.2 + IL_0027: add + IL_0028: conv.i2 + IL_0029: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_002e: ldarg.0 + IL_002f: dup + IL_0030: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0035: ldc.i4.3 + IL_0036: sub + IL_0037: conv.i2 + IL_0038: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_003d: ret + } // end of method CompoundAssignmentTest::ShortEnumTest + .method public hidebysig instance int32 PreIncrementInAddition(int32 i, int32 j) cil managed @@ -751,8 +800,46 @@ IL_0014: ret } // 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 - PreIncrementShortArrayElement(int16[] 'array', + 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) @@ -771,10 +858,10 @@ IL_0012: stobj [mscorlib]System.Int16 IL_0017: ldloc.0 IL_0018: ret - } // end of method CompoundAssignmentTest::PreIncrementShortArrayElement + } // end of method CompoundAssignmentTest::PreIncrementArrayElementShort .method public hidebysig instance int32 - PostIncrementShortArrayElement(int16[] 'array', + PostIncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 25 (0x19) @@ -793,10 +880,10 @@ IL_0012: stobj [mscorlib]System.Int16 IL_0017: ldloc.0 IL_0018: ret - } // end of method CompoundAssignmentTest::PostIncrementShortArrayElement + } // end of method CompoundAssignmentTest::PostIncrementArrayElementShort .method public hidebysig instance void - IncrementShortArrayElement(int16[] 'array', + IncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 22 (0x16) @@ -811,7 +898,47 @@ IL_000f: conv.i2 IL_0010: stobj [mscorlib]System.Int16 IL_0015: ret - } // end of method CompoundAssignmentTest::IncrementShortArrayElement + } // 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 PreIncrementInstanceField() cil managed @@ -866,6 +993,40 @@ IL_0013: ret } // 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 PreIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed { @@ -1025,6 +1186,40 @@ IL_0013: ret } // 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 { @@ -1081,6 +1276,42 @@ 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 PreIncrementStaticField() cil managed { @@ -1119,6 +1350,31 @@ IL_000c: ret } // 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 { @@ -1160,6 +1416,33 @@ 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 PreIncrementStaticProperty() cil managed { @@ -1198,6 +1481,31 @@ IL_000c: ret } // 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 { @@ -1266,7 +1574,7 @@ Issue954(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum& a, valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum b) cil managed { - // Code size 7 (0x7) + // Code size 21 (0x15) .maxstack 8 IL_0000: ldarg.1 IL_0001: ldarg.1 @@ -1274,7 +1582,13 @@ IL_0003: ldarg.2 IL_0004: rem IL_0005: stind.i4 - IL_0006: ret + 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 public hidebysig specialname rtspecialname diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il index 6f4cc80e5..51f5d33e7 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {8664D95A-CCCF-4302-9678-AEB0491B7A00} +// MVID: {9C969BC5-E3E2-4944-BB85-4B7EAAE52E4D} .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: 0x02D20000 +// Image base: 0x00480000 // =============== CLASS MEMBERS DECLARATION =================== @@ -190,6 +190,7 @@ .field private int32[] array1 .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/ShortEnum shortEnumField .field public static int32 StaticField .field public static int16 StaticShortField .field private static int32 'k__BackingField' @@ -662,7 +663,7 @@ .method public hidebysig instance void Enum() cil managed { - // Code size 30 (0x1e) + // Code size 58 (0x3a) .maxstack 8 IL_0000: ldarg.0 IL_0001: ldarg.0 @@ -676,9 +677,55 @@ IL_0015: ldc.i4.s -5 IL_0017: and 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 + .method public hidebysig instance void + ShortEnumTest() cil managed + { + // Code size 60 (0x3c) + .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.s -5 + IL_0017: and + IL_0018: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_001d: ldarg.0 + IL_001e: ldarg.0 + IL_001f: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0024: ldc.i4.2 + IL_0025: add + IL_0026: conv.i2 + IL_0027: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_002c: ldarg.0 + IL_002d: ldarg.0 + IL_002e: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0033: ldc.i4.3 + IL_0034: sub + IL_0035: conv.i2 + IL_0036: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_003b: ret + } // end of method CompoundAssignmentTest::ShortEnumTest + .method public hidebysig instance int32 PreIncrementInAddition(int32 i, int32 j) cil managed @@ -754,8 +801,46 @@ IL_000c: ret } // 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 - PreIncrementShortArrayElement(int16[] 'array', + PreIncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 17 (0x11) @@ -774,10 +859,10 @@ IL_000e: stind.i2 IL_000f: ldloc.0 IL_0010: ret - } // end of method CompoundAssignmentTest::PreIncrementShortArrayElement + } // end of method CompoundAssignmentTest::PreIncrementArrayElementShort .method public hidebysig instance int32 - PostIncrementShortArrayElement(int16[] 'array', + PostIncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 17 (0x11) @@ -796,10 +881,10 @@ IL_000e: stind.i2 IL_000f: ldloc.0 IL_0010: ret - } // end of method CompoundAssignmentTest::PostIncrementShortArrayElement + } // end of method CompoundAssignmentTest::PostIncrementArrayElementShort .method public hidebysig instance void - IncrementShortArrayElement(int16[] 'array', + IncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 14 (0xe) @@ -814,7 +899,47 @@ IL_000b: conv.i2 IL_000c: stind.i2 IL_000d: ret - } // end of method CompoundAssignmentTest::IncrementShortArrayElement + } // 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 PreIncrementInstanceField() cil managed @@ -869,6 +994,40 @@ IL_0013: ret } // 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 PreIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed { @@ -1031,6 +1190,40 @@ IL_0015: ret } // 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 { @@ -1090,6 +1283,42 @@ 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 PreIncrementStaticField() cil managed { @@ -1128,6 +1357,31 @@ IL_000c: ret } // 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 { @@ -1169,6 +1423,33 @@ 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 PreIncrementStaticProperty() cil managed { @@ -1207,6 +1488,31 @@ IL_000c: ret } // 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 { @@ -1272,7 +1578,7 @@ Issue954(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum& a, valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum b) cil managed { - // Code size 7 (0x7) + // Code size 21 (0x15) .maxstack 8 IL_0000: ldarg.1 IL_0001: ldarg.1 @@ -1280,7 +1586,13 @@ IL_0003: ldarg.2 IL_0004: rem IL_0005: stind.i4 - IL_0006: ret + 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 public hidebysig specialname rtspecialname diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il index 23b86054a..3f405ccac 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {9D118C00-E9E9-446E-9B2F-0C32732A9171} +// MVID: {AB7EC3EB-B732-497E-809B-7D4DBB442E2C} .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: 0x02BF0000 +// Image base: 0x019F0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -201,6 +201,7 @@ .field private int32[] array1 .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/ShortEnum shortEnumField .field public static int32 StaticField .field public static int16 StaticShortField .field private static int32 'k__BackingField' @@ -760,7 +761,7 @@ .method public hidebysig instance void Enum() cil managed { - // Code size 31 (0x1f) + // Code size 59 (0x3b) .maxstack 8 IL_0000: nop IL_0001: ldarg.0 @@ -775,9 +776,56 @@ IL_0016: ldc.i4.s -5 IL_0018: and IL_0019: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField - IL_001e: ret + IL_001e: ldarg.0 + IL_001f: ldarg.0 + IL_0020: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_0025: ldc.i4.2 + IL_0026: add + IL_0027: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_002c: ldarg.0 + IL_002d: ldarg.0 + IL_002e: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_0033: ldc.i4.3 + IL_0034: sub + IL_0035: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_003a: ret } // end of method CompoundAssignmentTest::Enum + .method public hidebysig instance void + ShortEnumTest() cil managed + { + // Code size 61 (0x3d) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldarg.0 + IL_0003: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0008: ldc.i4.2 + IL_0009: or + IL_000a: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_000f: ldarg.0 + IL_0010: ldarg.0 + IL_0011: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0016: ldc.i4.s -5 + IL_0018: and + IL_0019: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_001e: ldarg.0 + IL_001f: ldarg.0 + 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: ldarg.0 + 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 PreIncrementInAddition(int32 i, int32 j) cil managed @@ -872,8 +920,53 @@ IL_000d: ret } // end of method CompoundAssignmentTest::IncrementArrayElement + .method public hidebysig instance void + DoubleArrayElement(int32[] 'array', + int32 pos) cil managed + { + // Code size 14 (0xe) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int32 + IL_0008: dup + IL_0009: ldind.i4 + IL_000a: ldc.i4.2 + IL_000b: mul + IL_000c: stind.i4 + IL_000d: ret + } // end of method CompoundAssignmentTest::DoubleArrayElement + .method public hidebysig instance int32 - PreIncrementShortArrayElement(int16[] 'array', + DoubleArrayElementAndReturn(int32[] 'array', + int32 pos) cil managed + { + // Code size 21 (0x15) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int32 + IL_0008: dup + IL_0009: ldind.i4 + IL_000a: ldc.i4.2 + IL_000b: mul + IL_000c: dup + IL_000d: stloc.0 + IL_000e: stind.i4 + IL_000f: ldloc.0 + IL_0010: stloc.1 + IL_0011: br.s IL_0013 + + IL_0013: ldloc.1 + IL_0014: ret + } // end of method CompoundAssignmentTest::DoubleArrayElementAndReturn + + .method public hidebysig instance int32 + PreIncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 22 (0x16) @@ -898,10 +991,10 @@ IL_0014: ldloc.1 IL_0015: ret - } // end of method CompoundAssignmentTest::PreIncrementShortArrayElement + } // end of method CompoundAssignmentTest::PreIncrementArrayElementShort .method public hidebysig instance int32 - PostIncrementShortArrayElement(int16[] 'array', + PostIncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 22 (0x16) @@ -926,10 +1019,10 @@ IL_0014: ldloc.1 IL_0015: ret - } // end of method CompoundAssignmentTest::PostIncrementShortArrayElement + } // end of method CompoundAssignmentTest::PostIncrementArrayElementShort .method public hidebysig instance void - IncrementShortArrayElement(int16[] 'array', + IncrementArrayElementShort(int16[] 'array', int32 pos) cil managed { // Code size 15 (0xf) @@ -945,7 +1038,54 @@ IL_000c: conv.i2 IL_000d: stind.i2 IL_000e: ret - } // end of method CompoundAssignmentTest::IncrementShortArrayElement + } // end of method CompoundAssignmentTest::IncrementArrayElementShort + + .method public hidebysig instance void + DoubleArrayElementShort(int16[] 'array', + int32 pos) cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldind.i2 + IL_000a: ldc.i4.2 + IL_000b: mul + IL_000c: conv.i2 + IL_000d: stind.i2 + IL_000e: ret + } // end of method CompoundAssignmentTest::DoubleArrayElementShort + + .method public hidebysig instance int16 + DoubleArrayElementShortAndReturn(int16[] 'array', + int32 pos) cil managed + { + // Code size 22 (0x16) + .maxstack 3 + .locals init (int16 V_0, + int16 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldarg.2 + IL_0003: ldelema [mscorlib]System.Int16 + IL_0008: dup + IL_0009: ldind.i2 + IL_000a: ldc.i4.2 + IL_000b: mul + IL_000c: conv.i2 + IL_000d: dup + IL_000e: stloc.0 + IL_000f: stind.i2 + IL_0010: ldloc.0 + IL_0011: stloc.1 + IL_0012: br.s IL_0014 + + IL_0014: ldloc.1 + IL_0015: ret + } // end of method CompoundAssignmentTest::DoubleArrayElementShortAndReturn .method public hidebysig instance int32 PreIncrementInstanceField() cil managed @@ -1013,6 +1153,47 @@ IL_0014: ret } // end of method CompoundAssignmentTest::IncrementInstanceField + .method public hidebysig instance void + DoubleInstanceField() cil managed + { + // Code size 21 (0x15) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0014: ret + } // end of method CompoundAssignmentTest::DoubleInstanceField + + .method public hidebysig instance int32 + DoubleInstanceFieldAndReturn() cil managed + { + // Code size 28 (0x1c) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: dup + IL_0010: stloc.0 + IL_0011: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::Field + IL_0016: ldloc.0 + IL_0017: stloc.1 + IL_0018: br.s IL_001a + + IL_001a: ldloc.1 + IL_001b: ret + } // end of method CompoundAssignmentTest::DoubleInstanceFieldAndReturn + .method public hidebysig instance int32 PreIncrementInstanceField2(class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass m) cil managed { @@ -1217,6 +1398,49 @@ IL_0017: ret } // end of method CompoundAssignmentTest::IncrementInstanceProperty + .method public hidebysig instance void + DoubleInstanceProperty() cil managed + { + // Code size 22 (0x16) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property() + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32) + IL_0014: nop + IL_0015: ret + } // end of method CompoundAssignmentTest::DoubleInstanceProperty + + .method public hidebysig instance int32 + DoubleInstancePropertyAndReturn() cil managed + { + // Code size 29 (0x1d) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_Property() + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: dup + IL_0010: stloc.0 + IL_0011: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_Property(int32) + IL_0016: nop + IL_0017: ldloc.0 + IL_0018: stloc.1 + IL_0019: br.s IL_001b + + IL_001b: ldloc.1 + IL_001c: ret + } // end of method CompoundAssignmentTest::DoubleInstancePropertyAndReturn + .method public hidebysig instance int32 PreIncrementInstancePropertyByte() cil managed { @@ -1292,6 +1516,51 @@ IL_0018: ret } // end of method CompoundAssignmentTest::IncrementInstancePropertyByte + .method public hidebysig instance void + DoubleInstancePropertyByte() cil managed + { + // Code size 23 (0x17) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: conv.u1 + IL_0010: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0015: nop + IL_0016: ret + } // end of method CompoundAssignmentTest::DoubleInstancePropertyByte + + .method public hidebysig instance int32 + DoubleInstancePropertyByteAndReturn() cil managed + { + // Code size 30 (0x1e) + .maxstack 3 + .locals init (uint8 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance class ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::M() + IL_0007: dup + IL_0008: callvirt instance uint8 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::get_ByteProperty() + IL_000d: ldc.i4.2 + IL_000e: mul + IL_000f: conv.u1 + IL_0010: dup + IL_0011: stloc.0 + IL_0012: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MutableClass::set_ByteProperty(uint8) + IL_0017: nop + IL_0018: ldloc.0 + IL_0019: stloc.1 + IL_001a: br.s IL_001c + + IL_001c: ldloc.1 + IL_001d: ret + } // end of method CompoundAssignmentTest::DoubleInstancePropertyByteAndReturn + .method public hidebysig instance int32 PreIncrementStaticField() cil managed { @@ -1343,6 +1612,38 @@ IL_000d: ret } // end of method CompoundAssignmentTest::IncrementStaticField + .method public hidebysig instance void + DoubleStaticField() cil managed + { + // Code size 14 (0xe) + .maxstack 8 + IL_0000: nop + IL_0001: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField + IL_000d: ret + } // end of method CompoundAssignmentTest::DoubleStaticField + + .method public hidebysig instance int32 + DoubleStaticFieldAndReturn() cil managed + { + // Code size 19 (0x13) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: dup + IL_0009: stsfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticField + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method CompoundAssignmentTest::DoubleStaticFieldAndReturn + .method public hidebysig instance int32 PreIncrementStaticFieldShort() cil managed { @@ -1397,6 +1698,40 @@ IL_000e: ret } // end of method CompoundAssignmentTest::IncrementStaticFieldShort + .method public hidebysig instance void + DoubleStaticFieldShort() cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: conv.i2 + IL_0009: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_000e: ret + } // end of method CompoundAssignmentTest::DoubleStaticFieldShort + + .method public hidebysig instance int16 + DoubleStaticFieldAndReturnShort() cil managed + { + // Code size 20 (0x14) + .maxstack 2 + .locals init (int16 V_0) + IL_0000: nop + IL_0001: ldsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: conv.i2 + IL_0009: dup + IL_000a: stsfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::StaticShortField + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::DoubleStaticFieldAndReturnShort + .method public hidebysig instance int32 PreIncrementStaticProperty() cil managed { @@ -1451,6 +1786,40 @@ IL_000e: ret } // end of method CompoundAssignmentTest::IncrementStaticProperty + .method public hidebysig instance void + DoubleStaticProperty() cil managed + { + // Code size 15 (0xf) + .maxstack 8 + IL_0000: nop + IL_0001: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) + IL_000d: nop + IL_000e: ret + } // end of method CompoundAssignmentTest::DoubleStaticProperty + + .method public hidebysig instance int32 + DoubleStaticPropertyAndReturn() cil managed + { + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: call int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::get_StaticProperty() + IL_0006: ldc.i4.2 + IL_0007: mul + IL_0008: dup + IL_0009: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::set_StaticProperty(int32) + IL_000e: nop + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method CompoundAssignmentTest::DoubleStaticPropertyAndReturn + .method public hidebysig instance valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum PreIncrementStaticPropertyShort() cil managed { @@ -1542,7 +1911,7 @@ Issue954(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum& a, valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum b) cil managed { - // Code size 8 (0x8) + // Code size 22 (0x16) .maxstack 8 IL_0000: nop IL_0001: ldarg.1 @@ -1551,7 +1920,13 @@ IL_0004: ldarg.2 IL_0005: rem IL_0006: stind.i4 - IL_0007: ret + IL_0007: ldarg.0 + IL_0008: ldarg.0 + IL_0009: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_000e: ldarg.2 + IL_000f: rem + IL_0010: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::enumField + IL_0015: ret } // end of method CompoundAssignmentTest::Issue954 .method public hidebysig specialname rtspecialname diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 4443c0f27..1fcace7ee 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1078,7 +1078,7 @@ namespace ICSharpCode.Decompiler.CSharp if (NullableType.IsNullable(value.Type)) { targetType = NullableType.Create(compilation, targetType); } - value = value.ConvertTo(targetType, this, inst.CheckForOverflow); + value = value.ConvertTo(targetType, this, inst.CheckForOverflow, allowImplicitConversion: true); break; } case AssignmentOperatorType.Multiply: @@ -1091,7 +1091,7 @@ namespace ICSharpCode.Decompiler.CSharp if (NullableType.IsNullable(value.Type)) { targetType = NullableType.Create(compilation, targetType); } - value = value.ConvertTo(targetType, this, inst.CheckForOverflow); + value = value.ConvertTo(targetType, this, inst.CheckForOverflow, allowImplicitConversion: true); break; } } diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 280b21190..6748f7b84 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.IL /// Loads the address of a local variable. (ldarga/ldloca) LdLoca, /// 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) + /// 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()) StLoc, /// Stores the value into an anonymous temporary variable, and returns the address of that variable. AddressOf, @@ -139,7 +139,7 @@ namespace ICSharpCode.Decompiler.IL /// Indirect load (ref/pointer dereference). LdObj, /// Indirect store (store to ref/pointer). - /// Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value) + /// 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()) StObj, /// Boxes a value. Box, @@ -2223,7 +2223,7 @@ namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL { /// 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) + /// 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()) public sealed partial class StLoc : ILInstruction, IStoreInstruction { public StLoc(ILVariable variable, ILInstruction value) : base(OpCode.StLoc) @@ -3559,7 +3559,7 @@ namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL { /// Indirect store (store to ref/pointer). - /// Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value) + /// 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()) public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix { public StObj(ILInstruction target, ILInstruction value, IType type) : base(OpCode.StObj) diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index ccb17d8d6..9d01fcf8c 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -151,7 +151,7 @@ new OpCode("ldloca", "Loads the address of a local variable. (ldarga/ldloca)", CustomClassName("LdLoca"), NoArguments, ResultType("Ref"), HasVariableOperand("Address")), 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)", + + "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"), ResultType("variable.StackType")), new OpCode("addressof", "Stores the value into an anonymous temporary variable, and returns the address of that variable.", @@ -206,7 +206,7 @@ CustomClassName("LdObj"), CustomArguments("target"), HasTypeOperand, MemoryAccess, CustomWriteToButKeepOriginal, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, ResultType("type.GetStackType()")), 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)", + + "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, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, ResultType("type.GetStackType()")), diff --git a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs index ad6c46560..1b37fbec4 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs @@ -86,8 +86,16 @@ namespace ICSharpCode.Decompiler.IL type = NullableType.GetUnderlyingType(type); } if (type.Kind == TypeKind.Enum) { - if (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub) - return false; + 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 (type.GetSign() != binary.Sign) diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index 673cdba25..693d8c49d 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -279,32 +279,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms context.RequestRerun(); return; } - - if (inst.Value is BinaryNumericInstruction binary - && binary.Left is LdObj ldobj - && inst.Target.Match(ldobj.Target).Success - && SemanticHelper.IsPure(ldobj.Target.Flags)) - { - // 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 (CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) { - context.Step("compound assignment", inst); - // stobj(target, binary.op(ldobj(target), ...)) - // => compound.op(target, ...) - inst.ReplaceWith(new CompoundAssignmentInstruction( - binary, binary.Left, binary.Right, - targetType, CompoundAssignmentType.EvaluatesToNewValue)); - } - } + TransformAssignment.HandleStObjCompoundAssign(inst, context); } protected internal override void VisitIfInstruction(IfInstruction inst) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index df8c2ea45..587084d91 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -20,6 +20,7 @@ using System; using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.TypeSystem.Implementation; namespace ICSharpCode.Decompiler.IL.Transforms { @@ -124,7 +125,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms // in some cases it can be a compiler-generated local if (mainStLoc == null || (mainStLoc.Variable.Kind != VariableKind.StackSlot && mainStLoc.Variable.Kind != VariableKind.Local)) return false; - BinaryNumericInstruction binary = mainStLoc.Value as BinaryNumericInstruction; + ILInstruction value = mainStLoc.Value; + if (value is Conv conv && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) { + // for compound assignments to small integers, the compiler emits a "conv" instruction + value = conv.Argument; + } else { + conv = null; + } + BinaryNumericInstruction binary = value as BinaryNumericInstruction; ILVariable localVariable = mainStLoc.Variable; if (!localVariable.IsSingleDefinition) return false; @@ -142,13 +150,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (next.Descendants.Where(d => d.MatchLdLoc(localVariable)).Count() != 1) return false; - if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, getterCall.Method.ReturnType)) + IType targetType = getterCall.Method.ReturnType; + if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) return false; + if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow)) + return false; // conv does not match binary operation context.Step($"Inline compound assignment to '{getterCall.Method.AccessorOwner.Name}'", setterCall); block.Instructions.RemoveAt(i + 1); // remove setter call - binary.ReplaceWith(new CompoundAssignmentInstruction( + mainStLoc.Value = new CompoundAssignmentInstruction( binary, getterCall, binary.Right, - getterCall.Method.ReturnType, CompoundAssignmentType.EvaluatesToNewValue)); + targetType, CompoundAssignmentType.EvaluatesToNewValue); return true; } @@ -218,13 +229,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms // ==> stloc v(compound.op.new(callvirt(callvirt get_Property(ldloc S_1)), value)) setterValue = storeInSetter.Value; } + if (setterValue is Conv conv && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) { + // for compound assignments to small integers, the compiler emits a "conv" instruction + setterValue = conv.Argument; + } else { + conv = null; + } if (!(setterValue is BinaryNumericInstruction binary)) return false; var getterCall = binary.Left as CallInstruction; if (!MatchingGetterAndSetterCalls(getterCall, setterCall)) return false; - if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, getterCall.Method.ReturnType)) + IType targetType = getterCall.Method.ReturnType; + if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) return false; + if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow)) + return false; // conv does not match binary operation context.Step($"Compound assignment to '{getterCall.Method.AccessorOwner.Name}'", setterCall); ILInstruction newInst = new CompoundAssignmentInstruction( binary, getterCall, binary.Right, @@ -238,6 +258,52 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } + /// + /// stobj(target, binary.op(ldobj(target), ...)) + /// => compound.op(target, ...) + /// + /// + /// Called by ExpressionTransforms. + /// + internal static bool HandleStObjCompoundAssign(StObj inst, ILTransformContext context) + { + ILInstruction value = inst.Value; + if (value is Conv conv && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) { + // for compound assignments to small integers, the compiler emits a "conv" instruction + value = conv.Argument; + } else { + conv = null; + } + if (!(value 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 (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) + return false; + if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow)) + return false; // conv does not match binary operation + context.Step("compound assignment", inst); + inst.ReplaceWith(new CompoundAssignmentInstruction( + binary, binary.Left, binary.Right, + targetType, CompoundAssignmentType.EvaluatesToNewValue)); + return true; + } + /// /// stloc s(value) /// stloc l(ldloc s) @@ -280,8 +346,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms // conv instructions. return false; } - // With small integer types, test whether the value being stored - // is being truncated: + // 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: From 4c5f0b7e9ccc9ddc02211b1c5feee9e5015a6861 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 16:31:59 +0100 Subject: [PATCH 07/15] Convert TransformAssignment into a statement transform and add support for inline property assignments. --- .../TestCases/Pretty/InlineAssignmentTest.cs | 21 +- .../TestCases/Pretty/InlineAssignmentTest.il | 118 ++++++++- .../Pretty/InlineAssignmentTest.opt.il | 94 ++++++- .../CSharp/CSharpDecompiler.cs | 7 +- ICSharpCode.Decompiler/CSharp/CallBuilder.cs | 76 +++--- .../CSharp/ExpressionBuilder.cs | 15 ++ .../IL/Instructions/Block.cs | 62 ++++- .../CompoundAssignmentInstruction.cs | 2 +- .../IL/Transforms/TransformAssignment.cs | 250 +++++++++++------- 9 files changed, 494 insertions(+), 151 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs index f32d2fb6b..7dcb5d98d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs @@ -28,6 +28,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private int[] field3; private short field4; + public int InstanceProperty { + get; + set; + } + public static int StaticProperty { + get; + set; + } + public void SimpleInlineWithLocals() { int value; @@ -56,7 +65,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty this.UseShort(this.field4 = this.UseShort(0)); Console.WriteLine(this.field4); } - + public short UseShort(short s) { Console.WriteLine(s); @@ -112,5 +121,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { 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(); + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il index 9a1797896..891b11997 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly w1xqybg1 +.assembly dcbsz5ie { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module w1xqybg1.dll -// MVID: {1BE5829A-0D5E-43DC-8C02-E3012B1780A2} +.module dcbsz5ie.dll +// MVID: {CFA464E9-510B-40EC-AD90-3FB26B76D1A6} .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: 0x033B0000 +// Image base: 0x00690000 // =============== CLASS MEMBERS DECLARATION =================== @@ -40,6 +40,64 @@ .field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2 .field private int32[] field3 .field private int16 field4 + .field private int32 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private static int32 '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::'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::'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::'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::'k__BackingField' + IL_0006: ret + } // end of method InlineAssignmentTest::set_StaticProperty + .method public hidebysig instance void SimpleInlineWithLocals() cil managed { @@ -378,6 +436,48 @@ 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.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 instance void .ctor() cil managed { @@ -388,6 +488,16 @@ 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 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il index 2f944dee2..5b0daf795 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly f1ibwsev +.assembly idzuatf2 { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module f1ibwsev.dll -// MVID: {8DB4E6AA-A0C2-49F3-8E9C-A28CE30F145A} +.module idzuatf2.dll +// MVID: {0E6B135E-0CD7-486D-88EB-95340860F028} .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: 0x01400000 +// Image base: 0x02A70000 // =============== CLASS MEMBERS DECLARATION =================== @@ -40,6 +40,54 @@ .field private static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest field2 .field private int32[] field3 .field private int16 field4 + .field private int32 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private static int32 '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::'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::'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::'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::'k__BackingField' + IL_0006: ret + } // end of method InlineAssignmentTest::set_StaticProperty + .method public hidebysig instance void SimpleInlineWithLocals() cil managed { @@ -309,6 +357,34 @@ 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 { @@ -319,6 +395,16 @@ 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 diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 061e3015c..412f6370d 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -109,9 +109,6 @@ namespace ICSharpCode.Decompiler.CSharp // CachedDelegateInitialization must run after ConditionDetection and before/in LoopingBlockTransform // and must run before NullCoalescingTransform new CachedDelegateInitialization(), - new ILInlining(), - new TransformAssignment(), // must run before CopyPropagation - new CopyPropagation(), new StatementTransform( // per-block transforms that depend on each other, and thus need to // run interleaved (statement by statement). @@ -121,11 +118,13 @@ namespace ICSharpCode.Decompiler.CSharp // Inlining must be first, because it doesn't trigger re-runs. // Any other transform that opens up new inlining opportunities should call RequestRerun(). new ExpressionTransforms(), + new TransformAssignment(), // inline and compound assignments new NullCoalescingTransform(), new NullableLiftingStatementTransform(), new TransformArrayInitializers(), new TransformCollectionAndObjectInitializers() - ) + ), + new CopyPropagation() } }, new ProxyCallReplacer(), diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs index 3dd0e777a..33dfb7845 100644 --- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs @@ -47,28 +47,32 @@ namespace ICSharpCode.Decompiler.CSharp 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 callArguments) + { // Used for Call, CallVirt and NewObj TranslatedExpression target; - if (inst.OpCode == OpCode.NewObj) { - if (IL.Transforms.DelegateConstruction.IsDelegateConstruction((NewObj)inst, true)) { - return HandleDelegateConstruction(inst); - } + if (callOpCode == OpCode.NewObj) { target = default(TranslatedExpression); // no target } 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 var arguments = new List(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(); bool isExpandedForm = false; for (int i = 0; i < method.Parameters.Count; 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) { // Parameter is marked params // 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()); } } - if (IsUnambiguousCall(inst, target, method, Array.Empty(), expandedArguments) == OverloadResolutionErrors.None) { + if (IsUnambiguousCall(callOpCode, target, method, Array.Empty(), expandedArguments) == OverloadResolutionErrors.None) { isExpandedForm = true; expectedParameters = expandedParameters; 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); - if (inst.OpCode == OpCode.NewObj) { + if (callOpCode == OpCode.NewObj) { if (settings.AnonymousTypes && method.DeclaringType.IsAnonymousType()) { var argumentExpressions = arguments.SelectArray(arg => arg.Expression); AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); @@ -140,11 +144,10 @@ namespace ICSharpCode.Decompiler.CSharp } } return atce - .WithILInstruction(inst) .WithRR(rr); } else { - if (IsUnambiguousCall(inst, target, method, Array.Empty(), arguments) != OverloadResolutionErrors.None) { + if (IsUnambiguousCall(callOpCode, target, method, Array.Empty(), arguments) != OverloadResolutionErrors.None) { for (int i = 0; i < arguments.Count; i++) { if (settings.AnonymousTypes && expectedParameters[i].Type.ContainsAnonymousType()) { 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)) - .WithILInstruction(inst).WithRR(rr); + return new ObjectCreateExpression(expressionBuilder.ConvertType(method.DeclaringType), arguments.SelectArray(arg => arg.Expression)) + .WithRR(rr); } } else { int allowedParamCount = (method.ReturnType.IsKnownType(KnownTypeCode.Void) ? 1 : 0); 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) { - 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)) { return HandleDelegateEqualityComparison(method, arguments) - .WithILInstruction(inst).WithRR(rr); + .WithRR(rr); } else if (method.IsOperator && method.Name == "op_Implicit" && arguments.Count == 1) { - return HandleImplicitConversion(inst, arguments[0]); + return HandleImplicitConversion(method, arguments[0]); } else { bool requireTypeArguments = false; bool targetCasted = false; @@ -176,7 +179,7 @@ namespace ICSharpCode.Decompiler.CSharp IType[] typeArguments = Array.Empty(); OverloadResolutionErrors errors; - while ((errors = IsUnambiguousCall(inst, target, method, typeArguments, arguments)) != OverloadResolutionErrors.None) { + while ((errors = IsUnambiguousCall(callOpCode, target, method, typeArguments, arguments)) != OverloadResolutionErrors.None) { switch (errors) { case OverloadResolutionErrors.TypeInferenceFailed: case OverloadResolutionErrors.WrongNumberOfTypeArguments: @@ -213,7 +216,7 @@ namespace ICSharpCode.Decompiler.CSharp Expression targetExpr = target.Expression; string methodName = method.Name; // 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); methodName = method.ImplementedInterfaceMembers[0].Name; } @@ -221,7 +224,7 @@ namespace ICSharpCode.Decompiler.CSharp if (requireTypeArguments && (!settings.AnonymousTypes || !method.TypeArguments.Any(a => a.ContainsAnonymousType()))) mre.TypeArguments.AddRange(method.TypeArguments.Select(expressionBuilder.ConvertType)); 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); - IType targetType = call.Method.ReturnType; + IType targetType = method.ReturnType; 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 - argument = argument.ConvertTo(call.Method.Parameters[0].Type, expressionBuilder); + argument = argument.ConvertTo(method.Parameters[0].Type, expressionBuilder); conv = conversions.ImplicitConversion(argument.Type, targetType); } return new CastExpression(expressionBuilder.ConvertType(targetType), argument.Expression) - .WithILInstruction(call) .WithRR(new ConversionResolveResult(targetType, argument.ResolveResult, conv)); } - OverloadResolutionErrors IsUnambiguousCall(ILInstruction inst, TranslatedExpression target, IMethod method, IType[] typeArguments, IList arguments) + OverloadResolutionErrors IsUnambiguousCall(OpCode callOpCode, TranslatedExpression target, IMethod method, IType[] typeArguments, IList arguments) { var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var or = new OverloadResolution(resolver.Compilation, arguments.SelectArray(a => a.ResolveResult), typeArguments: typeArguments); - if (inst is NewObj newObj) { - foreach (IMethod ctor in newObj.Method.DeclaringType.GetConstructors()) { - if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == newObj.Method.DeclaringTypeDefinition)) { + if (callOpCode == OpCode.NewObj) { + foreach (IMethod ctor in method.DeclaringType.GetConstructors()) { + if (lookup.IsAccessible(ctor, allowProtectedAccess: resolver.CurrentTypeDefinition == method.DeclaringTypeDefinition)) { or.AddCandidate(ctor); } } @@ -304,7 +306,7 @@ namespace ICSharpCode.Decompiler.CSharp } if (or.BestCandidateErrors != OverloadResolutionErrors.None) 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.None; } @@ -327,12 +329,12 @@ namespace ICSharpCode.Decompiler.CSharp return true; } - TranslatedExpression HandleAccessorCall(ILInstruction inst, TranslatedExpression target, IMethod method, IList arguments) + ExpressionWithResolveResult HandleAccessorCall(bool isVirtCall, TranslatedExpression target, IMethod method, IList arguments) { var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly); var result = lookup.Lookup(target.ResolveResult, method.AccessorOwner.Name, EmptyList.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); var rr = new MemberResolveResult(target.ResolveResult, method.AccessorOwner); @@ -356,12 +358,12 @@ namespace ICSharpCode.Decompiler.CSharp 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 { 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 - 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); } } diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 1fcace7ee..8e3b12ea0 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1694,11 +1694,26 @@ namespace ICSharpCode.Decompiler.CSharp return TranslateObjectAndCollectionInitializer(block); case BlockType.PostfixOperator: return TranslatePostfixOperator(block); + case BlockType.CallInlineAssign: + return TranslateSetterCallAssignment(block); default: 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) { var stloc = block.Instructions.FirstOrDefault() as StLoc; diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs index e32ede62f..06cdc509b 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs @@ -108,8 +108,13 @@ namespace ICSharpCode.Decompiler.IL // only the last instruction may have an unreachable endpoint Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable)); } - if (this.Type == BlockType.ControlFlow) { - Debug.Assert(finalInstruction.OpCode == OpCode.Nop); + switch (this.Type) { + 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; } + + 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 + { + /// + /// 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). + /// ControlFlow, + /// + /// Block is used for array initializers, e.g. `new int[] { expr1, expr2 }`. + /// ArrayInitializer, CollectionInitializer, ObjectInitializer, - PostfixOperator + /// + /// Block is used for postfix operator on local variable. + /// + /// + /// Postfix operators on non-locals use CompoundAssignmentInstruction with CompoundAssignmentType.EvaluatesToOldValue. + /// + PostfixOperator, + /// + /// Block is used for using the result of a property setter inline. + /// Example: Use(this.Property = value); + /// 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(). + /// + /// + /// Block { + /// call setter(..., stloc s(...)) + /// final: ldloc s + /// } + /// + CallInlineAssign } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs index 1b37fbec4..0575e469d 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs @@ -107,7 +107,7 @@ namespace ICSharpCode.Decompiler.IL internal static bool IsValidCompoundAssignmentTarget(ILInstruction inst) { switch (inst.OpCode) { - case OpCode.LdLoc: + // case OpCode.LdLoc: -- not valid -- does not mark the variable as written to case OpCode.LdObj: return true; case OpCode.Call: diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index 587084d91..f2e6d3254 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -21,43 +21,49 @@ using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; +using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL.Transforms { /// /// Constructs compound assignments and inline assignments. /// - 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; - for (int i = block.Instructions.Count - 1; i >= 0; i--) { - if (TransformPostIncDecOperatorOnAddress(block, i) || TransformPostIncDecOnStaticField(block, i) || TransformCSharp4PostIncDecOperatorOnAddress(block, i)) { - block.Instructions.RemoveAt(i); - continue; - } - if (TransformPostIncDecOperator(block, i)) { - block.Instructions.RemoveAt(i); - continue; - } - if (TransformInlineAssignmentStObj(block, i) || TransformInlineAssignmentLocal(block, i)) - continue; - if (TransformInlineCompoundAssignmentCall(block, i)) - continue; - if (TransformRoslynCompoundAssignmentCall(block, i)) - continue; - if (TransformRoslynPostIncDecOperatorOnAddress(block, i)) - continue; + /*if (TransformPostIncDecOperatorOnAddress(block, i) || TransformPostIncDecOnStaticField(block, i) || TransformCSharp4PostIncDecOperatorOnAddress(block, i)) { + block.Instructions.RemoveAt(i); + continue; + } + if (TransformPostIncDecOperator(block, i)) { + block.Instructions.RemoveAt(i); + continue; + }*/ + if (TransformInlineAssignmentStObjOrCall(block, pos) || TransformInlineAssignmentLocal(block, pos)) { + // both inline assignments create a top-level stloc which might affect inlining + context.RequestRerun(); + return; } + /* + TransformInlineCompoundAssignmentCall(block, pos); + TransformRoslynCompoundAssignmentCall(block, pos); + // TODO: post-increment on local + // post-increment on address (e.g. field or array element) + TransformPostIncDecOperatorOnAddress(block, pos); + TransformRoslynPostIncDecOperatorOnAddress(block, pos); + // TODO: post-increment on call + */ } /// /// stloc s(value) /// stloc l(ldloc s) /// stobj(..., ldloc s) + /// where ... is pure and does not use s or l /// --> /// stloc l(stobj (..., value)) /// @@ -72,7 +78,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// stloc s(stobj (..., value)) /// /// e.g. used for inline assignment to static field - bool TransformInlineAssignmentStObj(Block block, int pos) + /// + /// -or- + /// + /// + /// stloc s(value) + /// call set_Property(..., ldloc s) + /// where the '...' arguments are free of side-effects and not using 's' + /// --> + /// stloc s(Block InlineAssign { call set_Property(..., stloc i(value)); final: ldloc i }) + /// + bool TransformInlineAssignmentStObjOrCall(Block block, int pos) { var inst = block.Instructions[pos] as StLoc; // in some cases it can be a compiler-generated local @@ -96,22 +112,75 @@ namespace ICSharpCode.Decompiler.IL.Transforms localStore = null; nextPos = pos + 1; } - if (!(block.Instructions[nextPos] is StObj stobj)) - return false; - if (!stobj.Value.MatchLdLoc(inst.Variable) || inst.Variable.IsUsedWithin(stobj.Target)) - return false; - if (IsImplicitTruncation(inst.Value, stobj.Type)) { - // 'stloc s' is implicitly truncating the value + 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; + } + context.Step("Inline assignment stobj", stobj); + block.Instructions.Remove(localStore); + block.Instructions.Remove(stobj); + stobj.Value = inst.Value; + inst.ReplaceWith(new StLoc(local, stobj)); + 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; + } + if (IsImplicitTruncation(inst.Value, call.Method.Parameters.Last().Type)) { + // setter call is implicitly truncating the value + return false; + } + // stloc s(Block InlineAssign { call set_Property(..., stloc i(value)); final: ldloc i }) + 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); + inst.ReplaceWith(new StLoc(local, new Block(BlockType.CallInlineAssign) { + Instructions = { call }, + FinalInstruction = new LdLoc(newVar) + })); + return true; + } else { return false; } - context.Step("Inline assignment stobj", stobj); - block.Instructions.Remove(localStore); - block.Instructions.Remove(stobj); - stobj.Value = inst.Value; - inst.ReplaceWith(new StLoc(local, stobj)); - return true; } + static ILInstruction UnwrapSmallIntegerConv(ILInstruction inst, out Conv conv) + { + conv = inst as Conv; + if (conv != null && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) { + // for compound assignments to small integers, the compiler emits a "conv" instruction + return conv.Argument; + } else { + return inst; + } + } + + static bool ValidateCompoundAssign(BinaryNumericInstruction binary, Conv conv, IType targetType) + { + if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) + return false; + if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow)) + return false; // conv does not match binary operation + return true; + } + /// /// stloc s(binary(callvirt(getter), value)) /// callvirt (setter, ldloc s) @@ -125,14 +194,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // in some cases it can be a compiler-generated local if (mainStLoc == null || (mainStLoc.Variable.Kind != VariableKind.StackSlot && mainStLoc.Variable.Kind != VariableKind.Local)) return false; - ILInstruction value = mainStLoc.Value; - if (value is Conv conv && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) { - // for compound assignments to small integers, the compiler emits a "conv" instruction - value = conv.Argument; - } else { - conv = null; - } - BinaryNumericInstruction binary = value as BinaryNumericInstruction; + BinaryNumericInstruction binary = UnwrapSmallIntegerConv(mainStLoc.Value, out var conv) as BinaryNumericInstruction; ILVariable localVariable = mainStLoc.Variable; if (!localVariable.IsSingleDefinition) return false; @@ -151,10 +213,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (next.Descendants.Where(d => d.MatchLdLoc(localVariable)).Count() != 1) return false; IType targetType = getterCall.Method.ReturnType; - if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) + if (!ValidateCompoundAssign(binary, conv, targetType)) return false; - if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow)) - return false; // conv does not match binary operation context.Step($"Inline compound assignment to '{getterCall.Method.AccessorOwner.Name}'", setterCall); block.Instructions.RemoveAt(i + 1); // remove setter call mainStLoc.Value = new CompoundAssignmentInstruction( @@ -267,14 +327,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// internal static bool HandleStObjCompoundAssign(StObj inst, ILTransformContext context) { - ILInstruction value = inst.Value; - if (value is Conv conv && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) { - // for compound assignments to small integers, the compiler emits a "conv" instruction - value = conv.Argument; - } else { - conv = null; - } - if (!(value is BinaryNumericInstruction binary)) + if (!(UnwrapSmallIntegerConv(inst.Value, out var conv) is BinaryNumericInstruction binary)) return false; if (!(binary.Left is LdObj ldobj)) return false; @@ -293,10 +346,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms } else { targetType = ldobj.Type; } - if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) + if (!ValidateCompoundAssign(binary, conv, targetType)) return false; - if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow)) - return false; // conv does not match binary operation context.Step("compound assignment", inst); inst.ReplaceWith(new CompoundAssignmentInstruction( binary, binary.Left, binary.Right, @@ -310,16 +361,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// --> /// stloc s(stloc l(value)) /// - bool TransformInlineAssignmentLocal(Block block, int i) + bool TransformInlineAssignmentLocal(Block block, int pos) { - var inst = block.Instructions[i] as StLoc; - var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; + var inst = block.Instructions[pos] as StLoc; + var nextInst = block.Instructions.ElementAtOrDefault(pos + 1) as StLoc; if (inst == null || nextInst == null) return false; if (inst.Variable.Kind != VariableKind.StackSlot) return false; Debug.Assert(!inst.Variable.Type.IsSmallIntegerType()); - if (nextInst.Variable.Kind != VariableKind.Local || !nextInst.Value.MatchLdLoc(inst.Variable)) + 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, nextInst.Variable.Type)) { // 'stloc l' is implicitly truncating the stack value @@ -329,7 +382,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var value = inst.Value; var var = nextInst.Variable; var stackVar = inst.Variable; - block.Instructions.RemoveAt(i); + block.Instructions.RemoveAt(pos); nextInst.ReplaceWith(new StLoc(stackVar, new StLoc(var, value))); return true; } @@ -408,48 +461,49 @@ namespace ICSharpCode.Decompiler.IL.Transforms nextInst.ReplaceWith(new StLoc(inst.Variable, assignment)); return true; } - - /// ldaddress ::= ldelema | ldflda | ldsflda; + /// - /// stloc s(ldaddress) - /// stloc l(ldobj(ldloc s)) - /// stobj(ldloc s, binary.op(ldloc l, ldc.i4 1)) + /// stobj(target, binary.add(stloc l(ldobj(target)), ldc.i4 1)) + /// where target is pure and does not use 'l' /// --> - /// stloc l(compound.op.old(ldobj(ldaddress), ldc.i4 1)) + /// stloc l(compound.op.old(ldobj(target), ldc.i4 1)) /// bool TransformPostIncDecOperatorOnAddress(Block block, int i) { - var inst = block.Instructions[i] as StLoc; - var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; - var stobj = block.Instructions.ElementAtOrDefault(i + 2) as StObj; - if (inst == null || nextInst == null || stobj == null) + if (!(block.Instructions[i] is StObj stobj)) return false; - if (!inst.Variable.IsSingleDefinition || inst.Variable.LoadCount != 2) + var binary = UnwrapSmallIntegerConv(stobj.Value, out var conv) as BinaryNumericInstruction; + if (binary == null || !binary.Right.MatchLdcI4(1)) return false; - if (!(inst.Value is LdElema || inst.Value is LdFlda || inst.Value is LdsFlda)) + if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub)) return false; - ILInstruction target; - IType targetType; - if (nextInst.Variable.Kind == VariableKind.StackSlot || !nextInst.Value.MatchLdObj(out target, out targetType) || !target.MatchLdLoc(inst.Variable)) + if (!(binary.Left is StLoc stloc)) return false; - if (!stobj.Target.MatchLdLoc(inst.Variable)) + if (!(stloc.Variable.Kind == VariableKind.Local || stloc.Variable.Kind == VariableKind.StackSlot)) 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)) + if (!(stloc.Value is LdObj ldobj)) 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); + if (!SemanticHelper.IsPure(ldobj.Target.Flags)) + return false; + if (!ldobj.Target.Match(stobj.Target).Success) + return false; + if (stloc.Variable.IsUsedWithin(ldobj.Target)) + return false; + IType targetType = ldobj.Type; + if (!ValidateCompoundAssign(binary, conv, targetType)) + return false; + context.Step("TransformPostIncDecOperatorOnAddress", stobj); + block.Instructions[i] = new StLoc(stloc.Variable, new CompoundAssignmentInstruction( + binary, ldobj, binary.Right, targetType, CompoundAssignmentType.EvaluatesToOldValue)); return true; } /// - /// stloc l(ldobj(ldflda(target))) - /// stobj(ldflda(target), binary.op(ldloc l, ldc.i4 1)) + /// stloc l(ldobj(target)) + /// stobj(target, binary.op(ldloc l, ldc.i4 1)) + /// target is pure and does not use 'l' /// --> - /// compound.op.old(ldobj(ldflda(target)), ldc.i4 1) + /// stloc l(compound.op.old(ldobj(target), ldc.i4 1)) /// bool TransformRoslynPostIncDecOperatorOnAddress(Block block, int i) { @@ -457,21 +511,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms var stobj = block.Instructions.ElementAtOrDefault(i + 1) as StObj; if (inst == null || stobj == null) return false; - if (!inst.Variable.IsSingleDefinition || inst.Variable.LoadCount != 1) + if (!(inst.Value is LdObj ldobj)) return false; - if (!inst.Value.MatchLdObj(out var loadTarget, out var loadType) || !loadTarget.MatchLdFlda(out var fieldTarget, out var field)) + if (!SemanticHelper.IsPure(ldobj.Target.Flags)) return false; - if (!stobj.Target.MatchLdFlda(out var fieldTarget2, out var field2)) + if (!ldobj.Target.Match(stobj.Target).Success) return false; - if (!fieldTarget.Match(fieldTarget2).Success || !field.Equals(field2)) + if (inst.Variable.IsUsedWithin(ldobj.Target)) return false; - var binary = stobj.Value as BinaryNumericInstruction; - if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1) - || (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub)) + var binary = UnwrapSmallIntegerConv(stobj.Value, out var conv) as BinaryNumericInstruction; + if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1)) + return false; + if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub)) return false; - context.Step("TransformRoslynPostIncDecOperator", inst); - stobj.ReplaceWith(new CompoundAssignmentInstruction(binary, inst.Value, binary.Right, loadType, CompoundAssignmentType.EvaluatesToOldValue)); - block.Instructions.RemoveAt(i); + var targetType = ldobj.Type; + if (!ValidateCompoundAssign(binary, conv, targetType)) + return false; + context.Step("TransformRoslynPostIncDecOperatorOnAddress", inst); + inst.Value = new CompoundAssignmentInstruction(binary, inst.Value, binary.Right, targetType, CompoundAssignmentType.EvaluatesToOldValue); + block.Instructions.RemoveAt(i + 1); return true; } From 7847a69d694a53a74f1a9e95e18ffc50905628d3 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 17:46:26 +0100 Subject: [PATCH 08/15] Fix compound assignment and post-increment. --- .../PrettyTestRunner.cs | 2 +- .../Pretty/CompoundAssignmentTest.cs | 2 +- .../Pretty/CompoundAssignmentTest.il | 48 +- .../Pretty/CompoundAssignmentTest.opt.il | 48 +- .../CompoundAssignmentTest.opt.roslyn.il | 38 +- .../Pretty/CompoundAssignmentTest.roslyn.il | 38 +- .../TestCases/Pretty/InlineAssignmentTest.cs | 15 +- .../TestCases/Pretty/InlineAssignmentTest.il | 69 ++- .../Pretty/InlineAssignmentTest.opt.il | 55 +- .../Pretty/InlineAssignmentTest.opt.roslyn.il | 431 ++++++++++++++ .../Pretty/InlineAssignmentTest.roslyn.il | 524 ++++++++++++++++++ .../IL/Instructions/MemoryInstructions.cs | 8 +- .../IL/Transforms/TransformAssignment.cs | 161 ++++-- 13 files changed, 1247 insertions(+), 192 deletions(-) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.roslyn.il create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.roslyn.il diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 4d2bb4285..9984a1110 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -74,7 +74,7 @@ namespace ICSharpCode.Decompiler.Tests } [Test] - public void InlineAssignmentTest([ValueSource("noRoslynOptions")] CompilerOptions cscOptions) + public void InlineAssignmentTest([ValueSource("defaultOptions")] CompilerOptions cscOptions) { Run(cscOptions: cscOptions); } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index e0d9ec95e..8a4dee7b7 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs @@ -236,7 +236,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void ShortEnumTest() { this.shortEnumField |= ShortEnum.Two; - this.shortEnumField &= ~ShortEnum.Four; + this.shortEnumField &= ShortEnum.Four; this.shortEnumField += 2; this.shortEnumField -= 3; } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il index c1e975417..f8942fdb4 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly oguadjyn +.assembly njho1304 { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module oguadjyn.dll -// MVID: {7DE8C1A3-5051-43F6-ACDA-EFB9A52251C4} +.module njho1304.dll +// MVID: {06E90287-B329-43EC-805F-F8BC42EE77DE} .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: 0x019F0000 +// Image base: 0x00C00000 // =============== CLASS MEMBERS DECLARATION =================== @@ -805,7 +805,7 @@ .method public hidebysig instance void ShortEnumTest() cil managed { - // Code size 63 (0x3f) + // Code size 62 (0x3e) .maxstack 8 IL_0000: nop IL_0001: ldarg.0 @@ -818,25 +818,25 @@ IL_0010: ldarg.0 IL_0011: dup IL_0012: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0017: ldc.i4.s -5 - IL_0019: and - IL_001a: conv.i2 - IL_001b: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0020: ldarg.0 - IL_0021: dup - IL_0022: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0027: ldc.i4.2 - IL_0028: add - IL_0029: conv.i2 - IL_002a: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_002f: ldarg.0 - IL_0030: dup - IL_0031: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0036: ldc.i4.3 - IL_0037: sub - IL_0038: conv.i2 - IL_0039: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_003e: ret + IL_0017: ldc.i4.4 + IL_0018: and + IL_0019: conv.i2 + IL_001a: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_001f: ldarg.0 + IL_0020: dup + IL_0021: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0026: ldc.i4.2 + IL_0027: add + IL_0028: conv.i2 + IL_0029: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_002e: ldarg.0 + IL_002f: dup + IL_0030: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0035: ldc.i4.3 + IL_0036: sub + IL_0037: conv.i2 + IL_0038: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_003d: ret } // end of method CompoundAssignmentTest::ShortEnumTest .method public hidebysig instance int32 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il index f318769c5..167a7e42f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly vm2ov5l1 +.assembly iwgzkcmd { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module vm2ov5l1.dll -// MVID: {F7BCAA28-E619-40E7-921D-149FF48046FD} +.module iwgzkcmd.dll +// MVID: {80313F66-9892-4910-999C-C098CFBAAB05} .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: 0x052F0000 +// Image base: 0x02540000 // =============== CLASS MEMBERS DECLARATION =================== @@ -692,7 +692,7 @@ .method public hidebysig instance void ShortEnumTest() cil managed { - // Code size 62 (0x3e) + // Code size 61 (0x3d) .maxstack 8 IL_0000: ldarg.0 IL_0001: dup @@ -704,25 +704,25 @@ 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.s -5 - IL_0018: and - IL_0019: conv.i2 - IL_001a: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_001f: ldarg.0 - IL_0020: dup - IL_0021: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0026: ldc.i4.2 - IL_0027: add - IL_0028: conv.i2 - IL_0029: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_002e: ldarg.0 - IL_002f: dup - IL_0030: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0035: ldc.i4.3 - IL_0036: sub - IL_0037: conv.i2 - IL_0038: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_003d: ret + 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 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il index 51f5d33e7..a2cb8397f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {9C969BC5-E3E2-4944-BB85-4B7EAAE52E4D} +// MVID: {F06B4897-D7A1-4604-8BC9-FB97832F7C40} .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: 0x00480000 +// Image base: 0x02D30000 // =============== CLASS MEMBERS DECLARATION =================== @@ -695,7 +695,7 @@ .method public hidebysig instance void ShortEnumTest() cil managed { - // Code size 60 (0x3c) + // Code size 59 (0x3b) .maxstack 8 IL_0000: ldarg.0 IL_0001: ldarg.0 @@ -706,24 +706,24 @@ 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.s -5 - IL_0017: and - IL_0018: stfld 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: ldarg.0 - IL_001f: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0024: ldc.i4.2 - IL_0025: add - IL_0026: conv.i2 - IL_0027: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + 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: ldarg.0 - IL_002e: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0033: ldc.i4.3 - IL_0034: sub - IL_0035: conv.i2 - IL_0036: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_003b: ret + 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 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il index 3f405ccac..61d682006 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {AB7EC3EB-B732-497E-809B-7D4DBB442E2C} +// MVID: {C9CD236E-5AA3-4F16-ABA1-33B72FC48FEA} .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: 0x019F0000 +// Image base: 0x01530000 // =============== CLASS MEMBERS DECLARATION =================== @@ -794,7 +794,7 @@ .method public hidebysig instance void ShortEnumTest() cil managed { - // Code size 61 (0x3d) + // Code size 60 (0x3c) .maxstack 8 IL_0000: nop IL_0001: ldarg.0 @@ -806,24 +806,24 @@ IL_000f: ldarg.0 IL_0010: ldarg.0 IL_0011: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField - IL_0016: ldc.i4.s -5 - IL_0018: and - IL_0019: stfld 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: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_001d: ldarg.0 IL_001e: ldarg.0 - IL_001f: ldarg.0 - 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_001f: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0024: ldc.i4.2 + IL_0025: add + IL_0026: conv.i2 + IL_0027: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_002c: ldarg.0 IL_002d: ldarg.0 - IL_002e: ldarg.0 - 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 + IL_002e: ldfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_0033: ldc.i4.3 + IL_0034: sub + IL_0035: conv.i2 + IL_0036: stfld valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::shortEnumField + IL_003b: ret } // end of method CompoundAssignmentTest::ShortEnumTest .method public hidebysig instance int32 diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs index 7dcb5d98d..89a70cf98 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs @@ -39,12 +39,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void SimpleInlineWithLocals() { - int value; - Console.WriteLine(value = 5); + int index; + Console.WriteLine(this.GetFormat(), index = this.GetIndex()); + Console.WriteLine(index); + InlineAssignmentTest value; + Console.WriteLine(this.GetFormat(), value = new InlineAssignmentTest()); Console.WriteLine(value); - InlineAssignmentTest value2; - Console.WriteLine(value2 = new InlineAssignmentTest()); - Console.WriteLine(value2); } public void SimpleInlineWithFields() @@ -112,6 +112,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty throw new NotImplementedException(); } + public string GetFormat() + { + return "{0}"; + } + public int GetValue(int value) { return value; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il index 891b11997..5ff162ea6 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly dcbsz5ie +.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.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 .ver 0:0:0:0 } -.module dcbsz5ie.dll -// MVID: {CFA464E9-510B-40EC-AD90-3FB26B76D1A6} +.module cljdpn4p.dll +// MVID: {4E91830C-4968-4AA2-B516-7FDA32452515} .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: 0x00690000 +// Image base: 0x006A0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -101,28 +101,36 @@ .method public hidebysig instance void SimpleInlineWithLocals() cil managed { - // Code size 38 (0x26) - .maxstack 2 + // 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: ldc.i4.5 - IL_0002: dup - IL_0003: stloc.0 - IL_0004: call void [mscorlib]System.Console::WriteLine(int32) - IL_0009: nop - 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: stloc.1 - IL_0018: call void [mscorlib]System.Console::WriteLine(object) - IL_001d: nop - IL_001e: ldloc.1 - IL_001f: call void [mscorlib]System.Console::WriteLine(object) - IL_0024: nop - IL_0025: ret + 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 @@ -394,6 +402,21 @@ 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 { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il index 5b0daf795..b6948ebda 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly idzuatf2 +.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.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 .ver 0:0:0:0 } -.module idzuatf2.dll -// MVID: {0E6B135E-0CD7-486D-88EB-95340860F028} +.module jfxjxuqt.dll +// MVID: {862986C8-F9C1-4FF3-8646-A3CA63D29744} .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: 0x02A70000 +// Image base: 0x010B0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -91,23 +91,31 @@ .method public hidebysig instance void SimpleInlineWithLocals() cil managed { - // Code size 33 (0x21) - .maxstack 2 + // Code size 55 (0x37) + .maxstack 3 .locals init (int32 V_0, class ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest V_1) - IL_0000: ldc.i4.5 - IL_0001: dup - IL_0002: stloc.0 - IL_0003: call void [mscorlib]System.Console::WriteLine(int32) - IL_0008: ldloc.0 - IL_0009: call void [mscorlib]System.Console::WriteLine(int32) - IL_000e: newobj instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::.ctor() - IL_0013: dup - IL_0014: stloc.1 - IL_0015: call void [mscorlib]System.Console::WriteLine(object) - IL_001a: ldloc.1 - IL_001b: call void [mscorlib]System.Console::WriteLine(object) - IL_0020: ret + 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 @@ -327,6 +335,15 @@ 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 { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.roslyn.il new file mode 100644 index 000000000..b8078b20b --- /dev/null +++ b/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 'k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .field private static int32 '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::'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::'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::'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::'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 *********************** diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.roslyn.il new file mode 100644 index 000000000..97287ae07 --- /dev/null +++ b/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 '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 '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::'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::'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::'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::'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 *********************** diff --git a/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs index 533973dc0..3f4a08fd9 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.IL if (this.MatchLdFld(out var target, out var field)) { ILRange.WriteTo(output, options); output.Write("ldfld "); - Disassembler.DisassemblerHelpers.WriteOperand(output, field); + field.WriteTo(output); output.Write('('); target.WriteTo(output, options); output.Write(')'); @@ -51,7 +51,7 @@ namespace ICSharpCode.Decompiler.IL } else if (this.MatchLdsFld(out field)) { ILRange.WriteTo(output, options); output.Write("ldsfld "); - Disassembler.DisassemblerHelpers.WriteOperand(output, field); + field.WriteTo(output); return; } } @@ -67,7 +67,7 @@ namespace ICSharpCode.Decompiler.IL if (this.MatchStFld(out var target, out var field, out var value)) { ILRange.WriteTo(output, options); output.Write("stfld "); - Disassembler.DisassemblerHelpers.WriteOperand(output, field); + field.WriteTo(output); output.Write('('); target.WriteTo(output, options); output.Write(", "); @@ -77,7 +77,7 @@ namespace ICSharpCode.Decompiler.IL } else if (this.MatchStsFld(out field, out value)) { ILRange.WriteTo(output, options); output.Write("stsfld "); - Disassembler.DisassemblerHelpers.WriteOperand(output, field); + field.WriteTo(output); output.Write('('); value.WriteTo(output, options); output.Write(')'); diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index f2e6d3254..d9add5071 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -35,28 +35,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms void IStatementTransform.Run(Block block, int pos, StatementTransformContext context) { this.context = context; - /*if (TransformPostIncDecOperatorOnAddress(block, i) || TransformPostIncDecOnStaticField(block, i) || TransformCSharp4PostIncDecOperatorOnAddress(block, i)) { - block.Instructions.RemoveAt(i); - continue; - } - if (TransformPostIncDecOperator(block, i)) { - block.Instructions.RemoveAt(i); - continue; - }*/ if (TransformInlineAssignmentStObjOrCall(block, pos) || TransformInlineAssignmentLocal(block, pos)) { // both inline assignments create a top-level stloc which might affect inlining context.RequestRerun(); return; } - /* - TransformInlineCompoundAssignmentCall(block, pos); - TransformRoslynCompoundAssignmentCall(block, pos); - // TODO: post-increment on local - // post-increment on address (e.g. field or array element) - TransformPostIncDecOperatorOnAddress(block, pos); - TransformRoslynPostIncDecOperatorOnAddress(block, pos); - // TODO: post-increment on call - */ + if (TransformPostIncDecOperatorWithInlineStore(block, pos) + || TransformPostIncDecOperator(block, pos) + || TransformPostIncDecOperatorLocal(block, pos)) + { + // again, new top-level stloc might need inlining: + context.RequestRerun(); + return; + } } /// @@ -126,6 +117,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms 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: @@ -151,10 +143,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms 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); - inst.ReplaceWith(new StLoc(local, new Block(BlockType.CallInlineAssign) { + 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 { return false; @@ -439,10 +440,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// final: ldloc s2 /// }) /// - bool TransformPostIncDecOperator(Block block, int i) + bool TransformPostIncDecOperatorLocal(Block block, int pos) { - var inst = block.Instructions[i] as StLoc; - var nextInst = block.Instructions.ElementAtOrDefault(i + 1) as StLoc; + var inst = block.Instructions[pos] 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)) return false; var binary = nextInst.Value as BinaryNumericInstruction; @@ -452,27 +453,86 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if ((binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub) || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1)) return false; - context.Step($"TransformPostIncDecOperator", inst); + context.Step($"TransformPostIncDecOperatorLocal", inst); var tempStore = context.Function.RegisterVariable(VariableKind.StackSlot, inst.Variable.Type); var assignment = new Block(BlockType.PostfixOperator); 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.FinalInstruction = new LdLoc(tempStore); - nextInst.ReplaceWith(new StLoc(inst.Variable, assignment)); + inst.Value = assignment; + block.Instructions.RemoveAt(pos + 1); // remove nextInst return true; } + + /// + /// Gets whether 'inst' is a possible store for use as a compound store. + /// + bool IsCompoundStore(ILInstruction inst, out IType storeType, out ILInstruction value) + { + value = null; + storeType = null; + if (inst is StObj stobj) { + storeType = stobj.Type; + value = stobj.Value; + return SemanticHelper.IsPure(stobj.Target.Flags); + } else if (inst is CallInstruction call && (call.OpCode == OpCode.Call || call.OpCode == OpCode.CallVirt)) { + if (call.Method.Parameters.Count == 0) { + return false; + } + foreach (var arg in call.Arguments.SkipLast(1)) { + if (!SemanticHelper.IsPure(arg.Flags)) { + return false; + } + } + storeType = call.Method.Parameters.Last().Type; + value = call.Arguments.Last(); + return call.Method.Equals((call.Method.AccessorOwner as IProperty)?.Setter); + } else { + return false; + } + } + + 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; + } + } /// /// stobj(target, binary.add(stloc l(ldobj(target)), ldc.i4 1)) /// where target is pure and does not use 'l' /// --> /// 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 target is pure and does not use 'l' + /// --> + /// stloc l(compound.op.old(call get_Prop(target), ldc.i4 1)) /// - bool TransformPostIncDecOperatorOnAddress(Block block, int i) + /// + /// 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). + /// + bool TransformPostIncDecOperatorWithInlineStore(Block block, int pos) { - if (!(block.Instructions[i] is StObj stobj)) + var store = block.Instructions[pos]; + if (!IsCompoundStore(store, out var targetType, out var value)) return false; - var binary = UnwrapSmallIntegerConv(stobj.Value, out var conv) as BinaryNumericInstruction; + var binary = UnwrapSmallIntegerConv(value, out var conv) as BinaryNumericInstruction; if (binary == null || !binary.Right.MatchLdcI4(1)) return false; if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub)) @@ -481,20 +541,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!(stloc.Variable.Kind == VariableKind.Local || stloc.Variable.Kind == VariableKind.StackSlot)) return false; - if (!(stloc.Value is LdObj ldobj)) - return false; - if (!SemanticHelper.IsPure(ldobj.Target.Flags)) - return false; - if (!ldobj.Target.Match(stobj.Target).Success) + if (!IsMatchingCompoundLoad(stloc.Value, store, stloc.Variable)) return false; - if (stloc.Variable.IsUsedWithin(ldobj.Target)) - return false; - IType targetType = ldobj.Type; if (!ValidateCompoundAssign(binary, conv, targetType)) return false; - context.Step("TransformPostIncDecOperatorOnAddress", stobj); - block.Instructions[i] = new StLoc(stloc.Variable, new CompoundAssignmentInstruction( - binary, ldobj, binary.Right, targetType, CompoundAssignmentType.EvaluatesToOldValue)); + context.Step("TransformPostIncDecOperatorWithInlineStore", store); + block.Instructions[pos] = new StLoc(stloc.Variable, new CompoundAssignmentInstruction( + binary, stloc.Value, binary.Right, targetType, CompoundAssignmentType.EvaluatesToOldValue)); return true; } @@ -505,31 +558,33 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// --> /// stloc l(compound.op.old(ldobj(target), ldc.i4 1)) /// - bool TransformRoslynPostIncDecOperatorOnAddress(Block block, int i) + /// + /// This pattern occurs with legacy csc for static fields, and with Roslyn for most post-increments. + /// + bool TransformPostIncDecOperator(Block block, int i) { var inst = block.Instructions[i] as StLoc; - var stobj = block.Instructions.ElementAtOrDefault(i + 1) as StObj; - if (inst == null || stobj == null) + var store = block.Instructions.ElementAtOrDefault(i + 1); + if (inst == null || store == null) return false; - if (!(inst.Value is LdObj ldobj)) + if (!IsCompoundStore(store, out var targetType, out var value)) return false; - if (!SemanticHelper.IsPure(ldobj.Target.Flags)) - return false; - if (!ldobj.Target.Match(stobj.Target).Success) - return false; - if (inst.Variable.IsUsedWithin(ldobj.Target)) + if (!IsMatchingCompoundLoad(inst.Value, store, inst.Variable)) return false; - var binary = UnwrapSmallIntegerConv(stobj.Value, out var conv) as BinaryNumericInstruction; + var binary = UnwrapSmallIntegerConv(value, out var conv) as BinaryNumericInstruction; if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1)) return false; if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub)) return false; - var targetType = ldobj.Type; if (!ValidateCompoundAssign(binary, conv, targetType)) return false; - context.Step("TransformRoslynPostIncDecOperatorOnAddress", inst); + 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; } @@ -590,10 +645,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// --> /// stloc s(compound.op.old(ldobj(ldsflda), ldc.i4 1)) /// - bool TransformPostIncDecOnStaticField(Block block, int i) + bool TransformPostIncDecOnStaticField(Block block, int pos) { - var inst = block.Instructions[i] as StLoc; - var stobj = block.Instructions.ElementAtOrDefault(i + 1) as StObj; + var inst = block.Instructions[pos] as StLoc; + var stobj = block.Instructions.ElementAtOrDefault(pos + 1) as StObj; if (inst == null || stobj == null) return false; ILInstruction target; From 11631d6cf0c7ae7ccb5f8076dcf69aecdfa634c4 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 17:57:15 +0100 Subject: [PATCH 09/15] Remove redundant code from TransformAssignment. --- .../IL/Transforms/TransformAssignment.cs | 154 +----------------- 1 file changed, 2 insertions(+), 152 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index d9add5071..0272b5e3f 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -181,78 +181,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; // conv does not match binary operation return true; } - - /// - /// 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)) - /// - bool TransformInlineCompoundAssignmentCall(Block block, int i) - { - var mainStLoc = block.Instructions[i] as StLoc; - // in some cases it can be a compiler-generated local - if (mainStLoc == null || (mainStLoc.Variable.Kind != VariableKind.StackSlot && mainStLoc.Variable.Kind != VariableKind.Local)) - return false; - BinaryNumericInstruction binary = UnwrapSmallIntegerConv(mainStLoc.Value, out var conv) as BinaryNumericInstruction; - ILVariable localVariable = mainStLoc.Variable; - 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; - IType targetType = getterCall.Method.ReturnType; - if (!ValidateCompoundAssign(binary, conv, targetType)) - return false; - context.Step($"Inline compound assignment to '{getterCall.Method.AccessorOwner.Name}'", setterCall); - block.Instructions.RemoveAt(i + 1); // remove setter call - mainStLoc.Value = new CompoundAssignmentInstruction( - binary, getterCall, binary.Right, - targetType, CompoundAssignmentType.EvaluatesToNewValue); - return true; - } - - /// - /// Roslyn compound assignment that's not inline within another instruction. - /// - bool TransformRoslynCompoundAssignmentCall(Block block, int i) - { - // stloc variable(callvirt get_Property(ldloc obj)) - // 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; - if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, getterCall.Method.ReturnType)) - return false; - 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; - } - + static bool MatchingGetterAndSetterCalls(CallInstruction getterCall, CallInstruction setterCall) { if (getterCall == null || setterCall == null || !IsSameMember(getterCall.Method.AccessorOwner, setterCall.Method.AccessorOwner)) @@ -486,7 +415,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } storeType = call.Method.Parameters.Last().Type; value = call.Arguments.Last(); - return call.Method.Equals((call.Method.AccessorOwner as IProperty)?.Setter); + return IsSameMember(call.Method, (call.Method.AccessorOwner as IProperty)?.Setter); } else { return false; } @@ -587,85 +516,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return true; } - - /// - /// 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)) - /// - 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; - } - BinaryNumericInstruction binary = stobj.Value as BinaryNumericInstruction; - if (binary == null || !binary.Left.MatchLdLoc(fieldValue.Variable) || !binary.Right.MatchLdcI4(1) - || (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub)) - return false; - 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; - } - - /// - /// stloc s(ldobj(ldsflda)) - /// stobj (ldsflda, binary.op(ldloc s, ldc.i4 1)) - /// --> - /// stloc s(compound.op.old(ldobj(ldsflda), ldc.i4 1)) - /// - bool TransformPostIncDecOnStaticField(Block block, int pos) - { - var inst = block.Instructions[pos] as StLoc; - var stobj = block.Instructions.ElementAtOrDefault(pos + 1) as StObj; - if (inst == null || stobj == null) - return false; - ILInstruction target; - IType type; - IField field, field2; - if (inst.Variable.Kind != VariableKind.StackSlot || !inst.Value.MatchLdObj(out target, out type) || !target.MatchLdsFlda(out field)) - return false; - if (!stobj.Target.MatchLdsFlda(out field2) || !IsSameMember(field, field2)) - return false; - var binary = stobj.Value as BinaryNumericInstruction; - if (binary == null || !binary.Left.MatchLdLoc(inst.Variable) || !binary.Right.MatchLdcI4(1)) - return false; - context.Step($"TransformPostIncDecOnStaticField", inst); - var assignment = new CompoundAssignmentInstruction(binary, inst.Value, binary.Right, type, CompoundAssignmentType.EvaluatesToOldValue); - stobj.ReplaceWith(new StLoc(inst.Variable, assignment)); - return true; - } static bool IsSameMember(IMember a, IMember b) { From a82430fc785c934e0f594fdc3fe2e7f62ea6a1ca Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 19:07:58 +0100 Subject: [PATCH 10/15] Add missing safety checks to inline assignment transforms. --- .../IL/Transforms/TransformAssignment.cs | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index 0272b5e3f..47dff8a0a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -54,7 +54,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// stloc s(value) /// stloc l(ldloc s) /// stobj(..., ldloc s) - /// where ... is pure and does not use s or l + /// where ... is pure and does not use s or l, + /// and where neither the 'stloc s' nor the 'stobj' truncates /// --> /// stloc l(stobj (..., value)) /// @@ -65,6 +66,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// stloc s(value) /// stobj (..., ldloc s) + /// where ... is pure and does not use s, and where the 'stobj' does not truncate /// --> /// stloc s(stobj (..., value)) /// @@ -75,9 +77,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// stloc s(value) /// call set_Property(..., ldloc s) - /// where the '...' arguments are free of side-effects and not using '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 /// bool TransformInlineAssignmentStObjOrCall(Block block, int pos) { @@ -94,6 +97,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (block.Instructions[pos + 1] is StLoc localStore) { // with extra local 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; @@ -211,30 +215,31 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal static bool HandleCallCompoundAssign(CallInstruction setterCall, StatementTransformContext context) { // 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 storeInSetter = setterValue as StLoc; if (storeInSetter != null) { // 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; } - if (setterValue is Conv conv && conv.Kind == ConversionKind.Truncate && conv.TargetType.IsSmallIntegerType()) { - // for compound assignments to small integers, the compiler emits a "conv" instruction - setterValue = conv.Argument; - } else { - conv = null; - } + setterValue = UnwrapSmallIntegerConv(setterValue, out var conv); if (!(setterValue is BinaryNumericInstruction binary)) return false; var getterCall = binary.Left as CallInstruction; if (!MatchingGetterAndSetterCalls(getterCall, setterCall)) return false; IType targetType = getterCall.Method.ReturnType; - if (!CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, targetType)) + if (!ValidateCompoundAssign(binary, conv, targetType)) return false; - if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow)) - return false; // conv does not match binary operation + 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); ILInstruction newInst = new CompoundAssignmentInstruction( binary, getterCall, binary.Right, @@ -250,6 +255,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// stobj(target, binary.op(ldobj(target), ...)) + /// where target is pure /// => compound.op(target, ...) /// /// @@ -288,6 +294,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// stloc s(value) /// stloc l(ldloc s) + /// where neither 'stloc s' nor 'stloc l' truncates the value /// --> /// stloc s(stloc l(value)) /// @@ -304,6 +311,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms 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; + } if (IsImplicitTruncation(inst.Value, nextInst.Variable.Type)) { // 'stloc l' is implicitly truncating the stack value return false; @@ -441,14 +452,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// stobj(target, binary.add(stloc l(ldobj(target)), ldc.i4 1)) - /// where target is pure and does not use 'l' + /// 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 target is pure and does not use 'l' + /// where args.. are pure and do not use 'l', and the 'stloc l' does not truncate /// --> /// stloc l(compound.op.old(call get_Prop(target), ldc.i4 1)) /// @@ -474,6 +485,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (!ValidateCompoundAssign(binary, conv, targetType)) return false; + if (IsImplicitTruncation(stloc.Value, stloc.Variable.Type)) + return false; context.Step("TransformPostIncDecOperatorWithInlineStore", store); block.Instructions[pos] = new StLoc(stloc.Variable, new CompoundAssignmentInstruction( binary, stloc.Value, binary.Right, targetType, CompoundAssignmentType.EvaluatesToOldValue)); @@ -483,7 +496,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// stloc l(ldobj(target)) /// stobj(target, binary.op(ldloc l, ldc.i4 1)) - /// target is pure and does not use 'l' + /// target is pure and does not use 'l', 'stloc does not truncate' /// --> /// stloc l(compound.op.old(ldobj(target), ldc.i4 1)) /// @@ -507,6 +520,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; 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); From 9e25ed562a74fba0a3c03b22e8240b028144eec9 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 1 Nov 2017 21:21:00 +0100 Subject: [PATCH 11/15] Remove unused RequiredGetCurrentTransformation.UninlineAndUseExistingVariable --- .../CSharp/StatementBuilder.cs | 55 ++----------------- 1 file changed, 4 insertions(+), 51 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index c537ccf89..995b7a247 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -463,26 +463,6 @@ namespace ICSharpCode.Decompiler.CSharp foreachVariable.Kind = VariableKind.ForeachLocal; foreachVariable.Name = AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation(), foreachVariable); break; - case RequiredGetCurrentTransformation.UninlineAndUseExistingVariable: - // Unwrap stloc chain. - var nestedStores = new Stack(); - 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: foreachVariable = currentFunction.RegisterVariable( VariableKind.ForeachLocal, type, @@ -567,16 +547,6 @@ namespace ICSharpCode.Decompiler.CSharp /// UseExistingVariable, /// - /// Uninline (and possibly reorder) multiple stloc instructions and insert stloc foreachVar(call get_Current()) as first statement in the loop body. - /// - /// ... (stloc foreachVar(stloc otherVar(call get_Current())) ... - /// => - /// stloc foreachVar(call get_Current()) - /// ... (stloc otherVar(ldloc foreachVar)) ... - /// - /// - UninlineAndUseExistingVariable, - /// /// No store was found, thus create a new variable and use it as foreach variable. /// /// ... (call get_Current()) ... @@ -617,32 +587,15 @@ namespace ICSharpCode.Decompiler.CSharp // the result of call get_Current is casted. while (inst.Parent is UnboxAny || inst.Parent is CastClass) inst = inst.Parent; - // Gather all nested assignments to determine the foreach variable. - List nestedStores = new List(); - 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. - 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. - if (nestedStores[0].Parent == loopBody && VariableIsOnlyUsedInBlock(nestedStores[0], usingContainer)) { - foreachVariable = nestedStores[0].Variable; + if (stloc.Parent == loopBody && VariableIsOnlyUsedInBlock(stloc, usingContainer)) { + foreachVariable = stloc.Variable; 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; } From deca445d89cc54cab82d69f60cadfa42d44e2b67 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 21:01:33 +0100 Subject: [PATCH 12/15] Restore the CopyPropagation's pass old position before the statement transforms. Instead run TransformAssignment twice to avoid pass ordering issues. --- .../Pretty/CompoundAssignmentTest.cs | 8 ++++ .../Pretty/CompoundAssignmentTest.il | 46 ++++++++++++++++--- .../Pretty/CompoundAssignmentTest.opt.il | 43 ++++++++++++++--- .../CompoundAssignmentTest.opt.roslyn.il | 39 ++++++++++++++-- .../Pretty/CompoundAssignmentTest.roslyn.il | 43 ++++++++++++++--- .../CSharp/CSharpDecompiler.cs | 7 ++- 6 files changed, 160 insertions(+), 26 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index 8a4dee7b7..841444434 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { @@ -78,6 +79,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty private int[] array1; private StructContainer field1; private MyEnum enumField; + private Dictionary ushortDict = new Dictionary(); + private ushort ushortField; private ShortEnum shortEnumField; public static int StaticField; public static short StaticShortField; @@ -509,5 +512,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty // same with enum field: this.enumField = (MyEnum)((int)this.enumField % (int)b); } + + private void Issue588(ushort val) + { + this.ushortDict.Add(this.ushortField++, val); + } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il index f8942fdb4..6b8eb3413 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly njho1304 +.assembly ky5fl4b0 { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module njho1304.dll -// MVID: {06E90287-B329-43EC-805F-F8BC42EE77DE} +.module ky5fl4b0.dll +// MVID: {C370770B-D135-491B-8AAA-78D09B51E79A} .custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 ) .imagebase 0x10000000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00C00000 +// Image base: 0x018D0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -203,6 +203,8 @@ .field private int32[] array1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField + .field private class [mscorlib]System.Collections.Generic.Dictionary`2 ushortDict + .field private uint16 ushortField .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum shortEnumField .field public static int32 StaticField .field public static int16 StaticShortField @@ -1936,14 +1938,44 @@ IL_0015: ret } // end of method CompoundAssignmentTest::Issue954 + .method private hidebysig instance void + Issue588(uint16 val) cil managed + { + // Code size 33 (0x21) + .maxstack 4 + .locals init (uint16 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortDict + IL_0007: ldarg.0 + IL_0008: dup + IL_0009: ldfld uint16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortField + IL_000e: dup + IL_000f: stloc.0 + IL_0010: ldc.i4.1 + IL_0011: add + IL_0012: conv.u2 + IL_0013: stfld uint16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortField + IL_0018: ldloc.0 + IL_0019: ldarg.1 + IL_001a: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_001f: nop + IL_0020: ret + } // end of method CompoundAssignmentTest::Issue588 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { - // Code size 7 (0x7) + // Code size 19 (0x13) .maxstack 8 IL_0000: ldarg.0 - IL_0001: call instance void [mscorlib]System.Object::.ctor() - IL_0006: ret + IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor() + IL_0006: stfld class [mscorlib]System.Collections.Generic.Dictionary`2 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortDict + IL_000b: ldarg.0 + IL_000c: call instance void [mscorlib]System.Object::.ctor() + IL_0011: nop + IL_0012: ret } // end of method CompoundAssignmentTest::.ctor .property int32 StaticProperty() diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il index 167a7e42f..f46ecd5d9 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly iwgzkcmd +.assembly fwwjsv0p { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module iwgzkcmd.dll -// MVID: {80313F66-9892-4910-999C-C098CFBAAB05} +.module fwwjsv0p.dll +// MVID: {115B8AEA-ECDD-40D2-AD1D-BE7A4D5D451E} .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: 0x02540000 +// Image base: 0x00950000 // =============== CLASS MEMBERS DECLARATION =================== @@ -186,6 +186,8 @@ .field private int32[] array1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField + .field private class [mscorlib]System.Collections.Generic.Dictionary`2 ushortDict + .field private uint16 ushortField .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum shortEnumField .field public static int32 StaticField .field public static int16 StaticShortField @@ -1591,14 +1593,41 @@ 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 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::Add(!0, + !1) + IL_001e: ret + } // end of method CompoundAssignmentTest::Issue588 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { - // Code size 7 (0x7) + // Code size 18 (0x12) .maxstack 8 IL_0000: ldarg.0 - IL_0001: call instance void [mscorlib]System.Object::.ctor() - IL_0006: ret + IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor() + IL_0006: stfld class [mscorlib]System.Collections.Generic.Dictionary`2 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 .property int32 StaticProperty() diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il index a2cb8397f..3a4b5498b 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {F06B4897-D7A1-4604-8BC9-FB97832F7C40} +// MVID: {6E167114-971D-41D3-B5C0-4D9D477E18F9} .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: 0x02D30000 +// Image base: 0x00C70000 // =============== CLASS MEMBERS DECLARATION =================== @@ -190,6 +190,8 @@ .field private int32[] array1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField + .field private class [mscorlib]System.Collections.Generic.Dictionary`2 ushortDict + .field private uint16 ushortField .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum shortEnumField .field public static int32 StaticField .field public static int16 StaticShortField @@ -1595,14 +1597,41 @@ 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 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::Add(!0, + !1) + IL_001e: ret + } // end of method CompoundAssignmentTest::Issue588 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { - // Code size 7 (0x7) + // Code size 18 (0x12) .maxstack 8 IL_0000: ldarg.0 - IL_0001: call instance void [mscorlib]System.Object::.ctor() - IL_0006: ret + IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor() + IL_0006: stfld class [mscorlib]System.Collections.Generic.Dictionary`2 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 .property int32 StaticProperty() diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il index 61d682006..f7a98b5b4 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {C9CD236E-5AA3-4F16-ABA1-33B72FC48FEA} +// MVID: {A617B3F7-CCDD-4058-9EEB-9D57B526A02A} .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: 0x01530000 +// Image base: 0x02410000 // =============== CLASS MEMBERS DECLARATION =================== @@ -201,6 +201,8 @@ .field private int32[] array1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer field1 .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/MyEnum enumField + .field private class [mscorlib]System.Collections.Generic.Dictionary`2 ushortDict + .field private uint16 ushortField .field private valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/ShortEnum shortEnumField .field public static int32 StaticField .field public static int16 StaticShortField @@ -1929,15 +1931,44 @@ IL_0015: ret } // end of method CompoundAssignmentTest::Issue954 + .method private hidebysig instance void + Issue588(uint16 val) cil managed + { + // Code size 33 (0x21) + .maxstack 4 + .locals init (uint16 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortDict + IL_0007: ldarg.0 + IL_0008: ldarg.0 + IL_0009: ldfld uint16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortField + IL_000e: stloc.0 + IL_000f: ldloc.0 + IL_0010: ldc.i4.1 + IL_0011: add + IL_0012: conv.u2 + IL_0013: stfld uint16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortField + IL_0018: ldloc.0 + IL_0019: ldarg.1 + IL_001a: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_001f: nop + IL_0020: ret + } // end of method CompoundAssignmentTest::Issue588 + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { - // Code size 8 (0x8) + // Code size 19 (0x13) .maxstack 8 IL_0000: ldarg.0 - IL_0001: call instance void [mscorlib]System.Object::.ctor() - IL_0006: nop - IL_0007: ret + IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor() + IL_0006: stfld class [mscorlib]System.Collections.Generic.Dictionary`2 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::ushortDict + IL_000b: ldarg.0 + IL_000c: call instance void [mscorlib]System.Object::.ctor() + IL_0011: nop + IL_0012: ret } // end of method CompoundAssignmentTest::.ctor .property int32 StaticProperty() diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 412f6370d..f236ceab6 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -109,6 +109,12 @@ namespace ICSharpCode.Decompiler.CSharp // CachedDelegateInitialization must run after ConditionDetection and before/in LoopingBlockTransform // and must run before NullCoalescingTransform new CachedDelegateInitialization(), + // Run the assignment transform both before and after copy propagation. + // 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 StatementTransform( // per-block transforms that depend on each other, and thus need to // run interleaved (statement by statement). @@ -124,7 +130,6 @@ namespace ICSharpCode.Decompiler.CSharp new TransformArrayInitializers(), new TransformCollectionAndObjectInitializers() ), - new CopyPropagation() } }, new ProxyCallReplacer(), From e813ebcc0330e00d5b5cf6cd16727cb47d233274 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 22:00:54 +0100 Subject: [PATCH 13/15] Adjust Loops test. --- .../Helpers/CodeAssert.cs | 31 ++++++++++--------- .../Helpers/Tester.cs | 24 +++++++++++--- .../PrettyTestRunner.cs | 2 +- .../TestCases/Pretty/Loops.cs | 6 ++++ 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs b/ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs index 1c8f8c3d0..ee98b6ee3 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/CodeAssert.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; using DiffLib; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using NUnit.Framework; namespace ICSharpCode.Decompiler.Tests.Helpers @@ -115,24 +117,23 @@ namespace ICSharpCode.Decompiler.Tests.Helpers return NormalizeLine(line) == string.Empty; } - private static IEnumerable NormalizeAndSplitCode(string input, string[] definedSymbols) + class DeleteDisabledTextRewriter : CSharpSyntaxRewriter { - bool include = true; - foreach (string line in input.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries)) { - var temp = line.Trim(); - if (temp.StartsWith("#if !", StringComparison.Ordinal)) { - 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; + public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) + { + if (trivia.IsKind(SyntaxKind.DisabledTextTrivia)) { + return default(SyntaxTrivia); // delete } - if (include) yield return line; + return base.VisitTrivia(trivia); } } + + private static IEnumerable NormalizeAndSplitCode(string input, IEnumerable 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); + } } } diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index f75d79759..b8434c9b5 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -158,6 +158,24 @@ namespace ICSharpCode.Decompiler.Tests.Helpers }; }); + + public static List GetPreprocessorSymbols(CompilerOptions flags) + { + var preprocessorSymbols = new List(); + 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) { List sourceFileNames = new List { sourceFileName }; @@ -165,10 +183,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers sourceFileNames.Add(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFileName), match.Groups[1].Value))); } - var preprocessorSymbols = new List(); - if (flags.HasFlag(CompilerOptions.UseDebug)) { - preprocessorSymbols.Add("DEBUG"); - } + var preprocessorSymbols = GetPreprocessorSymbols(flags); if (flags.HasFlag(CompilerOptions.UseRoslyn)) { var parseOptions = new CSharpParseOptions(preprocessorSymbols: preprocessorSymbols.ToArray()); @@ -194,7 +209,6 @@ namespace ICSharpCode.Decompiler.Tests.Helpers } return results; } else { - preprocessorSymbols.Add("LEGACY_CSC"); var provider = new CSharpCodeProvider(new Dictionary { { "CompilerVersion", "v4.0" } }); CompilerParameters options = new CompilerParameters(); options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library); diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index 9984a1110..7c755f0ef 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -226,7 +226,7 @@ namespace ICSharpCode.Decompiler.Tests var executable = Tester.AssembleIL(ilFile, asmOptions | AssemblerOptions.Library); 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()); } } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs index 8345eaf1c..c931d815d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs @@ -388,8 +388,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static void ForeachWithRefUsage(List 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; Loops.Operation(ref current); +#else + int num = item; + Loops.Operation(ref num); +#endif } } From dda1742013b9c874c242d223d260d1f3e4c1775d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 23:10:11 +0100 Subject: [PATCH 14/15] Probably due to the code changes in e813ebcc03 (additional use of Microsoft.CodeAnalysis.CSharp), the stupid build system started copying an older version of System.Collections.Immutable and System.ValueType (the one referenced by Roslyn) to the BamlDecompiler.Tests output directly, causing the tests to fail due to a missing dependency. Upgrade our Roslyn package version and downgrade the System.Collections.Immutable and System.ValueType versions, so that there's only one version of each assembly in play. --- .../ICSharpCode.Decompiler.Tests.csproj | 4 ++-- ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index adb328120..a722b7b70 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 764707c72..fd5d7f1b7 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -51,8 +51,8 @@ - - + + From 174a0d9eca65ab47e4606ab41aff6d2c8c31f545 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 23:43:32 +0100 Subject: [PATCH 15/15] Add some more tests for compound assignment on struct members. Closes #864. --- .../Pretty/CompoundAssignmentTest.cs | 2 + .../Pretty/CompoundAssignmentTest.il | 43 +++++++++++++------ .../Pretty/CompoundAssignmentTest.opt.il | 43 +++++++++++++------ .../CompoundAssignmentTest.opt.roslyn.il | 38 ++++++++++++---- .../Pretty/CompoundAssignmentTest.roslyn.il | 41 +++++++++++++----- 5 files changed, 124 insertions(+), 43 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index 841444434..1ba1b67f8 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs @@ -224,6 +224,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public void NestedField() { if (this.field1.HasIndex) { + Console.WriteLine(this.field1.Field *= 2); + this.field1.Field++; Console.WriteLine(this.field1.Field++); } } diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il index 6b8eb3413..d77abfb22 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly ky5fl4b0 +.assembly c4ghupf5 { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module ky5fl4b0.dll -// MVID: {C370770B-D135-491B-8AAA-78D09B51E79A} +.module c4ghupf5.dll +// MVID: {A420A635-A261-460E-9F30-F603256DEDB0} .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: 0x018D0000 +// Image base: 0x02FD0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -740,7 +740,7 @@ .method public hidebysig instance void NestedField() cil managed { - // Code size 50 (0x32) + // Code size 97 (0x61) .maxstack 3 .locals init (bool V_0, int32 V_1) @@ -752,23 +752,42 @@ IL_000d: ceq IL_000f: stloc.0 IL_0010: ldloc.0 - IL_0011: brtrue.s IL_0031 + IL_0011: brtrue.s IL_0060 IL_0013: nop IL_0014: ldarg.0 IL_0015: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 IL_001a: dup IL_001b: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field - IL_0020: dup - IL_0021: stloc.1 - IL_0022: ldc.i4.1 - IL_0023: add + IL_0020: ldc.i4.2 + IL_0021: mul + IL_0022: dup + IL_0023: stloc.1 IL_0024: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field IL_0029: ldloc.1 IL_002a: call void [mscorlib]System.Console::WriteLine(int32) IL_002f: nop - IL_0030: nop - IL_0031: ret + IL_0030: ldarg.0 + IL_0031: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 + IL_0036: dup + IL_0037: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field + IL_003c: ldc.i4.1 + IL_003d: add + IL_003e: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field + IL_0043: ldarg.0 + IL_0044: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 + IL_0049: dup + IL_004a: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field + IL_004f: dup + IL_0050: stloc.1 + IL_0051: ldc.i4.1 + IL_0052: add + IL_0053: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field + IL_0058: ldloc.1 + IL_0059: call void [mscorlib]System.Console::WriteLine(int32) + IL_005e: nop + IL_005f: nop + IL_0060: ret } // end of method CompoundAssignmentTest::NestedField .method public hidebysig instance void diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il index f46ecd5d9..11dd18ecb 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly fwwjsv0p +.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.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 .ver 0:0:0:0 } -.module fwwjsv0p.dll -// MVID: {115B8AEA-ECDD-40D2-AD1D-BE7A4D5D451E} +.module '0ffxad1m.dll' +// MVID: {C53B3CFA-3FF4-4724-8DBE-8B180FA612BA} .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: 0x00950000 +// Image base: 0x028A0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -637,26 +637,45 @@ .method public hidebysig instance void NestedField() cil managed { - // Code size 41 (0x29) + // Code size 87 (0x57) .maxstack 3 - .locals init (int32 V_0) + .locals init (int32 V_0, + int32 V_1) IL_0000: ldarg.0 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_000b: brfalse.s IL_0028 + IL_000b: brfalse.s IL_0056 IL_000d: ldarg.0 IL_000e: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 IL_0013: dup IL_0014: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field - IL_0019: dup - IL_001a: stloc.0 - IL_001b: ldc.i4.1 - IL_001c: add + IL_0019: ldc.i4.2 + IL_001a: mul + IL_001b: dup + IL_001c: stloc.0 IL_001d: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field IL_0022: ldloc.0 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 .method public hidebysig instance void diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il index 3a4b5498b..5642cef0d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.opt.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {6E167114-971D-41D3-B5C0-4D9D477E18F9} +// MVID: {EE880025-0C8C-414F-BD89-E5DB86D9B5FA} .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: 0x00C70000 +// Image base: 0x016C0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -639,27 +639,47 @@ .method public hidebysig instance void NestedField() cil managed { - // Code size 38 (0x26) + // Code size 78 (0x4e) .maxstack 3 .locals init (int32 V_0) IL_0000: ldarg.0 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_000b: brfalse.s IL_0025 + IL_000b: brfalse.s IL_004d IL_000d: ldarg.0 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_0018: dup IL_0019: ldind.i4 - IL_001a: stloc.0 - IL_001b: ldloc.0 - IL_001c: ldc.i4.1 - IL_001d: add + IL_001a: ldc.i4.2 + IL_001b: mul + IL_001c: dup + IL_001d: stloc.0 IL_001e: stind.i4 IL_001f: ldloc.0 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 .method public hidebysig instance void diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il index f7a98b5b4..8360d1d10 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module CompoundAssignmentTest.dll -// MVID: {A617B3F7-CCDD-4058-9EEB-9D57B526A02A} +// MVID: {367B213F-CE98-4EEA-B458-88A41927D3BC} .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: 0x02410000 +// Image base: 0x006A0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -730,7 +730,7 @@ .method public hidebysig instance void NestedField() cil managed { - // Code size 44 (0x2c) + // Code size 85 (0x55) .maxstack 3 .locals init (bool V_0, int32 V_1) @@ -740,7 +740,7 @@ IL_0007: ldfld bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::HasIndex IL_000c: stloc.0 IL_000d: ldloc.0 - IL_000e: brfalse.s IL_002b + IL_000e: brfalse.s IL_0054 IL_0010: nop IL_0011: ldarg.0 @@ -748,16 +748,37 @@ IL_0017: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field IL_001c: dup IL_001d: ldind.i4 - IL_001e: stloc.1 - IL_001f: ldloc.1 - IL_0020: ldc.i4.1 - IL_0021: add + IL_001e: ldc.i4.2 + IL_001f: mul + IL_0020: dup + IL_0021: stloc.1 IL_0022: stind.i4 IL_0023: ldloc.1 IL_0024: call void [mscorlib]System.Console::WriteLine(int32) IL_0029: nop - IL_002a: nop - IL_002b: ret + IL_002a: ldarg.0 + IL_002b: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 + IL_0030: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field + IL_0035: dup + IL_0036: ldind.i4 + IL_0037: ldc.i4.1 + IL_0038: add + IL_0039: stind.i4 + IL_003a: ldarg.0 + IL_003b: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest::field1 + IL_0040: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.CompoundAssignmentTest/StructContainer::Field + IL_0045: dup + IL_0046: ldind.i4 + IL_0047: stloc.1 + IL_0048: ldloc.1 + IL_0049: ldc.i4.1 + IL_004a: add + IL_004b: stind.i4 + IL_004c: ldloc.1 + IL_004d: call void [mscorlib]System.Console::WriteLine(int32) + IL_0052: nop + IL_0053: nop + IL_0054: ret } // end of method CompoundAssignmentTest::NestedField .method public hidebysig instance void