diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs index c156299b2..285f3a86c 100644 --- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs @@ -121,7 +121,10 @@ namespace ICSharpCode.Decompiler.Tests [Test] public void Switch([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions) { - RunForLibrary(cscOptions: cscOptions); + RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings { + // legacy csc generates a dead store in debug builds + RemoveDeadCode = (cscOptions == CSharpCompilerOptions.None) + }); } [Test] diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs index 7e71ca0f5..3bb096a87 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -105,6 +106,40 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public static void SparseIntegerSwitch2(int i) + { + switch (i) { + case 4: + case 10: + case 11: + case 13: + case 21: + case 29: + case 33: + case 49: + case 50: + case 55: + Console.WriteLine(); + break; + } + } + + public static bool SparseIntegerSwitch3(int i) + { + switch (i) { + case 0: + case 10: + case 11: + case 12: + case 100: + case 101: + case 200: + return true; + default: + return false; + } + } + public static string SwitchOverNullableInt(int? i) { switch (i) { @@ -222,6 +257,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + // SwitchDetection.UseCSharpSwitch requires more complex heuristic to identify this when compiled with Roslyn + public static void CompactSwitchOverInt(int i) + { + switch (i) { + case 0: + case 1: + case 2: + Console.WriteLine("012"); + break; + case 3: + Console.WriteLine("3"); + break; + default: + Console.WriteLine("default"); + break; + } + Console.WriteLine("end"); + } + public static string ShortSwitchOverString(string text) { Console.WriteLine("ShortSwitchOverString: " + text); @@ -369,6 +423,85 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty Console.WriteLine("End of method"); } + // Needs to be long enough to generate a hashtable + public static void SwitchWithGotoString(string s) + { + Console.WriteLine("SwitchWithGotoString: " + s); + switch (s) { + 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; + case "5": + Console.WriteLine("five"); + return; + case "6": + Console.WriteLine("six"); + return; + case "7": + Console.WriteLine("seven"); + return; + case "8": + Console.WriteLine("eight"); + return; + case "9": + Console.WriteLine("nine"); + return; + default: + Console.WriteLine("default"); + break; + } + Console.WriteLine("End of method"); + } + + public static void SwitchWithGotoComplex(string s) + { + Console.WriteLine("SwitchWithGotoComplex: " + s); + switch (s) { + case "1": + Console.WriteLine("one"); + goto case "8"; + case "2": + Console.WriteLine("two"); + goto case "3"; + case "3": + Console.WriteLine("three"); + if (s.Length != 2) { + break; + } + goto case "5"; + case "4": + Console.WriteLine("four"); + goto case "5"; + case "5": + Console.WriteLine("five"); + goto case "8"; + case "6": + Console.WriteLine("six"); + goto case "5"; + case "8": + Console.WriteLine("eight"); + return; + // add a default case so that case "7": isn't redundant + default: + Console.WriteLine("default"); + break; + // note that goto case "7" will decompile as break; + // cases with a single break have the highest IL offset and are moved to the bottom + case "7": + break; + } + Console.WriteLine("End of method"); + } + private static SetProperty[] GetProperties() { return new SetProperty[0]; @@ -447,5 +580,537 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } Console.WriteLine("end"); } + + public static void SwitchWithContinue1(int i, bool b) + { + while (true) { + switch (i) { +#if OPT + case 1: + continue; +#endif + case 0: + if (b) { + continue; + } + break; + case 2: + if (!b) { + continue; + } + break; +#if !OPT + case 1: + continue; +#endif + } + Console.WriteLine(); + } + } + + // while condition, return and break cases + public static void SwitchWithContinue2(int i, bool b) + { + while (i < 10) { + switch (i) { + case 0: + if (b) { + Console.WriteLine("0b"); + continue; + } + Console.WriteLine("0!b"); + break; + case 2: +#if OPT + if (b) { + Console.WriteLine("2b"); + return; + } + Console.WriteLine("2!b"); + continue; +#else + if (!b) { + Console.WriteLine("2!b"); + continue; + } + Console.WriteLine("2b"); + return; +#endif + default: + Console.WriteLine("default"); + break; + case 3: + break; + case 1: + continue; + } + Console.WriteLine("loop-tail"); + i++; + } + } + + // for loop version + public static void SwitchWithContinue3(bool b) + { + for (int i = 0; i < 10; i++) { + switch (i) { + case 0: + if (b) { + Console.WriteLine("0b"); + continue; + } + Console.WriteLine("0!b"); + break; + case 2: +#if OPT + if (b) { + Console.WriteLine("2b"); + return; + } + Console.WriteLine("2!b"); + continue; +#else + if (!b) { + Console.WriteLine("2!b"); + continue; + } + Console.WriteLine("2b"); + return; +#endif + default: + Console.WriteLine("default"); + break; + case 3: + break; + case 1: + continue; + } + Console.WriteLine("loop-tail"); + } + } + + // foreach version + public static void SwitchWithContinue4(bool b) + { + foreach (int item in Enumerable.Range(0, 10)) { + Console.WriteLine("loop: " + item); + switch (item) { + case 1: + if (b) { + continue; + } + break; + case 3: + if (!b) { + continue; + } + return; + case 4: + Console.WriteLine(4); + goto case 7; + case 5: + Console.WriteLine(5); + goto default; + case 6: + if (b) { + continue; + } + goto case 3; + case 7: + if (item % 2 == 0) { + goto case 3; + } + if (!b) { + continue; + } + goto case 8; + case 8: + if (b) { + continue; + } + goto case 5; + default: + Console.WriteLine("default"); + break; + case 2: + continue; + } + Console.WriteLine("break: " + item); + } + } + // internal if statement, loop increment block not dominated by the switch head + public static void SwitchWithContinue5(bool b) + { + for (int i = 0; i < 10; i++) { + if (i < 5) { + switch (i) { + case 0: + if (b) { + Console.WriteLine("0b"); + continue; + } + Console.WriteLine("0!b"); + break; + case 2: +#if OPT + if (b) { + Console.WriteLine("2b"); + return; + } + Console.WriteLine("2!b"); + continue; +#else + if (!b) { + Console.WriteLine("2!b"); + continue; + } + Console.WriteLine("2b"); + return; +#endif + default: + Console.WriteLine("default"); + break; + case 3: + break; + case 1: + continue; + } + Console.WriteLine("break-target"); + } + Console.WriteLine("loop-tail"); + } + } + + // do-while loop version + public static void SwitchWithContinue6(int i, bool b) + { + do { + switch (i) { + case 0: + if (!b) { + Console.WriteLine("0!b"); + break; + } + Console.WriteLine("0b"); + // ConditionDetection doesn't recognise Do-While continues yet + continue; + case 2: + if (b) { + Console.WriteLine("2b"); + return; + } + Console.WriteLine("2!b"); + continue; + default: + Console.WriteLine("default"); + break; + case 3: + break; + case 1: + continue; + } + Console.WriteLine("loop-tail"); + } while (++i < 10); + } + + // double break from switch to loop exit requires additional pattern matching in HighLevelLoopTransform + public static void SwitchWithContinue7() + { + for (int num = 0; num >= 0; num--) { + Console.WriteLine("loop-head"); + switch (num) { + default: + Console.WriteLine("default"); + break; + case 0: + continue; + case 1: + break; + } + break; + } + Console.WriteLine("end"); + } + + public static void SwitchWithContinueInDoubleLoop() + { + bool value = false; + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + switch (i + j) { + case 1: + case 3: + case 5: + case 7: + case 11: + case 13: + case 17: + break; + default: + continue; + } + value = true; + break; + } + } + Console.WriteLine(value); + } + + public static void SwitchLoopNesting() + { + for (int i = 0; i < 10; i++) { + switch (i) { + case 0: + Console.WriteLine(0); + break; + case 1: + Console.WriteLine(1); + break; + default: + if (i % 2 == 0) { + while (i % 3 != 0) { + Console.WriteLine(i++); + } + } + Console.WriteLine(); + break; + } + + if (i > 4) { + Console.WriteLine("high"); + } else { + Console.WriteLine("low"); + } + } + } + + // These decompile poorly into switch statements and should be left as is + #region Overagressive Switch Use + + #if ROSLYN || OPT + public static void SingleIf1(int i, bool a) + { + if (i == 1 || (i == 2 && a)) { + Console.WriteLine(1); + } + Console.WriteLine(2); + } + #endif + + public static void SingleIf2(int i, bool a, bool b) + { + if (i == 1 || (i == 2 && a) || (i == 3 && b)) { + Console.WriteLine(1); + } + Console.WriteLine(2); + } + + public static void SingleIf3(int i, bool a, bool b) + { + if (a || i == 1 || (i == 2 && b)) { + Console.WriteLine(1); + } + Console.WriteLine(2); + } + + public static void SingleIf4(int i, bool a) + { + if (i == 1 || i == 2 || (i != 3 && a) || i != 4) { + Console.WriteLine(1); + } + Console.WriteLine(2); + } + + public static void NestedIf(int i) + { + if (i != 1) { + if (i == 2) { + Console.WriteLine(2); + } + Console.WriteLine("default"); + } + Console.WriteLine(); + } + + public static void IfChainWithCondition(int i) + { + if (i == 0) { + Console.WriteLine(0); + } else if (i == 1) { + Console.WriteLine(1); + } else if (i == 2) { + Console.WriteLine(2); + } else if (i == 3) { + Console.WriteLine(3); + } else if (i == 4) { + Console.WriteLine(4); + } else if (i == 5 && Console.CapsLock) { + Console.WriteLine("5A"); + } else { + Console.WriteLine("default"); + } + + Console.WriteLine(); + } + + public static bool SwitchlikeIf(int i, int j) + { + if (i != 0 && j != 0) { + if (i == -1 && j == -1) { + Console.WriteLine("-1, -1"); + } + if (i == -1 && j == 1) { + Console.WriteLine("-1, 1"); + } + if (i == 1 && j == -1) { + Console.WriteLine("1, -1"); + } + if (i == 1 && j == 1) { + Console.WriteLine("1, 1"); + } + return false; + } + + if (i != 0) { + if (i == -1) { + Console.WriteLine("-1, 0"); + } + if (i == 1) { + Console.WriteLine("1, 0"); + } + return false; + } + + if (j != 0) { + if (j == -1) { + Console.WriteLine("0, -1"); + } + if (j == 1) { + Console.WriteLine("0, 1"); + } + return false; + } + + return true; + } + + public static bool SwitchlikeIf2(int i) + { + if (i != 0) { + // note that using else-if in this chain creates a nice-looking switch here (as expected) + if (i == 1) { + Console.WriteLine(1); + } + if (i == 2) { + Console.WriteLine(2); + } + if (i == 3) { + Console.WriteLine(3); + } + return false; + } + return false; + } + + public static void SingleIntervalIf(char c) + { + if (c >= 'A' && c <= 'Z') { + Console.WriteLine("alphabet"); + } + Console.WriteLine("end"); + } + + public static bool Loop8(char c, bool b, Func getChar) + { + if (b) { + while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + c = getChar(); + } + } + + return true; + } + + public static void Loop9(Func getChar) + { + char c; + do { + c = getChar(); + } while (c != -1 && c != '\n' && c != '\u2028' && c != '\u2029'); + } + #endregion + + // Ensure correctness of SwitchDetection.UseCSharpSwitch control flow heuristics + public static void SwitchWithBreakCase(int i, bool b) + { + if (b) { + switch (i) { + case 1: + Console.WriteLine(1); + break; + default: + Console.WriteLine("default"); + break; + case 2: + break; + } + Console.WriteLine("b"); + } + Console.WriteLine("end"); + } + + public static void SwitchWithReturnAndBreak(int i, bool b) + { + switch (i) { + case 0: + if (b) { + return; + } + break; + case 1: + if (!b) { + return; + } + break; + } + Console.WriteLine(); + } + + public static int SwitchWithReturnAndBreak2(int i, bool b) + { + switch (i) { + case 4: + case 33: + Console.WriteLine(); + return 1; + case 334: + if (b) { + return 2; + } + break; + case 395: + case 410: + case 455: + Console.WriteLine(); + break; + } + Console.WriteLine(); + return 0; + } + + public static void SwitchWithReturnAndBreak3(int i) + { + switch (i) { + default: + return; + case 0: + Console.WriteLine(0); + break; + case 1: + Console.WriteLine(1); + break; + } + Console.WriteLine(); + } } } \ No newline at end of file diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il index 476dbee82..5f70f6ec0 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il @@ -8,6 +8,11 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } +.assembly extern System.Core +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} .assembly Switch { .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 @@ -293,6 +298,119 @@ IL_00d0: ret } // end of method Switch::SparseIntegerSwitch + .method public hidebysig static void SparseIntegerSwitch2(int32 i) cil managed + { + // Code size 94 (0x5e) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: ldc.i4.s 21 + IL_0006: bgt.s IL_002c + + IL_0008: ldloc.0 + IL_0009: ldc.i4.4 + IL_000a: beq.s IL_0055 + + IL_000c: ldloc.0 + IL_000d: ldc.i4.s 10 + IL_000f: sub + IL_0010: switch ( + IL_0055, + IL_0055, + IL_005d, + IL_0055) + IL_0025: ldloc.0 + IL_0026: ldc.i4.s 21 + IL_0028: beq.s IL_0055 + + IL_002a: br.s IL_005d + + IL_002c: ldloc.0 + IL_002d: ldc.i4.s 33 + IL_002f: bgt.s IL_003d + + IL_0031: ldloc.0 + IL_0032: ldc.i4.s 29 + IL_0034: beq.s IL_0055 + + IL_0036: ldloc.0 + IL_0037: ldc.i4.s 33 + IL_0039: beq.s IL_0055 + + IL_003b: br.s IL_005d + + IL_003d: ldloc.0 + IL_003e: ldc.i4.s 49 + IL_0040: sub + IL_0041: switch ( + IL_0055, + IL_0055) + IL_004e: ldloc.0 + IL_004f: ldc.i4.s 55 + IL_0051: beq.s IL_0055 + + IL_0053: br.s IL_005d + + IL_0055: call void [mscorlib]System.Console::WriteLine() + IL_005a: nop + IL_005b: br.s IL_005d + + IL_005d: ret + } // end of method Switch::SparseIntegerSwitch2 + + .method public hidebysig static bool SparseIntegerSwitch3(int32 i) cil managed + { + // Code size 72 (0x48) + .maxstack 2 + .locals init (bool V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.1 + IL_0003: ldloc.1 + IL_0004: ldc.i4.s 12 + IL_0006: bgt.s IL_0023 + + IL_0008: ldloc.1 + IL_0009: ldc.i4.0 + IL_000a: beq.s IL_003e + + IL_000c: ldloc.1 + IL_000d: ldc.i4.s 10 + IL_000f: sub + IL_0010: switch ( + IL_003e, + IL_003e, + IL_003e) + IL_0021: br.s IL_0042 + + IL_0023: ldloc.1 + IL_0024: ldc.i4.s 100 + IL_0026: sub + IL_0027: switch ( + IL_003e, + IL_003e) + IL_0034: ldloc.1 + IL_0035: ldc.i4 0xc8 + IL_003a: beq.s IL_003e + + IL_003c: br.s IL_0042 + + IL_003e: ldc.i4.1 + IL_003f: stloc.0 + IL_0040: br.s IL_0046 + + IL_0042: ldc.i4.0 + IL_0043: stloc.0 + IL_0044: br.s IL_0046 + + IL_0046: ldloc.0 + IL_0047: ret + } // end of method Switch::SparseIntegerSwitch3 + .method public hidebysig static string SwitchOverNullableInt(valuetype [mscorlib]System.Nullable`1 i) cil managed { @@ -743,6 +861,43 @@ IL_008f: ret } // end of method Switch::SwitchOverInt + .method public hidebysig static void CompactSwitchOverInt(int32 i) cil managed + { + // Code size 78 (0x4e) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: switch ( + IL_001b, + IL_001b, + IL_001b, + IL_0028) + IL_0019: br.s IL_0035 + + IL_001b: ldstr "012" + IL_0020: call void [mscorlib]System.Console::WriteLine(string) + IL_0025: nop + IL_0026: br.s IL_0042 + + IL_0028: ldstr "3" + IL_002d: call void [mscorlib]System.Console::WriteLine(string) + IL_0032: nop + IL_0033: br.s IL_0042 + + IL_0035: ldstr "default" + IL_003a: call void [mscorlib]System.Console::WriteLine(string) + IL_003f: nop + IL_0040: br.s IL_0042 + + IL_0042: ldstr "end" + IL_0047: call void [mscorlib]System.Console::WriteLine(string) + IL_004c: nop + IL_004d: ret + } // end of method Switch::CompactSwitchOverInt + .method public hidebysig static string ShortSwitchOverString(string text) cil managed { @@ -876,7 +1031,7 @@ IL_0015: brfalse IL_00e9 IL_001a: volatile. - IL_001c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000d-1' + IL_001c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000010-1' IL_0021: brtrue.s IL_0084 IL_0023: ldc.i4.7 @@ -917,9 +1072,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 ''::'$$method0x600000d-1' + IL_007f: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000010-1' IL_0084: volatile. - IL_0086: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000d-1' + IL_0086: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000010-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, @@ -991,7 +1146,7 @@ IL_0013: brfalse IL_0158 IL_0018: volatile. - IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000e-1' + IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000011-1' IL_001f: brtrue IL_00b8 IL_0024: ldc.i4.s 11 @@ -1052,9 +1207,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 ''::'$$method0x600000e-1' + IL_00b3: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000011-1' IL_00b8: volatile. - IL_00ba: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000e-1' + IL_00ba: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000011-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, @@ -1287,6 +1442,300 @@ IL_007f: ret } // end of method Switch::SwitchWithGoto + .method public hidebysig static void SwitchWithGotoString(string s) cil managed + { + // Code size 363 (0x16b) + .maxstack 4 + .locals init (string V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldstr "SwitchWithGotoString: " + IL_0006: ldarg.0 + IL_0007: call string [mscorlib]System.String::Concat(string, + string) + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: ldarg.0 + IL_0013: stloc.0 + IL_0014: ldloc.0 + IL_0015: brfalse IL_0152 + + IL_001a: volatile. + IL_001c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000015-1' + IL_0021: brtrue.s IL_009d + + IL_0023: ldc.i4.s 9 + IL_0025: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor(int32) + IL_002a: dup + IL_002b: ldstr "1" + IL_0030: ldc.i4.0 + IL_0031: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0036: dup + IL_0037: ldstr "2" + IL_003c: ldc.i4.1 + IL_003d: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0042: dup + IL_0043: ldstr "3" + IL_0048: ldc.i4.2 + IL_0049: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_004e: dup + IL_004f: ldstr "4" + IL_0054: ldc.i4.3 + IL_0055: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_005a: dup + IL_005b: ldstr "5" + IL_0060: ldc.i4.4 + IL_0061: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0066: dup + IL_0067: ldstr "6" + IL_006c: ldc.i4.5 + IL_006d: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0072: dup + IL_0073: ldstr "7" + IL_0078: ldc.i4.6 + IL_0079: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_007e: dup + IL_007f: ldstr "8" + IL_0084: ldc.i4.7 + IL_0085: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_008a: dup + IL_008b: ldstr "9" + IL_0090: ldc.i4.8 + IL_0091: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0096: volatile. + IL_0098: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000015-1' + IL_009d: volatile. + IL_009f: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000015-1' + IL_00a4: ldloc.0 + IL_00a5: ldloca.s V_1 + IL_00a7: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, + !1&) + IL_00ac: brfalse IL_0152 + + IL_00b1: ldloc.1 + IL_00b2: switch ( + IL_00dd, + IL_00ea, + IL_00f7, + IL_0104, + IL_0111, + IL_011e, + IL_012b, + IL_0138, + IL_0145) + IL_00db: br.s IL_0152 + + IL_00dd: ldstr "one" + IL_00e2: call void [mscorlib]System.Console::WriteLine(string) + IL_00e7: nop + IL_00e8: br.s IL_0152 + + IL_00ea: ldstr "two" + IL_00ef: call void [mscorlib]System.Console::WriteLine(string) + IL_00f4: nop + IL_00f5: br.s IL_00f7 + + IL_00f7: ldstr "three" + IL_00fc: call void [mscorlib]System.Console::WriteLine(string) + IL_0101: nop + IL_0102: br.s IL_015f + + IL_0104: ldstr "four" + IL_0109: call void [mscorlib]System.Console::WriteLine(string) + IL_010e: nop + IL_010f: br.s IL_016a + + IL_0111: ldstr "five" + IL_0116: call void [mscorlib]System.Console::WriteLine(string) + IL_011b: nop + IL_011c: br.s IL_016a + + IL_011e: ldstr "six" + IL_0123: call void [mscorlib]System.Console::WriteLine(string) + IL_0128: nop + IL_0129: br.s IL_016a + + IL_012b: ldstr "seven" + IL_0130: call void [mscorlib]System.Console::WriteLine(string) + IL_0135: nop + IL_0136: br.s IL_016a + + IL_0138: ldstr "eight" + IL_013d: call void [mscorlib]System.Console::WriteLine(string) + IL_0142: nop + IL_0143: br.s IL_016a + + IL_0145: ldstr "nine" + IL_014a: call void [mscorlib]System.Console::WriteLine(string) + IL_014f: nop + IL_0150: br.s IL_016a + + IL_0152: ldstr "default" + IL_0157: call void [mscorlib]System.Console::WriteLine(string) + IL_015c: nop + IL_015d: br.s IL_015f + + IL_015f: ldstr "End of method" + IL_0164: call void [mscorlib]System.Console::WriteLine(string) + IL_0169: nop + IL_016a: ret + } // end of method Switch::SwitchWithGotoString + + .method public hidebysig static void SwitchWithGotoComplex(string s) cil managed + { + // Code size 338 (0x152) + .maxstack 4 + .locals init (string V_0, + int32 V_1, + bool V_2) + IL_0000: nop + IL_0001: ldstr "SwitchWithGotoComplex: " + IL_0006: ldarg.0 + IL_0007: call string [mscorlib]System.String::Concat(string, + string) + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: ldarg.0 + IL_0013: stloc.0 + IL_0014: ldloc.0 + IL_0015: brfalse IL_0137 + + IL_001a: volatile. + IL_001c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000016-1' + IL_0021: brtrue.s IL_0090 + + IL_0023: ldc.i4.8 + IL_0024: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor(int32) + IL_0029: dup + IL_002a: ldstr "1" + IL_002f: ldc.i4.0 + IL_0030: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0035: dup + IL_0036: ldstr "2" + IL_003b: ldc.i4.1 + IL_003c: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0041: dup + IL_0042: ldstr "3" + IL_0047: ldc.i4.2 + IL_0048: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_004d: dup + IL_004e: ldstr "4" + IL_0053: ldc.i4.3 + IL_0054: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0059: dup + IL_005a: ldstr "5" + IL_005f: ldc.i4.4 + IL_0060: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0065: dup + IL_0066: ldstr "6" + IL_006b: ldc.i4.5 + IL_006c: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0071: dup + IL_0072: ldstr "8" + IL_0077: ldc.i4.6 + IL_0078: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_007d: dup + IL_007e: ldstr "7" + IL_0083: ldc.i4.7 + IL_0084: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0089: volatile. + IL_008b: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000016-1' + IL_0090: volatile. + IL_0092: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000016-1' + IL_0097: ldloc.0 + IL_0098: ldloca.s V_1 + IL_009a: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, + !1&) + IL_009f: brfalse IL_0137 + + IL_00a4: ldloc.1 + IL_00a5: switch ( + IL_00cc, + IL_00d9, + IL_00e6, + IL_0103, + IL_0110, + IL_011d, + IL_012a, + IL_0144) + IL_00ca: br.s IL_0137 + + IL_00cc: ldstr "one" + IL_00d1: call void [mscorlib]System.Console::WriteLine(string) + IL_00d6: nop + IL_00d7: br.s IL_012a + + IL_00d9: ldstr "two" + IL_00de: call void [mscorlib]System.Console::WriteLine(string) + IL_00e3: nop + IL_00e4: br.s IL_00e6 + + IL_00e6: ldstr "three" + IL_00eb: call void [mscorlib]System.Console::WriteLine(string) + IL_00f0: nop + IL_00f1: ldarg.0 + IL_00f2: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_00f7: ldc.i4.2 + IL_00f8: ceq + IL_00fa: stloc.2 + IL_00fb: ldloc.2 + IL_00fc: brtrue.s IL_0101 + + IL_00fe: nop + IL_00ff: br.s IL_0146 + + IL_0101: br.s IL_0110 + + IL_0103: ldstr "four" + IL_0108: call void [mscorlib]System.Console::WriteLine(string) + IL_010d: nop + IL_010e: br.s IL_0110 + + IL_0110: ldstr "five" + IL_0115: call void [mscorlib]System.Console::WriteLine(string) + IL_011a: nop + IL_011b: br.s IL_012a + + IL_011d: ldstr "six" + IL_0122: call void [mscorlib]System.Console::WriteLine(string) + IL_0127: nop + IL_0128: br.s IL_0110 + + IL_012a: ldstr "eight" + IL_012f: call void [mscorlib]System.Console::WriteLine(string) + IL_0134: nop + IL_0135: br.s IL_0151 + + IL_0137: ldstr "default" + IL_013c: call void [mscorlib]System.Console::WriteLine(string) + IL_0141: nop + IL_0142: br.s IL_0146 + + IL_0144: br.s IL_0146 + + IL_0146: ldstr "End of method" + IL_014b: call void [mscorlib]System.Console::WriteLine(string) + IL_0150: nop + IL_0151: ret + } // end of method Switch::SwitchWithGotoComplex + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch/SetProperty[] GetProperties() cil managed { @@ -1342,7 +1791,7 @@ IL_003b: brfalse IL_012c IL_0040: volatile. - IL_0042: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000013-1' + IL_0042: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000018-1' IL_0047: brtrue.s IL_009e IL_0049: ldc.i4.6 @@ -1378,9 +1827,9 @@ IL_0092: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_0097: volatile. - IL_0099: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000013-1' + IL_0099: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000018-1' IL_009e: volatile. - IL_00a0: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000013-1' + IL_00a0: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000018-1' IL_00a5: ldloc.s V_5 IL_00a7: ldloca.s V_6 IL_00a9: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -1605,15 +2054,1728 @@ IL_007d: ret } // end of method Switch::SwitchWithArray + .method public hidebysig static void SwitchWithContinue1(int32 i, + bool b) cil managed + { + // Code size 62 (0x3e) + .maxstack 2 + .locals init (int32 V_0, + bool V_1) + IL_0000: nop + IL_0001: br.s IL_003a + + IL_0003: nop + IL_0004: ldarg.0 + IL_0005: stloc.0 + IL_0006: ldloc.0 + IL_0007: switch ( + IL_001a, + IL_0031, + IL_0027) + IL_0018: br.s IL_0033 + + IL_001a: ldarg.1 + IL_001b: ldc.i4.0 + IL_001c: ceq + IL_001e: stloc.1 + IL_001f: ldloc.1 + IL_0020: brtrue.s IL_0025 + + IL_0022: nop + IL_0023: br.s IL_003a + + IL_0025: br.s IL_0033 + + IL_0027: ldarg.1 + IL_0028: stloc.1 + IL_0029: ldloc.1 + IL_002a: brtrue.s IL_002f + + IL_002c: nop + IL_002d: br.s IL_003a + + IL_002f: br.s IL_0033 + + IL_0031: br.s IL_003a + + IL_0033: call void [mscorlib]System.Console::WriteLine() + IL_0038: nop + IL_0039: nop + IL_003a: ldc.i4.1 + IL_003b: stloc.1 + IL_003c: br.s IL_0003 + } // end of method Switch::SwitchWithContinue1 + + .method public hidebysig static void SwitchWithContinue2(int32 i, + bool b) cil managed + { + // Code size 147 (0x93) + .maxstack 2 + .locals init (int32 V_0, + bool V_1) + IL_0000: nop + IL_0001: br IL_0086 + + IL_0006: nop + IL_0007: ldarg.0 + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: switch ( + IL_0021, + IL_0073, + IL_0044, + IL_0071) + IL_001f: br.s IL_0064 + + IL_0021: ldarg.1 + IL_0022: ldc.i4.0 + IL_0023: ceq + IL_0025: stloc.1 + IL_0026: ldloc.1 + IL_0027: brtrue.s IL_0037 + + IL_0029: nop + IL_002a: ldstr "0b" + IL_002f: call void [mscorlib]System.Console::WriteLine(string) + IL_0034: nop + IL_0035: br.s IL_0086 + + IL_0037: ldstr "0!b" + IL_003c: call void [mscorlib]System.Console::WriteLine(string) + IL_0041: nop + IL_0042: br.s IL_0075 + + IL_0044: ldarg.1 + IL_0045: stloc.1 + IL_0046: ldloc.1 + IL_0047: brtrue.s IL_0057 + + IL_0049: nop + IL_004a: ldstr "2!b" + IL_004f: call void [mscorlib]System.Console::WriteLine(string) + IL_0054: nop + IL_0055: br.s IL_0086 + + IL_0057: ldstr "2b" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: nop + IL_0062: br.s IL_0092 + + IL_0064: ldstr "default" + IL_0069: call void [mscorlib]System.Console::WriteLine(string) + IL_006e: nop + IL_006f: br.s IL_0075 + + IL_0071: br.s IL_0075 + + IL_0073: br.s IL_0086 + + IL_0075: ldstr "loop-tail" + IL_007a: call void [mscorlib]System.Console::WriteLine(string) + IL_007f: nop + IL_0080: ldarg.0 + IL_0081: ldc.i4.1 + IL_0082: add + IL_0083: starg.s i + IL_0085: nop + IL_0086: ldarg.0 + IL_0087: ldc.i4.s 10 + IL_0089: clt + IL_008b: stloc.1 + IL_008c: ldloc.1 + IL_008d: brtrue IL_0006 + + IL_0092: ret + } // end of method Switch::SwitchWithContinue2 + + .method public hidebysig static void SwitchWithContinue3(bool b) cil managed + { + // Code size 145 (0x91) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1, + bool V_2) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br.s IL_0084 + + IL_0005: nop + IL_0006: ldloc.0 + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: switch ( + IL_0020, + IL_0072, + IL_0043, + IL_0070) + IL_001e: br.s IL_0063 + + IL_0020: ldarg.0 + IL_0021: ldc.i4.0 + IL_0022: ceq + IL_0024: stloc.2 + IL_0025: ldloc.2 + IL_0026: brtrue.s IL_0036 + + IL_0028: nop + IL_0029: ldstr "0b" + IL_002e: call void [mscorlib]System.Console::WriteLine(string) + IL_0033: nop + IL_0034: br.s IL_0080 + + IL_0036: ldstr "0!b" + IL_003b: call void [mscorlib]System.Console::WriteLine(string) + IL_0040: nop + IL_0041: br.s IL_0074 + + IL_0043: ldarg.0 + IL_0044: stloc.2 + IL_0045: ldloc.2 + IL_0046: brtrue.s IL_0056 + + IL_0048: nop + IL_0049: ldstr "2!b" + IL_004e: call void [mscorlib]System.Console::WriteLine(string) + IL_0053: nop + IL_0054: br.s IL_0080 + + IL_0056: ldstr "2b" + IL_005b: call void [mscorlib]System.Console::WriteLine(string) + IL_0060: nop + IL_0061: br.s IL_0090 + + IL_0063: ldstr "default" + IL_0068: call void [mscorlib]System.Console::WriteLine(string) + IL_006d: nop + IL_006e: br.s IL_0074 + + IL_0070: br.s IL_0074 + + IL_0072: br.s IL_0080 + + IL_0074: ldstr "loop-tail" + IL_0079: call void [mscorlib]System.Console::WriteLine(string) + IL_007e: nop + IL_007f: nop + IL_0080: ldloc.0 + IL_0081: ldc.i4.1 + IL_0082: add + IL_0083: stloc.0 + IL_0084: ldloc.0 + IL_0085: ldc.i4.s 10 + IL_0087: clt + IL_0089: stloc.2 + IL_008a: ldloc.2 + IL_008b: brtrue IL_0005 + + IL_0090: ret + } // end of method Switch::SwitchWithContinue3 + + .method public hidebysig static void SwitchWithContinue4(bool b) cil managed + { + // Code size 263 (0x107) + .maxstack 2 + .locals init (int32 V_0, + class [mscorlib]System.Collections.Generic.IEnumerator`1 V_1, + int32 V_2, + bool V_3) + IL_0000: nop + IL_0001: nop + IL_0002: ldc.i4.0 + IL_0003: ldc.i4.s 10 + IL_0005: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Range(int32, + int32) + IL_000a: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_000f: stloc.1 + .try + { + IL_0010: br IL_00e5 + + IL_0015: ldloc.1 + IL_0016: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() + IL_001b: stloc.0 + IL_001c: nop + IL_001d: ldstr "loop: " + IL_0022: ldloc.0 + IL_0023: box [mscorlib]System.Int32 + IL_0028: call string [mscorlib]System.String::Concat(object, + object) + IL_002d: call void [mscorlib]System.Console::WriteLine(string) + IL_0032: nop + IL_0033: ldloc.0 + IL_0034: stloc.2 + IL_0035: ldloc.2 + IL_0036: ldc.i4.1 + IL_0037: sub + IL_0038: switch ( + IL_005f, + IL_00cc, + IL_006c, + IL_0079, + IL_0082, + IL_008b, + IL_0098, + IL_00b2) + IL_005d: br.s IL_00bf + + IL_005f: ldarg.0 + IL_0060: ldc.i4.0 + IL_0061: ceq + IL_0063: stloc.3 + IL_0064: ldloc.3 + IL_0065: brtrue.s IL_006a + + IL_0067: nop + IL_0068: br.s IL_00e5 + + IL_006a: br.s IL_00ce + + IL_006c: ldarg.0 + IL_006d: stloc.3 + IL_006e: ldloc.3 + IL_006f: brtrue.s IL_0074 + + IL_0071: nop + IL_0072: br.s IL_00e5 + + IL_0074: leave IL_0105 + + IL_0079: ldc.i4.4 + IL_007a: call void [mscorlib]System.Console::WriteLine(int32) + IL_007f: nop + IL_0080: br.s IL_0098 + + IL_0082: ldc.i4.5 + IL_0083: call void [mscorlib]System.Console::WriteLine(int32) + IL_0088: nop + IL_0089: br.s IL_00bf + + IL_008b: ldarg.0 + IL_008c: ldc.i4.0 + IL_008d: ceq + IL_008f: stloc.3 + IL_0090: ldloc.3 + IL_0091: brtrue.s IL_0096 + + IL_0093: nop + IL_0094: br.s IL_00e5 + + IL_0096: br.s IL_006c + + IL_0098: ldloc.0 + IL_0099: ldc.i4.2 + IL_009a: rem + IL_009b: ldc.i4.0 + IL_009c: ceq + IL_009e: ldc.i4.0 + IL_009f: ceq + IL_00a1: stloc.3 + IL_00a2: ldloc.3 + IL_00a3: brtrue.s IL_00a8 + + IL_00a5: nop + IL_00a6: br.s IL_006c + + IL_00a8: ldarg.0 + IL_00a9: stloc.3 + IL_00aa: ldloc.3 + IL_00ab: brtrue.s IL_00b0 + + IL_00ad: nop + IL_00ae: br.s IL_00e5 + + IL_00b0: br.s IL_00b2 + + IL_00b2: ldarg.0 + IL_00b3: ldc.i4.0 + IL_00b4: ceq + IL_00b6: stloc.3 + IL_00b7: ldloc.3 + IL_00b8: brtrue.s IL_00bd + + IL_00ba: nop + IL_00bb: br.s IL_00e5 + + IL_00bd: br.s IL_0082 + + IL_00bf: ldstr "default" + IL_00c4: call void [mscorlib]System.Console::WriteLine(string) + IL_00c9: nop + IL_00ca: br.s IL_00ce + + IL_00cc: br.s IL_00e5 + + IL_00ce: ldstr "break: " + IL_00d3: ldloc.0 + IL_00d4: box [mscorlib]System.Int32 + IL_00d9: call string [mscorlib]System.String::Concat(object, + object) + IL_00de: call void [mscorlib]System.Console::WriteLine(string) + IL_00e3: nop + IL_00e4: nop + IL_00e5: ldloc.1 + IL_00e6: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_00eb: stloc.3 + IL_00ec: ldloc.3 + IL_00ed: brtrue IL_0015 + + IL_00f2: leave.s IL_0104 + + } // end .try + finally + { + IL_00f4: ldloc.1 + IL_00f5: ldnull + IL_00f6: ceq + IL_00f8: stloc.3 + IL_00f9: ldloc.3 + IL_00fa: brtrue.s IL_0103 + + IL_00fc: ldloc.1 + IL_00fd: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_0102: nop + IL_0103: endfinally + } // end handler + IL_0104: nop + IL_0105: nop + IL_0106: ret + } // end of method Switch::SwitchWithContinue4 + + .method public hidebysig static void SwitchWithContinue5(bool b) cil managed + { + // Code size 172 (0xac) + .maxstack 2 + .locals init (int32 V_0, + bool V_1, + int32 V_2) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br IL_009f + + IL_0008: nop + IL_0009: ldloc.0 + IL_000a: ldc.i4.5 + IL_000b: clt + IL_000d: ldc.i4.0 + IL_000e: ceq + IL_0010: stloc.1 + IL_0011: ldloc.1 + IL_0012: brtrue.s IL_008f + + IL_0014: nop + IL_0015: ldloc.0 + IL_0016: stloc.2 + IL_0017: ldloc.2 + IL_0018: switch ( + IL_002f, + IL_0081, + IL_0052, + IL_007f) + IL_002d: br.s IL_0072 + + IL_002f: ldarg.0 + IL_0030: ldc.i4.0 + IL_0031: ceq + IL_0033: stloc.1 + IL_0034: ldloc.1 + IL_0035: brtrue.s IL_0045 + + IL_0037: nop + IL_0038: ldstr "0b" + IL_003d: call void [mscorlib]System.Console::WriteLine(string) + IL_0042: nop + IL_0043: br.s IL_009b + + IL_0045: ldstr "0!b" + IL_004a: call void [mscorlib]System.Console::WriteLine(string) + IL_004f: nop + IL_0050: br.s IL_0083 + + IL_0052: ldarg.0 + IL_0053: stloc.1 + IL_0054: ldloc.1 + IL_0055: brtrue.s IL_0065 + + IL_0057: nop + IL_0058: ldstr "2!b" + IL_005d: call void [mscorlib]System.Console::WriteLine(string) + IL_0062: nop + IL_0063: br.s IL_009b + + IL_0065: ldstr "2b" + IL_006a: call void [mscorlib]System.Console::WriteLine(string) + IL_006f: nop + IL_0070: br.s IL_00ab + + IL_0072: ldstr "default" + IL_0077: call void [mscorlib]System.Console::WriteLine(string) + IL_007c: nop + IL_007d: br.s IL_0083 + + IL_007f: br.s IL_0083 + + IL_0081: br.s IL_009b + + IL_0083: ldstr "break-target" + IL_0088: call void [mscorlib]System.Console::WriteLine(string) + IL_008d: nop + IL_008e: nop + IL_008f: ldstr "loop-tail" + IL_0094: call void [mscorlib]System.Console::WriteLine(string) + IL_0099: nop + IL_009a: nop + IL_009b: ldloc.0 + IL_009c: ldc.i4.1 + IL_009d: add + IL_009e: stloc.0 + IL_009f: ldloc.0 + IL_00a0: ldc.i4.s 10 + IL_00a2: clt + IL_00a4: stloc.1 + IL_00a5: ldloc.1 + IL_00a6: brtrue IL_0008 + + IL_00ab: ret + } // end of method Switch::SwitchWithContinue5 + + .method public hidebysig static void SwitchWithContinue6(int32 i, + bool b) cil managed + { + // Code size 142 (0x8e) + .maxstack 2 + .locals init (int32 V_0, + bool V_1) + IL_0000: nop + IL_0001: nop + IL_0002: ldarg.0 + IL_0003: stloc.0 + IL_0004: ldloc.0 + IL_0005: switch ( + IL_001c, + IL_006e, + IL_003c, + IL_006c) + IL_001a: br.s IL_005f + + IL_001c: ldarg.1 + IL_001d: stloc.1 + IL_001e: ldloc.1 + IL_001f: brtrue.s IL_002f + + IL_0021: nop + IL_0022: ldstr "0!b" + IL_0027: call void [mscorlib]System.Console::WriteLine(string) + IL_002c: nop + IL_002d: br.s IL_0070 + + IL_002f: ldstr "0b" + IL_0034: call void [mscorlib]System.Console::WriteLine(string) + IL_0039: nop + IL_003a: br.s IL_007c + + IL_003c: ldarg.1 + IL_003d: ldc.i4.0 + IL_003e: ceq + IL_0040: stloc.1 + IL_0041: ldloc.1 + IL_0042: brtrue.s IL_0052 + + IL_0044: nop + IL_0045: ldstr "2b" + IL_004a: call void [mscorlib]System.Console::WriteLine(string) + IL_004f: nop + IL_0050: br.s IL_008d + + IL_0052: ldstr "2!b" + IL_0057: call void [mscorlib]System.Console::WriteLine(string) + IL_005c: nop + IL_005d: br.s IL_007c + + IL_005f: ldstr "default" + IL_0064: call void [mscorlib]System.Console::WriteLine(string) + IL_0069: nop + IL_006a: br.s IL_0070 + + IL_006c: br.s IL_0070 + + IL_006e: br.s IL_007c + + IL_0070: ldstr "loop-tail" + IL_0075: call void [mscorlib]System.Console::WriteLine(string) + IL_007a: nop + IL_007b: nop + IL_007c: ldarg.0 + IL_007d: ldc.i4.1 + IL_007e: add + IL_007f: dup + IL_0080: starg.s i + IL_0082: ldc.i4.s 10 + IL_0084: clt + IL_0086: stloc.1 + IL_0087: ldloc.1 + IL_0088: brtrue IL_0001 + + IL_008d: ret + } // end of method Switch::SwitchWithContinue6 + + .method public hidebysig static void SwitchWithContinue7() cil managed + { + // Code size 81 (0x51) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1, + bool V_2) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br.s IL_003a + + IL_0005: nop + IL_0006: ldstr "loop-head" + IL_000b: call void [mscorlib]System.Console::WriteLine(string) + IL_0010: nop + IL_0011: ldloc.0 + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: switch ( + IL_0030, + IL_0032) + IL_0021: br.s IL_0023 + + IL_0023: ldstr "default" + IL_0028: call void [mscorlib]System.Console::WriteLine(string) + IL_002d: nop + IL_002e: br.s IL_0034 + + IL_0030: br.s IL_0036 + + IL_0032: br.s IL_0034 + + IL_0034: br.s IL_0045 + + IL_0036: ldloc.0 + IL_0037: ldc.i4.1 + IL_0038: sub + IL_0039: stloc.0 + IL_003a: ldloc.0 + IL_003b: ldc.i4.0 + IL_003c: clt + IL_003e: ldc.i4.0 + IL_003f: ceq + IL_0041: stloc.2 + IL_0042: ldloc.2 + IL_0043: brtrue.s IL_0005 + + IL_0045: ldstr "end" + IL_004a: call void [mscorlib]System.Console::WriteLine(string) + IL_004f: nop + IL_0050: ret + } // end of method Switch::SwitchWithContinue7 + + .method public hidebysig static void SwitchWithContinueInDoubleLoop() cil managed + { + // Code size 128 (0x80) + .maxstack 2 + .locals init (bool V_0, + int32 V_1, + int32 V_2, + int32 V_3, + bool V_4) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: ldc.i4.0 + IL_0004: stloc.1 + IL_0005: br.s IL_006d + + IL_0007: nop + IL_0008: ldc.i4.0 + IL_0009: stloc.2 + IL_000a: br.s IL_005d + + IL_000c: nop + IL_000d: ldloc.1 + IL_000e: ldloc.2 + IL_000f: add + IL_0010: stloc.3 + IL_0011: ldloc.3 + IL_0012: ldc.i4.1 + IL_0013: sub + IL_0014: switch ( + IL_0051, + IL_0053, + IL_0051, + IL_0053, + IL_0051, + IL_0053, + IL_0051) + IL_0035: ldloc.3 + IL_0036: ldc.i4.s 11 + IL_0038: sub + IL_0039: switch ( + IL_0051, + IL_0053, + IL_0051) + IL_004a: ldloc.3 + IL_004b: ldc.i4.s 17 + IL_004d: beq.s IL_0051 + + IL_004f: br.s IL_0053 + + IL_0051: br.s IL_0055 + + IL_0053: br.s IL_0059 + + IL_0055: ldc.i4.1 + IL_0056: stloc.0 + IL_0057: br.s IL_0068 + + IL_0059: ldloc.2 + IL_005a: ldc.i4.1 + IL_005b: add + IL_005c: stloc.2 + IL_005d: ldloc.2 + IL_005e: ldc.i4.s 10 + IL_0060: clt + IL_0062: stloc.s V_4 + IL_0064: ldloc.s V_4 + IL_0066: brtrue.s IL_000c + + IL_0068: nop + IL_0069: ldloc.1 + IL_006a: ldc.i4.1 + IL_006b: add + IL_006c: stloc.1 + IL_006d: ldloc.1 + IL_006e: ldc.i4.s 10 + IL_0070: clt + IL_0072: stloc.s V_4 + IL_0074: ldloc.s V_4 + IL_0076: brtrue.s IL_0007 + + IL_0078: ldloc.0 + IL_0079: call void [mscorlib]System.Console::WriteLine(bool) + IL_007e: nop + IL_007f: ret + } // end of method Switch::SwitchWithContinueInDoubleLoop + + .method public hidebysig static void SwitchLoopNesting() cil managed + { + // Code size 153 (0x99) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1, + bool V_2) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br IL_008c + + IL_0008: nop + IL_0009: ldloc.0 + IL_000a: stloc.1 + IL_000b: ldloc.1 + IL_000c: switch ( + IL_001b, + IL_0024) + IL_0019: br.s IL_002d + + IL_001b: ldc.i4.0 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: nop + IL_0022: br.s IL_0060 + + IL_0024: ldc.i4.1 + IL_0025: call void [mscorlib]System.Console::WriteLine(int32) + IL_002a: nop + IL_002b: br.s IL_0060 + + IL_002d: ldloc.0 + IL_002e: ldc.i4.2 + IL_002f: rem + IL_0030: ldc.i4.0 + IL_0031: ceq + IL_0033: ldc.i4.0 + IL_0034: ceq + IL_0036: stloc.2 + IL_0037: ldloc.2 + IL_0038: brtrue.s IL_0058 + + IL_003a: nop + IL_003b: br.s IL_004a + + IL_003d: nop + IL_003e: ldloc.0 + IL_003f: dup + IL_0040: ldc.i4.1 + IL_0041: add + IL_0042: stloc.0 + IL_0043: call void [mscorlib]System.Console::WriteLine(int32) + IL_0048: nop + IL_0049: nop + IL_004a: ldloc.0 + IL_004b: ldc.i4.3 + IL_004c: rem + IL_004d: ldc.i4.0 + IL_004e: ceq + IL_0050: ldc.i4.0 + IL_0051: ceq + IL_0053: stloc.2 + IL_0054: ldloc.2 + IL_0055: brtrue.s IL_003d + + IL_0057: nop + IL_0058: call void [mscorlib]System.Console::WriteLine() + IL_005d: nop + IL_005e: br.s IL_0060 + + IL_0060: ldloc.0 + IL_0061: ldc.i4.4 + IL_0062: cgt + IL_0064: ldc.i4.0 + IL_0065: ceq + IL_0067: stloc.2 + IL_0068: ldloc.2 + IL_0069: brtrue.s IL_007a + + IL_006b: nop + IL_006c: ldstr "high" + IL_0071: call void [mscorlib]System.Console::WriteLine(string) + IL_0076: nop + IL_0077: nop + IL_0078: br.s IL_0087 + + IL_007a: nop + IL_007b: ldstr "low" + IL_0080: call void [mscorlib]System.Console::WriteLine(string) + IL_0085: nop + IL_0086: nop + IL_0087: nop + IL_0088: ldloc.0 + IL_0089: ldc.i4.1 + IL_008a: add + IL_008b: stloc.0 + IL_008c: ldloc.0 + IL_008d: ldc.i4.s 10 + IL_008f: clt + IL_0091: stloc.2 + IL_0092: ldloc.2 + IL_0093: brtrue IL_0008 + + IL_0098: ret + } // end of method Switch::SwitchLoopNesting + + .method public hidebysig static void SingleIf2(int32 i, + bool a, + bool b) cil managed + { + // Code size 49 (0x31) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.1 + IL_0003: beq.s IL_001a + + IL_0005: ldarg.0 + IL_0006: ldc.i4.2 + IL_0007: bne.un.s IL_000c + + IL_0009: ldarg.1 + IL_000a: brtrue.s IL_001a + + IL_000c: ldarg.0 + IL_000d: ldc.i4.3 + IL_000e: bne.un.s IL_0016 + + IL_0010: ldarg.2 + IL_0011: ldc.i4.0 + IL_0012: ceq + IL_0014: br.s IL_0017 + + IL_0016: ldc.i4.1 + IL_0017: nop + IL_0018: br.s IL_001b + + IL_001a: ldc.i4.0 + IL_001b: nop + IL_001c: stloc.0 + IL_001d: ldloc.0 + IL_001e: brtrue.s IL_0029 + + IL_0020: nop + IL_0021: ldc.i4.1 + IL_0022: call void [mscorlib]System.Console::WriteLine(int32) + IL_0027: nop + IL_0028: nop + IL_0029: ldc.i4.2 + IL_002a: call void [mscorlib]System.Console::WriteLine(int32) + IL_002f: nop + IL_0030: ret + } // end of method Switch::SingleIf2 + + .method public hidebysig static void SingleIf3(int32 i, + bool a, + bool b) cil managed + { + // Code size 45 (0x2d) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: brtrue.s IL_0016 + + IL_0004: ldarg.0 + IL_0005: ldc.i4.1 + IL_0006: beq.s IL_0016 + + IL_0008: ldarg.0 + IL_0009: ldc.i4.2 + IL_000a: bne.un.s IL_0012 + + IL_000c: ldarg.2 + IL_000d: ldc.i4.0 + IL_000e: ceq + IL_0010: br.s IL_0013 + + IL_0012: ldc.i4.1 + IL_0013: nop + IL_0014: br.s IL_0017 + + IL_0016: ldc.i4.0 + IL_0017: nop + IL_0018: stloc.0 + IL_0019: ldloc.0 + IL_001a: brtrue.s IL_0025 + + IL_001c: nop + IL_001d: ldc.i4.1 + IL_001e: call void [mscorlib]System.Console::WriteLine(int32) + IL_0023: nop + IL_0024: nop + IL_0025: ldc.i4.2 + IL_0026: call void [mscorlib]System.Console::WriteLine(int32) + IL_002b: nop + IL_002c: ret + } // end of method Switch::SingleIf3 + + .method public hidebysig static void SingleIf4(int32 i, + bool a) cil managed + { + // Code size 45 (0x2d) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.1 + IL_0003: beq.s IL_0016 + + IL_0005: ldarg.0 + IL_0006: ldc.i4.2 + IL_0007: beq.s IL_0016 + + IL_0009: ldarg.0 + IL_000a: ldc.i4.3 + IL_000b: beq.s IL_0010 + + IL_000d: ldarg.1 + IL_000e: brtrue.s IL_0016 + + IL_0010: ldarg.0 + IL_0011: ldc.i4.4 + IL_0012: ceq + IL_0014: br.s IL_0017 + + IL_0016: ldc.i4.0 + IL_0017: nop + IL_0018: stloc.0 + IL_0019: ldloc.0 + IL_001a: brtrue.s IL_0025 + + IL_001c: nop + IL_001d: ldc.i4.1 + IL_001e: call void [mscorlib]System.Console::WriteLine(int32) + IL_0023: nop + IL_0024: nop + IL_0025: ldc.i4.2 + IL_0026: call void [mscorlib]System.Console::WriteLine(int32) + IL_002b: nop + IL_002c: ret + } // end of method Switch::SingleIf4 + + .method public hidebysig static void NestedIf(int32 i) cil managed + { + // Code size 49 (0x31) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.1 + IL_0003: ceq + IL_0005: stloc.0 + IL_0006: ldloc.0 + IL_0007: brtrue.s IL_002a + + IL_0009: nop + IL_000a: ldarg.0 + IL_000b: ldc.i4.2 + IL_000c: ceq + IL_000e: ldc.i4.0 + IL_000f: ceq + IL_0011: stloc.0 + IL_0012: ldloc.0 + IL_0013: brtrue.s IL_001e + + IL_0015: nop + IL_0016: ldc.i4.2 + IL_0017: call void [mscorlib]System.Console::WriteLine(int32) + IL_001c: nop + IL_001d: nop + IL_001e: ldstr "default" + IL_0023: call void [mscorlib]System.Console::WriteLine(string) + IL_0028: nop + IL_0029: nop + IL_002a: call void [mscorlib]System.Console::WriteLine() + IL_002f: nop + IL_0030: ret + } // end of method Switch::NestedIf + + .method public hidebysig static void IfChainWithCondition(int32 i) cil managed + { + // Code size 169 (0xa9) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.0 + IL_0003: ceq + IL_0005: ldc.i4.0 + IL_0006: ceq + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: brtrue.s IL_001a + + IL_000c: nop + IL_000d: ldc.i4.0 + IL_000e: call void [mscorlib]System.Console::WriteLine(int32) + IL_0013: nop + IL_0014: nop + IL_0015: br IL_00a2 + + IL_001a: ldarg.0 + IL_001b: ldc.i4.1 + IL_001c: ceq + IL_001e: ldc.i4.0 + IL_001f: ceq + IL_0021: stloc.0 + IL_0022: ldloc.0 + IL_0023: brtrue.s IL_0030 + + IL_0025: nop + IL_0026: ldc.i4.1 + IL_0027: call void [mscorlib]System.Console::WriteLine(int32) + IL_002c: nop + IL_002d: nop + IL_002e: br.s IL_00a2 + + IL_0030: ldarg.0 + IL_0031: ldc.i4.2 + IL_0032: ceq + IL_0034: ldc.i4.0 + IL_0035: ceq + IL_0037: stloc.0 + IL_0038: ldloc.0 + IL_0039: brtrue.s IL_0046 + + IL_003b: nop + IL_003c: ldc.i4.2 + IL_003d: call void [mscorlib]System.Console::WriteLine(int32) + IL_0042: nop + IL_0043: nop + IL_0044: br.s IL_00a2 + + IL_0046: ldarg.0 + IL_0047: ldc.i4.3 + IL_0048: ceq + IL_004a: ldc.i4.0 + IL_004b: ceq + IL_004d: stloc.0 + IL_004e: ldloc.0 + IL_004f: brtrue.s IL_005c + + IL_0051: nop + IL_0052: ldc.i4.3 + IL_0053: call void [mscorlib]System.Console::WriteLine(int32) + IL_0058: nop + IL_0059: nop + IL_005a: br.s IL_00a2 + + IL_005c: ldarg.0 + IL_005d: ldc.i4.4 + IL_005e: ceq + IL_0060: ldc.i4.0 + IL_0061: ceq + IL_0063: stloc.0 + IL_0064: ldloc.0 + IL_0065: brtrue.s IL_0072 + + IL_0067: nop + IL_0068: ldc.i4.4 + IL_0069: call void [mscorlib]System.Console::WriteLine(int32) + IL_006e: nop + IL_006f: nop + IL_0070: br.s IL_00a2 + + IL_0072: ldarg.0 + IL_0073: ldc.i4.5 + IL_0074: bne.un.s IL_0080 + + IL_0076: call bool [mscorlib]System.Console::get_CapsLock() + IL_007b: ldc.i4.0 + IL_007c: ceq + IL_007e: br.s IL_0081 + + IL_0080: ldc.i4.1 + IL_0081: nop + IL_0082: stloc.0 + IL_0083: ldloc.0 + IL_0084: brtrue.s IL_0095 + + IL_0086: nop + IL_0087: ldstr "5A" + IL_008c: call void [mscorlib]System.Console::WriteLine(string) + IL_0091: nop + IL_0092: nop + IL_0093: br.s IL_00a2 + + IL_0095: nop + IL_0096: ldstr "default" + IL_009b: call void [mscorlib]System.Console::WriteLine(string) + IL_00a0: nop + IL_00a1: nop + IL_00a2: call void [mscorlib]System.Console::WriteLine() + IL_00a7: nop + IL_00a8: ret + } // end of method Switch::IfChainWithCondition + + .method public hidebysig static bool SwitchlikeIf(int32 i, + int32 j) cil managed + { + // Code size 280 (0x118) + .maxstack 2 + .locals init (bool V_0, + bool V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: brfalse.s IL_000a + + IL_0004: ldarg.1 + IL_0005: ldc.i4.0 + IL_0006: ceq + IL_0008: br.s IL_000b + + IL_000a: ldc.i4.1 + IL_000b: nop + IL_000c: stloc.1 + IL_000d: ldloc.1 + IL_000e: brtrue IL_0098 + + IL_0013: nop + IL_0014: ldarg.0 + IL_0015: ldc.i4.m1 + IL_0016: bne.un.s IL_0021 + + IL_0018: ldarg.1 + IL_0019: ldc.i4.m1 + IL_001a: ceq + IL_001c: ldc.i4.0 + IL_001d: ceq + IL_001f: br.s IL_0022 + + IL_0021: ldc.i4.1 + IL_0022: nop + IL_0023: stloc.1 + IL_0024: ldloc.1 + IL_0025: brtrue.s IL_0034 + + IL_0027: nop + IL_0028: ldstr "-1, -1" + IL_002d: call void [mscorlib]System.Console::WriteLine(string) + IL_0032: nop + IL_0033: nop + IL_0034: ldarg.0 + IL_0035: ldc.i4.m1 + IL_0036: bne.un.s IL_0041 + + IL_0038: ldarg.1 + IL_0039: ldc.i4.1 + IL_003a: ceq + IL_003c: ldc.i4.0 + IL_003d: ceq + IL_003f: br.s IL_0042 + + IL_0041: ldc.i4.1 + IL_0042: nop + IL_0043: stloc.1 + IL_0044: ldloc.1 + IL_0045: brtrue.s IL_0054 + + IL_0047: nop + IL_0048: ldstr "-1, 1" + IL_004d: call void [mscorlib]System.Console::WriteLine(string) + IL_0052: nop + IL_0053: nop + IL_0054: ldarg.0 + IL_0055: ldc.i4.1 + IL_0056: bne.un.s IL_0061 + + IL_0058: ldarg.1 + IL_0059: ldc.i4.m1 + IL_005a: ceq + IL_005c: ldc.i4.0 + IL_005d: ceq + IL_005f: br.s IL_0062 + + IL_0061: ldc.i4.1 + IL_0062: nop + IL_0063: stloc.1 + IL_0064: ldloc.1 + IL_0065: brtrue.s IL_0074 + + IL_0067: nop + IL_0068: ldstr "1, -1" + IL_006d: call void [mscorlib]System.Console::WriteLine(string) + IL_0072: nop + IL_0073: nop + IL_0074: ldarg.0 + IL_0075: ldc.i4.1 + IL_0076: bne.un.s IL_0081 + + IL_0078: ldarg.1 + IL_0079: ldc.i4.1 + IL_007a: ceq + IL_007c: ldc.i4.0 + IL_007d: ceq + IL_007f: br.s IL_0082 + + IL_0081: ldc.i4.1 + IL_0082: nop + IL_0083: stloc.1 + IL_0084: ldloc.1 + IL_0085: brtrue.s IL_0094 + + IL_0087: nop + IL_0088: ldstr "1, 1" + IL_008d: call void [mscorlib]System.Console::WriteLine(string) + IL_0092: nop + IL_0093: nop + IL_0094: ldc.i4.0 + IL_0095: stloc.0 + IL_0096: br.s IL_0116 + + IL_0098: ldarg.0 + IL_0099: ldc.i4.0 + IL_009a: ceq + IL_009c: stloc.1 + IL_009d: ldloc.1 + IL_009e: brtrue.s IL_00d5 + + IL_00a0: nop + IL_00a1: ldarg.0 + IL_00a2: ldc.i4.m1 + IL_00a3: ceq + IL_00a5: ldc.i4.0 + IL_00a6: ceq + IL_00a8: stloc.1 + IL_00a9: ldloc.1 + IL_00aa: brtrue.s IL_00b9 + + IL_00ac: nop + IL_00ad: ldstr "-1, 0" + IL_00b2: call void [mscorlib]System.Console::WriteLine(string) + IL_00b7: nop + IL_00b8: nop + IL_00b9: ldarg.0 + IL_00ba: ldc.i4.1 + IL_00bb: ceq + IL_00bd: ldc.i4.0 + IL_00be: ceq + IL_00c0: stloc.1 + IL_00c1: ldloc.1 + IL_00c2: brtrue.s IL_00d1 + + IL_00c4: nop + IL_00c5: ldstr "1, 0" + IL_00ca: call void [mscorlib]System.Console::WriteLine(string) + IL_00cf: nop + IL_00d0: nop + IL_00d1: ldc.i4.0 + IL_00d2: stloc.0 + IL_00d3: br.s IL_0116 + + IL_00d5: ldarg.1 + IL_00d6: ldc.i4.0 + IL_00d7: ceq + IL_00d9: stloc.1 + IL_00da: ldloc.1 + IL_00db: brtrue.s IL_0112 + + IL_00dd: nop + IL_00de: ldarg.1 + IL_00df: ldc.i4.m1 + IL_00e0: ceq + IL_00e2: ldc.i4.0 + IL_00e3: ceq + IL_00e5: stloc.1 + IL_00e6: ldloc.1 + IL_00e7: brtrue.s IL_00f6 + + IL_00e9: nop + IL_00ea: ldstr "0, -1" + IL_00ef: call void [mscorlib]System.Console::WriteLine(string) + IL_00f4: nop + IL_00f5: nop + IL_00f6: ldarg.1 + IL_00f7: ldc.i4.1 + IL_00f8: ceq + IL_00fa: ldc.i4.0 + IL_00fb: ceq + IL_00fd: stloc.1 + IL_00fe: ldloc.1 + IL_00ff: brtrue.s IL_010e + + IL_0101: nop + IL_0102: ldstr "0, 1" + IL_0107: call void [mscorlib]System.Console::WriteLine(string) + IL_010c: nop + IL_010d: nop + IL_010e: ldc.i4.0 + IL_010f: stloc.0 + IL_0110: br.s IL_0116 + + IL_0112: ldc.i4.1 + IL_0113: stloc.0 + IL_0114: br.s IL_0116 + + IL_0116: ldloc.0 + IL_0117: ret + } // end of method Switch::SwitchlikeIf + + .method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed + { + // Code size 80 (0x50) + .maxstack 2 + .locals init (bool V_0, + bool V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.0 + IL_0003: ceq + IL_0005: stloc.1 + IL_0006: ldloc.1 + IL_0007: brtrue.s IL_004a + + IL_0009: nop + IL_000a: ldarg.0 + IL_000b: ldc.i4.1 + IL_000c: ceq + IL_000e: ldc.i4.0 + IL_000f: ceq + IL_0011: stloc.1 + IL_0012: ldloc.1 + IL_0013: brtrue.s IL_001e + + IL_0015: nop + IL_0016: ldc.i4.1 + IL_0017: call void [mscorlib]System.Console::WriteLine(int32) + IL_001c: nop + IL_001d: nop + IL_001e: ldarg.0 + IL_001f: ldc.i4.2 + IL_0020: ceq + IL_0022: ldc.i4.0 + IL_0023: ceq + IL_0025: stloc.1 + IL_0026: ldloc.1 + IL_0027: brtrue.s IL_0032 + + IL_0029: nop + IL_002a: ldc.i4.2 + IL_002b: call void [mscorlib]System.Console::WriteLine(int32) + IL_0030: nop + IL_0031: nop + IL_0032: ldarg.0 + IL_0033: ldc.i4.3 + IL_0034: ceq + IL_0036: ldc.i4.0 + IL_0037: ceq + IL_0039: stloc.1 + IL_003a: ldloc.1 + IL_003b: brtrue.s IL_0046 + + IL_003d: nop + IL_003e: ldc.i4.3 + IL_003f: call void [mscorlib]System.Console::WriteLine(int32) + IL_0044: nop + IL_0045: nop + IL_0046: ldc.i4.0 + IL_0047: stloc.0 + IL_0048: br.s IL_004e + + IL_004a: ldc.i4.0 + IL_004b: stloc.0 + IL_004c: br.s IL_004e + + IL_004e: ldloc.0 + IL_004f: ret + } // end of method Switch::SwitchlikeIf2 + + .method public hidebysig static void SingleIntervalIf(char c) cil managed + { + // Code size 44 (0x2c) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.s 65 + IL_0004: blt.s IL_000d + + IL_0006: ldarg.0 + IL_0007: ldc.i4.s 90 + IL_0009: cgt + IL_000b: br.s IL_000e + + IL_000d: ldc.i4.1 + IL_000e: nop + IL_000f: stloc.0 + IL_0010: ldloc.0 + IL_0011: brtrue.s IL_0020 + + IL_0013: nop + IL_0014: ldstr "alphabet" + IL_0019: call void [mscorlib]System.Console::WriteLine(string) + IL_001e: nop + IL_001f: nop + IL_0020: ldstr "end" + IL_0025: call void [mscorlib]System.Console::WriteLine(string) + IL_002a: nop + IL_002b: ret + } // end of method Switch::SingleIntervalIf + + .method public hidebysig static bool Loop8(char c, + bool b, + class [mscorlib]System.Func`1 getChar) cil managed + { + // Code size 64 (0x40) + .maxstack 2 + .locals init (bool V_0, + bool V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldc.i4.0 + IL_0003: ceq + IL_0005: stloc.1 + IL_0006: ldloc.1 + IL_0007: brtrue.s IL_003a + + IL_0009: nop + IL_000a: br.s IL_0016 + + IL_000c: nop + IL_000d: ldarg.2 + IL_000e: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_0013: starg.s c + IL_0015: nop + IL_0016: ldarg.0 + IL_0017: ldc.i4.s 97 + IL_0019: blt.s IL_0020 + + IL_001b: ldarg.0 + IL_001c: ldc.i4.s 122 + IL_001e: ble.s IL_0033 + + IL_0020: ldarg.0 + IL_0021: ldc.i4.s 65 + IL_0023: blt.s IL_002f + + IL_0025: ldarg.0 + IL_0026: ldc.i4.s 90 + IL_0028: cgt + IL_002a: ldc.i4.0 + IL_002b: ceq + IL_002d: br.s IL_0030 + + IL_002f: ldc.i4.0 + IL_0030: nop + IL_0031: br.s IL_0034 + + IL_0033: ldc.i4.1 + IL_0034: nop + IL_0035: stloc.1 + IL_0036: ldloc.1 + IL_0037: brtrue.s IL_000c + + IL_0039: nop + IL_003a: ldc.i4.1 + IL_003b: stloc.0 + IL_003c: br.s IL_003e + + IL_003e: ldloc.0 + IL_003f: ret + } // end of method Switch::Loop8 + + .method public hidebysig static void Loop9(class [mscorlib]System.Func`1 getChar) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (char V_0, + bool V_1) + IL_0000: nop + IL_0001: nop + IL_0002: ldarg.0 + IL_0003: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_0008: stloc.0 + IL_0009: nop + IL_000a: ldloc.0 + IL_000b: ldc.i4.m1 + IL_000c: beq.s IL_0028 + + IL_000e: ldloc.0 + IL_000f: ldc.i4.s 10 + IL_0011: beq.s IL_0028 + + IL_0013: ldloc.0 + IL_0014: ldc.i4 0x2028 + IL_0019: beq.s IL_0028 + + IL_001b: ldloc.0 + IL_001c: ldc.i4 0x2029 + IL_0021: ceq + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: br.s IL_0029 + + IL_0028: ldc.i4.0 + IL_0029: nop + IL_002a: stloc.1 + IL_002b: ldloc.1 + IL_002c: brtrue.s IL_0001 + + IL_002e: ret + } // end of method Switch::Loop9 + + .method public hidebysig static void SwitchWithBreakCase(int32 i, + bool b) cil managed + { + // Code size 78 (0x4e) + .maxstack 2 + .locals init (bool V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldc.i4.0 + IL_0003: ceq + IL_0005: stloc.0 + IL_0006: ldloc.0 + IL_0007: brtrue.s IL_0042 + + IL_0009: nop + IL_000a: ldarg.0 + IL_000b: stloc.1 + IL_000c: ldloc.1 + IL_000d: ldc.i4.1 + IL_000e: sub + IL_000f: switch ( + IL_001e, + IL_0034) + IL_001c: br.s IL_0027 + + IL_001e: ldc.i4.1 + IL_001f: call void [mscorlib]System.Console::WriteLine(int32) + IL_0024: nop + IL_0025: br.s IL_0036 + + IL_0027: ldstr "default" + IL_002c: call void [mscorlib]System.Console::WriteLine(string) + IL_0031: nop + IL_0032: br.s IL_0036 + + IL_0034: br.s IL_0036 + + IL_0036: ldstr "b" + IL_003b: call void [mscorlib]System.Console::WriteLine(string) + IL_0040: nop + IL_0041: nop + IL_0042: ldstr "end" + IL_0047: call void [mscorlib]System.Console::WriteLine(string) + IL_004c: nop + IL_004d: ret + } // end of method Switch::SwitchWithBreakCase + + .method public hidebysig static void SwitchWithReturnAndBreak(int32 i, + bool b) cil managed + { + // Code size 49 (0x31) + .maxstack 2 + .locals init (int32 V_0, + bool V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: switch ( + IL_0013, + IL_0020) + IL_0011: br.s IL_002a + + IL_0013: ldarg.1 + IL_0014: ldc.i4.0 + IL_0015: ceq + IL_0017: stloc.1 + IL_0018: ldloc.1 + IL_0019: brtrue.s IL_001e + + IL_001b: nop + IL_001c: br.s IL_0030 + + IL_001e: br.s IL_002a + + IL_0020: ldarg.1 + IL_0021: stloc.1 + IL_0022: ldloc.1 + IL_0023: brtrue.s IL_0028 + + IL_0025: nop + IL_0026: br.s IL_0030 + + IL_0028: br.s IL_002a + + IL_002a: call void [mscorlib]System.Console::WriteLine() + IL_002f: nop + IL_0030: ret + } // end of method Switch::SwitchWithReturnAndBreak + + .method public hidebysig static int32 SwitchWithReturnAndBreak2(int32 i, + bool b) cil managed + { + // Code size 101 (0x65) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1, + bool V_2) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.1 + IL_0003: ldloc.1 + IL_0004: ldc.i4 0x14e + IL_0009: bgt.s IL_001e + + IL_000b: ldloc.1 + IL_000c: ldc.i4.4 + IL_000d: beq.s IL_0038 + + IL_000f: ldloc.1 + IL_0010: ldc.i4.s 33 + IL_0012: beq.s IL_0038 + + IL_0014: ldloc.1 + IL_0015: ldc.i4 0x14e + IL_001a: beq.s IL_0042 + + IL_001c: br.s IL_0059 + + IL_001e: ldloc.1 + IL_001f: ldc.i4 0x18b + IL_0024: beq.s IL_0051 + + IL_0026: ldloc.1 + IL_0027: ldc.i4 0x19a + IL_002c: beq.s IL_0051 + + IL_002e: ldloc.1 + IL_002f: ldc.i4 0x1c7 + IL_0034: beq.s IL_0051 + + IL_0036: br.s IL_0059 + + IL_0038: call void [mscorlib]System.Console::WriteLine() + IL_003d: nop + IL_003e: ldc.i4.1 + IL_003f: stloc.0 + IL_0040: br.s IL_0063 + + IL_0042: ldarg.1 + IL_0043: ldc.i4.0 + IL_0044: ceq + IL_0046: stloc.2 + IL_0047: ldloc.2 + IL_0048: brtrue.s IL_004f + + IL_004a: nop + IL_004b: ldc.i4.2 + IL_004c: stloc.0 + IL_004d: br.s IL_0063 + + IL_004f: br.s IL_0059 + + IL_0051: call void [mscorlib]System.Console::WriteLine() + IL_0056: nop + IL_0057: br.s IL_0059 + + IL_0059: call void [mscorlib]System.Console::WriteLine() + IL_005e: nop + IL_005f: ldc.i4.0 + IL_0060: stloc.0 + IL_0061: br.s IL_0063 + + IL_0063: ldloc.0 + IL_0064: ret + } // end of method Switch::SwitchWithReturnAndBreak2 + + .method public hidebysig static void SwitchWithReturnAndBreak3(int32 i) cil managed + { + // Code size 46 (0x2e) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: switch ( + IL_0015, + IL_001e) + IL_0011: br.s IL_0013 + + IL_0013: br.s IL_002d + + IL_0015: ldc.i4.0 + IL_0016: call void [mscorlib]System.Console::WriteLine(int32) + IL_001b: nop + IL_001c: br.s IL_0027 + + IL_001e: ldc.i4.1 + IL_001f: call void [mscorlib]System.Console::WriteLine(int32) + IL_0024: nop + IL_0025: br.s IL_0027 + + IL_0027: call void [mscorlib]System.Console::WriteLine() + IL_002c: nop + IL_002d: ret + } // end of method Switch::SwitchWithReturnAndBreak3 + } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch .class private auto ansi '' 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 '$$method0x600000d-1' - .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x600000e-1' - .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000013-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000010-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000011-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000015-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000016-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000018-1' } // end of class '' diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il index 719b11561..c17a273e4 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il @@ -8,6 +8,11 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } +.assembly extern System.Core +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} .assembly Switch.opt { .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 @@ -251,6 +256,106 @@ IL_00b4: ret } // end of method Switch::SparseIntegerSwitch + .method public hidebysig static void SparseIntegerSwitch2(int32 i) cil managed + { + // Code size 87 (0x57) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: ldc.i4.s 21 + IL_0005: bgt.s IL_002a + + IL_0007: ldloc.0 + IL_0008: ldc.i4.4 + IL_0009: beq.s IL_0051 + + IL_000b: ldloc.0 + IL_000c: ldc.i4.s 10 + IL_000e: sub + IL_000f: switch ( + IL_0051, + IL_0051, + IL_0056, + IL_0051) + IL_0024: ldloc.0 + IL_0025: ldc.i4.s 21 + IL_0027: beq.s IL_0051 + + IL_0029: ret + + IL_002a: ldloc.0 + IL_002b: ldc.i4.s 33 + IL_002d: bgt.s IL_003a + + IL_002f: ldloc.0 + IL_0030: ldc.i4.s 29 + IL_0032: beq.s IL_0051 + + IL_0034: ldloc.0 + IL_0035: ldc.i4.s 33 + IL_0037: beq.s IL_0051 + + IL_0039: ret + + IL_003a: ldloc.0 + IL_003b: ldc.i4.s 49 + IL_003d: sub + IL_003e: switch ( + IL_0051, + IL_0051) + IL_004b: ldloc.0 + IL_004c: ldc.i4.s 55 + IL_004e: beq.s IL_0051 + + IL_0050: ret + + IL_0051: call void [mscorlib]System.Console::WriteLine() + IL_0056: ret + } // end of method Switch::SparseIntegerSwitch2 + + .method public hidebysig static bool SparseIntegerSwitch3(int32 i) cil managed + { + // Code size 63 (0x3f) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: ldc.i4.s 12 + IL_0005: bgt.s IL_0022 + + IL_0007: ldloc.0 + IL_0008: ldc.i4.0 + IL_0009: beq.s IL_003b + + IL_000b: ldloc.0 + IL_000c: ldc.i4.s 10 + IL_000e: sub + IL_000f: switch ( + IL_003b, + IL_003b, + IL_003b) + IL_0020: br.s IL_003d + + IL_0022: ldloc.0 + IL_0023: ldc.i4.s 100 + IL_0025: sub + IL_0026: switch ( + IL_003b, + IL_003b) + IL_0033: ldloc.0 + IL_0034: ldc.i4 0xc8 + IL_0039: bne.un.s IL_003d + + IL_003b: ldc.i4.1 + IL_003c: ret + + IL_003d: ldc.i4.0 + IL_003e: ret + } // end of method Switch::SparseIntegerSwitch3 + .method public hidebysig static string SwitchOverNullableInt(valuetype [mscorlib]System.Nullable`1 i) cil managed { @@ -635,6 +740,36 @@ IL_007c: ret } // end of method Switch::SwitchOverInt + .method public hidebysig static void CompactSwitchOverInt(int32 i) cil managed + { + // Code size 71 (0x47) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: switch ( + IL_001a, + IL_001a, + IL_001a, + IL_0026) + IL_0018: br.s IL_0032 + + IL_001a: ldstr "012" + IL_001f: call void [mscorlib]System.Console::WriteLine(string) + IL_0024: br.s IL_003c + + IL_0026: ldstr "3" + IL_002b: call void [mscorlib]System.Console::WriteLine(string) + IL_0030: br.s IL_003c + + IL_0032: ldstr "default" + IL_0037: call void [mscorlib]System.Console::WriteLine(string) + IL_003c: ldstr "end" + IL_0041: call void [mscorlib]System.Console::WriteLine(string) + IL_0046: ret + } // end of method Switch::CompactSwitchOverInt + .method public hidebysig static string ShortSwitchOverString(string text) cil managed { @@ -745,7 +880,7 @@ IL_0013: brfalse IL_00db IL_0018: volatile. - IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000d-1' + IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000010-1' IL_001f: brtrue.s IL_0082 IL_0021: ldc.i4.7 @@ -786,9 +921,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 ''::'$$method0x600000d-1' + IL_007d: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000010-1' IL_0082: volatile. - IL_0084: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000d-1' + IL_0084: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000010-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, @@ -846,7 +981,7 @@ IL_0011: brfalse IL_013d IL_0016: volatile. - IL_0018: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000e-1' + IL_0018: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000011-1' IL_001d: brtrue IL_00b6 IL_0022: ldc.i4.s 11 @@ -907,9 +1042,9 @@ IL_00aa: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_00af: volatile. - IL_00b1: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000e-1' + IL_00b1: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000011-1' IL_00b6: volatile. - IL_00b8: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x600000e-1' + IL_00b8: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000011-1' IL_00bd: ldloc.0 IL_00be: ldloca.s V_1 IL_00c0: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -1090,6 +1225,257 @@ IL_0072: ret } // end of method Switch::SwitchWithGoto + .method public hidebysig static void SwitchWithGotoString(string s) cil managed + { + // Code size 340 (0x154) + .maxstack 4 + .locals init (string V_0, + int32 V_1) + IL_0000: ldstr "SwitchWithGotoString: " + IL_0005: ldarg.0 + IL_0006: call string [mscorlib]System.String::Concat(string, + string) + IL_000b: call void [mscorlib]System.Console::WriteLine(string) + IL_0010: ldarg.0 + IL_0011: dup + IL_0012: stloc.0 + IL_0013: brfalse IL_013f + + IL_0018: volatile. + IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000015-1' + IL_001f: brtrue.s IL_009b + + IL_0021: ldc.i4.s 9 + IL_0023: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor(int32) + IL_0028: dup + IL_0029: ldstr "1" + IL_002e: ldc.i4.0 + IL_002f: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0034: dup + IL_0035: ldstr "2" + IL_003a: ldc.i4.1 + IL_003b: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0040: dup + IL_0041: ldstr "3" + IL_0046: ldc.i4.2 + IL_0047: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_004c: dup + IL_004d: ldstr "4" + IL_0052: ldc.i4.3 + IL_0053: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0058: dup + IL_0059: ldstr "5" + IL_005e: ldc.i4.4 + IL_005f: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0064: dup + IL_0065: ldstr "6" + IL_006a: ldc.i4.5 + IL_006b: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0070: dup + IL_0071: ldstr "7" + IL_0076: ldc.i4.6 + IL_0077: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_007c: dup + IL_007d: ldstr "8" + IL_0082: ldc.i4.7 + IL_0083: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0088: dup + IL_0089: ldstr "9" + IL_008e: ldc.i4.8 + IL_008f: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0094: volatile. + IL_0096: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000015-1' + IL_009b: volatile. + IL_009d: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000015-1' + IL_00a2: ldloc.0 + IL_00a3: ldloca.s V_1 + IL_00a5: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, + !1&) + IL_00aa: brfalse IL_013f + + IL_00af: ldloc.1 + IL_00b0: switch ( + IL_00db, + IL_00e7, + IL_00f1, + IL_00fd, + IL_0108, + IL_0113, + IL_011e, + IL_0129, + IL_0134) + IL_00d9: br.s IL_013f + + IL_00db: ldstr "one" + IL_00e0: call void [mscorlib]System.Console::WriteLine(string) + IL_00e5: br.s IL_013f + + IL_00e7: ldstr "two" + IL_00ec: call void [mscorlib]System.Console::WriteLine(string) + IL_00f1: ldstr "three" + IL_00f6: call void [mscorlib]System.Console::WriteLine(string) + IL_00fb: br.s IL_0149 + + IL_00fd: ldstr "four" + IL_0102: call void [mscorlib]System.Console::WriteLine(string) + IL_0107: ret + + IL_0108: ldstr "five" + IL_010d: call void [mscorlib]System.Console::WriteLine(string) + IL_0112: ret + + IL_0113: ldstr "six" + IL_0118: call void [mscorlib]System.Console::WriteLine(string) + IL_011d: ret + + IL_011e: ldstr "seven" + IL_0123: call void [mscorlib]System.Console::WriteLine(string) + IL_0128: ret + + IL_0129: ldstr "eight" + IL_012e: call void [mscorlib]System.Console::WriteLine(string) + IL_0133: ret + + IL_0134: ldstr "nine" + IL_0139: call void [mscorlib]System.Console::WriteLine(string) + IL_013e: ret + + IL_013f: ldstr "default" + IL_0144: call void [mscorlib]System.Console::WriteLine(string) + IL_0149: ldstr "End of method" + IL_014e: call void [mscorlib]System.Console::WriteLine(string) + IL_0153: ret + } // end of method Switch::SwitchWithGotoString + + .method public hidebysig static void SwitchWithGotoComplex(string s) cil managed + { + // Code size 311 (0x137) + .maxstack 4 + .locals init (string V_0, + int32 V_1) + IL_0000: ldstr "SwitchWithGotoComplex: " + IL_0005: ldarg.0 + IL_0006: call string [mscorlib]System.String::Concat(string, + string) + IL_000b: call void [mscorlib]System.Console::WriteLine(string) + IL_0010: ldarg.0 + IL_0011: dup + IL_0012: stloc.0 + IL_0013: brfalse IL_0122 + + IL_0018: volatile. + IL_001a: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000016-1' + IL_001f: brtrue.s IL_008e + + IL_0021: ldc.i4.8 + IL_0022: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor(int32) + IL_0027: dup + IL_0028: ldstr "1" + IL_002d: ldc.i4.0 + IL_002e: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0033: dup + IL_0034: ldstr "2" + IL_0039: ldc.i4.1 + IL_003a: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_003f: dup + IL_0040: ldstr "3" + IL_0045: ldc.i4.2 + IL_0046: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_004b: dup + IL_004c: ldstr "4" + IL_0051: ldc.i4.3 + IL_0052: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0057: dup + IL_0058: ldstr "5" + IL_005d: ldc.i4.4 + IL_005e: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0063: dup + IL_0064: ldstr "6" + IL_0069: ldc.i4.5 + IL_006a: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_006f: dup + IL_0070: ldstr "8" + IL_0075: ldc.i4.6 + IL_0076: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_007b: dup + IL_007c: ldstr "7" + IL_0081: ldc.i4.7 + IL_0082: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, + !1) + IL_0087: volatile. + IL_0089: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000016-1' + IL_008e: volatile. + IL_0090: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000016-1' + IL_0095: ldloc.0 + IL_0096: ldloca.s V_1 + IL_0098: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, + !1&) + IL_009d: brfalse IL_0122 + + IL_00a2: ldloc.1 + IL_00a3: switch ( + IL_00ca, + IL_00d6, + IL_00e0, + IL_00f5, + IL_00ff, + IL_010b, + IL_0117, + IL_012c) + IL_00c8: br.s IL_0122 + + IL_00ca: ldstr "one" + IL_00cf: call void [mscorlib]System.Console::WriteLine(string) + IL_00d4: br.s IL_0117 + + IL_00d6: ldstr "two" + IL_00db: call void [mscorlib]System.Console::WriteLine(string) + IL_00e0: ldstr "three" + IL_00e5: call void [mscorlib]System.Console::WriteLine(string) + IL_00ea: ldarg.0 + IL_00eb: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_00f0: ldc.i4.2 + IL_00f1: beq.s IL_00ff + + IL_00f3: br.s IL_012c + + IL_00f5: ldstr "four" + IL_00fa: call void [mscorlib]System.Console::WriteLine(string) + IL_00ff: ldstr "five" + IL_0104: call void [mscorlib]System.Console::WriteLine(string) + IL_0109: br.s IL_0117 + + IL_010b: ldstr "six" + IL_0110: call void [mscorlib]System.Console::WriteLine(string) + IL_0115: br.s IL_00ff + + IL_0117: ldstr "eight" + IL_011c: call void [mscorlib]System.Console::WriteLine(string) + IL_0121: ret + + IL_0122: ldstr "default" + IL_0127: call void [mscorlib]System.Console::WriteLine(string) + IL_012c: ldstr "End of method" + IL_0131: call void [mscorlib]System.Console::WriteLine(string) + IL_0136: ret + } // end of method Switch::SwitchWithGotoComplex + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch/SetProperty[] GetProperties() cil managed { @@ -1135,7 +1521,7 @@ IL_0037: brfalse IL_011f IL_003c: volatile. - IL_003e: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000013-1' + IL_003e: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000018-1' IL_0043: brtrue.s IL_009a IL_0045: ldc.i4.6 @@ -1171,9 +1557,9 @@ IL_008e: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2::Add(!0, !1) IL_0093: volatile. - IL_0095: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000013-1' + IL_0095: stsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000018-1' IL_009a: volatile. - IL_009c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000013-1' + IL_009c: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2 ''::'$$method0x6000018-1' IL_00a1: ldloc.s V_5 IL_00a3: ldloca.s V_6 IL_00a5: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2::TryGetValue(!0, @@ -1365,15 +1751,1084 @@ IL_0075: ret } // end of method Switch::SwitchWithArray + .method public hidebysig static void SwitchWithContinue1(int32 i, + bool b) cil managed + { + // Code size 37 (0x25) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: switch ( + IL_0016, + IL_0000, + IL_001b) + IL_0014: br.s IL_001e + + IL_0016: ldarg.1 + IL_0017: brfalse.s IL_001e + + IL_0019: br.s IL_0000 + + IL_001b: ldarg.1 + IL_001c: brfalse.s IL_0000 + + IL_001e: call void [mscorlib]System.Console::WriteLine() + IL_0023: br.s IL_0000 + } // end of method Switch::SwitchWithContinue1 + + .method public hidebysig static void SwitchWithContinue2(int32 i, + bool b) cil managed + { + // Code size 112 (0x70) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: br.s IL_006a + + IL_0002: ldarg.0 + IL_0003: stloc.0 + IL_0004: ldloc.0 + IL_0005: switch ( + IL_001c, + IL_006a, + IL_0037, + IL_005b) + IL_001a: br.s IL_0051 + + IL_001c: ldarg.1 + IL_001d: brfalse.s IL_002b + + IL_001f: ldstr "0b" + IL_0024: call void [mscorlib]System.Console::WriteLine(string) + IL_0029: br.s IL_006a + + IL_002b: ldstr "0!b" + IL_0030: call void [mscorlib]System.Console::WriteLine(string) + IL_0035: br.s IL_005b + + IL_0037: ldarg.1 + IL_0038: brfalse.s IL_0045 + + IL_003a: ldstr "2b" + IL_003f: call void [mscorlib]System.Console::WriteLine(string) + IL_0044: ret + + IL_0045: ldstr "2!b" + IL_004a: call void [mscorlib]System.Console::WriteLine(string) + IL_004f: br.s IL_006a + + IL_0051: ldstr "default" + IL_0056: call void [mscorlib]System.Console::WriteLine(string) + IL_005b: ldstr "loop-tail" + IL_0060: call void [mscorlib]System.Console::WriteLine(string) + IL_0065: ldarg.0 + IL_0066: ldc.i4.1 + IL_0067: add + IL_0068: starg.s i + IL_006a: ldarg.0 + IL_006b: ldc.i4.s 10 + IL_006d: blt.s IL_0002 + + IL_006f: ret + } // end of method Switch::SwitchWithContinue2 + + .method public hidebysig static void SwitchWithContinue3(bool b) cil managed + { + // Code size 113 (0x71) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: br.s IL_006b + + IL_0004: ldloc.0 + IL_0005: stloc.1 + IL_0006: ldloc.1 + IL_0007: switch ( + IL_001e, + IL_0067, + IL_0039, + IL_005d) + IL_001c: br.s IL_0053 + + IL_001e: ldarg.0 + IL_001f: brfalse.s IL_002d + + IL_0021: ldstr "0b" + IL_0026: call void [mscorlib]System.Console::WriteLine(string) + IL_002b: br.s IL_0067 + + IL_002d: ldstr "0!b" + IL_0032: call void [mscorlib]System.Console::WriteLine(string) + IL_0037: br.s IL_005d + + IL_0039: ldarg.0 + IL_003a: brfalse.s IL_0047 + + IL_003c: ldstr "2b" + IL_0041: call void [mscorlib]System.Console::WriteLine(string) + IL_0046: ret + + IL_0047: ldstr "2!b" + IL_004c: call void [mscorlib]System.Console::WriteLine(string) + IL_0051: br.s IL_0067 + + IL_0053: ldstr "default" + IL_0058: call void [mscorlib]System.Console::WriteLine(string) + IL_005d: ldstr "loop-tail" + IL_0062: call void [mscorlib]System.Console::WriteLine(string) + IL_0067: ldloc.0 + IL_0068: ldc.i4.1 + IL_0069: add + IL_006a: stloc.0 + IL_006b: ldloc.0 + IL_006c: ldc.i4.s 10 + IL_006e: blt.s IL_0004 + + IL_0070: ret + } // end of method Switch::SwitchWithContinue3 + + .method public hidebysig static void SwitchWithContinue4(bool b) cil managed + { + // Code size 190 (0xbe) + .maxstack 2 + .locals init (int32 V_0, + class [mscorlib]System.Collections.Generic.IEnumerator`1 V_1, + int32 V_2) + IL_0000: ldc.i4.0 + IL_0001: ldc.i4.s 10 + IL_0003: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Range(int32, + int32) + IL_0008: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_000d: stloc.1 + .try + { + IL_000e: br IL_00a6 + + IL_0013: ldloc.1 + IL_0014: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() + IL_0019: stloc.0 + IL_001a: ldstr "loop: " + IL_001f: ldloc.0 + IL_0020: box [mscorlib]System.Int32 + IL_0025: call string [mscorlib]System.String::Concat(object, + object) + IL_002a: call void [mscorlib]System.Console::WriteLine(string) + IL_002f: ldloc.0 + IL_0030: stloc.2 + IL_0031: ldloc.2 + IL_0032: ldc.i4.1 + IL_0033: sub + IL_0034: switch ( + IL_005b, + IL_00a6, + IL_0060, + IL_0065, + IL_006d, + IL_0075, + IL_007a, + IL_0082) + IL_0059: br.s IL_0087 + + IL_005b: ldarg.0 + IL_005c: brfalse.s IL_0091 + + IL_005e: br.s IL_00a6 + + IL_0060: ldarg.0 + IL_0061: brfalse.s IL_00a6 + + IL_0063: leave.s IL_00bd + + IL_0065: ldc.i4.4 + IL_0066: call void [mscorlib]System.Console::WriteLine(int32) + IL_006b: br.s IL_007a + + IL_006d: ldc.i4.5 + IL_006e: call void [mscorlib]System.Console::WriteLine(int32) + IL_0073: br.s IL_0087 + + IL_0075: ldarg.0 + IL_0076: brfalse.s IL_0060 + + IL_0078: br.s IL_00a6 + + IL_007a: ldloc.0 + IL_007b: ldc.i4.2 + IL_007c: rem + IL_007d: brfalse.s IL_0060 + + IL_007f: ldarg.0 + IL_0080: brfalse.s IL_00a6 + + IL_0082: ldarg.0 + IL_0083: brfalse.s IL_006d + + IL_0085: br.s IL_00a6 + + IL_0087: ldstr "default" + IL_008c: call void [mscorlib]System.Console::WriteLine(string) + IL_0091: ldstr "break: " + IL_0096: ldloc.0 + IL_0097: box [mscorlib]System.Int32 + IL_009c: call string [mscorlib]System.String::Concat(object, + object) + IL_00a1: call void [mscorlib]System.Console::WriteLine(string) + IL_00a6: ldloc.1 + IL_00a7: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_00ac: brtrue IL_0013 + + IL_00b1: leave.s IL_00bd + + } // end .try + finally + { + IL_00b3: ldloc.1 + IL_00b4: brfalse.s IL_00bc + + IL_00b6: ldloc.1 + IL_00b7: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_00bc: endfinally + } // end handler + IL_00bd: ret + } // end of method Switch::SwitchWithContinue4 + + .method public hidebysig static void SwitchWithContinue5(bool b) cil managed + { + // Code size 127 (0x7f) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: br.s IL_0079 + + IL_0004: ldloc.0 + IL_0005: ldc.i4.5 + IL_0006: bge.s IL_006b + + IL_0008: ldloc.0 + IL_0009: stloc.1 + IL_000a: ldloc.1 + IL_000b: switch ( + IL_0022, + IL_0075, + IL_003d, + IL_0061) + IL_0020: br.s IL_0057 + + IL_0022: ldarg.0 + IL_0023: brfalse.s IL_0031 + + IL_0025: ldstr "0b" + IL_002a: call void [mscorlib]System.Console::WriteLine(string) + IL_002f: br.s IL_0075 + + IL_0031: ldstr "0!b" + IL_0036: call void [mscorlib]System.Console::WriteLine(string) + IL_003b: br.s IL_0061 + + IL_003d: ldarg.0 + IL_003e: brfalse.s IL_004b + + IL_0040: ldstr "2b" + IL_0045: call void [mscorlib]System.Console::WriteLine(string) + IL_004a: ret + + IL_004b: ldstr "2!b" + IL_0050: call void [mscorlib]System.Console::WriteLine(string) + IL_0055: br.s IL_0075 + + IL_0057: ldstr "default" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: ldstr "break-target" + IL_0066: call void [mscorlib]System.Console::WriteLine(string) + IL_006b: ldstr "loop-tail" + IL_0070: call void [mscorlib]System.Console::WriteLine(string) + IL_0075: ldloc.0 + IL_0076: ldc.i4.1 + IL_0077: add + IL_0078: stloc.0 + IL_0079: ldloc.0 + IL_007a: ldc.i4.s 10 + IL_007c: blt.s IL_0004 + + IL_007e: ret + } // end of method Switch::SwitchWithContinue5 + + .method public hidebysig static void SwitchWithContinue6(int32 i, + bool b) cil managed + { + // Code size 110 (0x6e) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: switch ( + IL_001a, + IL_0063, + IL_0035, + IL_0059) + IL_0018: br.s IL_004f + + IL_001a: ldarg.1 + IL_001b: brtrue.s IL_0029 + + IL_001d: ldstr "0!b" + IL_0022: call void [mscorlib]System.Console::WriteLine(string) + IL_0027: br.s IL_0059 + + IL_0029: ldstr "0b" + IL_002e: call void [mscorlib]System.Console::WriteLine(string) + IL_0033: br.s IL_0063 + + IL_0035: ldarg.1 + IL_0036: brfalse.s IL_0043 + + IL_0038: ldstr "2b" + IL_003d: call void [mscorlib]System.Console::WriteLine(string) + IL_0042: ret + + IL_0043: ldstr "2!b" + IL_0048: call void [mscorlib]System.Console::WriteLine(string) + IL_004d: br.s IL_0063 + + IL_004f: ldstr "default" + IL_0054: call void [mscorlib]System.Console::WriteLine(string) + IL_0059: ldstr "loop-tail" + IL_005e: call void [mscorlib]System.Console::WriteLine(string) + IL_0063: ldarg.0 + IL_0064: ldc.i4.1 + IL_0065: add + IL_0066: dup + IL_0067: starg.s i + IL_0069: ldc.i4.s 10 + IL_006b: blt.s IL_0000 + + IL_006d: ret + } // end of method Switch::SwitchWithContinue6 + + .method public hidebysig static void SwitchWithContinue7() cil managed + { + // Code size 61 (0x3d) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: br.s IL_002e + + IL_0004: ldstr "loop-head" + IL_0009: call void [mscorlib]System.Console::WriteLine(string) + IL_000e: ldloc.0 + IL_000f: stloc.1 + IL_0010: ldloc.1 + IL_0011: switch ( + IL_002a, + IL_0032) + IL_001e: ldstr "default" + IL_0023: call void [mscorlib]System.Console::WriteLine(string) + IL_0028: br.s IL_0032 + + IL_002a: ldloc.0 + IL_002b: ldc.i4.1 + IL_002c: sub + IL_002d: stloc.0 + IL_002e: ldloc.0 + IL_002f: ldc.i4.0 + IL_0030: bge.s IL_0004 + + IL_0032: ldstr "end" + IL_0037: call void [mscorlib]System.Console::WriteLine(string) + IL_003c: ret + } // end of method Switch::SwitchWithContinue7 + + .method public hidebysig static void SwitchWithContinueInDoubleLoop() cil managed + { + // Code size 105 (0x69) + .maxstack 2 + .locals init (bool V_0, + int32 V_1, + int32 V_2, + int32 V_3) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: ldc.i4.0 + IL_0003: stloc.1 + IL_0004: br.s IL_005d + + IL_0006: ldc.i4.0 + IL_0007: stloc.2 + IL_0008: br.s IL_0054 + + IL_000a: ldloc.1 + IL_000b: ldloc.2 + IL_000c: add + IL_000d: stloc.3 + IL_000e: ldloc.3 + IL_000f: ldc.i4.1 + IL_0010: sub + IL_0011: switch ( + IL_004c, + IL_0050, + IL_004c, + IL_0050, + IL_004c, + IL_0050, + IL_004c) + IL_0032: ldloc.3 + IL_0033: ldc.i4.s 11 + IL_0035: sub + IL_0036: switch ( + IL_004c, + IL_0050, + IL_004c) + IL_0047: ldloc.3 + IL_0048: ldc.i4.s 17 + IL_004a: bne.un.s IL_0050 + + IL_004c: ldc.i4.1 + IL_004d: stloc.0 + IL_004e: br.s IL_0059 + + IL_0050: ldloc.2 + IL_0051: ldc.i4.1 + IL_0052: add + IL_0053: stloc.2 + IL_0054: ldloc.2 + IL_0055: ldc.i4.s 10 + IL_0057: blt.s IL_000a + + IL_0059: ldloc.1 + IL_005a: ldc.i4.1 + IL_005b: add + IL_005c: stloc.1 + IL_005d: ldloc.1 + IL_005e: ldc.i4.s 10 + IL_0060: blt.s IL_0006 + + IL_0062: ldloc.0 + IL_0063: call void [mscorlib]System.Console::WriteLine(bool) + IL_0068: ret + } // end of method Switch::SwitchWithContinueInDoubleLoop + + .method public hidebysig static void SwitchLoopNesting() cil managed + { + // Code size 101 (0x65) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: br.s IL_005f + + IL_0004: ldloc.0 + IL_0005: stloc.1 + IL_0006: ldloc.1 + IL_0007: switch ( + IL_0016, + IL_001e) + IL_0014: br.s IL_0026 + + IL_0016: ldc.i4.0 + IL_0017: call void [mscorlib]System.Console::WriteLine(int32) + IL_001c: br.s IL_0041 + + IL_001e: ldc.i4.1 + IL_001f: call void [mscorlib]System.Console::WriteLine(int32) + IL_0024: br.s IL_0041 + + IL_0026: ldloc.0 + IL_0027: ldc.i4.2 + IL_0028: rem + IL_0029: brtrue.s IL_003c + + IL_002b: br.s IL_0037 + + IL_002d: ldloc.0 + IL_002e: dup + IL_002f: ldc.i4.1 + IL_0030: add + IL_0031: stloc.0 + IL_0032: call void [mscorlib]System.Console::WriteLine(int32) + IL_0037: ldloc.0 + IL_0038: ldc.i4.3 + IL_0039: rem + IL_003a: brtrue.s IL_002d + + IL_003c: call void [mscorlib]System.Console::WriteLine() + IL_0041: ldloc.0 + IL_0042: ldc.i4.4 + IL_0043: ble.s IL_0051 + + IL_0045: ldstr "high" + IL_004a: call void [mscorlib]System.Console::WriteLine(string) + IL_004f: br.s IL_005b + + IL_0051: ldstr "low" + IL_0056: call void [mscorlib]System.Console::WriteLine(string) + IL_005b: ldloc.0 + IL_005c: ldc.i4.1 + IL_005d: add + IL_005e: stloc.0 + IL_005f: ldloc.0 + IL_0060: ldc.i4.s 10 + IL_0062: blt.s IL_0004 + + IL_0064: ret + } // end of method Switch::SwitchLoopNesting + + .method public hidebysig static void SingleIf1(int32 i, + bool a) cil managed + { + // Code size 24 (0x18) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: beq.s IL_000b + + IL_0004: ldarg.0 + IL_0005: ldc.i4.2 + IL_0006: bne.un.s IL_0011 + + IL_0008: ldarg.1 + IL_0009: brfalse.s IL_0011 + + IL_000b: ldc.i4.1 + IL_000c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0011: ldc.i4.2 + IL_0012: call void [mscorlib]System.Console::WriteLine(int32) + IL_0017: ret + } // end of method Switch::SingleIf1 + + .method public hidebysig static void SingleIf2(int32 i, + bool a, + bool b) cil managed + { + // Code size 31 (0x1f) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: beq.s IL_0012 + + IL_0004: ldarg.0 + IL_0005: ldc.i4.2 + IL_0006: bne.un.s IL_000b + + IL_0008: ldarg.1 + IL_0009: brtrue.s IL_0012 + + IL_000b: ldarg.0 + IL_000c: ldc.i4.3 + IL_000d: bne.un.s IL_0018 + + IL_000f: ldarg.2 + IL_0010: brfalse.s IL_0018 + + IL_0012: ldc.i4.1 + IL_0013: call void [mscorlib]System.Console::WriteLine(int32) + IL_0018: ldc.i4.2 + IL_0019: call void [mscorlib]System.Console::WriteLine(int32) + IL_001e: ret + } // end of method Switch::SingleIf2 + + .method public hidebysig static void SingleIf3(int32 i, + bool a, + bool b) cil managed + { + // Code size 27 (0x1b) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: brtrue.s IL_000e + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: beq.s IL_000e + + IL_0007: ldarg.0 + IL_0008: ldc.i4.2 + IL_0009: bne.un.s IL_0014 + + IL_000b: ldarg.2 + IL_000c: brfalse.s IL_0014 + + IL_000e: ldc.i4.1 + IL_000f: call void [mscorlib]System.Console::WriteLine(int32) + IL_0014: ldc.i4.2 + IL_0015: call void [mscorlib]System.Console::WriteLine(int32) + IL_001a: ret + } // end of method Switch::SingleIf3 + + .method public hidebysig static void SingleIf4(int32 i, + bool a) cil managed + { + // Code size 32 (0x20) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: beq.s IL_0013 + + IL_0004: ldarg.0 + IL_0005: ldc.i4.2 + IL_0006: beq.s IL_0013 + + IL_0008: ldarg.0 + IL_0009: ldc.i4.3 + IL_000a: beq.s IL_000f + + IL_000c: ldarg.1 + IL_000d: brtrue.s IL_0013 + + IL_000f: ldarg.0 + IL_0010: ldc.i4.4 + IL_0011: beq.s IL_0019 + + IL_0013: ldc.i4.1 + IL_0014: call void [mscorlib]System.Console::WriteLine(int32) + IL_0019: ldc.i4.2 + IL_001a: call void [mscorlib]System.Console::WriteLine(int32) + IL_001f: ret + } // end of method Switch::SingleIf4 + + .method public hidebysig static void NestedIf(int32 i) cil managed + { + // Code size 30 (0x1e) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: beq.s IL_0018 + + IL_0004: ldarg.0 + IL_0005: ldc.i4.2 + IL_0006: bne.un.s IL_000e + + IL_0008: ldc.i4.2 + IL_0009: call void [mscorlib]System.Console::WriteLine(int32) + IL_000e: ldstr "default" + IL_0013: call void [mscorlib]System.Console::WriteLine(string) + IL_0018: call void [mscorlib]System.Console::WriteLine() + IL_001d: ret + } // end of method Switch::NestedIf + + .method public hidebysig static void IfChainWithCondition(int32 i) cil managed + { + // Code size 98 (0x62) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: brtrue.s IL_000b + + IL_0003: ldc.i4.0 + IL_0004: call void [mscorlib]System.Console::WriteLine(int32) + IL_0009: br.s IL_005c + + IL_000b: ldarg.0 + IL_000c: ldc.i4.1 + IL_000d: bne.un.s IL_0017 + + IL_000f: ldc.i4.1 + IL_0010: call void [mscorlib]System.Console::WriteLine(int32) + IL_0015: br.s IL_005c + + IL_0017: ldarg.0 + IL_0018: ldc.i4.2 + IL_0019: bne.un.s IL_0023 + + IL_001b: ldc.i4.2 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: br.s IL_005c + + IL_0023: ldarg.0 + IL_0024: ldc.i4.3 + IL_0025: bne.un.s IL_002f + + IL_0027: ldc.i4.3 + IL_0028: call void [mscorlib]System.Console::WriteLine(int32) + IL_002d: br.s IL_005c + + IL_002f: ldarg.0 + IL_0030: ldc.i4.4 + IL_0031: bne.un.s IL_003b + + IL_0033: ldc.i4.4 + IL_0034: call void [mscorlib]System.Console::WriteLine(int32) + IL_0039: br.s IL_005c + + IL_003b: ldarg.0 + IL_003c: ldc.i4.5 + IL_003d: bne.un.s IL_0052 + + IL_003f: call bool [mscorlib]System.Console::get_CapsLock() + IL_0044: brfalse.s IL_0052 + + IL_0046: ldstr "5A" + IL_004b: call void [mscorlib]System.Console::WriteLine(string) + IL_0050: br.s IL_005c + + IL_0052: ldstr "default" + IL_0057: call void [mscorlib]System.Console::WriteLine(string) + IL_005c: call void [mscorlib]System.Console::WriteLine() + IL_0061: ret + } // end of method Switch::IfChainWithCondition + + .method public hidebysig static bool SwitchlikeIf(int32 i, + int32 j) cil managed + { + // Code size 148 (0x94) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0050 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0050 + + IL_0006: ldarg.0 + IL_0007: ldc.i4.m1 + IL_0008: bne.un.s IL_0018 + + IL_000a: ldarg.1 + IL_000b: ldc.i4.m1 + IL_000c: bne.un.s IL_0018 + + IL_000e: ldstr "-1, -1" + IL_0013: call void [mscorlib]System.Console::WriteLine(string) + IL_0018: ldarg.0 + IL_0019: ldc.i4.m1 + IL_001a: bne.un.s IL_002a + + IL_001c: ldarg.1 + IL_001d: ldc.i4.1 + IL_001e: bne.un.s IL_002a + + IL_0020: ldstr "-1, 1" + IL_0025: call void [mscorlib]System.Console::WriteLine(string) + IL_002a: ldarg.0 + IL_002b: ldc.i4.1 + IL_002c: bne.un.s IL_003c + + IL_002e: ldarg.1 + IL_002f: ldc.i4.m1 + IL_0030: bne.un.s IL_003c + + IL_0032: ldstr "1, -1" + IL_0037: call void [mscorlib]System.Console::WriteLine(string) + IL_003c: ldarg.0 + IL_003d: ldc.i4.1 + IL_003e: bne.un.s IL_004e + + IL_0040: ldarg.1 + IL_0041: ldc.i4.1 + IL_0042: bne.un.s IL_004e + + IL_0044: ldstr "1, 1" + IL_0049: call void [mscorlib]System.Console::WriteLine(string) + IL_004e: ldc.i4.0 + IL_004f: ret + + IL_0050: ldarg.0 + IL_0051: brfalse.s IL_0071 + + IL_0053: ldarg.0 + IL_0054: ldc.i4.m1 + IL_0055: bne.un.s IL_0061 + + IL_0057: ldstr "-1, 0" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: ldarg.0 + IL_0062: ldc.i4.1 + IL_0063: bne.un.s IL_006f + + IL_0065: ldstr "1, 0" + IL_006a: call void [mscorlib]System.Console::WriteLine(string) + IL_006f: ldc.i4.0 + IL_0070: ret + + IL_0071: ldarg.1 + IL_0072: brfalse.s IL_0092 + + IL_0074: ldarg.1 + IL_0075: ldc.i4.m1 + IL_0076: bne.un.s IL_0082 + + IL_0078: ldstr "0, -1" + IL_007d: call void [mscorlib]System.Console::WriteLine(string) + IL_0082: ldarg.1 + IL_0083: ldc.i4.1 + IL_0084: bne.un.s IL_0090 + + IL_0086: ldstr "0, 1" + IL_008b: call void [mscorlib]System.Console::WriteLine(string) + IL_0090: ldc.i4.0 + IL_0091: ret + + IL_0092: ldc.i4.1 + IL_0093: ret + } // end of method Switch::SwitchlikeIf + + .method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed + { + // Code size 37 (0x25) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0023 + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: bne.un.s IL_000d + + IL_0007: ldc.i4.1 + IL_0008: call void [mscorlib]System.Console::WriteLine(int32) + IL_000d: ldarg.0 + IL_000e: ldc.i4.2 + IL_000f: bne.un.s IL_0017 + + IL_0011: ldc.i4.2 + IL_0012: call void [mscorlib]System.Console::WriteLine(int32) + IL_0017: ldarg.0 + IL_0018: ldc.i4.3 + IL_0019: bne.un.s IL_0021 + + IL_001b: ldc.i4.3 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: ldc.i4.0 + IL_0022: ret + + IL_0023: ldc.i4.0 + IL_0024: ret + } // end of method Switch::SwitchlikeIf2 + + .method public hidebysig static void SingleIntervalIf(char c) cil managed + { + // Code size 31 (0x1f) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.s 65 + IL_0003: blt.s IL_0014 + + IL_0005: ldarg.0 + IL_0006: ldc.i4.s 90 + IL_0008: bgt.s IL_0014 + + IL_000a: ldstr "alphabet" + IL_000f: call void [mscorlib]System.Console::WriteLine(string) + IL_0014: ldstr "end" + IL_0019: call void [mscorlib]System.Console::WriteLine(string) + IL_001e: ret + } // end of method Switch::SingleIntervalIf + + .method public hidebysig static bool Loop8(char c, + bool b, + class [mscorlib]System.Func`1 getChar) cil managed + { + // Code size 35 (0x23) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: brfalse.s IL_0021 + + IL_0003: br.s IL_000d + + IL_0005: ldarg.2 + IL_0006: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_000b: starg.s c + IL_000d: ldarg.0 + IL_000e: ldc.i4.s 97 + IL_0010: blt.s IL_0017 + + IL_0012: ldarg.0 + IL_0013: ldc.i4.s 122 + IL_0015: ble.s IL_0005 + + IL_0017: ldarg.0 + IL_0018: ldc.i4.s 65 + IL_001a: blt.s IL_0021 + + IL_001c: ldarg.0 + IL_001d: ldc.i4.s 90 + IL_001f: ble.s IL_0005 + + IL_0021: ldc.i4.1 + IL_0022: ret + } // end of method Switch::Loop8 + + .method public hidebysig static void Loop9(class [mscorlib]System.Func`1 getChar) cil managed + { + // Code size 33 (0x21) + .maxstack 2 + .locals init (char V_0) + IL_0000: ldarg.0 + IL_0001: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: ldc.i4.m1 + IL_0009: beq.s IL_0020 + + IL_000b: ldloc.0 + IL_000c: ldc.i4.s 10 + IL_000e: beq.s IL_0020 + + IL_0010: ldloc.0 + IL_0011: ldc.i4 0x2028 + IL_0016: beq.s IL_0020 + + IL_0018: ldloc.0 + IL_0019: ldc.i4 0x2029 + IL_001e: bne.un.s IL_0000 + + IL_0020: ret + } // end of method Switch::Loop9 + + .method public hidebysig static void SwitchWithBreakCase(int32 i, + bool b) cil managed + { + // Code size 62 (0x3e) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldarg.1 + IL_0001: brfalse.s IL_0033 + + IL_0003: ldarg.0 + IL_0004: stloc.0 + IL_0005: ldloc.0 + IL_0006: ldc.i4.1 + IL_0007: sub + IL_0008: switch ( + IL_0017, + IL_0029) + IL_0015: br.s IL_001f + + IL_0017: ldc.i4.1 + IL_0018: call void [mscorlib]System.Console::WriteLine(int32) + IL_001d: br.s IL_0029 + + IL_001f: ldstr "default" + IL_0024: call void [mscorlib]System.Console::WriteLine(string) + IL_0029: ldstr "b" + IL_002e: call void [mscorlib]System.Console::WriteLine(string) + IL_0033: ldstr "end" + IL_0038: call void [mscorlib]System.Console::WriteLine(string) + IL_003d: ret + } // end of method Switch::SwitchWithBreakCase + + .method public hidebysig static void SwitchWithReturnAndBreak(int32 i, + bool b) cil managed + { + // Code size 32 (0x20) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: switch ( + IL_0012, + IL_0016) + IL_0010: br.s IL_001a + + IL_0012: ldarg.1 + IL_0013: brfalse.s IL_001a + + IL_0015: ret + + IL_0016: ldarg.1 + IL_0017: brtrue.s IL_001a + + IL_0019: ret + + IL_001a: call void [mscorlib]System.Console::WriteLine() + IL_001f: ret + } // end of method Switch::SwitchWithReturnAndBreak + + .method public hidebysig static int32 SwitchWithReturnAndBreak2(int32 i, + bool b) cil managed + { + // Code size 79 (0x4f) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: ldc.i4 0x14e + IL_0008: bgt.s IL_001d + + IL_000a: ldloc.0 + IL_000b: ldc.i4.4 + IL_000c: beq.s IL_0037 + + IL_000e: ldloc.0 + IL_000f: ldc.i4.s 33 + IL_0011: beq.s IL_0037 + + IL_0013: ldloc.0 + IL_0014: ldc.i4 0x14e + IL_0019: beq.s IL_003e + + IL_001b: br.s IL_0048 + + IL_001d: ldloc.0 + IL_001e: ldc.i4 0x18b + IL_0023: beq.s IL_0043 + + IL_0025: ldloc.0 + IL_0026: ldc.i4 0x19a + IL_002b: beq.s IL_0043 + + IL_002d: ldloc.0 + IL_002e: ldc.i4 0x1c7 + IL_0033: beq.s IL_0043 + + IL_0035: br.s IL_0048 + + IL_0037: call void [mscorlib]System.Console::WriteLine() + IL_003c: ldc.i4.1 + IL_003d: ret + + IL_003e: ldarg.1 + IL_003f: brfalse.s IL_0048 + + IL_0041: ldc.i4.2 + IL_0042: ret + + IL_0043: call void [mscorlib]System.Console::WriteLine() + IL_0048: call void [mscorlib]System.Console::WriteLine() + IL_004d: ldc.i4.0 + IL_004e: ret + } // end of method Switch::SwitchWithReturnAndBreak2 + + .method public hidebysig static void SwitchWithReturnAndBreak3(int32 i) cil managed + { + // Code size 37 (0x25) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: ldarg.0 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: switch ( + IL_0011, + IL_0019) + IL_0010: ret + + IL_0011: ldc.i4.0 + IL_0012: call void [mscorlib]System.Console::WriteLine(int32) + IL_0017: br.s IL_001f + + IL_0019: ldc.i4.1 + IL_001a: call void [mscorlib]System.Console::WriteLine(int32) + IL_001f: call void [mscorlib]System.Console::WriteLine() + IL_0024: ret + } // end of method Switch::SwitchWithReturnAndBreak3 + } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch .class private auto ansi '' 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 '$$method0x600000d-1' - .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x600000e-1' - .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000013-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000010-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000011-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000015-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000016-1' + .field static assembly class [mscorlib]System.Collections.Generic.Dictionary`2 '$$method0x6000018-1' } // end of class '' diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il index d1fcf4714..a5c1af55f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il @@ -8,6 +8,11 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } +.assembly extern System.Core +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} .assembly Switch { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) @@ -269,6 +274,104 @@ IL_00b8: ret } // end of method Switch::SparseIntegerSwitch + .method public hidebysig static void SparseIntegerSwitch2(int32 i) cil managed + { + // Code size 67 (0x43) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: ldc.i4.s 21 + IL_0003: bgt.s IL_0021 + + IL_0005: ldarg.0 + IL_0006: ldc.i4.s 11 + IL_0008: bgt.s IL_0016 + + IL_000a: ldarg.0 + IL_000b: ldc.i4.4 + IL_000c: beq.s IL_003d + + IL_000e: ldarg.0 + IL_000f: ldc.i4.s 10 + IL_0011: sub + IL_0012: ldc.i4.1 + IL_0013: ble.un.s IL_003d + + IL_0015: ret + + IL_0016: ldarg.0 + IL_0017: ldc.i4.s 13 + IL_0019: beq.s IL_003d + + IL_001b: ldarg.0 + IL_001c: ldc.i4.s 21 + IL_001e: beq.s IL_003d + + IL_0020: ret + + IL_0021: ldarg.0 + IL_0022: ldc.i4.s 33 + IL_0024: bgt.s IL_0031 + + IL_0026: ldarg.0 + IL_0027: ldc.i4.s 29 + IL_0029: beq.s IL_003d + + IL_002b: ldarg.0 + IL_002c: ldc.i4.s 33 + IL_002e: beq.s IL_003d + + IL_0030: ret + + IL_0031: ldarg.0 + IL_0032: ldc.i4.s 49 + IL_0034: sub + IL_0035: ldc.i4.1 + IL_0036: ble.un.s IL_003d + + IL_0038: ldarg.0 + IL_0039: ldc.i4.s 55 + IL_003b: bne.un.s IL_0042 + + IL_003d: call void [mscorlib]System.Console::WriteLine() + IL_0042: ret + } // end of method Switch::SparseIntegerSwitch2 + + .method public hidebysig static bool SparseIntegerSwitch3(int32 i) cil managed + { + // Code size 36 (0x24) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.s 12 + IL_0003: bgt.s IL_0011 + + IL_0005: ldarg.0 + IL_0006: brfalse.s IL_0020 + + IL_0008: ldarg.0 + IL_0009: ldc.i4.s 10 + IL_000b: sub + IL_000c: ldc.i4.2 + IL_000d: ble.un.s IL_0020 + + IL_000f: br.s IL_0022 + + IL_0011: ldarg.0 + IL_0012: ldc.i4.s 100 + IL_0014: sub + IL_0015: ldc.i4.1 + IL_0016: ble.un.s IL_0020 + + IL_0018: ldarg.0 + IL_0019: ldc.i4 0xc8 + IL_001e: bne.un.s IL_0022 + + IL_0020: ldc.i4.1 + IL_0021: ret + + IL_0022: ldc.i4.0 + IL_0023: ret + } // end of method Switch::SparseIntegerSwitch3 + .method public hidebysig static string SwitchOverNullableInt(valuetype [mscorlib]System.Nullable`1 i) cil managed { @@ -652,6 +755,35 @@ IL_0079: ret } // end of method Switch::SwitchOverInt + .method public hidebysig static void CompactSwitchOverInt(int32 i) cil managed + { + // Code size 55 (0x37) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.2 + IL_0002: ble.un.s IL_000a + + IL_0004: ldarg.0 + IL_0005: ldc.i4.3 + IL_0006: beq.s IL_0016 + + IL_0008: br.s IL_0022 + + IL_000a: ldstr "012" + IL_000f: call void [mscorlib]System.Console::WriteLine(string) + IL_0014: br.s IL_002c + + IL_0016: ldstr "3" + IL_001b: call void [mscorlib]System.Console::WriteLine(string) + IL_0020: br.s IL_002c + + IL_0022: ldstr "default" + IL_0027: call void [mscorlib]System.Console::WriteLine(string) + IL_002c: ldstr "end" + IL_0031: call void [mscorlib]System.Console::WriteLine(string) + IL_0036: ret + } // end of method Switch::CompactSwitchOverInt + .method public hidebysig static string ShortSwitchOverString(string text) cil managed { @@ -1203,6 +1335,353 @@ IL_0070: ret } // end of method Switch::SwitchWithGoto + .method public hidebysig static void SwitchWithGotoString(string s) cil managed + { + // Code size 443 (0x1bb) + .maxstack 2 + .locals init (uint32 V_0) + IL_0000: ldstr "SwitchWithGotoString: " + IL_0005: ldarg.0 + IL_0006: call string [mscorlib]System.String::Concat(string, + string) + IL_000b: call void [mscorlib]System.Console::WriteLine(string) + IL_0010: ldarg.0 + IL_0011: call uint32 ''::ComputeStringHash(string) + IL_0016: stloc.0 + IL_0017: ldloc.0 + IL_0018: ldc.i4 0x330ca589 + IL_001d: bgt.un.s IL_005d + + IL_001f: ldloc.0 + IL_0020: ldc.i4 0x310ca263 + IL_0025: bgt.un.s IL_0042 + + IL_0027: ldloc.0 + IL_0028: ldc.i4 0x300ca0d0 + IL_002d: beq IL_00ee + + IL_0032: ldloc.0 + IL_0033: ldc.i4 0x310ca263 + IL_0038: beq IL_00dc + + IL_003d: br IL_01a6 + + IL_0042: ldloc.0 + IL_0043: ldc.i4 0x320ca3f6 + IL_0048: beq IL_0112 + + IL_004d: ldloc.0 + IL_004e: ldc.i4 0x330ca589 + IL_0053: beq IL_0100 + + IL_0058: br IL_01a6 + + IL_005d: ldloc.0 + IL_005e: ldc.i4 0x360caa42 + IL_0063: bgt.un.s IL_007a + + IL_0065: ldloc.0 + IL_0066: ldc.i4 0x340ca71c + IL_006b: beq.s IL_009d + + IL_006d: ldloc.0 + IL_006e: ldc.i4 0x360caa42 + IL_0073: beq.s IL_00c7 + + IL_0075: br IL_01a6 + + IL_007a: ldloc.0 + IL_007b: ldc.i4 0x370cabd5 + IL_0080: beq.s IL_00b2 + + IL_0082: ldloc.0 + IL_0083: ldc.i4 0x3c0cb3b4 + IL_0088: beq IL_0133 + + IL_008d: ldloc.0 + IL_008e: ldc.i4 0x3d0cb547 + IL_0093: beq IL_0124 + + IL_0098: br IL_01a6 + + IL_009d: ldarg.0 + IL_009e: ldstr "1" + IL_00a3: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00a8: brtrue IL_0142 + + IL_00ad: br IL_01a6 + + IL_00b2: ldarg.0 + IL_00b3: ldstr "2" + IL_00b8: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00bd: brtrue IL_014e + + IL_00c2: br IL_01a6 + + IL_00c7: ldarg.0 + IL_00c8: ldstr "3" + IL_00cd: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00d2: brtrue IL_0158 + + IL_00d7: br IL_01a6 + + IL_00dc: ldarg.0 + IL_00dd: ldstr "4" + IL_00e2: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00e7: brtrue.s IL_0164 + + IL_00e9: br IL_01a6 + + IL_00ee: ldarg.0 + IL_00ef: ldstr "5" + IL_00f4: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00f9: brtrue.s IL_016f + + IL_00fb: br IL_01a6 + + IL_0100: ldarg.0 + IL_0101: ldstr "6" + IL_0106: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_010b: brtrue.s IL_017a + + IL_010d: br IL_01a6 + + IL_0112: ldarg.0 + IL_0113: ldstr "7" + IL_0118: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_011d: brtrue.s IL_0185 + + IL_011f: br IL_01a6 + + IL_0124: ldarg.0 + IL_0125: ldstr "8" + IL_012a: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_012f: brtrue.s IL_0190 + + IL_0131: br.s IL_01a6 + + IL_0133: ldarg.0 + IL_0134: ldstr "9" + IL_0139: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_013e: brtrue.s IL_019b + + IL_0140: br.s IL_01a6 + + IL_0142: ldstr "one" + IL_0147: call void [mscorlib]System.Console::WriteLine(string) + IL_014c: br.s IL_01a6 + + IL_014e: ldstr "two" + IL_0153: call void [mscorlib]System.Console::WriteLine(string) + IL_0158: ldstr "three" + IL_015d: call void [mscorlib]System.Console::WriteLine(string) + IL_0162: br.s IL_01b0 + + IL_0164: ldstr "four" + IL_0169: call void [mscorlib]System.Console::WriteLine(string) + IL_016e: ret + + IL_016f: ldstr "five" + IL_0174: call void [mscorlib]System.Console::WriteLine(string) + IL_0179: ret + + IL_017a: ldstr "six" + IL_017f: call void [mscorlib]System.Console::WriteLine(string) + IL_0184: ret + + IL_0185: ldstr "seven" + IL_018a: call void [mscorlib]System.Console::WriteLine(string) + IL_018f: ret + + IL_0190: ldstr "eight" + IL_0195: call void [mscorlib]System.Console::WriteLine(string) + IL_019a: ret + + IL_019b: ldstr "nine" + IL_01a0: call void [mscorlib]System.Console::WriteLine(string) + IL_01a5: ret + + IL_01a6: ldstr "default" + IL_01ab: call void [mscorlib]System.Console::WriteLine(string) + IL_01b0: ldstr "End of method" + IL_01b5: call void [mscorlib]System.Console::WriteLine(string) + IL_01ba: ret + } // end of method Switch::SwitchWithGotoString + + .method public hidebysig static void SwitchWithGotoComplex(string s) cil managed + { + // Code size 387 (0x183) + .maxstack 2 + .locals init (uint32 V_0) + IL_0000: ldstr "SwitchWithGotoComplex: " + IL_0005: ldarg.0 + IL_0006: call string [mscorlib]System.String::Concat(string, + string) + IL_000b: call void [mscorlib]System.Console::WriteLine(string) + IL_0010: ldarg.0 + IL_0011: call uint32 ''::ComputeStringHash(string) + IL_0016: stloc.0 + IL_0017: ldloc.0 + IL_0018: ldc.i4 0x330ca589 + IL_001d: bgt.un.s IL_005d + + IL_001f: ldloc.0 + IL_0020: ldc.i4 0x310ca263 + IL_0025: bgt.un.s IL_0042 + + IL_0027: ldloc.0 + IL_0028: ldc.i4 0x300ca0d0 + IL_002d: beq IL_00d7 + + IL_0032: ldloc.0 + IL_0033: ldc.i4 0x310ca263 + IL_0038: beq IL_00c5 + + IL_003d: br IL_016e + + IL_0042: ldloc.0 + IL_0043: ldc.i4 0x320ca3f6 + IL_0048: beq IL_0107 + + IL_004d: ldloc.0 + IL_004e: ldc.i4 0x330ca589 + IL_0053: beq IL_00e9 + + IL_0058: br IL_016e + + IL_005d: ldloc.0 + IL_005e: ldc.i4 0x360caa42 + IL_0063: bgt.un.s IL_007a + + IL_0065: ldloc.0 + IL_0066: ldc.i4 0x340ca71c + IL_006b: beq.s IL_008f + + IL_006d: ldloc.0 + IL_006e: ldc.i4 0x360caa42 + IL_0073: beq.s IL_00b3 + + IL_0075: br IL_016e + + IL_007a: ldloc.0 + IL_007b: ldc.i4 0x370cabd5 + IL_0080: beq.s IL_00a1 + + IL_0082: ldloc.0 + IL_0083: ldc.i4 0x3d0cb547 + IL_0088: beq.s IL_00f8 + + IL_008a: br IL_016e + + IL_008f: ldarg.0 + IL_0090: ldstr "1" + IL_0095: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_009a: brtrue.s IL_0116 + + IL_009c: br IL_016e + + IL_00a1: ldarg.0 + IL_00a2: ldstr "2" + IL_00a7: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00ac: brtrue.s IL_0122 + + IL_00ae: br IL_016e + + IL_00b3: ldarg.0 + IL_00b4: ldstr "3" + IL_00b9: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00be: brtrue.s IL_012c + + IL_00c0: br IL_016e + + IL_00c5: ldarg.0 + IL_00c6: ldstr "4" + IL_00cb: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00d0: brtrue.s IL_0141 + + IL_00d2: br IL_016e + + IL_00d7: ldarg.0 + IL_00d8: ldstr "5" + IL_00dd: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00e2: brtrue.s IL_014b + + IL_00e4: br IL_016e + + IL_00e9: ldarg.0 + IL_00ea: ldstr "6" + IL_00ef: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00f4: brtrue.s IL_0157 + + IL_00f6: br.s IL_016e + + IL_00f8: ldarg.0 + IL_00f9: ldstr "8" + IL_00fe: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_0103: brtrue.s IL_0163 + + IL_0105: br.s IL_016e + + IL_0107: ldarg.0 + IL_0108: ldstr "7" + IL_010d: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_0112: brtrue.s IL_0178 + + IL_0114: br.s IL_016e + + IL_0116: ldstr "one" + IL_011b: call void [mscorlib]System.Console::WriteLine(string) + IL_0120: br.s IL_0163 + + IL_0122: ldstr "two" + IL_0127: call void [mscorlib]System.Console::WriteLine(string) + IL_012c: ldstr "three" + IL_0131: call void [mscorlib]System.Console::WriteLine(string) + IL_0136: ldarg.0 + IL_0137: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_013c: ldc.i4.2 + IL_013d: beq.s IL_014b + + IL_013f: br.s IL_0178 + + IL_0141: ldstr "four" + IL_0146: call void [mscorlib]System.Console::WriteLine(string) + IL_014b: ldstr "five" + IL_0150: call void [mscorlib]System.Console::WriteLine(string) + IL_0155: br.s IL_0163 + + IL_0157: ldstr "six" + IL_015c: call void [mscorlib]System.Console::WriteLine(string) + IL_0161: br.s IL_014b + + IL_0163: ldstr "eight" + IL_0168: call void [mscorlib]System.Console::WriteLine(string) + IL_016d: ret + + IL_016e: ldstr "default" + IL_0173: call void [mscorlib]System.Console::WriteLine(string) + IL_0178: ldstr "End of method" + IL_017d: call void [mscorlib]System.Console::WriteLine(string) + IL_0182: ret + } // end of method Switch::SwitchWithGotoComplex + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch/SetProperty[] GetProperties() cil managed { @@ -1449,6 +1928,1060 @@ IL_0072: ret } // end of method Switch::SwitchWithArray + .method public hidebysig static void SwitchWithContinue1(int32 i, + bool b) cil managed + { + // Code size 35 (0x23) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: switch ( + IL_0014, + IL_0000, + IL_0019) + IL_0012: br.s IL_001c + + IL_0014: ldarg.1 + IL_0015: brfalse.s IL_001c + + IL_0017: br.s IL_0000 + + IL_0019: ldarg.1 + IL_001a: brfalse.s IL_0000 + + IL_001c: call void [mscorlib]System.Console::WriteLine() + IL_0021: br.s IL_0000 + } // end of method Switch::SwitchWithContinue1 + + .method public hidebysig static void SwitchWithContinue2(int32 i, + bool b) cil managed + { + // Code size 110 (0x6e) + .maxstack 2 + IL_0000: br.s IL_0068 + + IL_0002: ldarg.0 + IL_0003: switch ( + IL_001a, + IL_0068, + IL_0035, + IL_0059) + IL_0018: br.s IL_004f + + IL_001a: ldarg.1 + IL_001b: brfalse.s IL_0029 + + IL_001d: ldstr "0b" + IL_0022: call void [mscorlib]System.Console::WriteLine(string) + IL_0027: br.s IL_0068 + + IL_0029: ldstr "0!b" + IL_002e: call void [mscorlib]System.Console::WriteLine(string) + IL_0033: br.s IL_0059 + + IL_0035: ldarg.1 + IL_0036: brfalse.s IL_0043 + + IL_0038: ldstr "2b" + IL_003d: call void [mscorlib]System.Console::WriteLine(string) + IL_0042: ret + + IL_0043: ldstr "2!b" + IL_0048: call void [mscorlib]System.Console::WriteLine(string) + IL_004d: br.s IL_0068 + + IL_004f: ldstr "default" + IL_0054: call void [mscorlib]System.Console::WriteLine(string) + IL_0059: ldstr "loop-tail" + IL_005e: call void [mscorlib]System.Console::WriteLine(string) + IL_0063: ldarg.0 + IL_0064: ldc.i4.1 + IL_0065: add + IL_0066: starg.s i + IL_0068: ldarg.0 + IL_0069: ldc.i4.s 10 + IL_006b: blt.s IL_0002 + + IL_006d: ret + } // end of method Switch::SwitchWithContinue2 + + .method public hidebysig static void SwitchWithContinue3(bool b) cil managed + { + // Code size 111 (0x6f) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: br.s IL_0069 + + IL_0004: ldloc.0 + IL_0005: switch ( + IL_001c, + IL_0065, + IL_0037, + IL_005b) + IL_001a: br.s IL_0051 + + IL_001c: ldarg.0 + IL_001d: brfalse.s IL_002b + + IL_001f: ldstr "0b" + IL_0024: call void [mscorlib]System.Console::WriteLine(string) + IL_0029: br.s IL_0065 + + IL_002b: ldstr "0!b" + IL_0030: call void [mscorlib]System.Console::WriteLine(string) + IL_0035: br.s IL_005b + + IL_0037: ldarg.0 + IL_0038: brfalse.s IL_0045 + + IL_003a: ldstr "2b" + IL_003f: call void [mscorlib]System.Console::WriteLine(string) + IL_0044: ret + + IL_0045: ldstr "2!b" + IL_004a: call void [mscorlib]System.Console::WriteLine(string) + IL_004f: br.s IL_0065 + + IL_0051: ldstr "default" + IL_0056: call void [mscorlib]System.Console::WriteLine(string) + IL_005b: ldstr "loop-tail" + IL_0060: call void [mscorlib]System.Console::WriteLine(string) + IL_0065: ldloc.0 + IL_0066: ldc.i4.1 + IL_0067: add + IL_0068: stloc.0 + IL_0069: ldloc.0 + IL_006a: ldc.i4.s 10 + IL_006c: blt.s IL_0004 + + IL_006e: ret + } // end of method Switch::SwitchWithContinue3 + + .method public hidebysig static void SwitchWithContinue4(bool b) cil managed + { + // Code size 188 (0xbc) + .maxstack 2 + .locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1 V_0, + int32 V_1) + IL_0000: ldc.i4.0 + IL_0001: ldc.i4.s 10 + IL_0003: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Range(int32, + int32) + IL_0008: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_000d: stloc.0 + .try + { + IL_000e: br IL_00a4 + + IL_0013: ldloc.0 + IL_0014: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() + IL_0019: stloc.1 + IL_001a: ldstr "loop: " + IL_001f: ldloc.1 + IL_0020: box [mscorlib]System.Int32 + IL_0025: call string [mscorlib]System.String::Concat(object, + object) + IL_002a: call void [mscorlib]System.Console::WriteLine(string) + IL_002f: ldloc.1 + IL_0030: ldc.i4.1 + IL_0031: sub + IL_0032: switch ( + IL_0059, + IL_00a4, + IL_005e, + IL_0063, + IL_006b, + IL_0073, + IL_0078, + IL_0080) + IL_0057: br.s IL_0085 + + IL_0059: ldarg.0 + IL_005a: brfalse.s IL_008f + + IL_005c: br.s IL_00a4 + + IL_005e: ldarg.0 + IL_005f: brfalse.s IL_00a4 + + IL_0061: leave.s IL_00bb + + IL_0063: ldc.i4.4 + IL_0064: call void [mscorlib]System.Console::WriteLine(int32) + IL_0069: br.s IL_0078 + + IL_006b: ldc.i4.5 + IL_006c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0071: br.s IL_0085 + + IL_0073: ldarg.0 + IL_0074: brfalse.s IL_005e + + IL_0076: br.s IL_00a4 + + IL_0078: ldloc.1 + IL_0079: ldc.i4.2 + IL_007a: rem + IL_007b: brfalse.s IL_005e + + IL_007d: ldarg.0 + IL_007e: brfalse.s IL_00a4 + + IL_0080: ldarg.0 + IL_0081: brfalse.s IL_006b + + IL_0083: br.s IL_00a4 + + IL_0085: ldstr "default" + IL_008a: call void [mscorlib]System.Console::WriteLine(string) + IL_008f: ldstr "break: " + IL_0094: ldloc.1 + IL_0095: box [mscorlib]System.Int32 + IL_009a: call string [mscorlib]System.String::Concat(object, + object) + IL_009f: call void [mscorlib]System.Console::WriteLine(string) + IL_00a4: ldloc.0 + IL_00a5: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_00aa: brtrue IL_0013 + + IL_00af: leave.s IL_00bb + + } // end .try + finally + { + IL_00b1: ldloc.0 + IL_00b2: brfalse.s IL_00ba + + IL_00b4: ldloc.0 + IL_00b5: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_00ba: endfinally + } // end handler + IL_00bb: ret + } // end of method Switch::SwitchWithContinue4 + + .method public hidebysig static void SwitchWithContinue5(bool b) cil managed + { + // Code size 125 (0x7d) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: br.s IL_0077 + + IL_0004: ldloc.0 + IL_0005: ldc.i4.5 + IL_0006: bge.s IL_0069 + + IL_0008: ldloc.0 + IL_0009: switch ( + IL_0020, + IL_0073, + IL_003b, + IL_005f) + IL_001e: br.s IL_0055 + + IL_0020: ldarg.0 + IL_0021: brfalse.s IL_002f + + IL_0023: ldstr "0b" + IL_0028: call void [mscorlib]System.Console::WriteLine(string) + IL_002d: br.s IL_0073 + + IL_002f: ldstr "0!b" + IL_0034: call void [mscorlib]System.Console::WriteLine(string) + IL_0039: br.s IL_005f + + IL_003b: ldarg.0 + IL_003c: brfalse.s IL_0049 + + IL_003e: ldstr "2b" + IL_0043: call void [mscorlib]System.Console::WriteLine(string) + IL_0048: ret + + IL_0049: ldstr "2!b" + IL_004e: call void [mscorlib]System.Console::WriteLine(string) + IL_0053: br.s IL_0073 + + IL_0055: ldstr "default" + IL_005a: call void [mscorlib]System.Console::WriteLine(string) + IL_005f: ldstr "break-target" + IL_0064: call void [mscorlib]System.Console::WriteLine(string) + IL_0069: ldstr "loop-tail" + IL_006e: call void [mscorlib]System.Console::WriteLine(string) + IL_0073: ldloc.0 + IL_0074: ldc.i4.1 + IL_0075: add + IL_0076: stloc.0 + IL_0077: ldloc.0 + IL_0078: ldc.i4.s 10 + IL_007a: blt.s IL_0004 + + IL_007c: ret + } // end of method Switch::SwitchWithContinue5 + + .method public hidebysig static void SwitchWithContinue6(int32 i, + bool b) cil managed + { + // Code size 108 (0x6c) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: switch ( + IL_0018, + IL_0061, + IL_0033, + IL_0057) + IL_0016: br.s IL_004d + + IL_0018: ldarg.1 + IL_0019: brtrue.s IL_0027 + + IL_001b: ldstr "0!b" + IL_0020: call void [mscorlib]System.Console::WriteLine(string) + IL_0025: br.s IL_0057 + + IL_0027: ldstr "0b" + IL_002c: call void [mscorlib]System.Console::WriteLine(string) + IL_0031: br.s IL_0061 + + IL_0033: ldarg.1 + IL_0034: brfalse.s IL_0041 + + IL_0036: ldstr "2b" + IL_003b: call void [mscorlib]System.Console::WriteLine(string) + IL_0040: ret + + IL_0041: ldstr "2!b" + IL_0046: call void [mscorlib]System.Console::WriteLine(string) + IL_004b: br.s IL_0061 + + IL_004d: ldstr "default" + IL_0052: call void [mscorlib]System.Console::WriteLine(string) + IL_0057: ldstr "loop-tail" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: ldarg.0 + IL_0062: ldc.i4.1 + IL_0063: add + IL_0064: dup + IL_0065: starg.s i + IL_0067: ldc.i4.s 10 + IL_0069: blt.s IL_0000 + + IL_006b: ret + } // end of method Switch::SwitchWithContinue6 + + .method public hidebysig static void SwitchWithContinue7() cil managed + { + // Code size 52 (0x34) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: br.s IL_0025 + + IL_0004: ldstr "loop-head" + IL_0009: call void [mscorlib]System.Console::WriteLine(string) + IL_000e: ldloc.0 + IL_000f: brfalse.s IL_0021 + + IL_0011: ldloc.0 + IL_0012: ldc.i4.1 + IL_0013: beq.s IL_0029 + + IL_0015: ldstr "default" + IL_001a: call void [mscorlib]System.Console::WriteLine(string) + IL_001f: br.s IL_0029 + + IL_0021: ldloc.0 + IL_0022: ldc.i4.1 + IL_0023: sub + IL_0024: stloc.0 + IL_0025: ldloc.0 + IL_0026: ldc.i4.0 + IL_0027: bge.s IL_0004 + + IL_0029: ldstr "end" + IL_002e: call void [mscorlib]System.Console::WriteLine(string) + IL_0033: ret + } // end of method Switch::SwitchWithContinue7 + + .method public hidebysig static void SwitchWithContinueInDoubleLoop() cil managed + { + // Code size 101 (0x65) + .maxstack 2 + .locals init (bool V_0, + int32 V_1, + int32 V_2, + int32 V_3) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: ldc.i4.0 + IL_0003: stloc.1 + IL_0004: br.s IL_0059 + + IL_0006: ldc.i4.0 + IL_0007: stloc.2 + IL_0008: br.s IL_0050 + + IL_000a: ldloc.1 + IL_000b: ldloc.2 + IL_000c: add + IL_000d: stloc.3 + IL_000e: ldloc.3 + IL_000f: ldc.i4.s 11 + IL_0011: bgt.s IL_003e + + IL_0013: ldloc.3 + IL_0014: ldc.i4.1 + IL_0015: sub + IL_0016: switch ( + IL_0048, + IL_004c, + IL_0048, + IL_004c, + IL_0048, + IL_004c, + IL_0048) + IL_0037: ldloc.3 + IL_0038: ldc.i4.s 11 + IL_003a: beq.s IL_0048 + + IL_003c: br.s IL_004c + + IL_003e: ldloc.3 + IL_003f: ldc.i4.s 13 + IL_0041: beq.s IL_0048 + + IL_0043: ldloc.3 + IL_0044: ldc.i4.s 17 + IL_0046: bne.un.s IL_004c + + IL_0048: ldc.i4.1 + IL_0049: stloc.0 + IL_004a: br.s IL_0055 + + IL_004c: ldloc.2 + IL_004d: ldc.i4.1 + IL_004e: add + IL_004f: stloc.2 + IL_0050: ldloc.2 + IL_0051: ldc.i4.s 10 + IL_0053: blt.s IL_000a + + IL_0055: ldloc.1 + IL_0056: ldc.i4.1 + IL_0057: add + IL_0058: stloc.1 + IL_0059: ldloc.1 + IL_005a: ldc.i4.s 10 + IL_005c: blt.s IL_0006 + + IL_005e: ldloc.0 + IL_005f: call void [mscorlib]System.Console::WriteLine(bool) + IL_0064: ret + } // end of method Switch::SwitchWithContinueInDoubleLoop + + .method public hidebysig static void SwitchLoopNesting() cil managed + { + // Code size 92 (0x5c) + .maxstack 3 + .locals init (int32 V_0) + IL_0000: ldc.i4.0 + IL_0001: stloc.0 + IL_0002: br.s IL_0056 + + IL_0004: ldloc.0 + IL_0005: brfalse.s IL_000d + + IL_0007: ldloc.0 + IL_0008: ldc.i4.1 + IL_0009: beq.s IL_0015 + + IL_000b: br.s IL_001d + + IL_000d: ldc.i4.0 + IL_000e: call void [mscorlib]System.Console::WriteLine(int32) + IL_0013: br.s IL_0038 + + IL_0015: ldc.i4.1 + IL_0016: call void [mscorlib]System.Console::WriteLine(int32) + IL_001b: br.s IL_0038 + + IL_001d: ldloc.0 + IL_001e: ldc.i4.2 + IL_001f: rem + IL_0020: brtrue.s IL_0033 + + IL_0022: br.s IL_002e + + IL_0024: ldloc.0 + IL_0025: dup + IL_0026: ldc.i4.1 + IL_0027: add + IL_0028: stloc.0 + IL_0029: call void [mscorlib]System.Console::WriteLine(int32) + IL_002e: ldloc.0 + IL_002f: ldc.i4.3 + IL_0030: rem + IL_0031: brtrue.s IL_0024 + + IL_0033: call void [mscorlib]System.Console::WriteLine() + IL_0038: ldloc.0 + IL_0039: ldc.i4.4 + IL_003a: ble.s IL_0048 + + IL_003c: ldstr "high" + IL_0041: call void [mscorlib]System.Console::WriteLine(string) + IL_0046: br.s IL_0052 + + IL_0048: ldstr "low" + IL_004d: call void [mscorlib]System.Console::WriteLine(string) + IL_0052: ldloc.0 + IL_0053: ldc.i4.1 + IL_0054: add + IL_0055: stloc.0 + IL_0056: ldloc.0 + IL_0057: ldc.i4.s 10 + IL_0059: blt.s IL_0004 + + IL_005b: ret + } // end of method Switch::SwitchLoopNesting + + .method public hidebysig static void SingleIf1(int32 i, + bool a) cil managed + { + // Code size 25 (0x19) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: beq.s IL_000c + + IL_0004: ldarg.0 + IL_0005: ldc.i4.2 + IL_0006: ceq + IL_0008: ldarg.1 + IL_0009: and + IL_000a: brfalse.s IL_0012 + + IL_000c: ldc.i4.1 + IL_000d: call void [mscorlib]System.Console::WriteLine(int32) + IL_0012: ldc.i4.2 + IL_0013: call void [mscorlib]System.Console::WriteLine(int32) + IL_0018: ret + } // end of method Switch::SingleIf1 + + .method public hidebysig static void SingleIf2(int32 i, + bool a, + bool b) cil managed + { + // Code size 33 (0x21) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: beq.s IL_0014 + + IL_0004: ldarg.0 + IL_0005: ldc.i4.2 + IL_0006: ceq + IL_0008: ldarg.1 + IL_0009: and + IL_000a: brtrue.s IL_0014 + + IL_000c: ldarg.0 + IL_000d: ldc.i4.3 + IL_000e: ceq + IL_0010: ldarg.2 + IL_0011: and + IL_0012: brfalse.s IL_001a + + IL_0014: ldc.i4.1 + IL_0015: call void [mscorlib]System.Console::WriteLine(int32) + IL_001a: ldc.i4.2 + IL_001b: call void [mscorlib]System.Console::WriteLine(int32) + IL_0020: ret + } // end of method Switch::SingleIf2 + + .method public hidebysig static void SingleIf3(int32 i, + bool a, + bool b) cil managed + { + // Code size 28 (0x1c) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: brtrue.s IL_000f + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: beq.s IL_000f + + IL_0007: ldarg.0 + IL_0008: ldc.i4.2 + IL_0009: ceq + IL_000b: ldarg.2 + IL_000c: and + IL_000d: brfalse.s IL_0015 + + IL_000f: ldc.i4.1 + IL_0010: call void [mscorlib]System.Console::WriteLine(int32) + IL_0015: ldc.i4.2 + IL_0016: call void [mscorlib]System.Console::WriteLine(int32) + IL_001b: ret + } // end of method Switch::SingleIf3 + + .method public hidebysig static void SingleIf4(int32 i, + bool a) cil managed + { + // Code size 36 (0x24) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: beq.s IL_0017 + + IL_0004: ldarg.0 + IL_0005: ldc.i4.2 + IL_0006: beq.s IL_0017 + + IL_0008: ldarg.0 + IL_0009: ldc.i4.3 + IL_000a: ceq + IL_000c: ldc.i4.0 + IL_000d: ceq + IL_000f: ldarg.1 + IL_0010: and + IL_0011: brtrue.s IL_0017 + + IL_0013: ldarg.0 + IL_0014: ldc.i4.4 + IL_0015: beq.s IL_001d + + IL_0017: ldc.i4.1 + IL_0018: call void [mscorlib]System.Console::WriteLine(int32) + IL_001d: ldc.i4.2 + IL_001e: call void [mscorlib]System.Console::WriteLine(int32) + IL_0023: ret + } // end of method Switch::SingleIf4 + + .method public hidebysig static void NestedIf(int32 i) cil managed + { + // Code size 30 (0x1e) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: beq.s IL_0018 + + IL_0004: ldarg.0 + IL_0005: ldc.i4.2 + IL_0006: bne.un.s IL_000e + + IL_0008: ldc.i4.2 + IL_0009: call void [mscorlib]System.Console::WriteLine(int32) + IL_000e: ldstr "default" + IL_0013: call void [mscorlib]System.Console::WriteLine(string) + IL_0018: call void [mscorlib]System.Console::WriteLine() + IL_001d: ret + } // end of method Switch::NestedIf + + .method public hidebysig static void IfChainWithCondition(int32 i) cil managed + { + // Code size 98 (0x62) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: brtrue.s IL_000b + + IL_0003: ldc.i4.0 + IL_0004: call void [mscorlib]System.Console::WriteLine(int32) + IL_0009: br.s IL_005c + + IL_000b: ldarg.0 + IL_000c: ldc.i4.1 + IL_000d: bne.un.s IL_0017 + + IL_000f: ldc.i4.1 + IL_0010: call void [mscorlib]System.Console::WriteLine(int32) + IL_0015: br.s IL_005c + + IL_0017: ldarg.0 + IL_0018: ldc.i4.2 + IL_0019: bne.un.s IL_0023 + + IL_001b: ldc.i4.2 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: br.s IL_005c + + IL_0023: ldarg.0 + IL_0024: ldc.i4.3 + IL_0025: bne.un.s IL_002f + + IL_0027: ldc.i4.3 + IL_0028: call void [mscorlib]System.Console::WriteLine(int32) + IL_002d: br.s IL_005c + + IL_002f: ldarg.0 + IL_0030: ldc.i4.4 + IL_0031: bne.un.s IL_003b + + IL_0033: ldc.i4.4 + IL_0034: call void [mscorlib]System.Console::WriteLine(int32) + IL_0039: br.s IL_005c + + IL_003b: ldarg.0 + IL_003c: ldc.i4.5 + IL_003d: bne.un.s IL_0052 + + IL_003f: call bool [mscorlib]System.Console::get_CapsLock() + IL_0044: brfalse.s IL_0052 + + IL_0046: ldstr "5A" + IL_004b: call void [mscorlib]System.Console::WriteLine(string) + IL_0050: br.s IL_005c + + IL_0052: ldstr "default" + IL_0057: call void [mscorlib]System.Console::WriteLine(string) + IL_005c: call void [mscorlib]System.Console::WriteLine() + IL_0061: ret + } // end of method Switch::IfChainWithCondition + + .method public hidebysig static bool SwitchlikeIf(int32 i, + int32 j) cil managed + { + // Code size 148 (0x94) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0050 + + IL_0003: ldarg.1 + IL_0004: brfalse.s IL_0050 + + IL_0006: ldarg.0 + IL_0007: ldc.i4.m1 + IL_0008: bne.un.s IL_0018 + + IL_000a: ldarg.1 + IL_000b: ldc.i4.m1 + IL_000c: bne.un.s IL_0018 + + IL_000e: ldstr "-1, -1" + IL_0013: call void [mscorlib]System.Console::WriteLine(string) + IL_0018: ldarg.0 + IL_0019: ldc.i4.m1 + IL_001a: bne.un.s IL_002a + + IL_001c: ldarg.1 + IL_001d: ldc.i4.1 + IL_001e: bne.un.s IL_002a + + IL_0020: ldstr "-1, 1" + IL_0025: call void [mscorlib]System.Console::WriteLine(string) + IL_002a: ldarg.0 + IL_002b: ldc.i4.1 + IL_002c: bne.un.s IL_003c + + IL_002e: ldarg.1 + IL_002f: ldc.i4.m1 + IL_0030: bne.un.s IL_003c + + IL_0032: ldstr "1, -1" + IL_0037: call void [mscorlib]System.Console::WriteLine(string) + IL_003c: ldarg.0 + IL_003d: ldc.i4.1 + IL_003e: bne.un.s IL_004e + + IL_0040: ldarg.1 + IL_0041: ldc.i4.1 + IL_0042: bne.un.s IL_004e + + IL_0044: ldstr "1, 1" + IL_0049: call void [mscorlib]System.Console::WriteLine(string) + IL_004e: ldc.i4.0 + IL_004f: ret + + IL_0050: ldarg.0 + IL_0051: brfalse.s IL_0071 + + IL_0053: ldarg.0 + IL_0054: ldc.i4.m1 + IL_0055: bne.un.s IL_0061 + + IL_0057: ldstr "-1, 0" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: ldarg.0 + IL_0062: ldc.i4.1 + IL_0063: bne.un.s IL_006f + + IL_0065: ldstr "1, 0" + IL_006a: call void [mscorlib]System.Console::WriteLine(string) + IL_006f: ldc.i4.0 + IL_0070: ret + + IL_0071: ldarg.1 + IL_0072: brfalse.s IL_0092 + + IL_0074: ldarg.1 + IL_0075: ldc.i4.m1 + IL_0076: bne.un.s IL_0082 + + IL_0078: ldstr "0, -1" + IL_007d: call void [mscorlib]System.Console::WriteLine(string) + IL_0082: ldarg.1 + IL_0083: ldc.i4.1 + IL_0084: bne.un.s IL_0090 + + IL_0086: ldstr "0, 1" + IL_008b: call void [mscorlib]System.Console::WriteLine(string) + IL_0090: ldc.i4.0 + IL_0091: ret + + IL_0092: ldc.i4.1 + IL_0093: ret + } // end of method Switch::SwitchlikeIf + + .method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed + { + // Code size 37 (0x25) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0023 + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: bne.un.s IL_000d + + IL_0007: ldc.i4.1 + IL_0008: call void [mscorlib]System.Console::WriteLine(int32) + IL_000d: ldarg.0 + IL_000e: ldc.i4.2 + IL_000f: bne.un.s IL_0017 + + IL_0011: ldc.i4.2 + IL_0012: call void [mscorlib]System.Console::WriteLine(int32) + IL_0017: ldarg.0 + IL_0018: ldc.i4.3 + IL_0019: bne.un.s IL_0021 + + IL_001b: ldc.i4.3 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: ldc.i4.0 + IL_0022: ret + + IL_0023: ldc.i4.0 + IL_0024: ret + } // end of method Switch::SwitchlikeIf2 + + .method public hidebysig static void SingleIntervalIf(char c) cil managed + { + // Code size 31 (0x1f) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.s 65 + IL_0003: blt.s IL_0014 + + IL_0005: ldarg.0 + IL_0006: ldc.i4.s 90 + IL_0008: bgt.s IL_0014 + + IL_000a: ldstr "alphabet" + IL_000f: call void [mscorlib]System.Console::WriteLine(string) + IL_0014: ldstr "end" + IL_0019: call void [mscorlib]System.Console::WriteLine(string) + IL_001e: ret + } // end of method Switch::SingleIntervalIf + + .method public hidebysig static bool Loop8(char c, + bool b, + class [mscorlib]System.Func`1 getChar) cil managed + { + // Code size 35 (0x23) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: brfalse.s IL_0021 + + IL_0003: br.s IL_000d + + IL_0005: ldarg.2 + IL_0006: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_000b: starg.s c + IL_000d: ldarg.0 + IL_000e: ldc.i4.s 97 + IL_0010: blt.s IL_0017 + + IL_0012: ldarg.0 + IL_0013: ldc.i4.s 122 + IL_0015: ble.s IL_0005 + + IL_0017: ldarg.0 + IL_0018: ldc.i4.s 65 + IL_001a: blt.s IL_0021 + + IL_001c: ldarg.0 + IL_001d: ldc.i4.s 90 + IL_001f: ble.s IL_0005 + + IL_0021: ldc.i4.1 + IL_0022: ret + } // end of method Switch::Loop8 + + .method public hidebysig static void Loop9(class [mscorlib]System.Func`1 getChar) cil managed + { + // Code size 33 (0x21) + .maxstack 2 + .locals init (char V_0) + IL_0000: ldarg.0 + IL_0001: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: ldc.i4.m1 + IL_0009: beq.s IL_0020 + + IL_000b: ldloc.0 + IL_000c: ldc.i4.s 10 + IL_000e: beq.s IL_0020 + + IL_0010: ldloc.0 + IL_0011: ldc.i4 0x2028 + IL_0016: beq.s IL_0020 + + IL_0018: ldloc.0 + IL_0019: ldc.i4 0x2029 + IL_001e: bne.un.s IL_0000 + + IL_0020: ret + } // end of method Switch::Loop9 + + .method public hidebysig static void SwitchWithBreakCase(int32 i, + bool b) cil managed + { + // Code size 52 (0x34) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: brfalse.s IL_0029 + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: beq.s IL_000d + + IL_0007: ldarg.0 + IL_0008: ldc.i4.2 + IL_0009: beq.s IL_001f + + IL_000b: br.s IL_0015 + + IL_000d: ldc.i4.1 + IL_000e: call void [mscorlib]System.Console::WriteLine(int32) + IL_0013: br.s IL_001f + + IL_0015: ldstr "default" + IL_001a: call void [mscorlib]System.Console::WriteLine(string) + IL_001f: ldstr "b" + IL_0024: call void [mscorlib]System.Console::WriteLine(string) + IL_0029: ldstr "end" + IL_002e: call void [mscorlib]System.Console::WriteLine(string) + IL_0033: ret + } // end of method Switch::SwitchWithBreakCase + + .method public hidebysig static void SwitchWithReturnAndBreak(int32 i, + bool b) cil managed + { + // Code size 23 (0x17) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0009 + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: beq.s IL_000d + + IL_0007: br.s IL_0011 + + IL_0009: ldarg.1 + IL_000a: brfalse.s IL_0011 + + IL_000c: ret + + IL_000d: ldarg.1 + IL_000e: brtrue.s IL_0011 + + IL_0010: ret + + IL_0011: call void [mscorlib]System.Console::WriteLine() + IL_0016: ret + } // end of method Switch::SwitchWithReturnAndBreak + + .method public hidebysig static int32 SwitchWithReturnAndBreak2(int32 i, + bool b) cil managed + { + // Code size 77 (0x4d) + .maxstack 2 + IL_0000: ldarg.0 + IL_0001: ldc.i4 0x14e + IL_0006: bgt.s IL_001b + + IL_0008: ldarg.0 + IL_0009: ldc.i4.4 + IL_000a: beq.s IL_0035 + + IL_000c: ldarg.0 + IL_000d: ldc.i4.s 33 + IL_000f: beq.s IL_0035 + + IL_0011: ldarg.0 + IL_0012: ldc.i4 0x14e + IL_0017: beq.s IL_003c + + IL_0019: br.s IL_0046 + + IL_001b: ldarg.0 + IL_001c: ldc.i4 0x18b + IL_0021: beq.s IL_0041 + + IL_0023: ldarg.0 + IL_0024: ldc.i4 0x19a + IL_0029: beq.s IL_0041 + + IL_002b: ldarg.0 + IL_002c: ldc.i4 0x1c7 + IL_0031: beq.s IL_0041 + + IL_0033: br.s IL_0046 + + IL_0035: call void [mscorlib]System.Console::WriteLine() + IL_003a: ldc.i4.1 + IL_003b: ret + + IL_003c: ldarg.1 + IL_003d: brfalse.s IL_0046 + + IL_003f: ldc.i4.2 + IL_0040: ret + + IL_0041: call void [mscorlib]System.Console::WriteLine() + IL_0046: call void [mscorlib]System.Console::WriteLine() + IL_004b: ldc.i4.0 + IL_004c: ret + } // end of method Switch::SwitchWithReturnAndBreak2 + + .method public hidebysig static void SwitchWithReturnAndBreak3(int32 i) cil managed + { + // Code size 28 (0x1c) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: brfalse.s IL_0008 + + IL_0003: ldarg.0 + IL_0004: ldc.i4.1 + IL_0005: beq.s IL_0010 + + IL_0007: ret + + IL_0008: ldc.i4.0 + IL_0009: call void [mscorlib]System.Console::WriteLine(int32) + IL_000e: br.s IL_0016 + + IL_0010: ldc.i4.1 + IL_0011: call void [mscorlib]System.Console::WriteLine(int32) + IL_0016: call void [mscorlib]System.Console::WriteLine() + IL_001b: ret + } // end of method Switch::SwitchWithReturnAndBreak3 + } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch .class private auto ansi sealed '' diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il index 369af405d..c08307c3d 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il @@ -8,6 +8,11 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } +.assembly extern System.Core +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} .assembly Switch { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) @@ -325,6 +330,137 @@ IL_00e1: ret } // end of method Switch::SparseIntegerSwitch + .method public hidebysig static void SparseIntegerSwitch2(int32 i) cil managed + { + // Code size 86 (0x56) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: ldc.i4.s 21 + IL_0006: bgt.s IL_002a + + IL_0008: ldloc.0 + IL_0009: ldc.i4.s 11 + IL_000b: bgt.s IL_001c + + IL_000d: ldloc.0 + IL_000e: ldc.i4.4 + IL_000f: beq.s IL_004d + + IL_0011: br.s IL_0013 + + IL_0013: ldloc.0 + IL_0014: ldc.i4.s 10 + IL_0016: sub + IL_0017: ldc.i4.1 + IL_0018: ble.un.s IL_004d + + IL_001a: br.s IL_0055 + + IL_001c: ldloc.0 + IL_001d: ldc.i4.s 13 + IL_001f: beq.s IL_004d + + IL_0021: br.s IL_0023 + + IL_0023: ldloc.0 + IL_0024: ldc.i4.s 21 + IL_0026: beq.s IL_004d + + IL_0028: br.s IL_0055 + + IL_002a: ldloc.0 + IL_002b: ldc.i4.s 33 + IL_002d: bgt.s IL_003d + + IL_002f: ldloc.0 + IL_0030: ldc.i4.s 29 + IL_0032: beq.s IL_004d + + IL_0034: br.s IL_0036 + + IL_0036: ldloc.0 + IL_0037: ldc.i4.s 33 + IL_0039: beq.s IL_004d + + IL_003b: br.s IL_0055 + + IL_003d: ldloc.0 + IL_003e: ldc.i4.s 49 + IL_0040: sub + IL_0041: ldc.i4.1 + IL_0042: ble.un.s IL_004d + + IL_0044: br.s IL_0046 + + IL_0046: ldloc.0 + IL_0047: ldc.i4.s 55 + IL_0049: beq.s IL_004d + + IL_004b: br.s IL_0055 + + IL_004d: call void [mscorlib]System.Console::WriteLine() + IL_0052: nop + IL_0053: br.s IL_0055 + + IL_0055: ret + } // end of method Switch::SparseIntegerSwitch2 + + .method public hidebysig static bool SparseIntegerSwitch3(int32 i) cil managed + { + // Code size 51 (0x33) + .maxstack 2 + .locals init (int32 V_0, + bool V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: ldc.i4.s 12 + IL_0006: bgt.s IL_0016 + + IL_0008: ldloc.0 + IL_0009: brfalse.s IL_0029 + + IL_000b: br.s IL_000d + + IL_000d: ldloc.0 + IL_000e: ldc.i4.s 10 + IL_0010: sub + IL_0011: ldc.i4.2 + IL_0012: ble.un.s IL_0029 + + IL_0014: br.s IL_002d + + IL_0016: ldloc.0 + IL_0017: ldc.i4.s 100 + IL_0019: sub + IL_001a: ldc.i4.1 + IL_001b: ble.un.s IL_0029 + + IL_001d: br.s IL_001f + + IL_001f: ldloc.0 + IL_0020: ldc.i4 0xc8 + IL_0025: beq.s IL_0029 + + IL_0027: br.s IL_002d + + IL_0029: ldc.i4.1 + IL_002a: stloc.1 + IL_002b: br.s IL_0031 + + IL_002d: ldc.i4.0 + IL_002e: stloc.1 + IL_002f: br.s IL_0031 + + IL_0031: ldloc.1 + IL_0032: ret + } // end of method Switch::SparseIntegerSwitch3 + .method public hidebysig static string SwitchOverNullableInt(valuetype [mscorlib]System.Nullable`1 i) cil managed { @@ -827,6 +963,47 @@ IL_0096: ret } // end of method Switch::SwitchOverInt + .method public hidebysig static void CompactSwitchOverInt(int32 i) cil managed + { + // Code size 66 (0x42) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: ldc.i4.2 + IL_0005: ble.un.s IL_000f + + IL_0007: br.s IL_0009 + + IL_0009: ldloc.0 + IL_000a: ldc.i4.3 + IL_000b: beq.s IL_001c + + IL_000d: br.s IL_0029 + + IL_000f: ldstr "012" + IL_0014: call void [mscorlib]System.Console::WriteLine(string) + IL_0019: nop + IL_001a: br.s IL_0036 + + IL_001c: ldstr "3" + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: br.s IL_0036 + + IL_0029: ldstr "default" + IL_002e: call void [mscorlib]System.Console::WriteLine(string) + IL_0033: nop + IL_0034: br.s IL_0036 + + IL_0036: ldstr "end" + IL_003b: call void [mscorlib]System.Console::WriteLine(string) + IL_0040: nop + IL_0041: ret + } // end of method Switch::CompactSwitchOverInt + .method public hidebysig static string ShortSwitchOverString(string text) cil managed { @@ -1511,6 +1688,422 @@ IL_007f: ret } // end of method Switch::SwitchWithGoto + .method public hidebysig static void SwitchWithGotoString(string s) cil managed + { + // Code size 484 (0x1e4) + .maxstack 2 + .locals init (string V_0, + uint32 V_1) + IL_0000: nop + IL_0001: ldstr "SwitchWithGotoString: " + IL_0006: ldarg.0 + IL_0007: call string [mscorlib]System.String::Concat(string, + string) + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: ldarg.0 + IL_0013: stloc.0 + IL_0014: ldloc.0 + IL_0015: call uint32 ''::ComputeStringHash(string) + IL_001a: stloc.1 + IL_001b: ldloc.1 + IL_001c: ldc.i4 0x330ca589 + IL_0021: bgt.un.s IL_0065 + + IL_0023: ldloc.1 + IL_0024: ldc.i4 0x310ca263 + IL_0029: bgt.un.s IL_0048 + + IL_002b: ldloc.1 + IL_002c: ldc.i4 0x300ca0d0 + IL_0031: beq IL_00ff + + IL_0036: br.s IL_0038 + + IL_0038: ldloc.1 + IL_0039: ldc.i4 0x310ca263 + IL_003e: beq IL_00ea + + IL_0043: br IL_01cb + + IL_0048: ldloc.1 + IL_0049: ldc.i4 0x320ca3f6 + IL_004e: beq IL_0123 + + IL_0053: br.s IL_0055 + + IL_0055: ldloc.1 + IL_0056: ldc.i4 0x330ca589 + IL_005b: beq IL_0111 + + IL_0060: br IL_01cb + + IL_0065: ldloc.1 + IL_0066: ldc.i4 0x360caa42 + IL_006b: bgt.un.s IL_0084 + + IL_006d: ldloc.1 + IL_006e: ldc.i4 0x340ca71c + IL_0073: beq.s IL_00ab + + IL_0075: br.s IL_0077 + + IL_0077: ldloc.1 + IL_0078: ldc.i4 0x360caa42 + IL_007d: beq.s IL_00d5 + + IL_007f: br IL_01cb + + IL_0084: ldloc.1 + IL_0085: ldc.i4 0x370cabd5 + IL_008a: beq.s IL_00c0 + + IL_008c: br.s IL_008e + + IL_008e: ldloc.1 + IL_008f: ldc.i4 0x3c0cb3b4 + IL_0094: beq IL_0147 + + IL_0099: br.s IL_009b + + IL_009b: ldloc.1 + IL_009c: ldc.i4 0x3d0cb547 + IL_00a1: beq IL_0135 + + IL_00a6: br IL_01cb + + IL_00ab: ldloc.0 + IL_00ac: ldstr "1" + IL_00b1: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00b6: brtrue IL_0156 + + IL_00bb: br IL_01cb + + IL_00c0: ldloc.0 + IL_00c1: ldstr "2" + IL_00c6: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00cb: brtrue IL_0163 + + IL_00d0: br IL_01cb + + IL_00d5: ldloc.0 + IL_00d6: ldstr "3" + IL_00db: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00e0: brtrue IL_0170 + + IL_00e5: br IL_01cb + + IL_00ea: ldloc.0 + IL_00eb: ldstr "4" + IL_00f0: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00f5: brtrue IL_017d + + IL_00fa: br IL_01cb + + IL_00ff: ldloc.0 + IL_0100: ldstr "5" + IL_0105: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_010a: brtrue.s IL_018a + + IL_010c: br IL_01cb + + IL_0111: ldloc.0 + IL_0112: ldstr "6" + IL_0117: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_011c: brtrue.s IL_0197 + + IL_011e: br IL_01cb + + IL_0123: ldloc.0 + IL_0124: ldstr "7" + IL_0129: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_012e: brtrue.s IL_01a4 + + IL_0130: br IL_01cb + + IL_0135: ldloc.0 + IL_0136: ldstr "8" + IL_013b: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_0140: brtrue.s IL_01b1 + + IL_0142: br IL_01cb + + IL_0147: ldloc.0 + IL_0148: ldstr "9" + IL_014d: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_0152: brtrue.s IL_01be + + IL_0154: br.s IL_01cb + + IL_0156: ldstr "one" + IL_015b: call void [mscorlib]System.Console::WriteLine(string) + IL_0160: nop + IL_0161: br.s IL_01cb + + IL_0163: ldstr "two" + IL_0168: call void [mscorlib]System.Console::WriteLine(string) + IL_016d: nop + IL_016e: br.s IL_0170 + + IL_0170: ldstr "three" + IL_0175: call void [mscorlib]System.Console::WriteLine(string) + IL_017a: nop + IL_017b: br.s IL_01d8 + + IL_017d: ldstr "four" + IL_0182: call void [mscorlib]System.Console::WriteLine(string) + IL_0187: nop + IL_0188: br.s IL_01e3 + + IL_018a: ldstr "five" + IL_018f: call void [mscorlib]System.Console::WriteLine(string) + IL_0194: nop + IL_0195: br.s IL_01e3 + + IL_0197: ldstr "six" + IL_019c: call void [mscorlib]System.Console::WriteLine(string) + IL_01a1: nop + IL_01a2: br.s IL_01e3 + + IL_01a4: ldstr "seven" + IL_01a9: call void [mscorlib]System.Console::WriteLine(string) + IL_01ae: nop + IL_01af: br.s IL_01e3 + + IL_01b1: ldstr "eight" + IL_01b6: call void [mscorlib]System.Console::WriteLine(string) + IL_01bb: nop + IL_01bc: br.s IL_01e3 + + IL_01be: ldstr "nine" + IL_01c3: call void [mscorlib]System.Console::WriteLine(string) + IL_01c8: nop + IL_01c9: br.s IL_01e3 + + IL_01cb: ldstr "default" + IL_01d0: call void [mscorlib]System.Console::WriteLine(string) + IL_01d5: nop + IL_01d6: br.s IL_01d8 + + IL_01d8: ldstr "End of method" + IL_01dd: call void [mscorlib]System.Console::WriteLine(string) + IL_01e2: nop + IL_01e3: ret + } // end of method Switch::SwitchWithGotoString + + .method public hidebysig static void SwitchWithGotoComplex(string s) cil managed + { + // Code size 436 (0x1b4) + .maxstack 2 + .locals init (string V_0, + uint32 V_1, + bool V_2) + IL_0000: nop + IL_0001: ldstr "SwitchWithGotoComplex: " + IL_0006: ldarg.0 + IL_0007: call string [mscorlib]System.String::Concat(string, + string) + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: ldarg.0 + IL_0013: stloc.0 + IL_0014: ldloc.0 + IL_0015: call uint32 ''::ComputeStringHash(string) + IL_001a: stloc.1 + IL_001b: ldloc.1 + IL_001c: ldc.i4 0x330ca589 + IL_0021: bgt.un.s IL_0065 + + IL_0023: ldloc.1 + IL_0024: ldc.i4 0x310ca263 + IL_0029: bgt.un.s IL_0048 + + IL_002b: ldloc.1 + IL_002c: ldc.i4 0x300ca0d0 + IL_0031: beq IL_00e9 + + IL_0036: br.s IL_0038 + + IL_0038: ldloc.1 + IL_0039: ldc.i4 0x310ca263 + IL_003e: beq IL_00d4 + + IL_0043: br IL_0199 + + IL_0048: ldloc.1 + IL_0049: ldc.i4 0x320ca3f6 + IL_004e: beq IL_011c + + IL_0053: br.s IL_0055 + + IL_0055: ldloc.1 + IL_0056: ldc.i4 0x330ca589 + IL_005b: beq IL_00fb + + IL_0060: br IL_0199 + + IL_0065: ldloc.1 + IL_0066: ldc.i4 0x360caa42 + IL_006b: bgt.un.s IL_0084 + + IL_006d: ldloc.1 + IL_006e: ldc.i4 0x340ca71c + IL_0073: beq.s IL_009b + + IL_0075: br.s IL_0077 + + IL_0077: ldloc.1 + IL_0078: ldc.i4 0x360caa42 + IL_007d: beq.s IL_00c2 + + IL_007f: br IL_0199 + + IL_0084: ldloc.1 + IL_0085: ldc.i4 0x370cabd5 + IL_008a: beq.s IL_00b0 + + IL_008c: br.s IL_008e + + IL_008e: ldloc.1 + IL_008f: ldc.i4 0x3d0cb547 + IL_0094: beq.s IL_010d + + IL_0096: br IL_0199 + + IL_009b: ldloc.0 + IL_009c: ldstr "1" + IL_00a1: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00a6: brtrue IL_012b + + IL_00ab: br IL_0199 + + IL_00b0: ldloc.0 + IL_00b1: ldstr "2" + IL_00b6: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00bb: brtrue.s IL_0138 + + IL_00bd: br IL_0199 + + IL_00c2: ldloc.0 + IL_00c3: ldstr "3" + IL_00c8: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00cd: brtrue.s IL_0145 + + IL_00cf: br IL_0199 + + IL_00d4: ldloc.0 + IL_00d5: ldstr "4" + IL_00da: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00df: brtrue IL_0165 + + IL_00e4: br IL_0199 + + IL_00e9: ldloc.0 + IL_00ea: ldstr "5" + IL_00ef: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_00f4: brtrue.s IL_0172 + + IL_00f6: br IL_0199 + + IL_00fb: ldloc.0 + IL_00fc: ldstr "6" + IL_0101: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_0106: brtrue.s IL_017f + + IL_0108: br IL_0199 + + IL_010d: ldloc.0 + IL_010e: ldstr "8" + IL_0113: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_0118: brtrue.s IL_018c + + IL_011a: br.s IL_0199 + + IL_011c: ldloc.0 + IL_011d: ldstr "7" + IL_0122: call bool [mscorlib]System.String::op_Equality(string, + string) + IL_0127: brtrue.s IL_01a6 + + IL_0129: br.s IL_0199 + + IL_012b: ldstr "one" + IL_0130: call void [mscorlib]System.Console::WriteLine(string) + IL_0135: nop + IL_0136: br.s IL_018c + + IL_0138: ldstr "two" + IL_013d: call void [mscorlib]System.Console::WriteLine(string) + IL_0142: nop + IL_0143: br.s IL_0145 + + IL_0145: ldstr "three" + IL_014a: call void [mscorlib]System.Console::WriteLine(string) + IL_014f: nop + IL_0150: ldarg.0 + IL_0151: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_0156: ldc.i4.2 + IL_0157: ceq + IL_0159: ldc.i4.0 + IL_015a: ceq + IL_015c: stloc.2 + IL_015d: ldloc.2 + IL_015e: brfalse.s IL_0163 + + IL_0160: nop + IL_0161: br.s IL_01a8 + + IL_0163: br.s IL_0172 + + IL_0165: ldstr "four" + IL_016a: call void [mscorlib]System.Console::WriteLine(string) + IL_016f: nop + IL_0170: br.s IL_0172 + + IL_0172: ldstr "five" + IL_0177: call void [mscorlib]System.Console::WriteLine(string) + IL_017c: nop + IL_017d: br.s IL_018c + + IL_017f: ldstr "six" + IL_0184: call void [mscorlib]System.Console::WriteLine(string) + IL_0189: nop + IL_018a: br.s IL_0172 + + IL_018c: ldstr "eight" + IL_0191: call void [mscorlib]System.Console::WriteLine(string) + IL_0196: nop + IL_0197: br.s IL_01b3 + + IL_0199: ldstr "default" + IL_019e: call void [mscorlib]System.Console::WriteLine(string) + IL_01a3: nop + IL_01a4: br.s IL_01a8 + + IL_01a6: br.s IL_01a8 + + IL_01a8: ldstr "End of method" + IL_01ad: call void [mscorlib]System.Console::WriteLine(string) + IL_01b2: nop + IL_01b3: ret + } // end of method Switch::SwitchWithGotoComplex + .method private hidebysig static class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch/SetProperty[] GetProperties() cil managed { @@ -1799,6 +2392,1756 @@ IL_007a: ret } // end of method Switch::SwitchWithArray + .method public hidebysig static void SwitchWithContinue1(int32 i, + bool b) cil managed + { + // Code size 62 (0x3e) + .maxstack 2 + .locals init (int32 V_0, + bool V_1, + bool V_2, + bool V_3) + IL_0000: nop + IL_0001: br.s IL_003a + + IL_0003: nop + IL_0004: ldarg.0 + IL_0005: stloc.0 + IL_0006: ldloc.0 + IL_0007: switch ( + IL_001a, + IL_0031, + IL_0024) + IL_0018: br.s IL_0033 + + IL_001a: ldarg.1 + IL_001b: stloc.1 + IL_001c: ldloc.1 + IL_001d: brfalse.s IL_0022 + + IL_001f: nop + IL_0020: br.s IL_003a + + IL_0022: br.s IL_0033 + + IL_0024: ldarg.1 + IL_0025: ldc.i4.0 + IL_0026: ceq + IL_0028: stloc.2 + IL_0029: ldloc.2 + IL_002a: brfalse.s IL_002f + + IL_002c: nop + IL_002d: br.s IL_003a + + IL_002f: br.s IL_0033 + + IL_0031: br.s IL_003a + + IL_0033: call void [mscorlib]System.Console::WriteLine() + IL_0038: nop + IL_0039: nop + IL_003a: ldc.i4.1 + IL_003b: stloc.3 + IL_003c: br.s IL_0003 + } // end of method Switch::SwitchWithContinue1 + + .method public hidebysig static void SwitchWithContinue2(int32 i, + bool b) cil managed + { + // Code size 147 (0x93) + .maxstack 2 + .locals init (int32 V_0, + bool V_1, + bool V_2, + bool V_3) + IL_0000: nop + IL_0001: br IL_0086 + + IL_0006: nop + IL_0007: ldarg.0 + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: switch ( + IL_0021, + IL_0073, + IL_0041, + IL_0071) + IL_001f: br.s IL_0064 + + IL_0021: ldarg.1 + IL_0022: stloc.1 + IL_0023: ldloc.1 + IL_0024: brfalse.s IL_0034 + + IL_0026: nop + IL_0027: ldstr "0b" + IL_002c: call void [mscorlib]System.Console::WriteLine(string) + IL_0031: nop + IL_0032: br.s IL_0086 + + IL_0034: ldstr "0!b" + IL_0039: call void [mscorlib]System.Console::WriteLine(string) + IL_003e: nop + IL_003f: br.s IL_0075 + + IL_0041: ldarg.1 + IL_0042: ldc.i4.0 + IL_0043: ceq + IL_0045: stloc.2 + IL_0046: ldloc.2 + IL_0047: brfalse.s IL_0057 + + IL_0049: nop + IL_004a: ldstr "2!b" + IL_004f: call void [mscorlib]System.Console::WriteLine(string) + IL_0054: nop + IL_0055: br.s IL_0086 + + IL_0057: ldstr "2b" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: nop + IL_0062: br.s IL_0092 + + IL_0064: ldstr "default" + IL_0069: call void [mscorlib]System.Console::WriteLine(string) + IL_006e: nop + IL_006f: br.s IL_0075 + + IL_0071: br.s IL_0075 + + IL_0073: br.s IL_0086 + + IL_0075: ldstr "loop-tail" + IL_007a: call void [mscorlib]System.Console::WriteLine(string) + IL_007f: nop + IL_0080: ldarg.0 + IL_0081: ldc.i4.1 + IL_0082: add + IL_0083: starg.s i + IL_0085: nop + IL_0086: ldarg.0 + IL_0087: ldc.i4.s 10 + IL_0089: clt + IL_008b: stloc.3 + IL_008c: ldloc.3 + IL_008d: brtrue IL_0006 + + IL_0092: ret + } // end of method Switch::SwitchWithContinue2 + + .method public hidebysig static void SwitchWithContinue3(bool b) cil managed + { + // Code size 147 (0x93) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1, + bool V_2, + bool V_3, + bool V_4) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br.s IL_0084 + + IL_0005: nop + IL_0006: ldloc.0 + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: switch ( + IL_0020, + IL_0072, + IL_0040, + IL_0070) + IL_001e: br.s IL_0063 + + IL_0020: ldarg.0 + IL_0021: stloc.2 + IL_0022: ldloc.2 + IL_0023: brfalse.s IL_0033 + + IL_0025: nop + IL_0026: ldstr "0b" + IL_002b: call void [mscorlib]System.Console::WriteLine(string) + IL_0030: nop + IL_0031: br.s IL_0080 + + IL_0033: ldstr "0!b" + IL_0038: call void [mscorlib]System.Console::WriteLine(string) + IL_003d: nop + IL_003e: br.s IL_0074 + + IL_0040: ldarg.0 + IL_0041: ldc.i4.0 + IL_0042: ceq + IL_0044: stloc.3 + IL_0045: ldloc.3 + IL_0046: brfalse.s IL_0056 + + IL_0048: nop + IL_0049: ldstr "2!b" + IL_004e: call void [mscorlib]System.Console::WriteLine(string) + IL_0053: nop + IL_0054: br.s IL_0080 + + IL_0056: ldstr "2b" + IL_005b: call void [mscorlib]System.Console::WriteLine(string) + IL_0060: nop + IL_0061: br.s IL_0092 + + IL_0063: ldstr "default" + IL_0068: call void [mscorlib]System.Console::WriteLine(string) + IL_006d: nop + IL_006e: br.s IL_0074 + + IL_0070: br.s IL_0074 + + IL_0072: br.s IL_0080 + + IL_0074: ldstr "loop-tail" + IL_0079: call void [mscorlib]System.Console::WriteLine(string) + IL_007e: nop + IL_007f: nop + IL_0080: ldloc.0 + IL_0081: ldc.i4.1 + IL_0082: add + IL_0083: stloc.0 + IL_0084: ldloc.0 + IL_0085: ldc.i4.s 10 + IL_0087: clt + IL_0089: stloc.s V_4 + IL_008b: ldloc.s V_4 + IL_008d: brtrue IL_0005 + + IL_0092: ret + } // end of method Switch::SwitchWithContinue3 + + .method public hidebysig static void SwitchWithContinue4(bool b) cil managed + { + // Code size 261 (0x105) + .maxstack 2 + .locals init (class [mscorlib]System.Collections.Generic.IEnumerator`1 V_0, + int32 V_1, + int32 V_2, + bool V_3, + bool V_4, + bool V_5, + bool V_6, + bool V_7, + bool V_8) + IL_0000: nop + IL_0001: nop + IL_0002: ldc.i4.0 + IL_0003: ldc.i4.s 10 + IL_0005: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [System.Core]System.Linq.Enumerable::Range(int32, + int32) + IL_000a: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_000f: stloc.0 + .try + { + IL_0010: br IL_00ec + + IL_0015: ldloc.0 + IL_0016: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() + IL_001b: stloc.1 + IL_001c: nop + IL_001d: ldstr "loop: " + IL_0022: ldloc.1 + IL_0023: box [mscorlib]System.Int32 + IL_0028: call string [mscorlib]System.String::Concat(object, + object) + IL_002d: call void [mscorlib]System.Console::WriteLine(string) + IL_0032: nop + IL_0033: ldloc.1 + IL_0034: stloc.2 + IL_0035: ldloc.2 + IL_0036: ldc.i4.1 + IL_0037: sub + IL_0038: switch ( + IL_005f, + IL_00d3, + IL_006c, + IL_007e, + IL_0087, + IL_0090, + IL_009c, + IL_00ba) + IL_005d: br.s IL_00c6 + + IL_005f: ldarg.0 + IL_0060: stloc.3 + IL_0061: ldloc.3 + IL_0062: brfalse.s IL_006a + + IL_0064: nop + IL_0065: br IL_00ec + + IL_006a: br.s IL_00d5 + + IL_006c: ldarg.0 + IL_006d: ldc.i4.0 + IL_006e: ceq + IL_0070: stloc.s V_4 + IL_0072: ldloc.s V_4 + IL_0074: brfalse.s IL_0079 + + IL_0076: nop + IL_0077: br.s IL_00ec + + IL_0079: leave IL_0104 + + IL_007e: ldc.i4.4 + IL_007f: call void [mscorlib]System.Console::WriteLine(int32) + IL_0084: nop + IL_0085: br.s IL_009c + + IL_0087: ldc.i4.5 + IL_0088: call void [mscorlib]System.Console::WriteLine(int32) + IL_008d: nop + IL_008e: br.s IL_00c6 + + IL_0090: ldarg.0 + IL_0091: stloc.s V_5 + IL_0093: ldloc.s V_5 + IL_0095: brfalse.s IL_009a + + IL_0097: nop + IL_0098: br.s IL_00ec + + IL_009a: br.s IL_006c + + IL_009c: ldloc.1 + IL_009d: ldc.i4.2 + IL_009e: rem + IL_009f: ldc.i4.0 + IL_00a0: ceq + IL_00a2: stloc.s V_6 + IL_00a4: ldloc.s V_6 + IL_00a6: brfalse.s IL_00ab + + IL_00a8: nop + IL_00a9: br.s IL_006c + + IL_00ab: ldarg.0 + IL_00ac: ldc.i4.0 + IL_00ad: ceq + IL_00af: stloc.s V_7 + IL_00b1: ldloc.s V_7 + IL_00b3: brfalse.s IL_00b8 + + IL_00b5: nop + IL_00b6: br.s IL_00ec + + IL_00b8: br.s IL_00ba + + IL_00ba: ldarg.0 + IL_00bb: stloc.s V_8 + IL_00bd: ldloc.s V_8 + IL_00bf: brfalse.s IL_00c4 + + IL_00c1: nop + IL_00c2: br.s IL_00ec + + IL_00c4: br.s IL_0087 + + IL_00c6: ldstr "default" + IL_00cb: call void [mscorlib]System.Console::WriteLine(string) + IL_00d0: nop + IL_00d1: br.s IL_00d5 + + IL_00d3: br.s IL_00ec + + IL_00d5: ldstr "break: " + IL_00da: ldloc.1 + IL_00db: box [mscorlib]System.Int32 + IL_00e0: call string [mscorlib]System.String::Concat(object, + object) + IL_00e5: call void [mscorlib]System.Console::WriteLine(string) + IL_00ea: nop + IL_00eb: nop + IL_00ec: ldloc.0 + IL_00ed: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_00f2: brtrue IL_0015 + + IL_00f7: leave.s IL_0104 + + } // end .try + finally + { + IL_00f9: ldloc.0 + IL_00fa: brfalse.s IL_0103 + + IL_00fc: ldloc.0 + IL_00fd: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_0102: nop + IL_0103: endfinally + } // end handler + IL_0104: ret + } // end of method Switch::SwitchWithContinue4 + + .method public hidebysig static void SwitchWithContinue5(bool b) cil managed + { + // Code size 173 (0xad) + .maxstack 2 + .locals init (int32 V_0, + bool V_1, + int32 V_2, + bool V_3, + bool V_4, + bool V_5) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br IL_009e + + IL_0008: nop + IL_0009: ldloc.0 + IL_000a: ldc.i4.5 + IL_000b: clt + IL_000d: stloc.1 + IL_000e: ldloc.1 + IL_000f: brfalse.s IL_008e + + IL_0011: nop + IL_0012: ldloc.0 + IL_0013: stloc.2 + IL_0014: ldloc.2 + IL_0015: switch ( + IL_002c, + IL_0080, + IL_004c, + IL_007e) + IL_002a: br.s IL_0071 + + IL_002c: ldarg.0 + IL_002d: stloc.3 + IL_002e: ldloc.3 + IL_002f: brfalse.s IL_003f + + IL_0031: nop + IL_0032: ldstr "0b" + IL_0037: call void [mscorlib]System.Console::WriteLine(string) + IL_003c: nop + IL_003d: br.s IL_009a + + IL_003f: ldstr "0!b" + IL_0044: call void [mscorlib]System.Console::WriteLine(string) + IL_0049: nop + IL_004a: br.s IL_0082 + + IL_004c: ldarg.0 + IL_004d: ldc.i4.0 + IL_004e: ceq + IL_0050: stloc.s V_4 + IL_0052: ldloc.s V_4 + IL_0054: brfalse.s IL_0064 + + IL_0056: nop + IL_0057: ldstr "2!b" + IL_005c: call void [mscorlib]System.Console::WriteLine(string) + IL_0061: nop + IL_0062: br.s IL_009a + + IL_0064: ldstr "2b" + IL_0069: call void [mscorlib]System.Console::WriteLine(string) + IL_006e: nop + IL_006f: br.s IL_00ac + + IL_0071: ldstr "default" + IL_0076: call void [mscorlib]System.Console::WriteLine(string) + IL_007b: nop + IL_007c: br.s IL_0082 + + IL_007e: br.s IL_0082 + + IL_0080: br.s IL_009a + + IL_0082: ldstr "break-target" + IL_0087: call void [mscorlib]System.Console::WriteLine(string) + IL_008c: nop + IL_008d: nop + IL_008e: ldstr "loop-tail" + IL_0093: call void [mscorlib]System.Console::WriteLine(string) + IL_0098: nop + IL_0099: nop + IL_009a: ldloc.0 + IL_009b: ldc.i4.1 + IL_009c: add + IL_009d: stloc.0 + IL_009e: ldloc.0 + IL_009f: ldc.i4.s 10 + IL_00a1: clt + IL_00a3: stloc.s V_5 + IL_00a5: ldloc.s V_5 + IL_00a7: brtrue IL_0008 + + IL_00ac: ret + } // end of method Switch::SwitchWithContinue5 + + .method public hidebysig static void SwitchWithContinue6(int32 i, + bool b) cil managed + { + // Code size 142 (0x8e) + .maxstack 2 + .locals init (int32 V_0, + bool V_1, + bool V_2, + bool V_3) + IL_0000: nop + IL_0001: nop + IL_0002: ldarg.0 + IL_0003: stloc.0 + IL_0004: ldloc.0 + IL_0005: switch ( + IL_001c, + IL_006e, + IL_003f, + IL_006c) + IL_001a: br.s IL_005f + + IL_001c: ldarg.1 + IL_001d: ldc.i4.0 + IL_001e: ceq + IL_0020: stloc.1 + IL_0021: ldloc.1 + IL_0022: brfalse.s IL_0032 + + IL_0024: nop + IL_0025: ldstr "0!b" + IL_002a: call void [mscorlib]System.Console::WriteLine(string) + IL_002f: nop + IL_0030: br.s IL_0070 + + IL_0032: ldstr "0b" + IL_0037: call void [mscorlib]System.Console::WriteLine(string) + IL_003c: nop + IL_003d: br.s IL_007c + + IL_003f: ldarg.1 + IL_0040: stloc.2 + IL_0041: ldloc.2 + IL_0042: brfalse.s IL_0052 + + IL_0044: nop + IL_0045: ldstr "2b" + IL_004a: call void [mscorlib]System.Console::WriteLine(string) + IL_004f: nop + IL_0050: br.s IL_008d + + IL_0052: ldstr "2!b" + IL_0057: call void [mscorlib]System.Console::WriteLine(string) + IL_005c: nop + IL_005d: br.s IL_007c + + IL_005f: ldstr "default" + IL_0064: call void [mscorlib]System.Console::WriteLine(string) + IL_0069: nop + IL_006a: br.s IL_0070 + + IL_006c: br.s IL_0070 + + IL_006e: br.s IL_007c + + IL_0070: ldstr "loop-tail" + IL_0075: call void [mscorlib]System.Console::WriteLine(string) + IL_007a: nop + IL_007b: nop + IL_007c: ldarg.0 + IL_007d: ldc.i4.1 + IL_007e: add + IL_007f: dup + IL_0080: starg.s i + IL_0082: ldc.i4.s 10 + IL_0084: clt + IL_0086: stloc.3 + IL_0087: ldloc.3 + IL_0088: brtrue IL_0001 + + IL_008d: ret + } // end of method Switch::SwitchWithContinue6 + + .method public hidebysig static void SwitchWithContinue7() cil managed + { + // Code size 76 (0x4c) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1, + bool V_2) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br.s IL_0035 + + IL_0005: nop + IL_0006: ldstr "loop-head" + IL_000b: call void [mscorlib]System.Console::WriteLine(string) + IL_0010: nop + IL_0011: ldloc.0 + IL_0012: stloc.1 + IL_0013: ldloc.1 + IL_0014: brfalse.s IL_002b + + IL_0016: br.s IL_0018 + + IL_0018: ldloc.1 + IL_0019: ldc.i4.1 + IL_001a: beq.s IL_002d + + IL_001c: br.s IL_001e + + IL_001e: ldstr "default" + IL_0023: call void [mscorlib]System.Console::WriteLine(string) + IL_0028: nop + IL_0029: br.s IL_002f + + IL_002b: br.s IL_0031 + + IL_002d: br.s IL_002f + + IL_002f: br.s IL_0040 + + IL_0031: ldloc.0 + IL_0032: ldc.i4.1 + IL_0033: sub + IL_0034: stloc.0 + IL_0035: ldloc.0 + IL_0036: ldc.i4.0 + IL_0037: clt + IL_0039: ldc.i4.0 + IL_003a: ceq + IL_003c: stloc.2 + IL_003d: ldloc.2 + IL_003e: brtrue.s IL_0005 + + IL_0040: ldstr "end" + IL_0045: call void [mscorlib]System.Console::WriteLine(string) + IL_004a: nop + IL_004b: ret + } // end of method Switch::SwitchWithContinue7 + + .method public hidebysig static void SwitchWithContinueInDoubleLoop() cil managed + { + // Code size 128 (0x80) + .maxstack 2 + .locals init (bool V_0, + int32 V_1, + int32 V_2, + int32 V_3, + bool V_4, + bool V_5) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: ldc.i4.0 + IL_0004: stloc.1 + IL_0005: br.s IL_006d + + IL_0007: nop + IL_0008: ldc.i4.0 + IL_0009: stloc.2 + IL_000a: br.s IL_005d + + IL_000c: nop + IL_000d: ldloc.1 + IL_000e: ldloc.2 + IL_000f: add + IL_0010: stloc.3 + IL_0011: ldloc.3 + IL_0012: ldc.i4.s 11 + IL_0014: bgt.s IL_0043 + + IL_0016: ldloc.3 + IL_0017: ldc.i4.1 + IL_0018: sub + IL_0019: switch ( + IL_0051, + IL_0053, + IL_0051, + IL_0053, + IL_0051, + IL_0053, + IL_0051) + IL_003a: br.s IL_003c + + IL_003c: ldloc.3 + IL_003d: ldc.i4.s 11 + IL_003f: beq.s IL_0051 + + IL_0041: br.s IL_0053 + + IL_0043: ldloc.3 + IL_0044: ldc.i4.s 13 + IL_0046: beq.s IL_0051 + + IL_0048: br.s IL_004a + + IL_004a: ldloc.3 + IL_004b: ldc.i4.s 17 + IL_004d: beq.s IL_0051 + + IL_004f: br.s IL_0053 + + IL_0051: br.s IL_0055 + + IL_0053: br.s IL_0059 + + IL_0055: ldc.i4.1 + IL_0056: stloc.0 + IL_0057: br.s IL_0068 + + IL_0059: ldloc.2 + IL_005a: ldc.i4.1 + IL_005b: add + IL_005c: stloc.2 + IL_005d: ldloc.2 + IL_005e: ldc.i4.s 10 + IL_0060: clt + IL_0062: stloc.s V_4 + IL_0064: ldloc.s V_4 + IL_0066: brtrue.s IL_000c + + IL_0068: nop + IL_0069: ldloc.1 + IL_006a: ldc.i4.1 + IL_006b: add + IL_006c: stloc.1 + IL_006d: ldloc.1 + IL_006e: ldc.i4.s 10 + IL_0070: clt + IL_0072: stloc.s V_5 + IL_0074: ldloc.s V_5 + IL_0076: brtrue.s IL_0007 + + IL_0078: ldloc.0 + IL_0079: call void [mscorlib]System.Console::WriteLine(bool) + IL_007e: nop + IL_007f: ret + } // end of method Switch::SwitchWithContinueInDoubleLoop + + .method public hidebysig static void SwitchLoopNesting() cil managed + { + // Code size 140 (0x8c) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1, + bool V_2, + bool V_3, + bool V_4, + bool V_5) + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + IL_0003: br.s IL_007d + + IL_0005: nop + IL_0006: ldloc.0 + IL_0007: stloc.1 + IL_0008: ldloc.1 + IL_0009: brfalse.s IL_0013 + + IL_000b: br.s IL_000d + + IL_000d: ldloc.1 + IL_000e: ldc.i4.1 + IL_000f: beq.s IL_001c + + IL_0011: br.s IL_0025 + + IL_0013: ldc.i4.0 + IL_0014: call void [mscorlib]System.Console::WriteLine(int32) + IL_0019: nop + IL_001a: br.s IL_0052 + + IL_001c: ldc.i4.1 + IL_001d: call void [mscorlib]System.Console::WriteLine(int32) + IL_0022: nop + IL_0023: br.s IL_0052 + + IL_0025: ldloc.0 + IL_0026: ldc.i4.2 + IL_0027: rem + IL_0028: ldc.i4.0 + IL_0029: ceq + IL_002b: stloc.2 + IL_002c: ldloc.2 + IL_002d: brfalse.s IL_004a + + IL_002f: nop + IL_0030: br.s IL_003f + + IL_0032: nop + IL_0033: ldloc.0 + IL_0034: dup + IL_0035: ldc.i4.1 + IL_0036: add + IL_0037: stloc.0 + IL_0038: call void [mscorlib]System.Console::WriteLine(int32) + IL_003d: nop + IL_003e: nop + IL_003f: ldloc.0 + IL_0040: ldc.i4.3 + IL_0041: rem + IL_0042: ldc.i4.0 + IL_0043: cgt.un + IL_0045: stloc.3 + IL_0046: ldloc.3 + IL_0047: brtrue.s IL_0032 + + IL_0049: nop + IL_004a: call void [mscorlib]System.Console::WriteLine() + IL_004f: nop + IL_0050: br.s IL_0052 + + IL_0052: ldloc.0 + IL_0053: ldc.i4.4 + IL_0054: cgt + IL_0056: stloc.s V_4 + IL_0058: ldloc.s V_4 + IL_005a: brfalse.s IL_006b + + IL_005c: nop + IL_005d: ldstr "high" + IL_0062: call void [mscorlib]System.Console::WriteLine(string) + IL_0067: nop + IL_0068: nop + IL_0069: br.s IL_0078 + + IL_006b: nop + IL_006c: ldstr "low" + IL_0071: call void [mscorlib]System.Console::WriteLine(string) + IL_0076: nop + IL_0077: nop + IL_0078: nop + IL_0079: ldloc.0 + IL_007a: ldc.i4.1 + IL_007b: add + IL_007c: stloc.0 + IL_007d: ldloc.0 + IL_007e: ldc.i4.s 10 + IL_0080: clt + IL_0082: stloc.s V_5 + IL_0084: ldloc.s V_5 + IL_0086: brtrue IL_0005 + + IL_008b: ret + } // end of method Switch::SwitchLoopNesting + + .method public hidebysig static void SingleIf1(int32 i, + bool a) cil managed + { + // Code size 35 (0x23) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.1 + IL_0003: beq.s IL_000d + + IL_0005: ldarg.0 + IL_0006: ldc.i4.2 + IL_0007: ceq + IL_0009: ldarg.1 + IL_000a: and + IL_000b: br.s IL_000e + + IL_000d: ldc.i4.1 + IL_000e: stloc.0 + IL_000f: ldloc.0 + IL_0010: brfalse.s IL_001b + + IL_0012: nop + IL_0013: ldc.i4.1 + IL_0014: call void [mscorlib]System.Console::WriteLine(int32) + IL_0019: nop + IL_001a: nop + IL_001b: ldc.i4.2 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: nop + IL_0022: ret + } // end of method Switch::SingleIf1 + + .method public hidebysig static void SingleIf2(int32 i, + bool a, + bool b) cil managed + { + // Code size 43 (0x2b) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.1 + IL_0003: beq.s IL_0015 + + IL_0005: ldarg.0 + IL_0006: ldc.i4.2 + IL_0007: ceq + IL_0009: ldarg.1 + IL_000a: and + IL_000b: brtrue.s IL_0015 + + IL_000d: ldarg.0 + IL_000e: ldc.i4.3 + IL_000f: ceq + IL_0011: ldarg.2 + IL_0012: and + IL_0013: br.s IL_0016 + + IL_0015: ldc.i4.1 + IL_0016: stloc.0 + IL_0017: ldloc.0 + IL_0018: brfalse.s IL_0023 + + IL_001a: nop + IL_001b: ldc.i4.1 + IL_001c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0021: nop + IL_0022: nop + IL_0023: ldc.i4.2 + IL_0024: call void [mscorlib]System.Console::WriteLine(int32) + IL_0029: nop + IL_002a: ret + } // end of method Switch::SingleIf2 + + .method public hidebysig static void SingleIf3(int32 i, + bool a, + bool b) cil managed + { + // Code size 38 (0x26) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: brtrue.s IL_0010 + + IL_0004: ldarg.0 + IL_0005: ldc.i4.1 + IL_0006: beq.s IL_0010 + + IL_0008: ldarg.0 + IL_0009: ldc.i4.2 + IL_000a: ceq + IL_000c: ldarg.2 + IL_000d: and + IL_000e: br.s IL_0011 + + IL_0010: ldc.i4.1 + IL_0011: stloc.0 + IL_0012: ldloc.0 + IL_0013: brfalse.s IL_001e + + IL_0015: nop + IL_0016: ldc.i4.1 + IL_0017: call void [mscorlib]System.Console::WriteLine(int32) + IL_001c: nop + IL_001d: nop + IL_001e: ldc.i4.2 + IL_001f: call void [mscorlib]System.Console::WriteLine(int32) + IL_0024: nop + IL_0025: ret + } // end of method Switch::SingleIf3 + + .method public hidebysig static void SingleIf4(int32 i, + bool a) cil managed + { + // Code size 51 (0x33) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.1 + IL_0003: beq.s IL_001d + + IL_0005: ldarg.0 + IL_0006: ldc.i4.2 + IL_0007: beq.s IL_001d + + IL_0009: ldarg.0 + IL_000a: ldc.i4.3 + IL_000b: ceq + IL_000d: ldc.i4.0 + IL_000e: ceq + IL_0010: ldarg.1 + IL_0011: and + IL_0012: brtrue.s IL_001d + + IL_0014: ldarg.0 + IL_0015: ldc.i4.4 + IL_0016: ceq + IL_0018: ldc.i4.0 + IL_0019: ceq + IL_001b: br.s IL_001e + + IL_001d: ldc.i4.1 + IL_001e: stloc.0 + IL_001f: ldloc.0 + IL_0020: brfalse.s IL_002b + + IL_0022: nop + IL_0023: ldc.i4.1 + IL_0024: call void [mscorlib]System.Console::WriteLine(int32) + IL_0029: nop + IL_002a: nop + IL_002b: ldc.i4.2 + IL_002c: call void [mscorlib]System.Console::WriteLine(int32) + IL_0031: nop + IL_0032: ret + } // end of method Switch::SingleIf4 + + .method public hidebysig static void NestedIf(int32 i) cil managed + { + // Code size 49 (0x31) + .maxstack 2 + .locals init (bool V_0, + bool V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.1 + IL_0003: ceq + IL_0005: ldc.i4.0 + IL_0006: ceq + IL_0008: stloc.0 + IL_0009: ldloc.0 + IL_000a: brfalse.s IL_002a + + IL_000c: nop + IL_000d: ldarg.0 + IL_000e: ldc.i4.2 + IL_000f: ceq + IL_0011: stloc.1 + IL_0012: ldloc.1 + IL_0013: brfalse.s IL_001e + + IL_0015: nop + IL_0016: ldc.i4.2 + IL_0017: call void [mscorlib]System.Console::WriteLine(int32) + IL_001c: nop + IL_001d: nop + IL_001e: ldstr "default" + IL_0023: call void [mscorlib]System.Console::WriteLine(string) + IL_0028: nop + IL_0029: nop + IL_002a: call void [mscorlib]System.Console::WriteLine() + IL_002f: nop + IL_0030: ret + } // end of method Switch::NestedIf + + .method public hidebysig static void IfChainWithCondition(int32 i) cil managed + { + // Code size 151 (0x97) + .maxstack 2 + .locals init (bool V_0, + bool V_1, + bool V_2, + bool V_3, + bool V_4, + bool V_5) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.0 + IL_0003: ceq + IL_0005: stloc.0 + IL_0006: ldloc.0 + IL_0007: brfalse.s IL_0014 + + IL_0009: nop + IL_000a: ldc.i4.0 + IL_000b: call void [mscorlib]System.Console::WriteLine(int32) + IL_0010: nop + IL_0011: nop + IL_0012: br.s IL_0090 + + IL_0014: ldarg.0 + IL_0015: ldc.i4.1 + IL_0016: ceq + IL_0018: stloc.1 + IL_0019: ldloc.1 + IL_001a: brfalse.s IL_0027 + + IL_001c: nop + IL_001d: ldc.i4.1 + IL_001e: call void [mscorlib]System.Console::WriteLine(int32) + IL_0023: nop + IL_0024: nop + IL_0025: br.s IL_0090 + + IL_0027: ldarg.0 + IL_0028: ldc.i4.2 + IL_0029: ceq + IL_002b: stloc.2 + IL_002c: ldloc.2 + IL_002d: brfalse.s IL_003a + + IL_002f: nop + IL_0030: ldc.i4.2 + IL_0031: call void [mscorlib]System.Console::WriteLine(int32) + IL_0036: nop + IL_0037: nop + IL_0038: br.s IL_0090 + + IL_003a: ldarg.0 + IL_003b: ldc.i4.3 + IL_003c: ceq + IL_003e: stloc.3 + IL_003f: ldloc.3 + IL_0040: brfalse.s IL_004d + + IL_0042: nop + IL_0043: ldc.i4.3 + IL_0044: call void [mscorlib]System.Console::WriteLine(int32) + IL_0049: nop + IL_004a: nop + IL_004b: br.s IL_0090 + + IL_004d: ldarg.0 + IL_004e: ldc.i4.4 + IL_004f: ceq + IL_0051: stloc.s V_4 + IL_0053: ldloc.s V_4 + IL_0055: brfalse.s IL_0062 + + IL_0057: nop + IL_0058: ldc.i4.4 + IL_0059: call void [mscorlib]System.Console::WriteLine(int32) + IL_005e: nop + IL_005f: nop + IL_0060: br.s IL_0090 + + IL_0062: ldarg.0 + IL_0063: ldc.i4.5 + IL_0064: bne.un.s IL_006d + + IL_0066: call bool [mscorlib]System.Console::get_CapsLock() + IL_006b: br.s IL_006e + + IL_006d: ldc.i4.0 + IL_006e: stloc.s V_5 + IL_0070: ldloc.s V_5 + IL_0072: brfalse.s IL_0083 + + IL_0074: nop + IL_0075: ldstr "5A" + IL_007a: call void [mscorlib]System.Console::WriteLine(string) + IL_007f: nop + IL_0080: nop + IL_0081: br.s IL_0090 + + IL_0083: nop + IL_0084: ldstr "default" + IL_0089: call void [mscorlib]System.Console::WriteLine(string) + IL_008e: nop + IL_008f: nop + IL_0090: call void [mscorlib]System.Console::WriteLine() + IL_0095: nop + IL_0096: ret + } // end of method Switch::IfChainWithCondition + + .method public hidebysig static bool SwitchlikeIf(int32 i, + int32 j) cil managed + { + // Code size 270 (0x10e) + .maxstack 2 + .locals init (bool V_0, + bool V_1, + bool V_2, + bool V_3, + bool V_4, + bool V_5, + bool V_6, + bool V_7, + bool V_8, + bool V_9, + bool V_10, + bool V_11) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: brfalse.s IL_000a + + IL_0004: ldarg.1 + IL_0005: ldc.i4.0 + IL_0006: cgt.un + IL_0008: br.s IL_000b + + IL_000a: ldc.i4.0 + IL_000b: stloc.0 + IL_000c: ldloc.0 + IL_000d: brfalse.s IL_008a + + IL_000f: nop + IL_0010: ldarg.0 + IL_0011: ldc.i4.m1 + IL_0012: bne.un.s IL_001a + + IL_0014: ldarg.1 + IL_0015: ldc.i4.m1 + IL_0016: ceq + IL_0018: br.s IL_001b + + IL_001a: ldc.i4.0 + IL_001b: stloc.1 + IL_001c: ldloc.1 + IL_001d: brfalse.s IL_002c + + IL_001f: nop + IL_0020: ldstr "-1, -1" + IL_0025: call void [mscorlib]System.Console::WriteLine(string) + IL_002a: nop + IL_002b: nop + IL_002c: ldarg.0 + IL_002d: ldc.i4.m1 + IL_002e: bne.un.s IL_0036 + + IL_0030: ldarg.1 + IL_0031: ldc.i4.1 + IL_0032: ceq + IL_0034: br.s IL_0037 + + IL_0036: ldc.i4.0 + IL_0037: stloc.2 + IL_0038: ldloc.2 + IL_0039: brfalse.s IL_0048 + + IL_003b: nop + IL_003c: ldstr "-1, 1" + IL_0041: call void [mscorlib]System.Console::WriteLine(string) + IL_0046: nop + IL_0047: nop + IL_0048: ldarg.0 + IL_0049: ldc.i4.1 + IL_004a: bne.un.s IL_0052 + + IL_004c: ldarg.1 + IL_004d: ldc.i4.m1 + IL_004e: ceq + IL_0050: br.s IL_0053 + + IL_0052: ldc.i4.0 + IL_0053: stloc.3 + IL_0054: ldloc.3 + IL_0055: brfalse.s IL_0064 + + IL_0057: nop + IL_0058: ldstr "1, -1" + IL_005d: call void [mscorlib]System.Console::WriteLine(string) + IL_0062: nop + IL_0063: nop + IL_0064: ldarg.0 + IL_0065: ldc.i4.1 + IL_0066: bne.un.s IL_006e + + IL_0068: ldarg.1 + IL_0069: ldc.i4.1 + IL_006a: ceq + IL_006c: br.s IL_006f + + IL_006e: ldc.i4.0 + IL_006f: stloc.s V_4 + IL_0071: ldloc.s V_4 + IL_0073: brfalse.s IL_0082 + + IL_0075: nop + IL_0076: ldstr "1, 1" + IL_007b: call void [mscorlib]System.Console::WriteLine(string) + IL_0080: nop + IL_0081: nop + IL_0082: ldc.i4.0 + IL_0083: stloc.s V_5 + IL_0085: br IL_010b + + IL_008a: ldarg.0 + IL_008b: ldc.i4.0 + IL_008c: cgt.un + IL_008e: stloc.s V_6 + IL_0090: ldloc.s V_6 + IL_0092: brfalse.s IL_00c8 + + IL_0094: nop + IL_0095: ldarg.0 + IL_0096: ldc.i4.m1 + IL_0097: ceq + IL_0099: stloc.s V_7 + IL_009b: ldloc.s V_7 + IL_009d: brfalse.s IL_00ac + + IL_009f: nop + IL_00a0: ldstr "-1, 0" + IL_00a5: call void [mscorlib]System.Console::WriteLine(string) + IL_00aa: nop + IL_00ab: nop + IL_00ac: ldarg.0 + IL_00ad: ldc.i4.1 + IL_00ae: ceq + IL_00b0: stloc.s V_8 + IL_00b2: ldloc.s V_8 + IL_00b4: brfalse.s IL_00c3 + + IL_00b6: nop + IL_00b7: ldstr "1, 0" + IL_00bc: call void [mscorlib]System.Console::WriteLine(string) + IL_00c1: nop + IL_00c2: nop + IL_00c3: ldc.i4.0 + IL_00c4: stloc.s V_5 + IL_00c6: br.s IL_010b + + IL_00c8: ldarg.1 + IL_00c9: ldc.i4.0 + IL_00ca: cgt.un + IL_00cc: stloc.s V_9 + IL_00ce: ldloc.s V_9 + IL_00d0: brfalse.s IL_0106 + + IL_00d2: nop + IL_00d3: ldarg.1 + IL_00d4: ldc.i4.m1 + IL_00d5: ceq + IL_00d7: stloc.s V_10 + IL_00d9: ldloc.s V_10 + IL_00db: brfalse.s IL_00ea + + IL_00dd: nop + IL_00de: ldstr "0, -1" + IL_00e3: call void [mscorlib]System.Console::WriteLine(string) + IL_00e8: nop + IL_00e9: nop + IL_00ea: ldarg.1 + IL_00eb: ldc.i4.1 + IL_00ec: ceq + IL_00ee: stloc.s V_11 + IL_00f0: ldloc.s V_11 + IL_00f2: brfalse.s IL_0101 + + IL_00f4: nop + IL_00f5: ldstr "0, 1" + IL_00fa: call void [mscorlib]System.Console::WriteLine(string) + IL_00ff: nop + IL_0100: nop + IL_0101: ldc.i4.0 + IL_0102: stloc.s V_5 + IL_0104: br.s IL_010b + + IL_0106: ldc.i4.1 + IL_0107: stloc.s V_5 + IL_0109: br.s IL_010b + + IL_010b: ldloc.s V_5 + IL_010d: ret + } // end of method Switch::SwitchlikeIf + + .method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed + { + // Code size 74 (0x4a) + .maxstack 2 + .locals init (bool V_0, + bool V_1, + bool V_2, + bool V_3, + bool V_4) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.0 + IL_0003: cgt.un + IL_0005: stloc.0 + IL_0006: ldloc.0 + IL_0007: brfalse.s IL_0042 + + IL_0009: nop + IL_000a: ldarg.0 + IL_000b: ldc.i4.1 + IL_000c: ceq + IL_000e: stloc.1 + IL_000f: ldloc.1 + IL_0010: brfalse.s IL_001b + + IL_0012: nop + IL_0013: ldc.i4.1 + IL_0014: call void [mscorlib]System.Console::WriteLine(int32) + IL_0019: nop + IL_001a: nop + IL_001b: ldarg.0 + IL_001c: ldc.i4.2 + IL_001d: ceq + IL_001f: stloc.2 + IL_0020: ldloc.2 + IL_0021: brfalse.s IL_002c + + IL_0023: nop + IL_0024: ldc.i4.2 + IL_0025: call void [mscorlib]System.Console::WriteLine(int32) + IL_002a: nop + IL_002b: nop + IL_002c: ldarg.0 + IL_002d: ldc.i4.3 + IL_002e: ceq + IL_0030: stloc.3 + IL_0031: ldloc.3 + IL_0032: brfalse.s IL_003d + + IL_0034: nop + IL_0035: ldc.i4.3 + IL_0036: call void [mscorlib]System.Console::WriteLine(int32) + IL_003b: nop + IL_003c: nop + IL_003d: ldc.i4.0 + IL_003e: stloc.s V_4 + IL_0040: br.s IL_0047 + + IL_0042: ldc.i4.0 + IL_0043: stloc.s V_4 + IL_0045: br.s IL_0047 + + IL_0047: ldloc.s V_4 + IL_0049: ret + } // end of method Switch::SwitchlikeIf2 + + .method public hidebysig static void SingleIntervalIf(char c) cil managed + { + // Code size 46 (0x2e) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldc.i4.s 65 + IL_0004: blt.s IL_0010 + + IL_0006: ldarg.0 + IL_0007: ldc.i4.s 90 + IL_0009: cgt + IL_000b: ldc.i4.0 + IL_000c: ceq + IL_000e: br.s IL_0011 + + IL_0010: ldc.i4.0 + IL_0011: stloc.0 + IL_0012: ldloc.0 + IL_0013: brfalse.s IL_0022 + + IL_0015: nop + IL_0016: ldstr "alphabet" + IL_001b: call void [mscorlib]System.Console::WriteLine(string) + IL_0020: nop + IL_0021: nop + IL_0022: ldstr "end" + IL_0027: call void [mscorlib]System.Console::WriteLine(string) + IL_002c: nop + IL_002d: ret + } // end of method Switch::SingleIntervalIf + + .method public hidebysig static bool Loop8(char c, + bool b, + class [mscorlib]System.Func`1 getChar) cil managed + { + // Code size 59 (0x3b) + .maxstack 2 + .locals init (bool V_0, + bool V_1, + bool V_2) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0035 + + IL_0006: nop + IL_0007: br.s IL_0013 + + IL_0009: nop + IL_000a: ldarg.2 + IL_000b: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_0010: starg.s c + IL_0012: nop + IL_0013: ldarg.0 + IL_0014: ldc.i4.s 97 + IL_0016: blt.s IL_001d + + IL_0018: ldarg.0 + IL_0019: ldc.i4.s 122 + IL_001b: ble.s IL_002f + + IL_001d: ldarg.0 + IL_001e: ldc.i4.s 65 + IL_0020: blt.s IL_002c + + IL_0022: ldarg.0 + IL_0023: ldc.i4.s 90 + IL_0025: cgt + IL_0027: ldc.i4.0 + IL_0028: ceq + IL_002a: br.s IL_002d + + IL_002c: ldc.i4.0 + IL_002d: br.s IL_0030 + + IL_002f: ldc.i4.1 + IL_0030: stloc.1 + IL_0031: ldloc.1 + IL_0032: brtrue.s IL_0009 + + IL_0034: nop + IL_0035: ldc.i4.1 + IL_0036: stloc.2 + IL_0037: br.s IL_0039 + + IL_0039: ldloc.2 + IL_003a: ret + } // end of method Switch::Loop8 + + .method public hidebysig static void Loop9(class [mscorlib]System.Func`1 getChar) cil managed + { + // Code size 46 (0x2e) + .maxstack 2 + .locals init (char V_0, + bool V_1) + IL_0000: nop + IL_0001: nop + IL_0002: ldarg.0 + IL_0003: callvirt instance !0 class [mscorlib]System.Func`1::Invoke() + IL_0008: stloc.0 + IL_0009: nop + IL_000a: ldloc.0 + IL_000b: ldc.i4.m1 + IL_000c: beq.s IL_0028 + + IL_000e: ldloc.0 + IL_000f: ldc.i4.s 10 + IL_0011: beq.s IL_0028 + + IL_0013: ldloc.0 + IL_0014: ldc.i4 0x2028 + IL_0019: beq.s IL_0028 + + IL_001b: ldloc.0 + IL_001c: ldc.i4 0x2029 + IL_0021: ceq + IL_0023: ldc.i4.0 + IL_0024: ceq + IL_0026: br.s IL_0029 + + IL_0028: ldc.i4.0 + IL_0029: stloc.1 + IL_002a: ldloc.1 + IL_002b: brtrue.s IL_0001 + + IL_002d: ret + } // end of method Switch::Loop9 + + .method public hidebysig static void SwitchWithBreakCase(int32 i, + bool b) cil managed + { + // Code size 69 (0x45) + .maxstack 2 + .locals init (bool V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0039 + + IL_0006: nop + IL_0007: ldarg.0 + IL_0008: stloc.1 + IL_0009: ldloc.1 + IL_000a: ldc.i4.1 + IL_000b: beq.s IL_0015 + + IL_000d: br.s IL_000f + + IL_000f: ldloc.1 + IL_0010: ldc.i4.2 + IL_0011: beq.s IL_002b + + IL_0013: br.s IL_001e + + IL_0015: ldc.i4.1 + IL_0016: call void [mscorlib]System.Console::WriteLine(int32) + IL_001b: nop + IL_001c: br.s IL_002d + + IL_001e: ldstr "default" + IL_0023: call void [mscorlib]System.Console::WriteLine(string) + IL_0028: nop + IL_0029: br.s IL_002d + + IL_002b: br.s IL_002d + + IL_002d: ldstr "b" + IL_0032: call void [mscorlib]System.Console::WriteLine(string) + IL_0037: nop + IL_0038: nop + IL_0039: ldstr "end" + IL_003e: call void [mscorlib]System.Console::WriteLine(string) + IL_0043: nop + IL_0044: ret + } // end of method Switch::SwitchWithBreakCase + + .method public hidebysig static void SwitchWithReturnAndBreak(int32 i, + bool b) cil managed + { + // Code size 44 (0x2c) + .maxstack 2 + .locals init (int32 V_0, + bool V_1, + bool V_2) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_000e + + IL_0006: br.s IL_0008 + + IL_0008: ldloc.0 + IL_0009: ldc.i4.1 + IL_000a: beq.s IL_0018 + + IL_000c: br.s IL_0025 + + IL_000e: ldarg.1 + IL_000f: stloc.1 + IL_0010: ldloc.1 + IL_0011: brfalse.s IL_0016 + + IL_0013: nop + IL_0014: br.s IL_002b + + IL_0016: br.s IL_0025 + + IL_0018: ldarg.1 + IL_0019: ldc.i4.0 + IL_001a: ceq + IL_001c: stloc.2 + IL_001d: ldloc.2 + IL_001e: brfalse.s IL_0023 + + IL_0020: nop + IL_0021: br.s IL_002b + + IL_0023: br.s IL_0025 + + IL_0025: call void [mscorlib]System.Console::WriteLine() + IL_002a: nop + IL_002b: ret + } // end of method Switch::SwitchWithReturnAndBreak + + .method public hidebysig static int32 SwitchWithReturnAndBreak2(int32 i, + bool b) cil managed + { + // Code size 106 (0x6a) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1, + bool V_2) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: ldc.i4 0x14e + IL_0009: bgt.s IL_0022 + + IL_000b: ldloc.0 + IL_000c: ldc.i4.4 + IL_000d: beq.s IL_0040 + + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ldc.i4.s 33 + IL_0014: beq.s IL_0040 + + IL_0016: br.s IL_0018 + + IL_0018: ldloc.0 + IL_0019: ldc.i4 0x14e + IL_001e: beq.s IL_004a + + IL_0020: br.s IL_005e + + IL_0022: ldloc.0 + IL_0023: ldc.i4 0x18b + IL_0028: beq.s IL_0056 + + IL_002a: br.s IL_002c + + IL_002c: ldloc.0 + IL_002d: ldc.i4 0x19a + IL_0032: beq.s IL_0056 + + IL_0034: br.s IL_0036 + + IL_0036: ldloc.0 + IL_0037: ldc.i4 0x1c7 + IL_003c: beq.s IL_0056 + + IL_003e: br.s IL_005e + + IL_0040: call void [mscorlib]System.Console::WriteLine() + IL_0045: nop + IL_0046: ldc.i4.1 + IL_0047: stloc.1 + IL_0048: br.s IL_0068 + + IL_004a: ldarg.1 + IL_004b: stloc.2 + IL_004c: ldloc.2 + IL_004d: brfalse.s IL_0054 + + IL_004f: nop + IL_0050: ldc.i4.2 + IL_0051: stloc.1 + IL_0052: br.s IL_0068 + + IL_0054: br.s IL_005e + + IL_0056: call void [mscorlib]System.Console::WriteLine() + IL_005b: nop + IL_005c: br.s IL_005e + + IL_005e: call void [mscorlib]System.Console::WriteLine() + IL_0063: nop + IL_0064: ldc.i4.0 + IL_0065: stloc.1 + IL_0066: br.s IL_0068 + + IL_0068: ldloc.1 + IL_0069: ret + } // end of method Switch::SwitchWithReturnAndBreak2 + + .method public hidebysig static void SwitchWithReturnAndBreak3(int32 i) cil managed + { + // Code size 41 (0x29) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0010 + + IL_0006: br.s IL_0008 + + IL_0008: ldloc.0 + IL_0009: ldc.i4.1 + IL_000a: beq.s IL_0019 + + IL_000c: br.s IL_000e + + IL_000e: br.s IL_0028 + + IL_0010: ldc.i4.0 + IL_0011: call void [mscorlib]System.Console::WriteLine(int32) + IL_0016: nop + IL_0017: br.s IL_0022 + + IL_0019: ldc.i4.1 + IL_001a: call void [mscorlib]System.Console::WriteLine(int32) + IL_001f: nop + IL_0020: br.s IL_0022 + + IL_0022: call void [mscorlib]System.Console::WriteLine() + IL_0027: nop + IL_0028: ret + } // end of method Switch::SwitchWithReturnAndBreak3 + } // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.Switch .class private auto ansi sealed '' diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs index ed8f0da97..ee44eea01 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs @@ -47,7 +47,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow private BlockTransformContext context; private ControlFlowNode cfgNode; private BlockContainer currentContainer; - private Block continueBlock; /// /// Builds structured control flow for the block associated with the control flow node. @@ -61,9 +60,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow this.context = context; currentContainer = (BlockContainer)block.Parent; - // for detection of continue statements - continueBlock = GuessContinueBlock(); - // We only embed blocks into this block if they aren't referenced anywhere else, // so those blocks are dominated by this block. // BlockILTransform thus guarantees that the blocks being embedded are already @@ -339,6 +335,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow && ThenInstIsSingleExit(elseIfInst); } + private void InvertIf(Block block, IfInstruction ifInst) => InvertIf(block, ifInst, context); + /// /// if (cond) { then... } /// else...; @@ -349,7 +347,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// /// Assumes ifInst does not have an else block /// - private void InvertIf(Block block, IfInstruction ifInst) + internal static void InvertIf(Block block, IfInstruction ifInst, ILTransformContext context) { Debug.Assert(ifInst.Parent == block); @@ -488,7 +486,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // breaks have highest priority in a switch if ((keyword1 == Keyword.Break) != (keyword2 == Keyword.Break)) return keyword1 == Keyword.Break ? 1 : -1; - } else { // breaks have lowest priority if ((keyword1 == Keyword.Break) != (keyword2 == Keyword.Break)) @@ -537,7 +534,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow keyword = Keyword.Other; switch (exitInst) { case Branch branch: - if (branch.TargetBlock == continueBlock) { + if (IsContinueBlock(branch.TargetContainer, branch.TargetBlock)) { keyword = Keyword.Continue; return true; } @@ -599,19 +596,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// Used to identify branches targetting this block as continue statements, for ordering priority. /// /// - private Block GuessContinueBlock() + private static bool IsContinueBlock(BlockContainer container, Block block) { - if (currentContainer.Kind != ContainerKind.Loop) - return null; + if (container.Kind != ContainerKind.Loop) + return false; - // continue blocks have exactly 2 incoming edges - if (currentContainer.EntryPoint.IncomingEdgeCount == 2) { - var forIncrement = HighLevelLoopTransform.GetIncrementBlock(currentContainer, currentContainer.EntryPoint); + // increment blocks have exactly 2 incoming edges + if (container.EntryPoint.IncomingEdgeCount == 2) { + var forIncrement = HighLevelLoopTransform.GetIncrementBlock(container, container.EntryPoint); if (forIncrement != null) - return forIncrement; + return block == forIncrement; } - return currentContainer.EntryPoint; + return block == container.EntryPoint; } /// diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs index 45c04f25d..9e0f4e0bc 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/LoopDetection.cs @@ -42,6 +42,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// Block container corresponding to the current cfg. BlockContainer currentBlockContainer; + + /// + /// Enabled during DetectSwitchBody, used by ExtendLoop and children + /// + private bool isSwitch; + /// + /// Used when isSwitch == true, to determine appropriate exit points within loops + /// + private SwitchDetection.LoopContext loopContext; /// /// Check whether 'block' is a loop head; and construct a loop instruction @@ -234,17 +243,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// /// Requires and maintains the invariant that a node is marked as visited iff it is contained in the loop. /// - void ExtendLoop(ControlFlowNode loopHead, List loop, out ControlFlowNode exitPoint, bool isSwitch=false) + void ExtendLoop(ControlFlowNode loopHead, List loop, out ControlFlowNode exitPoint) { - exitPoint = FindExitPoint(loopHead, loop, isSwitch); + exitPoint = FindExitPoint(loopHead, loop); Debug.Assert(!loop.Contains(exitPoint), "Cannot pick an exit point that is part of the natural loop"); if (exitPoint != null) { // Either we are in case 1 and just picked an exit that maximizes the amount of code // outside the loop, or we are in case 2 and found an exit point via post-dominance. // Note that if exitPoint == NoExitPoint, we end up adding all dominated blocks to the loop. var ep = exitPoint; - foreach (var node in TreeTraversal.PreOrder(loopHead, n => (n != ep) ? n.DominatorTreeChildren : null)) { - if (node != exitPoint && !node.Visited) { + foreach (var node in TreeTraversal.PreOrder(loopHead, n => DominatorTreeChildren(n, ep))) { + if (!node.Visited) { node.Visited = true; loop.Add(node); } @@ -272,14 +281,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// 3) otherwise (exit point unknown, heuristically extend loop): null /// /// This method must not write to the Visited flags on the CFG. - ControlFlowNode FindExitPoint(ControlFlowNode loopHead, IReadOnlyList naturalLoop, bool treatBackEdgesAsExits) + internal ControlFlowNode FindExitPoint(ControlFlowNode loopHead, IReadOnlyList naturalLoop) { - bool hasReachableExit = context.ControlFlowGraph.HasReachableExit(loopHead); - if (!hasReachableExit && treatBackEdgesAsExits) { - // If we're analyzing the switch, there's no reachable exit, but the loopHead (=switchHead) block - // is also a loop head, we consider the back-edge a reachable exit for the switch. - hasReachableExit = loopHead.Predecessors.Any(p => loopHead.Dominates(p)); - } + bool hasReachableExit = HasReachableExit(loopHead); if (!hasReachableExit) { // Case 1: // There are no nodes n so that loopHead dominates a predecessor of n but not n itself @@ -305,7 +309,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // We need to pick our exit point so that all paths from the loop head // to the reachable exits run through that exit point. var cfg = context.ControlFlowGraph.cfg; - var revCfg = PrepareReverseCFG(loopHead, treatBackEdgesAsExits, out int exitNodeArity); + var revCfg = PrepareReverseCFG(loopHead, out int exitNodeArity); //ControlFlowNode.ExportGraph(cfg).Show("cfg"); //ControlFlowNode.ExportGraph(revCfg).Show("rev"); ControlFlowNode commonAncestor = revCfg[loopHead.UserIndex]; @@ -338,13 +342,17 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // * The loop has a single exit point that wasn't considered during post-dominance analysis. // (which means the single exit isn't dominated by the loop head) // -> we should return NoExitPoint so that all code dominated by the loop head is included into the loop - if (exitNodeArity > 1) { + if (exitNodeArity > 1) return null; - } else { - // If exitNodeArity == 0, we should maybe look test if our exits out of the block container are all compatible? - // but I don't think it hurts to have a bit too much code inside the loop in this rare case. - return NoExitPoint; - } + + // Exit node is on the very edge of the tree, and isn't important for determining inclusion + // Still necessary for switch detection to insert correct leave statements + if (exitNodeArity == 1 && isSwitch) + return loopContext.GetBreakTargets(loopHead).Distinct().Single(); + + // If exitNodeArity == 0, we should maybe look test if our exits out of the block container are all compatible? + // but I don't think it hurts to have a bit too much code inside the loop in this rare case. + return NoExitPoint; } } @@ -385,6 +393,22 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } + /// + /// Extension of ControlFlowGraph.HasReachableExit + /// Uses loopContext.GetBreakTargets().Any() when analyzing switches to avoid + /// classifying continue blocks as reachable exits. + /// + bool HasReachableExit(ControlFlowNode node) => isSwitch + ? loopContext.GetBreakTargets(node).Any() + : context.ControlFlowGraph.HasReachableExit(node); + + /// + /// Returns the children in a loop dominator tree, with an optional exit point + /// Avoids returning continue statements when analysing switches (because increment blocks can be dominated) + /// + IEnumerable DominatorTreeChildren(ControlFlowNode n, ControlFlowNode exitPoint) => + n.DominatorTreeChildren.Where(c => c != exitPoint && (!isSwitch || !loopContext.MatchContinue(c))); + /// /// Pick exit point by picking any node that has no reachable exits. /// @@ -397,9 +421,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// This method must not write to the Visited flags on the CFG. void PickExitPoint(ControlFlowNode node, ref ControlFlowNode exitPoint, ref int exitPointILOffset) { + if (isSwitch && loopContext.MatchContinue(node)) + return; + Block block = (Block)node.UserData; if (block.ILRange.Start > exitPointILOffset - && !context.ControlFlowGraph.HasReachableExit(node) + && !HasReachableExit(node) && ((Block)node.UserData).Parent == currentBlockContainer) { // HasReachableExit(node) == false @@ -431,7 +458,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// or that leave the block Container. /// /// Entry point of the loop. - /// Whether to treat loop back edges as exit points. + /// Whether to ignore branches that map to C# 'continue' statements. /// out: The number of different CFG nodes. /// Possible values: /// 0 = no CFG nodes used as exit nodes (although edges leaving the block container might still be exits); @@ -439,7 +466,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// 2 = more than one CFG node (not dominated by loopHead) was used as an exit node. /// /// - ControlFlowNode[] PrepareReverseCFG(ControlFlowNode loopHead, bool treatBackEdgesAsExits, out int exitNodeArity) + ControlFlowNode[] PrepareReverseCFG(ControlFlowNode loopHead, out int exitNodeArity) { ControlFlowNode[] cfg = context.ControlFlowGraph.cfg; ControlFlowNode[] rev = new ControlFlowNode[cfg.Length + 1]; @@ -451,11 +478,16 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow ControlFlowNode exitNode = new ControlFlowNode { UserIndex = -1 }; rev[cfg.Length] = exitNode; for (int i = 0; i < cfg.Length; i++) { - if (!loopHead.Dominates(cfg[i])) + if (!loopHead.Dominates(cfg[i]) || isSwitch && cfg[i] != loopHead && loopContext.MatchContinue(cfg[i])) continue; + // Add reverse edges for all edges in cfg foreach (var succ in cfg[i].Successors) { - if (loopHead.Dominates(succ) && (!treatBackEdgesAsExits || loopHead != succ)) { + // edges to outer loops still count as exits (labelled continue not implemented) + if (isSwitch && loopContext.MatchContinue(succ, 1)) + continue; + + if (loopHead.Dominates(succ)) { rev[succ.UserIndex].AddEdgeTo(rev[i]); } else { if (nodeTreatedAsExitNode == null) @@ -658,11 +690,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow Debug.Assert(h.UserData == block); Debug.Assert(!TreeTraversal.PreOrder(h, n => n.DominatorTreeChildren).Any(n => n.Visited)); + isSwitch = true; + loopContext = new SwitchDetection.LoopContext(context.ControlFlowGraph, h); + var nodesInSwitch = new List(); nodesInSwitch.Add(h); h.Visited = true; - ExtendLoop(h, nodesInSwitch, out var exitPoint, isSwitch: true); - if (exitPoint != null && exitPoint.Predecessors.Count == 1 && !context.ControlFlowGraph.HasReachableExit(exitPoint)) { + ExtendLoop(h, nodesInSwitch, out var exitPoint); + if (exitPoint != null && h.Dominates(exitPoint) && exitPoint.Predecessors.Count == 1 && !HasReachableExit(exitPoint)) { // If the exit point is reachable from just one single "break;", // it's better to move the code into the switch. // (unlike loops which should not be nested unless necessary, @@ -705,6 +740,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow branch.ReplaceWith(new Leave(switchContainer) { ILRange = branch.ILRange }); } } + + isSwitch = false; } } } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs index 20767b136..ab264e3da 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchAnalysis.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; using System; +using System.Linq; namespace ICSharpCode.Decompiler.IL.ControlFlow { @@ -38,7 +39,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow public bool ContainsILSwitch { get; private set; } /// - /// Gets the sections that were detected by the previoous AnalyzeBlock() call. + /// Gets the sections that were detected by the previous AnalyzeBlock() call. /// public readonly List> Sections = new List>(); @@ -58,8 +59,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// Blocks that can be deleted if the tail of the initial block is replaced with a switch instruction. /// public readonly List InnerBlocks = new List(); - - Block rootBlock; + + public Block RootBlock { get; private set; } /// /// Analyze the last two statements in the block and see if they can be turned into a @@ -69,7 +70,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow public bool AnalyzeBlock(Block block) { switchVar = null; - rootBlock = block; + RootBlock = block; targetBlockToSectionIndex.Clear(); targetContainerToSectionIndex.Clear(); Sections.Clear(); @@ -99,12 +100,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; } if (tailOnly) { - Debug.Assert(block == rootBlock); + Debug.Assert(block == RootBlock); } else { Debug.Assert(switchVar != null); // switchVar should always be determined by the top-level call - if (block.IncomingEdgeCount != 1 || block == rootBlock) + if (block.IncomingEdgeCount != 1 || block == RootBlock) return false; // for now, let's only consider if-structures that form a tree - if (block.Parent != rootBlock.Parent) + if (block.Parent != RootBlock.Parent) return false; // all blocks should belong to the same container } LongSet trueValues; @@ -230,15 +231,30 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return inst.MatchLdLoc(out switchVar); } + bool MatchSwitchVar(ILInstruction inst, out long sub) + { + if (inst is BinaryNumericInstruction bn + && bn.Operator == BinaryNumericOperator.Sub + && !bn.CheckForOverflow && !bn.IsLifted + && bn.Right.MatchLdcI(out sub)) + { + return MatchSwitchVar(bn.Left); + } + + sub = 0; + return MatchSwitchVar(inst); + } + /// /// Analyzes the boolean condition, returning the set of values of the interesting /// variable for which the condition evaluates to true. /// private bool AnalyzeCondition(ILInstruction condition, out LongSet trueValues) { - if (condition is Comp comp && MatchSwitchVar(comp.Left) && comp.Right.MatchLdcI(out long val)) { - // if (comp(V OP val)) + if (condition is Comp comp && MatchSwitchVar(comp.Left, out var sub) && comp.Right.MatchLdcI(out long val)) { + // if (comp((V - sub) OP val)) trueValues = MakeSetWhereComparisonIsTrue(comp.Kind, val, comp.Sign); + trueValues = trueValues.AddOffset(sub); return true; } else if (MatchSwitchVar(condition)) { // if (ldloc V) --> branch for all values except 0 diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs index 7311d4f6a..d95fedb5b 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Diagnostics; +using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.TypeSystem; @@ -35,11 +36,106 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow /// class SwitchDetection : IILTransform { - SwitchAnalysis analysis = new SwitchAnalysis(); + private readonly SwitchAnalysis analysis = new SwitchAnalysis(); + + private ILTransformContext context; + private BlockContainer currentContainer; + private ControlFlowGraph controlFlowGraph; + private LoopContext loopContext; + + /// + /// When detecting a switch, it is important to distinguish Branch instructions which will + /// eventually decompile to continue; statements. + /// + /// A LoopContext is constructed for a node and its dominator tree, as for a Branch to be a continue; + /// statement, it must be contained within the target-loop + /// + /// This class also supplies the depth of the loop targetted by a continue; statement relative to the + /// context node, to avoid (or eventually support) labelled continues to outer loops + /// + public class LoopContext + { + private readonly IDictionary continueDepth = new Dictionary(); + + public LoopContext(ControlFlowGraph cfg, ControlFlowNode contextNode) + { + var loopHeads = new List(); + + void Analyze(ControlFlowNode n) + { + if (n.Visited) + return; + + n.Visited = true; + if (n.Dominates(contextNode)) + loopHeads.Add(n); + else + n.Successors.ForEach(Analyze); + } + contextNode.Successors.ForEach(Analyze); + ResetVisited(cfg.cfg); + + int l = 1; + foreach (var loopHead in loopHeads.OrderBy(n => n.PostOrderNumber)) + continueDepth[FindContinue(loopHead)] = l++; + } + + private static ControlFlowNode FindContinue(ControlFlowNode loopHead) + { + // potential continue target + var pred = loopHead.Predecessors.OnlyOrDefault(p => p != loopHead && loopHead.Dominates(p)); + if (pred == null) + return loopHead; + + // match for loop increment block + if (pred.Successors.Count == 1) { + if (HighLevelLoopTransform.MatchIncrementBlock((Block)pred.UserData, out var target) &&target == loopHead.UserData) + return pred; + } + + // match do-while condition + if (pred.Successors.Count <= 2) { + if (HighLevelLoopTransform.MatchDoWhileConditionBlock((Block)pred.UserData, out var t1, out var t2) && + (t1 == loopHead.UserData || t2 == loopHead.UserData)) + return pred; + } + + return loopHead; + } + + public bool MatchContinue(ControlFlowNode node) => MatchContinue(node, out var _); + + public bool MatchContinue(ControlFlowNode node, int depth) => + MatchContinue(node, out int _depth) && depth == _depth; + + public bool MatchContinue(ControlFlowNode node, out int depth) => continueDepth.TryGetValue(node, out depth); + + public int GetContinueDepth(ControlFlowNode node) => MatchContinue(node, out var depth) ? depth : 0; + + /// + /// Lists all potential targets for break; statements from a domination tree, + /// assuming the domination tree must be exited via either break; or continue; + /// + /// First list all nodes in the dominator tree (excluding continue nodes) + /// Then return the all successors not contained within said tree. + /// + /// Note that node will be returned once for each outgoing edge. + /// Labelled continue statements (depth > 1) are counted as break targets + /// + internal IEnumerable GetBreakTargets(ControlFlowNode dominator) => + TreeTraversal.PreOrder(dominator, n => n.DominatorTreeChildren.Where(c => !MatchContinue(c))) + .SelectMany(n => n.Successors) + .Where(n => !dominator.Dominates(n) && !MatchContinue(n, 1)); + } public void Run(ILFunction function, ILTransformContext context) { + this.context = context; + foreach (var container in function.Descendants.OfType()) { + currentContainer = container; + controlFlowGraph = null; + bool blockContainerNeedsCleanup = false; foreach (var block in container.Blocks) { context.CancellationToken.ThrowIfCancellationRequested(); @@ -47,7 +143,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } if (blockContainerNeedsCleanup) { Debug.Assert(container.Blocks.All(b => b.Instructions.Count != 0 || b.IncomingEdgeCount == 0)); - container.Blocks.RemoveAll(b => b.Instructions.Count == 0); + + // if the original code has an unreachable switch-like condition + // eg. if (i >= 0) { ... } else if (i == 2) { unreachable } + // then the 'i == 2' block head gets consumed and the unreachable code needs deleting + if (context.Settings.RemoveDeadCode) + container.SortBlocks(deleteUnreachableBlocks: true); + else + container.Blocks.RemoveAll(b => b.Instructions.Count == 0); } } } @@ -56,7 +159,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow { bool analysisSuccess = analysis.AnalyzeBlock(block); KeyValuePair defaultSection; - if (analysisSuccess && UseCSharpSwitch(analysis, out defaultSection)) { + if (analysisSuccess && UseCSharpSwitch(out defaultSection)) { // complex multi-block switch that can be combined into a single SwitchInstruction ILInstruction switchValue = new LdLoc(analysis.SwitchVariable); if (switchValue.ResultType == StackType.Unknown) { @@ -85,6 +188,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow Debug.Assert(innerBlock != ((BlockContainer)block.Parent).EntryPoint); innerBlock.Instructions.Clear(); } + + controlFlowGraph = null; // control flow graph is no-longer valid blockContainerNeedsCleanup = true; SortSwitchSections(sw); } else { @@ -151,15 +256,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } } - const ulong MaxValuesPerSection = 50; + const ulong MaxValuesPerSection = 100; /// /// Tests whether we should prefer a switch statement over an if statement. /// - static bool UseCSharpSwitch(SwitchAnalysis analysis, out KeyValuePair defaultSection) + private bool UseCSharpSwitch(out KeyValuePair defaultSection) { if (!analysis.InnerBlocks.Any()) { - defaultSection = default(KeyValuePair); + defaultSection = default; return false; } defaultSection = analysis.Sections.FirstOrDefault(s => s.Key.Count() > MaxValuesPerSection); @@ -168,24 +273,239 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // This should never happen, as we'd need 2^64/MaxValuesPerSection sections to hit this case... return false; } - ulong valuePerSectionLimit = MaxValuesPerSection; - if (!analysis.ContainsILSwitch) { - // If there's no IL switch involved, limit the number of keys per section - // much more drastically to avoid generating switches where an if condition - // would be shorter. - valuePerSectionLimit = Math.Min( - valuePerSectionLimit, - (ulong)analysis.InnerBlocks.Count); - } var defaultSectionKey = defaultSection.Key; - if (analysis.Sections.Any(s => !s.Key.SetEquals(defaultSectionKey) - && s.Key.Count() > valuePerSectionLimit)) { + if (analysis.Sections.Any(s => !s.Key.SetEquals(defaultSectionKey) && s.Key.Count() > MaxValuesPerSection)) { // Only the default section is allowed to have tons of keys. // C# doesn't support "case 1 to 100000000", and we don't want to generate // gigabytes of case labels. return false; } - return true; + + // good enough indicator that the surrounding code also forms a switch statement + if (analysis.ContainsILSwitch || MatchRoslynSwitchOnString()) + return true; + + // heuristic to determine if a block would be better represented as an if statement rather than switch + int ifCount = analysis.InnerBlocks.Count + 1; + int intervalCount = analysis.Sections.Where(s => !s.Key.SetEquals(defaultSectionKey)).Sum(s => s.Key.Intervals.Length); + if (ifCount < intervalCount) + return false; + + (var flowNodes, var caseNodes) = AnalyzeControlFlow(); + + // don't create switch statements with only one non-default label when the corresponding condition tree is flat + // it may be important that the switch-like conditions be inlined + // for example, a loop condition: while (c == '\n' || c == '\r') + if (analysis.Sections.Count == 2 && IsSingleCondition(flowNodes, caseNodes)) + return false; + + // if there is no ILSwitch, there's still many control flow patterns that + // match a switch statement but were originally just regular if statements, + // and converting them to switches results in poor quality code with goto statements + // + // If a single break target cannot be identified, then the equivalent switch statement would require goto statements. + // These goto statements may be "goto case x" or "goto default", but these are a hint that the original code was not a switch, + // and that the switch statement may be very poor quality. + // Thus the rule of thumb is no goto statements if the original code didn't include them + if (SwitchUsesGoto(flowNodes, caseNodes, out var breakBlock)) + return false; + + // valid switch construction, all code can be inlined + if (breakBlock == null) + return true; + + // The switch has a single break target and there is one more hint + // The break target cannot be inlined, and should have the highest IL offset of everything targetted by the switch + return breakBlock.ILRange.Start >= analysis.Sections.Select(s => s.Value.MatchBranch(out var b) ? b.ILRange.Start : -1).Max(); + } + + /// + /// stloc switchValueVar(call ComputeStringHash(switchValue)) + /// + private bool MatchRoslynSwitchOnString() + { + var insns = analysis.RootBlock.Instructions; + return insns.Count >= 3 && SwitchOnStringTransform.MatchComputeStringHashCall(insns[insns.Count - 3], analysis.SwitchVariable, out var switchLdLoc); + } + + /// + /// Builds the control flow graph for the current container (if necessary), establishes loopContext + /// and returns the ControlFlowNodes corresponding to the inner flow and case blocks of the potential switch + /// + private (List flowNodes, List caseNodes) AnalyzeControlFlow() + { + if (controlFlowGraph == null) + controlFlowGraph = new ControlFlowGraph(currentContainer, context.CancellationToken); + + var switchHead = controlFlowGraph.GetNode(analysis.RootBlock); + loopContext = new LoopContext(controlFlowGraph, switchHead); + + var flowNodes = new List { switchHead }; + flowNodes.AddRange(analysis.InnerBlocks.Select(controlFlowGraph.GetNode)); + + // grab the control flow nodes for blocks targetted by each section + var caseNodes = new List(); + foreach (var s in analysis.Sections) { + if (!s.Value.MatchBranch(out var block)) + continue; + + var node = controlFlowGraph.GetNode(block); + if (!loopContext.MatchContinue(node)) + caseNodes.Add(node); + } + + AddNullCase(flowNodes, caseNodes); + + Debug.Assert(flowNodes.SelectMany(n => n.Successors) + .All(n => flowNodes.Contains(n) || caseNodes.Contains(n) || loopContext.MatchContinue(n))); + + return (flowNodes, caseNodes); + } + + /// + /// Determines if the analysed switch can be constructed without any gotos + /// + private bool SwitchUsesGoto(List flowNodes, List caseNodes, out Block breakBlock) + { + // cases with predecessors that aren't part of the switch logic + // must either require "goto case" statements, or consist of a single "break;" + var externalCases = caseNodes.Where(c => c.Predecessors.Any(n => !flowNodes.Contains(n))).ToList(); + + breakBlock = null; + if (externalCases.Count > 1) + return true; // cannot have more than one break case without gotos + + // check that case nodes flow through a single point + var breakTargets = caseNodes.Except(externalCases).SelectMany(n => loopContext.GetBreakTargets(n)).ToHashSet(); + + // if there are multiple break targets, then gotos are required + // if there are none, then the external case (if any) can be the break target + if (breakTargets.Count != 1) + return breakTargets.Count > 1; + + breakBlock = (Block) breakTargets.Single().UserData; + + // external case must consist of a single "break;" + return externalCases.Count == 1 && breakBlock != externalCases.Single().UserData; + } + + /// + /// Does some of the analysis of SwitchOnNullableTransform to add the null case control flow + /// to the results of SwitchAnaylsis + /// + private void AddNullCase(List flowNodes, List caseNodes) + { + if (analysis.RootBlock.IncomingEdgeCount != 1) + return; + + // if (comp(logic.not(call get_HasValue(ldloca nullableVar))) br NullCase + // br RootBlock + var nullableBlock = (Block)controlFlowGraph.GetNode(analysis.RootBlock).Predecessors.SingleOrDefault()?.UserData; + if (nullableBlock == null || + nullableBlock.Instructions.Count < 2 || + !nullableBlock.Instructions.Last().MatchBranch(analysis.RootBlock) || + !nullableBlock.Instructions.SecondToLastOrDefault().MatchIfInstruction(out var cond, out var trueInst) || + !cond.MatchLogicNot(out var getHasValue) || + !NullableLiftingTransform.MatchHasValueCall(getHasValue, out ILInstruction nullableInst)) + return; + + // could check that nullableInst is ldloc or ldloca and that the switch variable matches a GetValueOrDefault + // but the effect of adding an incorrect block to the flowBlock list would only be disasterous if it branched directly + // to a candidate case block + + // must branch to a case label, otherwise we can proceed fine and let SwitchOnNullableTransform do all the work + if (!trueInst.MatchBranch(out var nullBlock) || !caseNodes.Exists(n => n.UserData == nullBlock)) + return; + + //add the null case logic to the incoming flow blocks + flowNodes.Add(controlFlowGraph.GetNode(nullableBlock)); + } + /// + /// Pattern matching for short circuit expressions + /// p + /// |\ + /// | n + /// |/ \ + /// s c + /// + /// where + /// p: if (a) goto n; goto s; + /// n: if (b) goto c; goto s; + /// + /// Can simplify to + /// p|n + /// / \ + /// s c + /// + /// where: + /// p|n: if (a && b) goto c; goto s; + /// + /// Note that if n has only 1 successor, but is still a flow node, then a short circuit expression + /// has a target (c) with no corresponding block (leave) + /// + /// A node with 2 successors + /// The successor index to consider n (the other successor will be the common sibling) + private static bool IsShortCircuit(ControlFlowNode parent, int side) + { + var node = parent.Successors[side]; + var sibling = parent.Successors[side ^ 1]; + + if (!IsFlowNode(node) || node.Successors.Count > 2 || node.Predecessors.Count != 1) + return false; + + return node.Successors.Contains(sibling); + } + + /// + /// A flow node contains only two instructions, the first of which is an IfInstruction + /// A short circuit expression is comprised of a root block ending in an IfInstruction and one or more flow nodes + /// + static bool IsFlowNode(ControlFlowNode n) => ((Block)n.UserData).Instructions.FirstOrDefault() is IfInstruction; + + /// + /// Determines whether the flowNodes are can be reduced to a single condition via short circuit operators + /// + private bool IsSingleCondition(List flowNodes, List caseNodes) + { + if (flowNodes.Count == 1) + return true; + + var rootNode = controlFlowGraph.GetNode(analysis.RootBlock); + rootNode.Visited = true; + + // search down the tree, marking nodes as visited while they continue the current condition + var n = rootNode; + while (n.Successors.Count > 0 && (n == rootNode || IsFlowNode(n))) { + if (n.Successors.Count == 1) { + // if there is more than one case node, then a flow node with only one successor is not part of the initial condition + if (caseNodes.Count > 1) + break; + + n = n.Successors[0]; + } + else { // 2 successors + if (IsShortCircuit(n, 0)) + n = n.Successors[0]; + else if (IsShortCircuit(n, 1)) + n = n.Successors[1]; + else + break; + } + + n.Visited = true; + if (loopContext.MatchContinue(n)) + break; + } + + var ret = flowNodes.All(f => f.Visited); + ResetVisited(controlFlowGraph.cfg); + return ret; + } + + private static void ResetVisited(IEnumerable nodes) + { + foreach (var n in nodes) + n.Visited = false; } } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs index 96743bcc1..ba119c84d 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs @@ -57,17 +57,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms // if (!loop-condition) leave loop-container // ... condition = null; - loopBody = null; - if (!(loop.EntryPoint.Instructions[0] is IfInstruction ifInstruction)) + loopBody = loop.EntryPoint; + if (!(loopBody.Instructions[0] is IfInstruction ifInstruction)) return false; + if (!ifInstruction.FalseInst.MatchNop()) return false; + if (UsesVariableCapturedInLoop(loop, ifInstruction.Condition)) return false; condition = ifInstruction; - if (!ifInstruction.TrueInst.MatchLeave(loop)) - return false; + if (!ifInstruction.TrueInst.MatchLeave(loop)) { + // sometimes the loop-body is nested within the if + // if (loop-condition) { loop-body } + // leave loop-container + + if (loopBody.Instructions.Count != 2 || !loop.EntryPoint.Instructions.Last().MatchLeave(loop)) + return false; + + if (!ifInstruction.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable)) + ((Block)ifInstruction.TrueInst).Instructions.Add(new Leave(loop)); + + ConditionDetection.InvertIf(loopBody, ifInstruction, context); + } context.Step("Transform to while (condition) loop", loop); loop.Kind = ContainerKind.While; @@ -95,26 +108,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms ExpressionTransforms.RunOnSingleStatment(inst, context); } }*/ - - // Invert condition and unwrap nested block, if loop ends in a break or return statement preceeded by an IfInstruction. - /*while (loopBody.Instructions.Last() is Leave leave && loopBody.Instructions.SecondToLastOrDefault() is IfInstruction nestedIf && nestedIf.FalseInst.MatchNop()) { - switch (nestedIf.TrueInst) { - case Block nestedBlock: - loopBody.Instructions.RemoveAt(leave.ChildIndex); - loopBody.Instructions.AddRange(nestedBlock.Instructions); - break; - case Branch br: - leave.ReplaceWith(nestedIf.TrueInst); - break; - default: - return true; - } - nestedIf.Condition = Comp.LogicNot(nestedIf.Condition); - nestedIf.TrueInst = leave; - ExpressionTransforms.RunOnSingleStatment(nestedIf, context); - if (!loopBody.HasFlag(InstructionFlags.EndPointUnreachable)) - loopBody.Instructions.Add(new Leave(loop)); - }*/ + return true; } @@ -325,11 +319,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } + // early match before block containers have been constructed + internal static bool MatchDoWhileConditionBlock(Block block, out Block target1, out Block target2) + { + target1 = target2 = null; + if (block.Instructions.Count < 2) + return false; + + var last = block.Instructions.Last(); + if (!(block.Instructions.SecondToLastOrDefault() is IfInstruction ifInstruction) || !ifInstruction.FalseInst.MatchNop()) + return false; + + return (ifInstruction.TrueInst.MatchBranch(out target1) || ifInstruction.TrueInst.MatchReturn(out var _)) && + (last.MatchBranch(out target2) || last.MatchReturn(out var _)); + } + internal static Block GetIncrementBlock(BlockContainer loop, Block whileLoopBody) => loop.Blocks.SingleOrDefault(b => b != whileLoopBody && b.Instructions.Last().MatchBranch(loop.EntryPoint) && b.Instructions.SkipLast(1).All(IsSimpleStatement)); + internal static bool MatchIncrementBlock(Block block, out Block loopHead) => + block.Instructions.Last().MatchBranch(out loopHead) + && block.Instructions.SkipLast(1).All(IsSimpleStatement); + bool MatchForLoop(BlockContainer loop, IfInstruction whileCondition, Block whileLoopBody) { // for loops have exactly two incoming edges at the entry point. diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs index da1bac999..fcd311b63 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs @@ -847,7 +847,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// /// Matches 'stloc(targetVar, call ComputeStringHash(ldloc switchValue))' /// - bool MatchComputeStringHashCall(ILInstruction inst, ILVariable targetVar, out LdLoc switchValue) + internal static bool MatchComputeStringHashCall(ILInstruction inst, ILVariable targetVar, out LdLoc switchValue) { switchValue = null; if (!inst.MatchStLoc(targetVar, out var value)) diff --git a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs index 31e0eebee..4c01285df 100644 --- a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs +++ b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs @@ -200,27 +200,28 @@ namespace ICSharpCode.Decompiler.Util /// public static IEnumerable Merge(this IEnumerable input1, IEnumerable input2, Comparison comparison) { - var enumA = input1.GetEnumerator(); - var enumB = input2.GetEnumerator(); - bool moreA = enumA.MoveNext(); - bool moreB = enumB.MoveNext(); - while (moreA && moreB) { - if (comparison(enumA.Current, enumB.Current) <= 0) { + using (var enumA = input1.GetEnumerator()) + using (var enumB = input2.GetEnumerator()) { + bool moreA = enumA.MoveNext(); + bool moreB = enumB.MoveNext(); + while (moreA && moreB) { + if (comparison(enumA.Current, enumB.Current) <= 0) { + yield return enumA.Current; + moreA = enumA.MoveNext(); + } else { + yield return enumB.Current; + moreB = enumB.MoveNext(); + } + } + while (moreA) { yield return enumA.Current; moreA = enumA.MoveNext(); - } else { + } + while (moreB) { yield return enumB.Current; moreB = enumB.MoveNext(); } } - while (moreA) { - yield return enumA.Current; - moreA = enumA.MoveNext(); - } - while (moreB) { - yield return enumB.Current; - moreB = enumB.MoveNext(); - } } /// @@ -306,6 +307,22 @@ namespace ICSharpCode.Decompiler.Util list.RemoveAt(list.Count - 1); } + public static T OnlyOrDefault(this IEnumerable source, Func predicate) => OnlyOrDefault(source.Where(predicate)); + + public static T OnlyOrDefault(this IEnumerable source) + { + bool any = false; + T first = default; + foreach (var t in source) { + if (any) + return default(T); + first = t; + any = true; + } + + return first; + } + #region Aliases/shortcuts for Enumerable extension methods public static bool Any(this ICollection list) => list.Count > 0; public static bool Any(this T[] array, Predicate match) => Array.Exists(array, match); diff --git a/ICSharpCode.Decompiler/Util/LongSet.cs b/ICSharpCode.Decompiler/Util/LongSet.cs index 17790360e..118701218 100644 --- a/ICSharpCode.Decompiler/Util/LongSet.cs +++ b/ICSharpCode.Decompiler/Util/LongSet.cs @@ -203,6 +203,9 @@ namespace ICSharpCode.Decompiler.Util /// public LongSet AddOffset(long val) { + if (val == 0) { + return this; + } var newIntervals = new List(Intervals.Length + 1); foreach (var element in Intervals) { long newStart = unchecked(element.Start + val);