From 51d13bfefedeeddf53cdcb00c97e0c6780ec045f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 11 Oct 2017 12:28:35 +0200 Subject: [PATCH] Add transform for Roslyn Switch-On-Nullable --- .../TestCases/Pretty/Switch.cs | 200 +++++----- .../TestCases/Pretty/Switch.il | 360 +++++++++++++++++- .../TestCases/Pretty/Switch.opt.il | 288 +++++++++++++- .../TestCases/Pretty/Switch.opt.roslyn.il | 255 ++++++++++++- .../TestCases/Pretty/Switch.roslyn.il | 358 ++++++++++++++++- .../Transforms/SwitchOnNullableTransform.cs | 60 +++ 6 files changed, 1373 insertions(+), 148 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs index e5f42c278..fcf01f6d9 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs @@ -82,83 +82,83 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } - //public static string SwitchOverNullableInt(int? i) - //{ - // switch (i) { - // case null: { - // return "null"; - // } - // case 0: { - // return "zero"; - // } - // case 5: { - // return "five"; - // } - // case 10: { - // return "ten"; - // } - // default: { - // return "large"; - // } - // } - //} + public static string SwitchOverNullableInt(int? i) + { + switch (i) { + case null: { + return "null"; + } + case 0: { + return "zero"; + } + case 5: { + return "five"; + } + case 10: { + return "ten"; + } + default: { + return "large"; + } + } + } - //public static string SwitchOverNullableIntShifted(int? i) - //{ - // switch (i + 5) { - // case null: { - // return "null"; - // } - // case 0: { - // return "zero"; - // } - // case 5: { - // return "five"; - // } - // case 10: { - // return "ten"; - // } - // default: { - // return "large"; - // } - // } - //} + public static string SwitchOverNullableIntShifted(int? i) + { + switch (i + 5) { + case null: { + return "null"; + } + case 0: { + return "zero"; + } + case 5: { + return "five"; + } + case 10: { + return "ten"; + } + default: { + return "large"; + } + } + } - //public static string SwitchOverNullableIntNoNullCase(int? i) - //{ - // switch (i) { - // case 0: { - // return "zero"; - // } - // case 5: { - // return "five"; - // } - // case 10: { - // return "ten"; - // } - // default: { - // return "other"; - // } - // } - //} + public static string SwitchOverNullableIntNoNullCase(int? i) + { + switch (i) { + case 0: { + return "zero"; + } + case 5: { + return "five"; + } + case 10: { + return "ten"; + } + default: { + return "other"; + } + } + } - //public static string SwitchOverNullableIntNoNullCaseShifted(int? i) - //{ - // switch (i + 5) { - // case 0: { - // return "zero"; - // } - // case 5: { - // return "five"; - // } - // case 10: { - // return "ten"; - // } - // default: { - // return "other"; - // } - // } - //} + public static string SwitchOverNullableIntNoNullCaseShifted(int? i) + { + switch (i + 5) { + case 0: { + return "zero"; + } + case 5: { + return "five"; + } + case 10: { + return "ten"; + } + default: { + return "other"; + } + } + } public static string ShortSwitchOverString(string text) { @@ -302,32 +302,32 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } - //public static void SwitchWithGoto(int i) - //{ - // Console.WriteLine("SwitchWithGoto: " + i); - // switch (i) { - // case 1: { - // Console.WriteLine("one"); - // goto default; - // } - // case 2: { - // Console.WriteLine("two"); - // goto case 3; - // } - // case 3: { - // Console.WriteLine("three"); - // break; - // } - // case 4: { - // Console.WriteLine("four"); - // return; - // } - // default: { - // Console.WriteLine("default"); - // break; - // } - // } - //} + public static void SwitchWithGoto(int i) + { + Console.WriteLine("SwitchWithGoto: " + i); + switch (i) { + case 1: { + Console.WriteLine("one"); + goto default; + } + case 2: { + Console.WriteLine("two"); + goto case 3; + } + case 3: { + Console.WriteLine("three"); + break; + } + case 4: { + Console.WriteLine("four"); + return; + } + default: { + Console.WriteLine("default"); + break; + } + } + } private static SetProperty[] GetProperties() { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il index eed5597a0..c6af28ac4 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il @@ -1,6 +1,6 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929 -// Copyright (c) Microsoft Corporation. All rights reserved. +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. Alle Rechte vorbehalten. @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly gn0oqkcb +.assembly nyniamwr { .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. @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module gn0oqkcb.dll -// MVID: {D3E1C722-15E3-49C8-B86B-96413DA7BEEE} +.module nyniamwr.dll +// MVID: {95C99B41-CBA3-42E4-A4DE-27E535671AB2} .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: 0x00C80000 +// Image base: 0x03080000 // =============== CLASS MEMBERS DECLARATION =================== @@ -214,6 +214,268 @@ IL_00df: ret } // end of method Switch::SparseIntegerSwitch + .method public hidebysig static string + SwitchOverNullableInt(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 79 (0x4f) + .maxstack 2 + .locals init (string V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarga.s i + IL_0003: dup + IL_0004: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0009: stloc.1 + IL_000a: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000f: brfalse.s IL_0020 + + IL_0011: ldloc.1 + IL_0012: ldc.i4.0 + IL_0013: beq.s IL_0029 + + IL_0015: ldloc.1 + IL_0016: ldc.i4.5 + IL_0017: beq.s IL_0032 + + IL_0019: ldloc.1 + IL_001a: ldc.i4.s 10 + IL_001c: beq.s IL_003b + + IL_001e: br.s IL_0044 + + IL_0020: nop + IL_0021: ldstr "null" + IL_0026: stloc.0 + IL_0027: br.s IL_004d + + IL_0029: nop + IL_002a: ldstr "zero" + IL_002f: stloc.0 + IL_0030: br.s IL_004d + + IL_0032: nop + IL_0033: ldstr "five" + IL_0038: stloc.0 + IL_0039: br.s IL_004d + + IL_003b: nop + IL_003c: ldstr "ten" + IL_0041: stloc.0 + IL_0042: br.s IL_004d + + IL_0044: nop + IL_0045: ldstr "large" + IL_004a: stloc.0 + IL_004b: br.s IL_004d + + IL_004d: ldloc.0 + IL_004e: ret + } // end of method Switch::SwitchOverNullableInt + + .method public hidebysig static string + SwitchOverNullableIntShifted(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 117 (0x75) + .maxstack 2 + .locals init (string V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + valuetype [mscorlib]System.Nullable`1 V_2, + int32 V_3) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.1 + IL_0003: ldloca.s V_1 + IL_0005: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000a: brtrue.s IL_0017 + + IL_000c: ldloca.s V_2 + IL_000e: initobj valuetype [mscorlib]System.Nullable`1 + IL_0014: ldloc.2 + IL_0015: br.s IL_0025 + + IL_0017: ldloca.s V_1 + IL_0019: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_001e: ldc.i4.5 + IL_001f: add + IL_0020: newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + IL_0025: nop + IL_0026: stloc.2 + IL_0027: ldloca.s V_2 + IL_0029: dup + IL_002a: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_002f: stloc.3 + IL_0030: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0035: brfalse.s IL_0046 + + IL_0037: ldloc.3 + IL_0038: ldc.i4.0 + IL_0039: beq.s IL_004f + + IL_003b: ldloc.3 + IL_003c: ldc.i4.5 + IL_003d: beq.s IL_0058 + + IL_003f: ldloc.3 + IL_0040: ldc.i4.s 10 + IL_0042: beq.s IL_0061 + + IL_0044: br.s IL_006a + + IL_0046: nop + IL_0047: ldstr "null" + IL_004c: stloc.0 + IL_004d: br.s IL_0073 + + IL_004f: nop + IL_0050: ldstr "zero" + IL_0055: stloc.0 + IL_0056: br.s IL_0073 + + IL_0058: nop + IL_0059: ldstr "five" + IL_005e: stloc.0 + IL_005f: br.s IL_0073 + + IL_0061: nop + IL_0062: ldstr "ten" + IL_0067: stloc.0 + IL_0068: br.s IL_0073 + + IL_006a: nop + IL_006b: ldstr "large" + IL_0070: stloc.0 + IL_0071: br.s IL_0073 + + IL_0073: ldloc.0 + IL_0074: ret + } // end of method Switch::SwitchOverNullableIntShifted + + .method public hidebysig static string + SwitchOverNullableIntNoNullCase(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 70 (0x46) + .maxstack 2 + .locals init (string V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarga.s i + IL_0003: dup + IL_0004: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0009: stloc.1 + IL_000a: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000f: brfalse.s IL_003b + + IL_0011: ldloc.1 + IL_0012: ldc.i4.0 + IL_0013: beq.s IL_0020 + + IL_0015: ldloc.1 + IL_0016: ldc.i4.5 + IL_0017: beq.s IL_0029 + + IL_0019: ldloc.1 + IL_001a: ldc.i4.s 10 + IL_001c: beq.s IL_0032 + + IL_001e: br.s IL_003b + + IL_0020: nop + IL_0021: ldstr "zero" + IL_0026: stloc.0 + IL_0027: br.s IL_0044 + + IL_0029: nop + IL_002a: ldstr "five" + IL_002f: stloc.0 + IL_0030: br.s IL_0044 + + IL_0032: nop + IL_0033: ldstr "ten" + IL_0038: stloc.0 + IL_0039: br.s IL_0044 + + IL_003b: nop + IL_003c: ldstr "other" + IL_0041: stloc.0 + IL_0042: br.s IL_0044 + + IL_0044: ldloc.0 + IL_0045: ret + } // end of method Switch::SwitchOverNullableIntNoNullCase + + .method public hidebysig static string + SwitchOverNullableIntNoNullCaseShifted(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 108 (0x6c) + .maxstack 2 + .locals init (string V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + valuetype [mscorlib]System.Nullable`1 V_2, + int32 V_3) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.1 + IL_0003: ldloca.s V_1 + IL_0005: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000a: brtrue.s IL_0017 + + IL_000c: ldloca.s V_2 + IL_000e: initobj valuetype [mscorlib]System.Nullable`1 + IL_0014: ldloc.2 + IL_0015: br.s IL_0025 + + IL_0017: ldloca.s V_1 + IL_0019: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_001e: ldc.i4.5 + IL_001f: add + IL_0020: newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + IL_0025: nop + IL_0026: stloc.2 + IL_0027: ldloca.s V_2 + IL_0029: dup + IL_002a: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_002f: stloc.3 + IL_0030: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0035: brfalse.s IL_0061 + + IL_0037: ldloc.3 + IL_0038: ldc.i4.0 + IL_0039: beq.s IL_0046 + + IL_003b: ldloc.3 + IL_003c: ldc.i4.5 + IL_003d: beq.s IL_004f + + IL_003f: ldloc.3 + IL_0040: ldc.i4.s 10 + IL_0042: beq.s IL_0058 + + IL_0044: br.s IL_0061 + + IL_0046: nop + IL_0047: ldstr "zero" + IL_004c: stloc.0 + IL_004d: br.s IL_006a + + IL_004f: nop + IL_0050: ldstr "five" + IL_0055: stloc.0 + IL_0056: br.s IL_006a + + IL_0058: nop + IL_0059: ldstr "ten" + IL_005e: stloc.0 + IL_005f: br.s IL_006a + + IL_0061: nop + IL_0062: ldstr "other" + IL_0067: stloc.0 + IL_0068: br.s IL_006a + + IL_006a: ldloc.0 + IL_006b: ret + } // end of method Switch::SwitchOverNullableIntNoNullCaseShifted + .method public hidebysig static string ShortSwitchOverString(string text) cil managed { @@ -298,7 +560,7 @@ IL_0015: brfalse IL_00ef IL_001a: volatile. - IL_001c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000003-1' + IL_001c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x6000007-1' IL_0021: brtrue.s IL_0084 IL_0023: ldc.i4.7 @@ -339,9 +601,9 @@ IL_0078: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_007d: volatile. - IL_007f: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000003-1' + IL_007f: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x6000007-1' IL_0084: volatile. - IL_0086: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000003-1' + IL_0086: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x6000007-1' IL_008b: ldloc.1 IL_008c: ldloca.s V_2 IL_008e: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -424,7 +686,7 @@ IL_0015: brfalse IL_0165 IL_001a: volatile. - IL_001c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000004-1' + IL_001c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x6000008-1' IL_0021: brtrue IL_00ba IL_0026: ldc.i4.s 11 @@ -485,9 +747,9 @@ IL_00ae: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_00b3: volatile. - IL_00b5: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000004-1' + IL_00b5: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x6000008-1' IL_00ba: volatile. - IL_00bc: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000004-1' + IL_00bc: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x6000008-1' IL_00c1: ldloc.2 IL_00c2: ldloca.s V_3 IL_00c4: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -689,6 +951,64 @@ IL_0091: ret } // end of method Switch::SwitchInLoop + .method public hidebysig static void SwitchWithGoto(int32 i) cil managed + { + // Code size 122 (0x7a) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "SwitchWithGoto: " + IL_0006: ldarg.0 + IL_0007: box [mscorlib]System.Int32 + IL_000c: call string [mscorlib]System.String::Concat(object, + object) + IL_0011: call void [mscorlib]System.Console::WriteLine(string) + IL_0016: nop + IL_0017: ldarg.0 + IL_0018: stloc.0 + IL_0019: ldloc.0 + IL_001a: ldc.i4.1 + IL_001b: sub + IL_001c: switch ( + IL_0033, + IL_0041, + IL_004f, + IL_005d) + IL_0031: br.s IL_006b + + IL_0033: nop + IL_0034: ldstr "one" + IL_0039: call void [mscorlib]System.Console::WriteLine(string) + IL_003e: nop + IL_003f: br.s IL_006b + + IL_0041: nop + IL_0042: ldstr "two" + IL_0047: call void [mscorlib]System.Console::WriteLine(string) + IL_004c: nop + IL_004d: br.s IL_004f + + IL_004f: nop + IL_0050: ldstr "three" + IL_0055: call void [mscorlib]System.Console::WriteLine(string) + IL_005a: nop + IL_005b: br.s IL_0079 + + IL_005d: nop + IL_005e: ldstr "four" + IL_0063: call void [mscorlib]System.Console::WriteLine(string) + IL_0068: nop + IL_0069: br.s IL_0079 + + IL_006b: nop + IL_006c: ldstr "default" + IL_0071: call void [mscorlib]System.Console::WriteLine(string) + IL_0076: nop + IL_0077: br.s IL_0079 + + IL_0079: ret + } // end of method Switch::SwitchWithGoto + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch/SetProperty[] GetProperties() cil managed { @@ -744,7 +1064,7 @@ IL_0034: brfalse IL_012d IL_0039: volatile. - IL_003b: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000008-1' + IL_003b: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x600000d-1' IL_0040: brtrue.s IL_0097 IL_0042: ldc.i4.6 @@ -780,9 +1100,9 @@ IL_008b: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_0090: volatile. - IL_0092: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000008-1' + IL_0092: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x600000d-1' IL_0097: volatile. - IL_0099: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}'::'$$method0x6000008-1' + IL_0099: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}'::'$$method0x600000d-1' IL_009e: ldloc.s V_6 IL_00a0: ldloca.s V_7 IL_00a2: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -876,17 +1196,17 @@ } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch -.class private auto ansi '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}' +.class private auto ansi '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}' extends [mscorlib]System.Object { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000003-1' - .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000004-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000007-1' .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000008-1' -} // end of class '{D3E1C722-15E3-49C8-B86B-96413DA7BEEE}' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x600000d-1' +} // end of class '{95C99B41-CBA3-42E4-A4DE-27E535671AB2}' // ============================================================= // *********** DISASSEMBLY COMPLETE *********************** -// WARNING: Created Win32 resource file ../../../TestCases/Pretty\Switch.res +// Warnung: Win32-Ressourcendatei "../../../TestCases/Pretty\Switch.res" wurde erstellt. diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il index becdf49a9..e09dd767c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il @@ -1,6 +1,6 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929 -// Copyright (c) Microsoft Corporation. All rights reserved. +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. Alle Rechte vorbehalten. @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly zlaei1fn +.assembly f3gworj3 { .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. @@ -20,15 +20,15 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module zlaei1fn.dll -// MVID: {64CCBA80-944A-4F77-9230-24B174DEE22A} +.module f3gworj3.dll +// MVID: {6837A40E-7A00-4F01-B2D7-DE0001F70EDF} .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: 0x00680000 +// Image base: 0x00780000 // =============== CLASS MEMBERS DECLARATION =================== @@ -176,6 +176,212 @@ IL_00b4: ret } // end of method Switch::SparseIntegerSwitch + .method public hidebysig static string + SwitchOverNullableInt(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 61 (0x3d) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldarga.s i + IL_0002: dup + IL_0003: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0008: stloc.0 + IL_0009: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000e: brfalse.s IL_001f + + IL_0010: ldloc.0 + IL_0011: ldc.i4.0 + IL_0012: beq.s IL_0025 + + IL_0014: ldloc.0 + IL_0015: ldc.i4.5 + IL_0016: beq.s IL_002b + + IL_0018: ldloc.0 + IL_0019: ldc.i4.s 10 + IL_001b: beq.s IL_0031 + + IL_001d: br.s IL_0037 + + IL_001f: ldstr "null" + IL_0024: ret + + IL_0025: ldstr "zero" + IL_002a: ret + + IL_002b: ldstr "five" + IL_0030: ret + + IL_0031: ldstr "ten" + IL_0036: ret + + IL_0037: ldstr "large" + IL_003c: ret + } // end of method Switch::SwitchOverNullableInt + + .method public hidebysig static string + SwitchOverNullableIntShifted(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 98 (0x62) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + valuetype [mscorlib]System.Nullable`1 V_2, + int32 V_3) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0009: brtrue.s IL_0016 + + IL_000b: ldloca.s V_1 + IL_000d: initobj valuetype [mscorlib]System.Nullable`1 + IL_0013: ldloc.1 + IL_0014: br.s IL_0024 + + IL_0016: ldloca.s V_0 + IL_0018: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_001d: ldc.i4.5 + IL_001e: add + IL_001f: newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + IL_0024: stloc.2 + IL_0025: ldloca.s V_2 + IL_0027: dup + IL_0028: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_002d: stloc.3 + IL_002e: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0033: brfalse.s IL_0044 + + IL_0035: ldloc.3 + IL_0036: ldc.i4.0 + IL_0037: beq.s IL_004a + + IL_0039: ldloc.3 + IL_003a: ldc.i4.5 + IL_003b: beq.s IL_0050 + + IL_003d: ldloc.3 + IL_003e: ldc.i4.s 10 + IL_0040: beq.s IL_0056 + + IL_0042: br.s IL_005c + + IL_0044: ldstr "null" + IL_0049: ret + + IL_004a: ldstr "zero" + IL_004f: ret + + IL_0050: ldstr "five" + IL_0055: ret + + IL_0056: ldstr "ten" + IL_005b: ret + + IL_005c: ldstr "large" + IL_0061: ret + } // end of method Switch::SwitchOverNullableIntShifted + + .method public hidebysig static string + SwitchOverNullableIntNoNullCase(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 55 (0x37) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldarga.s i + IL_0002: dup + IL_0003: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0008: stloc.0 + IL_0009: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000e: brfalse.s IL_0031 + + IL_0010: ldloc.0 + IL_0011: ldc.i4.0 + IL_0012: beq.s IL_001f + + IL_0014: ldloc.0 + IL_0015: ldc.i4.5 + IL_0016: beq.s IL_0025 + + IL_0018: ldloc.0 + IL_0019: ldc.i4.s 10 + IL_001b: beq.s IL_002b + + IL_001d: br.s IL_0031 + + IL_001f: ldstr "zero" + IL_0024: ret + + IL_0025: ldstr "five" + IL_002a: ret + + IL_002b: ldstr "ten" + IL_0030: ret + + IL_0031: ldstr "other" + IL_0036: ret + } // end of method Switch::SwitchOverNullableIntNoNullCase + + .method public hidebysig static string + SwitchOverNullableIntNoNullCaseShifted(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 92 (0x5c) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + valuetype [mscorlib]System.Nullable`1 V_2, + int32 V_3) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0009: brtrue.s IL_0016 + + IL_000b: ldloca.s V_1 + IL_000d: initobj valuetype [mscorlib]System.Nullable`1 + IL_0013: ldloc.1 + IL_0014: br.s IL_0024 + + IL_0016: ldloca.s V_0 + IL_0018: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_001d: ldc.i4.5 + IL_001e: add + IL_001f: newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + IL_0024: stloc.2 + IL_0025: ldloca.s V_2 + IL_0027: dup + IL_0028: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_002d: stloc.3 + IL_002e: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0033: brfalse.s IL_0056 + + IL_0035: ldloc.3 + IL_0036: ldc.i4.0 + IL_0037: beq.s IL_0044 + + IL_0039: ldloc.3 + IL_003a: ldc.i4.5 + IL_003b: beq.s IL_004a + + IL_003d: ldloc.3 + IL_003e: ldc.i4.s 10 + IL_0040: beq.s IL_0050 + + IL_0042: br.s IL_0056 + + IL_0044: ldstr "zero" + IL_0049: ret + + IL_004a: ldstr "five" + IL_004f: ret + + IL_0050: ldstr "ten" + IL_0055: ret + + IL_0056: ldstr "other" + IL_005b: ret + } // end of method Switch::SwitchOverNullableIntNoNullCaseShifted + .method public hidebysig static string ShortSwitchOverString(string text) cil managed { @@ -243,7 +449,7 @@ IL_0013: brfalse IL_00db IL_0018: volatile. - IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000003-1' + IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x6000007-1' IL_001f: brtrue.s IL_0082 IL_0021: ldc.i4.7 @@ -284,9 +490,9 @@ IL_0076: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_007b: volatile. - IL_007d: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000003-1' + IL_007d: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x6000007-1' IL_0082: volatile. - IL_0084: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000003-1' + IL_0084: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x6000007-1' IL_0089: ldloc.0 IL_008a: ldloca.s V_1 IL_008c: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -347,7 +553,7 @@ IL_0013: brfalse IL_013f IL_0018: volatile. - IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000004-1' + IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x6000008-1' IL_001f: brtrue IL_00b8 IL_0024: ldc.i4.s 11 @@ -408,9 +614,9 @@ IL_00ac: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_00b1: volatile. - IL_00b3: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000004-1' + IL_00b3: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x6000008-1' IL_00b8: volatile. - IL_00ba: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000004-1' + IL_00ba: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x6000008-1' IL_00bf: ldloc.1 IL_00c0: ldloca.s V_2 IL_00c2: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -551,6 +757,48 @@ IL_007a: br.s IL_0015 } // end of method Switch::SwitchInLoop + .method public hidebysig static void SwitchWithGoto(int32 i) cil managed + { + // Code size 104 (0x68) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldstr "SwitchWithGoto: " + IL_0005: ldarg.0 + IL_0006: box [mscorlib]System.Int32 + IL_000b: call string [mscorlib]System.String::Concat(object, + object) + IL_0010: call void [mscorlib]System.Console::WriteLine(string) + IL_0015: ldarg.0 + IL_0016: stloc.0 + IL_0017: ldloc.0 + IL_0018: ldc.i4.1 + IL_0019: sub + IL_001a: switch ( + IL_0031, + IL_003d, + IL_0047, + IL_0052) + IL_002f: br.s IL_005d + + IL_0031: ldstr "one" + IL_0036: call void [mscorlib]System.Console::WriteLine(string) + IL_003b: br.s IL_005d + + IL_003d: ldstr "two" + IL_0042: call void [mscorlib]System.Console::WriteLine(string) + IL_0047: ldstr "three" + IL_004c: call void [mscorlib]System.Console::WriteLine(string) + IL_0051: ret + + IL_0052: ldstr "four" + IL_0057: call void [mscorlib]System.Console::WriteLine(string) + IL_005c: ret + + IL_005d: ldstr "default" + IL_0062: call void [mscorlib]System.Console::WriteLine(string) + IL_0067: ret + } // end of method Switch::SwitchWithGoto + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch/SetProperty[] GetProperties() cil managed { @@ -597,7 +845,7 @@ IL_0031: brfalse IL_0119 IL_0036: volatile. - IL_0038: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000008-1' + IL_0038: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x600000d-1' IL_003d: brtrue.s IL_0094 IL_003f: ldc.i4.6 @@ -633,9 +881,9 @@ IL_0088: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_008d: volatile. - IL_008f: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000008-1' + IL_008f: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x600000d-1' IL_0094: volatile. - IL_0096: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{64CCBA80-944A-4F77-9230-24B174DEE22A}'::'$$method0x6000008-1' + IL_0096: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}'::'$$method0x600000d-1' IL_009b: ldloc.s V_6 IL_009d: ldloca.s V_7 IL_009f: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -707,17 +955,17 @@ } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch -.class private auto ansi '{64CCBA80-944A-4F77-9230-24B174DEE22A}' +.class private auto ansi '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}' extends [mscorlib]System.Object { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000003-1' - .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000004-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000007-1' .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000008-1' -} // end of class '{64CCBA80-944A-4F77-9230-24B174DEE22A}' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x600000d-1' +} // end of class '{6837A40E-7A00-4F01-B2D7-DE0001F70EDF}' // ============================================================= // *********** DISASSEMBLY COMPLETE *********************** -// WARNING: Created Win32 resource file ../../../TestCases/Pretty\Switch.opt.res +// Warnung: Win32-Ressourcendatei "../../../TestCases/Pretty\Switch.opt.res" wurde erstellt. diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il index 48993c1fe..bd0488bb3 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il @@ -1,6 +1,6 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929 -// Copyright (c) Microsoft Corporation. All rights reserved. +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. Alle Rechte vorbehalten. @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module Switch.dll -// MVID: {25FC064E-F764-4556-A3C7-F6570E457CDD} +// MVID: {04DBCBA6-8175-41CD-8917-9428C9765986} .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: 0x00B30000 +// Image base: 0x00830000 // =============== CLASS MEMBERS DECLARATION =================== @@ -185,6 +185,214 @@ IL_00b8: ret } // end of method Switch::SparseIntegerSwitch + .method public hidebysig static string + SwitchOverNullableInt(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 63 (0x3f) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + int32 V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0009: brfalse.s IL_0021 + + IL_000b: ldloca.s V_0 + IL_000d: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: brfalse.s IL_0027 + + IL_0016: ldloc.1 + IL_0017: ldc.i4.5 + IL_0018: beq.s IL_002d + + IL_001a: ldloc.1 + IL_001b: ldc.i4.s 10 + IL_001d: beq.s IL_0033 + + IL_001f: br.s IL_0039 + + IL_0021: ldstr "null" + IL_0026: ret + + IL_0027: ldstr "zero" + IL_002c: ret + + IL_002d: ldstr "five" + IL_0032: ret + + IL_0033: ldstr "ten" + IL_0038: ret + + IL_0039: ldstr "large" + IL_003e: ret + } // end of method Switch::SwitchOverNullableInt + + .method public hidebysig static string + SwitchOverNullableIntShifted(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 98 (0x62) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + valuetype [mscorlib]System.Nullable`1 V_2, + int32 V_3) + IL_0000: ldarg.0 + IL_0001: stloc.1 + IL_0002: ldloca.s V_1 + IL_0004: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0009: brtrue.s IL_0016 + + IL_000b: ldloca.s V_2 + IL_000d: initobj valuetype [mscorlib]System.Nullable`1 + IL_0013: ldloc.2 + IL_0014: br.s IL_0024 + + IL_0016: ldloca.s V_1 + IL_0018: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_001d: ldc.i4.5 + IL_001e: add + IL_001f: newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + IL_0024: stloc.0 + IL_0025: ldloca.s V_0 + IL_0027: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_002c: brfalse.s IL_0044 + + IL_002e: ldloca.s V_0 + IL_0030: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0035: stloc.3 + IL_0036: ldloc.3 + IL_0037: brfalse.s IL_004a + + IL_0039: ldloc.3 + IL_003a: ldc.i4.5 + IL_003b: beq.s IL_0050 + + IL_003d: ldloc.3 + IL_003e: ldc.i4.s 10 + IL_0040: beq.s IL_0056 + + IL_0042: br.s IL_005c + + IL_0044: ldstr "null" + IL_0049: ret + + IL_004a: ldstr "zero" + IL_004f: ret + + IL_0050: ldstr "five" + IL_0055: ret + + IL_0056: ldstr "ten" + IL_005b: ret + + IL_005c: ldstr "large" + IL_0061: ret + } // end of method Switch::SwitchOverNullableIntShifted + + .method public hidebysig static string + SwitchOverNullableIntNoNullCase(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 57 (0x39) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + int32 V_1) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloca.s V_0 + IL_0004: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0009: brfalse.s IL_0033 + + IL_000b: ldloca.s V_0 + IL_000d: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: brfalse.s IL_0021 + + IL_0016: ldloc.1 + IL_0017: ldc.i4.5 + IL_0018: beq.s IL_0027 + + IL_001a: ldloc.1 + IL_001b: ldc.i4.s 10 + IL_001d: beq.s IL_002d + + IL_001f: br.s IL_0033 + + IL_0021: ldstr "zero" + IL_0026: ret + + IL_0027: ldstr "five" + IL_002c: ret + + IL_002d: ldstr "ten" + IL_0032: ret + + IL_0033: ldstr "other" + IL_0038: ret + } // end of method Switch::SwitchOverNullableIntNoNullCase + + .method public hidebysig static string + SwitchOverNullableIntNoNullCaseShifted(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 92 (0x5c) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + valuetype [mscorlib]System.Nullable`1 V_2, + int32 V_3) + IL_0000: ldarg.0 + IL_0001: stloc.1 + IL_0002: ldloca.s V_1 + IL_0004: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_0009: brtrue.s IL_0016 + + IL_000b: ldloca.s V_2 + IL_000d: initobj valuetype [mscorlib]System.Nullable`1 + IL_0013: ldloc.2 + IL_0014: br.s IL_0024 + + IL_0016: ldloca.s V_1 + IL_0018: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_001d: ldc.i4.5 + IL_001e: add + IL_001f: newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + IL_0024: stloc.0 + IL_0025: ldloca.s V_0 + IL_0027: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_002c: brfalse.s IL_0056 + + IL_002e: ldloca.s V_0 + IL_0030: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0035: stloc.3 + IL_0036: ldloc.3 + IL_0037: brfalse.s IL_0044 + + IL_0039: ldloc.3 + IL_003a: ldc.i4.5 + IL_003b: beq.s IL_004a + + IL_003d: ldloc.3 + IL_003e: ldc.i4.s 10 + IL_0040: beq.s IL_0050 + + IL_0042: br.s IL_0056 + + IL_0044: ldstr "zero" + IL_0049: ret + + IL_004a: ldstr "five" + IL_004f: ret + + IL_0050: ldstr "ten" + IL_0055: ret + + IL_0056: ldstr "other" + IL_005b: ret + } // end of method Switch::SwitchOverNullableIntNoNullCaseShifted + .method public hidebysig static string ShortSwitchOverString(string text) cil managed { @@ -659,6 +867,45 @@ IL_0078: br.s IL_0015 } // end of method Switch::SwitchInLoop + .method public hidebysig static void SwitchWithGoto(int32 i) cil managed + { + // Code size 102 (0x66) + .maxstack 2 + IL_0000: ldstr "SwitchWithGoto: " + IL_0005: ldarg.0 + IL_0006: box [mscorlib]System.Int32 + IL_000b: call string [mscorlib]System.String::Concat(object, + object) + IL_0010: call void [mscorlib]System.Console::WriteLine(string) + IL_0015: ldarg.0 + IL_0016: ldc.i4.1 + IL_0017: sub + IL_0018: switch ( + IL_002f, + IL_003b, + IL_0045, + IL_0050) + IL_002d: br.s IL_005b + + IL_002f: ldstr "one" + IL_0034: call void [mscorlib]System.Console::WriteLine(string) + IL_0039: br.s IL_005b + + IL_003b: ldstr "two" + IL_0040: call void [mscorlib]System.Console::WriteLine(string) + IL_0045: ldstr "three" + IL_004a: call void [mscorlib]System.Console::WriteLine(string) + IL_004f: ret + + IL_0050: ldstr "four" + IL_0055: call void [mscorlib]System.Console::WriteLine(string) + IL_005a: ret + + IL_005b: ldstr "default" + IL_0060: call void [mscorlib]System.Console::WriteLine(string) + IL_0065: ret + } // end of method Switch::SwitchWithGoto + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch/SetProperty[] GetProperties() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il index 4da071b46..38331d470 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il @@ -1,6 +1,6 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17929 -// Copyright (c) Microsoft Corporation. All rights reserved. +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. Alle Rechte vorbehalten. @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module Switch.dll -// MVID: {134EA2E4-FA5A-4D44-A0FD-C4E5A18E39B1} +// MVID: {87DEBC09-DFAD-437D-9221-109E2117A07A} .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: 0x00C40000 +// Image base: 0x02960000 // =============== CLASS MEMBERS DECLARATION =================== @@ -229,6 +229,298 @@ IL_00ed: ret } // end of method Switch::SparseIntegerSwitch + .method public hidebysig static string + SwitchOverNullableInt(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 87 (0x57) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + int32 V_2, + string V_3) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.1 + IL_0003: ldloc.1 + IL_0004: stloc.0 + IL_0005: ldloca.s V_0 + IL_0007: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000c: brfalse.s IL_0028 + + IL_000e: ldloca.s V_0 + IL_0010: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0015: stloc.2 + IL_0016: ldloc.2 + IL_0017: brfalse.s IL_0031 + + IL_0019: br.s IL_001b + + IL_001b: ldloc.2 + IL_001c: ldc.i4.5 + IL_001d: beq.s IL_003a + + IL_001f: br.s IL_0021 + + IL_0021: ldloc.2 + IL_0022: ldc.i4.s 10 + IL_0024: beq.s IL_0043 + + IL_0026: br.s IL_004c + + IL_0028: nop + IL_0029: ldstr "null" + IL_002e: stloc.3 + IL_002f: br.s IL_0055 + + IL_0031: nop + IL_0032: ldstr "zero" + IL_0037: stloc.3 + IL_0038: br.s IL_0055 + + IL_003a: nop + IL_003b: ldstr "five" + IL_0040: stloc.3 + IL_0041: br.s IL_0055 + + IL_0043: nop + IL_0044: ldstr "ten" + IL_0049: stloc.3 + IL_004a: br.s IL_0055 + + IL_004c: nop + IL_004d: ldstr "large" + IL_0052: stloc.3 + IL_0053: br.s IL_0055 + + IL_0055: ldloc.3 + IL_0056: ret + } // end of method Switch::SwitchOverNullableInt + + .method public hidebysig static string + SwitchOverNullableIntShifted(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 132 (0x84) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + valuetype [mscorlib]System.Nullable`1 V_2, + valuetype [mscorlib]System.Nullable`1 V_3, + int32 V_4, + string V_5) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.2 + IL_0003: ldloca.s V_2 + IL_0005: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000a: brtrue.s IL_0017 + + IL_000c: ldloca.s V_3 + IL_000e: initobj valuetype [mscorlib]System.Nullable`1 + IL_0014: ldloc.3 + IL_0015: br.s IL_0025 + + IL_0017: ldloca.s V_2 + IL_0019: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_001e: ldc.i4.5 + IL_001f: add + IL_0020: newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + IL_0025: stloc.1 + IL_0026: ldloc.1 + IL_0027: stloc.0 + IL_0028: ldloca.s V_0 + IL_002a: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_002f: brfalse.s IL_004f + + IL_0031: ldloca.s V_0 + IL_0033: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0038: stloc.s V_4 + IL_003a: ldloc.s V_4 + IL_003c: brfalse.s IL_0059 + + IL_003e: br.s IL_0040 + + IL_0040: ldloc.s V_4 + IL_0042: ldc.i4.5 + IL_0043: beq.s IL_0063 + + IL_0045: br.s IL_0047 + + IL_0047: ldloc.s V_4 + IL_0049: ldc.i4.s 10 + IL_004b: beq.s IL_006d + + IL_004d: br.s IL_0077 + + IL_004f: nop + IL_0050: ldstr "null" + IL_0055: stloc.s V_5 + IL_0057: br.s IL_0081 + + IL_0059: nop + IL_005a: ldstr "zero" + IL_005f: stloc.s V_5 + IL_0061: br.s IL_0081 + + IL_0063: nop + IL_0064: ldstr "five" + IL_0069: stloc.s V_5 + IL_006b: br.s IL_0081 + + IL_006d: nop + IL_006e: ldstr "ten" + IL_0073: stloc.s V_5 + IL_0075: br.s IL_0081 + + IL_0077: nop + IL_0078: ldstr "large" + IL_007d: stloc.s V_5 + IL_007f: br.s IL_0081 + + IL_0081: ldloc.s V_5 + IL_0083: ret + } // end of method Switch::SwitchOverNullableIntShifted + + .method public hidebysig static string + SwitchOverNullableIntNoNullCase(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 78 (0x4e) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + int32 V_2, + string V_3) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.1 + IL_0003: ldloc.1 + IL_0004: stloc.0 + IL_0005: ldloca.s V_0 + IL_0007: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000c: brfalse.s IL_0043 + + IL_000e: ldloca.s V_0 + IL_0010: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0015: stloc.2 + IL_0016: ldloc.2 + IL_0017: brfalse.s IL_0028 + + IL_0019: br.s IL_001b + + IL_001b: ldloc.2 + IL_001c: ldc.i4.5 + IL_001d: beq.s IL_0031 + + IL_001f: br.s IL_0021 + + IL_0021: ldloc.2 + IL_0022: ldc.i4.s 10 + IL_0024: beq.s IL_003a + + IL_0026: br.s IL_0043 + + IL_0028: nop + IL_0029: ldstr "zero" + IL_002e: stloc.3 + IL_002f: br.s IL_004c + + IL_0031: nop + IL_0032: ldstr "five" + IL_0037: stloc.3 + IL_0038: br.s IL_004c + + IL_003a: nop + IL_003b: ldstr "ten" + IL_0040: stloc.3 + IL_0041: br.s IL_004c + + IL_0043: nop + IL_0044: ldstr "other" + IL_0049: stloc.3 + IL_004a: br.s IL_004c + + IL_004c: ldloc.3 + IL_004d: ret + } // end of method Switch::SwitchOverNullableIntNoNullCase + + .method public hidebysig static string + SwitchOverNullableIntNoNullCaseShifted(valuetype [mscorlib]System.Nullable`1 i) cil managed + { + // Code size 122 (0x7a) + .maxstack 2 + .locals init (valuetype [mscorlib]System.Nullable`1 V_0, + valuetype [mscorlib]System.Nullable`1 V_1, + valuetype [mscorlib]System.Nullable`1 V_2, + valuetype [mscorlib]System.Nullable`1 V_3, + int32 V_4, + string V_5) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.2 + IL_0003: ldloca.s V_2 + IL_0005: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_000a: brtrue.s IL_0017 + + IL_000c: ldloca.s V_3 + IL_000e: initobj valuetype [mscorlib]System.Nullable`1 + IL_0014: ldloc.3 + IL_0015: br.s IL_0025 + + IL_0017: ldloca.s V_2 + IL_0019: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_001e: ldc.i4.5 + IL_001f: add + IL_0020: newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + IL_0025: stloc.1 + IL_0026: ldloc.1 + IL_0027: stloc.0 + IL_0028: ldloca.s V_0 + IL_002a: call instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue() + IL_002f: brfalse.s IL_006d + + IL_0031: ldloca.s V_0 + IL_0033: call instance !0 valuetype [mscorlib]System.Nullable`1::GetValueOrDefault() + IL_0038: stloc.s V_4 + IL_003a: ldloc.s V_4 + IL_003c: brfalse.s IL_004f + + IL_003e: br.s IL_0040 + + IL_0040: ldloc.s V_4 + IL_0042: ldc.i4.5 + IL_0043: beq.s IL_0059 + + IL_0045: br.s IL_0047 + + IL_0047: ldloc.s V_4 + IL_0049: ldc.i4.s 10 + IL_004b: beq.s IL_0063 + + IL_004d: br.s IL_006d + + IL_004f: nop + IL_0050: ldstr "zero" + IL_0055: stloc.s V_5 + IL_0057: br.s IL_0077 + + IL_0059: nop + IL_005a: ldstr "five" + IL_005f: stloc.s V_5 + IL_0061: br.s IL_0077 + + IL_0063: nop + IL_0064: ldstr "ten" + IL_0069: stloc.s V_5 + IL_006b: br.s IL_0077 + + IL_006d: nop + IL_006e: ldstr "other" + IL_0073: stloc.s V_5 + IL_0075: br.s IL_0077 + + IL_0077: ldloc.s V_5 + IL_0079: ret + } // end of method Switch::SwitchOverNullableIntNoNullCaseShifted + .method public hidebysig static string ShortSwitchOverString(string text) cil managed { @@ -844,6 +1136,64 @@ IL_0091: ret } // end of method Switch::SwitchInLoop + .method public hidebysig static void SwitchWithGoto(int32 i) cil managed + { + // Code size 122 (0x7a) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "SwitchWithGoto: " + IL_0006: ldarg.0 + IL_0007: box [mscorlib]System.Int32 + IL_000c: call string [mscorlib]System.String::Concat(object, + object) + IL_0011: call void [mscorlib]System.Console::WriteLine(string) + IL_0016: nop + IL_0017: ldarg.0 + IL_0018: stloc.0 + IL_0019: ldloc.0 + IL_001a: ldc.i4.1 + IL_001b: sub + IL_001c: switch ( + IL_0033, + IL_0041, + IL_004f, + IL_005d) + IL_0031: br.s IL_006b + + IL_0033: nop + IL_0034: ldstr "one" + IL_0039: call void [mscorlib]System.Console::WriteLine(string) + IL_003e: nop + IL_003f: br.s IL_006b + + IL_0041: nop + IL_0042: ldstr "two" + IL_0047: call void [mscorlib]System.Console::WriteLine(string) + IL_004c: nop + IL_004d: br.s IL_004f + + IL_004f: nop + IL_0050: ldstr "three" + IL_0055: call void [mscorlib]System.Console::WriteLine(string) + IL_005a: nop + IL_005b: br.s IL_0079 + + IL_005d: nop + IL_005e: ldstr "four" + IL_0063: call void [mscorlib]System.Console::WriteLine(string) + IL_0068: nop + IL_0069: br.s IL_0079 + + IL_006b: nop + IL_006c: ldstr "default" + IL_0071: call void [mscorlib]System.Console::WriteLine(string) + IL_0076: nop + IL_0077: br.s IL_0079 + + IL_0079: ret + } // end of method Switch::SwitchWithGoto + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch/SetProperty[] GetProperties() cil managed { diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs index 30005e06b..f2e3107b2 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnNullableTransform.cs @@ -48,6 +48,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms changed = true; continue; } + if (MatchRoslynSwitchOnNullable(block.Instructions, i, out newSwitch)) { + block.Instructions[i - 1].ReplaceWith(newSwitch); + block.Instructions.RemoveRange(i, 2); + i--; + changed = true; + continue; + } } if (!changed) continue; SwitchDetection.SimplifySwitchInstruction(block); @@ -59,6 +66,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms container.SortBlocks(deleteUnreachableBlocks: true); } + /// + /// Matches legacy C# switch on nullable. + /// bool MatchSwitchOnNullable(InstructionCollection instructions, int i, out SwitchInstruction newSwitch) { newSwitch = null; @@ -113,5 +123,55 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return true; } + + /// + /// Matches Roslyn C# switch on nullable. + /// + bool MatchRoslynSwitchOnNullable(InstructionCollection instructions, int i, out SwitchInstruction newSwitch) + { + newSwitch = null; + // match first block: + // stloc tmp(ldloc switchValueVar) + // if (logic.not(call get_HasValue(ldloca tmp))) br nullCaseBlock + // br switchBlock + if (i < 1) return false; + if (!instructions[i - 1].MatchStLoc(out var tmp, out var switchValue) || + !instructions[i].MatchIfInstruction(out var condition, out var trueInst)) + return false; + if (!instructions[i + 1].MatchBranch(out var switchBlock) || !trueInst.MatchBranch(out var nullCaseBlock)) + return false; + if (!condition.MatchLogicNot(out var getHasValue) || !NullableLiftingTransform.MatchHasValueCall(getHasValue, out var target1) || target1 != tmp) + return false; + // match second block: switchBlock + // stloc switchVar(call GetValueOrDefault(ldloca tmp)) + // switch (ldloc switchVar) { + // case [0..1): br caseBlock1 + // ... more cases ... + // case [long.MinValue..0),[1..5),[6..10),[11..long.MaxValue]: br defaultBlock + // } + if (switchBlock.Instructions.Count != 2 || switchBlock.IncomingEdgeCount != 1) + return false; + if (!switchBlock.Instructions[0].MatchStLoc(out var switchVar, out var getValueOrDefault)) + return false; + if (!NullableLiftingTransform.MatchGetValueOrDefault(getValueOrDefault, out var target2) || target2 != tmp) + return false; + if (!(switchBlock.Instructions[1] is SwitchInstruction switchInst)) + return false; + newSwitch = new SwitchInstruction(switchValue); + newSwitch.IsLifted = true; + SwitchSection defaultSection = null; + foreach (var section in switchInst.Sections) { + if (defaultSection == null || section.Labels.Count() >= defaultSection.Labels.Count()) + defaultSection = section; + newSwitch.Sections.Add(section); + } + if (defaultSection.Body.MatchBranch(out var defaultBlock) && defaultBlock == nullCaseBlock) + defaultSection.HasNullLabel = true; + else { + newSwitch.Sections.Add(new SwitchSection { Body = new Branch(nullCaseBlock), HasNullLabel = true }); + } + return true; + } + } }