From deca445d89cc54cab82d69f60cadfa42d44e2b67 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Nov 2017 21:01:33 +0100 Subject: [PATCH] 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(),