Browse Source

Improve handling of short-circuiting operators.

pull/728/merge
Daniel Grunwald 9 years ago
parent
commit
5150cdce25
  1. 46
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 5
      ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
  3. 2
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  4. 14
      ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs
  5. 38
      ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
  6. 40
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  7. 1
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  8. 43
      ICSharpCode.Decompiler/Tests/PrettyTestRunner.cs
  9. 100
      ICSharpCode.Decompiler/Tests/TestCases/Pretty/ShortCircuit.cs
  10. 398
      ICSharpCode.Decompiler/Tests/TestCases/Pretty/ShortCircuit.il
  11. 300
      ICSharpCode.Decompiler/Tests/TestCases/Pretty/ShortCircuit.opt.il
  12. 2
      NRefactory

46
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1464,35 +1464,31 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1464,35 +1464,31 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitIfInstruction(IfInstruction inst, TranslationContext context)
{
var condition = TranslateCondition(inst.Condition);
var trueBranch = Translate(inst.TrueInst);
var falseBranch = Translate(inst.FalseInst);
if (falseBranch.Type.IsKnownType(KnownTypeCode.Boolean)) {
if (inst.TrueInst.MatchLdcI4(1)) {
// "a ? true : b" ==> "a || b"
return new BinaryOperatorExpression(
TranslateCondition(inst.Condition),
BinaryOperatorType.ConditionalOr,
falseBranch)
.WithILInstruction(inst)
.WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.Boolean)));
} else if (inst.TrueInst.MatchLdcI4(0)) {
// "!a ? false : b" ==> "a && b"
ILInstruction conditionInst;
Expression conditionExpr;
if (inst.Condition.MatchLogicNot(out conditionInst)) {
conditionExpr = TranslateCondition(conditionInst);
} else {
conditionExpr = LogicNot(TranslateCondition(inst.Condition));
}
return new BinaryOperatorExpression(
conditionExpr,
BinaryOperatorType.ConditionalAnd,
falseBranch)
ILInstruction lhsInst, rhsInst;
BinaryOperatorType op = BinaryOperatorType.Any;
TranslatedExpression rhs = default(TranslatedExpression);
if (inst.MatchLogicAnd(out lhsInst, out rhsInst)) {
op = BinaryOperatorType.ConditionalAnd;
Debug.Assert(rhsInst == inst.TrueInst);
rhs = trueBranch;
} else if (inst.MatchLogicOr(out lhsInst, out rhsInst)) {
op = BinaryOperatorType.ConditionalOr;
Debug.Assert(rhsInst == inst.FalseInst);
rhs = falseBranch;
}
// ILAst LogicAnd/LogicOr can return a different value than 0 or 1
// if the rhs is evaluated.
// We can only correctly translate it to C# if the rhs is of type boolean:
if (op != BinaryOperatorType.Any && rhs.Type.IsKnownType(KnownTypeCode.Boolean)) {
return new BinaryOperatorExpression(condition, op, rhs)
.WithILInstruction(inst)
.WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.Boolean)));
}
}
var condition = TranslateCondition(inst.Condition);
var trueBranch = Translate(inst.TrueInst);
IType targetType;
if (!trueBranch.Type.Equals(SpecialType.NullType) && !falseBranch.Type.Equals(SpecialType.NullType) && !trueBranch.Type.Equals(falseBranch.Type)) {
targetType = compilation.FindType(inst.ResultType.ToKnownTypeCode());

5
ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs

@ -141,6 +141,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -141,6 +141,11 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// -> "if (... && !nestedCondition) { ... } goto exitPoint;"
ifInst.Condition = IfInstruction.LogicAnd(ifInst.Condition, new LogicNot(nestedCondition));
targetBlock.Instructions.RemoveAt(0);
// Update targetBlock label now that we've removed the first instruction
if (targetBlock.Instructions.FirstOrDefault()?.ILRange.IsEmpty == false) {
int offset = targetBlock.Instructions[0].ILRange.Start;
targetBlock.ILRange = new Interval(offset, offset);
}
}
}

2
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs

@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.IL @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.IL
public static void WriteTo(this ISymbol symbol, ITextOutput output)
{
output.WriteReference(symbol.ToString(), symbol);
output.WriteReference(symbol.Name, symbol);
}
}
}

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

@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.IL @@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.IL
///
/// IfInstruction is also used to represent logical operators:
/// "a || b" ==> if (a) (ldc.i4 1) else (b)
/// "a && b" ==> if (logic.not(a)) (ldc.i4 0) else (b)
/// "a && b" ==> if (a) (b) else (ldc.i4 0)
/// "a ? b : c" ==> if (a) (b) else (c)
/// </remarks>
partial class IfInstruction : ILInstruction
@ -46,20 +46,12 @@ namespace ICSharpCode.Decompiler.IL @@ -46,20 +46,12 @@ namespace ICSharpCode.Decompiler.IL
public static IfInstruction LogicAnd(ILInstruction lhs, ILInstruction rhs)
{
return new IfInstruction(
new LogicNot(lhs),
new LdcI4(0),
rhs
);
return new IfInstruction(lhs, rhs, new LdcI4(0));
}
public static IfInstruction LogicOr(ILInstruction lhs, ILInstruction rhs)
{
return new IfInstruction(
lhs,
new LdcI4(1),
rhs
);
return new IfInstruction(lhs, new LdcI4(1), rhs);
}
internal override void CheckInvariant(ILPhase phase)

38
ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs

@ -143,7 +143,43 @@ namespace ICSharpCode.Decompiler.IL @@ -143,7 +143,43 @@ namespace ICSharpCode.Decompiler.IL
trueInst = null;
return false;
}
/// <summary>
/// Matches a 'logic and' instruction ("if (a) b else ldc.i4 0").
/// Note: unlike C# '&amp;&amp;', this instruction is not limited to booleans,
/// but allows passing through arbitrary I4 values on the rhs (but not on the lhs).
/// </summary>
public bool MatchLogicAnd(out ILInstruction lhs, out ILInstruction rhs)
{
var inst = this as IfInstruction;
if (inst != null && inst.FalseInst.MatchLdcI4(0)) {
lhs = inst.Condition;
rhs = inst.TrueInst;
return true;
}
lhs = null;
rhs = null;
return false;
}
/// <summary>
/// Matches a 'logic or' instruction ("if (a) ldc.i4 1 else b").
/// Note: unlike C# '||', this instruction is not limited to booleans,
/// but allows passing through arbitrary I4 values on the rhs (but not on the lhs).
/// </summary>
public bool MatchLogicOr(out ILInstruction lhs, out ILInstruction rhs)
{
var inst = this as IfInstruction;
if (inst != null && inst.TrueInst.MatchLdcI4(1)) {
lhs = inst.Condition;
rhs = inst.FalseInst;
return true;
}
lhs = null;
rhs = null;
return false;
}
public bool MatchTryCatchHandler(out ILVariable variable)
{
var inst = this as TryCatchHandler;

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

@ -104,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -104,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitLogicNot(LogicNot inst)
{
ILInstruction arg;
ILInstruction arg, lhs, rhs;
if (inst.Argument.MatchLogicNot(out arg)) {
// logic.not(logic.not(arg))
// ==> arg
@ -124,14 +124,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -124,14 +124,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms
stepper.Stepped();
}
comp.AcceptVisitor(this);
} else if (inst.Argument is IfInstruction && ((IfInstruction)inst.Argument).TrueInst is LdcI4) {
// Likely a logic and/or:
// logic.not(if (a) (ldc.i4 val) (c))
// ==> if (a) (ldc.i4 opposite_val) (logic.not(c))
} else if (inst.Argument.MatchLogicAnd(out lhs, out rhs)) {
// logic.not(if (lhs) rhs else ldc.i4 0)
// ==> if (logic.not(lhs)) ldc.i4 1 else logic.not(rhs)
IfInstruction ifInst = (IfInstruction)inst.Argument;
LdcI4 trueInst = (LdcI4)ifInst.TrueInst;
ifInst.TrueInst = new LdcI4(trueInst.Value != 0 ? 0 : 1) { ILRange = trueInst.ILRange };
ifInst.FalseInst = new LogicNot(ifInst.FalseInst) { ILRange = inst.ILRange };
var ldc0 = ifInst.FalseInst;
Debug.Assert(ldc0.MatchLdcI4(0));
ifInst.Condition = new LogicNot(lhs) { ILRange = inst.ILRange };
ifInst.TrueInst = new LdcI4(1) { ILRange = ldc0.ILRange };
ifInst.FalseInst = new LogicNot(rhs) { ILRange = inst.ILRange };
inst.ReplaceWith(ifInst);
stepper.Stepped();
ifInst.AcceptVisitor(this);
} else if (inst.Argument.MatchLogicOr(out lhs, out rhs)) {
// logic.not(if (lhs) ldc.i4 1 else rhs)
// ==> if (logic.not(lhs)) logic.not(rhs) else ldc.i4 0)
IfInstruction ifInst = (IfInstruction)inst.Argument;
var ldc1 = ifInst.TrueInst;
Debug.Assert(ldc1.MatchLdcI4(1));
ifInst.Condition = new LogicNot(lhs) { ILRange = inst.ILRange };
ifInst.TrueInst = new LogicNot(rhs) { ILRange = inst.ILRange };
ifInst.FalseInst = new LdcI4(0) { ILRange = ldc1.ILRange };
inst.ReplaceWith(ifInst);
stepper.Stepped();
ifInst.AcceptVisitor(this);
@ -226,7 +239,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -226,7 +239,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitIfInstruction(IfInstruction inst)
{
// Bring LogicAnd/LogicOr into their canonical forms:
// if (cond) ldc.i4 0 else RHS --> if (!cond) RHS else ldc.i4 0
// if (cond) RHS else ldc.i4 1 --> if (!cond) ldc.i4 1 else RHS
if (inst.TrueInst.MatchLdcI4(0) || inst.FalseInst.MatchLdcI4(1)) {
var t = inst.TrueInst;
inst.TrueInst = inst.FalseInst;
inst.FalseInst = t;
inst.Condition = new LogicNot(inst.Condition);
}
base.VisitIfInstruction(inst);
// if (cond) stloc (A, V1) else stloc (A, V2) --> stloc (A, if (cond) V1 else V2)
Block trueInst = inst.TrueInst as Block;
if (trueInst == null || trueInst.Instructions.Count != 1)

1
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -137,6 +137,7 @@ @@ -137,6 +137,7 @@
<Compile Include="TestCases\Pretty\CompoundAssignmentTest.cs" />
<Compile Include="TestCases\Pretty\HelloWorld.cs" />
<Compile Include="TestCases\Pretty\InlineAssignmentTest.cs" />
<Compile Include="TestCases\Pretty\ShortCircuit.cs" />
<Compile Include="TestTraceListener.cs" />
<Compile Include="Util\IntervalTests.cs" />
<Compile Include="Util\LongSetTests.cs" />

43
ICSharpCode.Decompiler/Tests/PrettyTestRunner.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Tests
foreach (var file in new DirectoryInfo(TestCasePath).EnumerateFiles()) {
if (file.Extension == ".txt" || file.Extension == ".exe")
continue;
var testName = Path.GetFileNameWithoutExtension(file.Name);
var testName = file.Name.Split('.')[0];
Assert.Contains(testName, testNames);
}
}
@ -68,38 +68,41 @@ namespace ICSharpCode.Decompiler.Tests @@ -68,38 +68,41 @@ namespace ICSharpCode.Decompiler.Tests
Run();
Run(asmOptions: AssemblerOptions.UseDebug);
}
[Test]
public void ShortCircuit()
public void ShortCircuit([Values(CompilerOptions.None, CompilerOptions.Optimize)] CompilerOptions cscOptions)
{
Run();
Run(asmOptions: AssemblerOptions.UseDebug);
Run(cscOptions: cscOptions);
}
void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None)
void Run([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None)
{
var ilFile = Path.Combine(TestCasePath, testName + ".il");
var ilFile = Path.Combine(TestCasePath, testName);
if ((cscOptions & CompilerOptions.Optimize) != 0)
ilFile += ".opt";
if ((cscOptions & CompilerOptions.Force32Bit) != 0)
ilFile += ".32";
if ((cscOptions & CompilerOptions.UseDebug) != 0)
ilFile += ".dbg";
ilFile += ".il";
var csFile = Path.Combine(TestCasePath, testName + ".cs");
EnsureSourceFilesExist(Path.Combine(TestCasePath, testName));
var executable = Tester.AssembleIL(ilFile, asmOptions | AssemblerOptions.Library);
var decompiled = Tester.DecompileCSharp(executable);
CodeAssert.FilesAreEqual(csFile, decompiled);
}
void EnsureSourceFilesExist(string fileName)
{
if (!File.Exists(fileName + ".il")) {
if (!File.Exists(ilFile)) {
// re-create .il file if necessary
CompilerResults output = null;
try {
output = Tester.CompileCSharp(fileName + ".cs", CompilerOptions.None);
Tester.Disassemble(output.PathToAssembly, fileName + ".il");
output = Tester.CompileCSharp(csFile, cscOptions | CompilerOptions.Library);
Tester.Disassemble(output.PathToAssembly, ilFile);
} finally {
if (output != null)
output.TempFiles.Delete();
}
}
var executable = Tester.AssembleIL(ilFile, asmOptions | AssemblerOptions.Library);
var decompiled = Tester.DecompileCSharp(executable);
CodeAssert.FilesAreEqual(csFile, decompiled);
}
}
}

100
ICSharpCode.Decompiler/Tests/TestCases/Pretty/ShortCircuit.cs

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
// compile:
// csc ShortCircuit.cs /t:Library && ildasm /text ShortCircuit.dll >ShortCircuit.il
// csc ShortCircuit.cs /t:Library /o /out:ShortCircuit.opt.dll && ildasm /text ShortCircuit.opt.dll >ShortCircuit.opt.il
using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public abstract class ShortCircuit
{
public abstract void B(bool b);
public abstract bool F(int i);
public abstract void M1();
public abstract void M2();
public abstract void E();
public void ExprAnd()
{
this.B(this.F(0) && this.F(1));
}
public void ExprOr()
{
this.B(this.F(0) || this.F(1));
}
public void ExprCond()
{
this.B(this.F(0) ? this.F(1) : this.F(2));
}
public void StmtAnd2()
{
if (this.F(0) && this.F(1)) {
this.M1();
} else {
this.M2();
}
this.E();
}
public void StmtOr2()
{
if (this.F(0) || this.F(1)) {
this.M1();
} else {
this.M2();
}
this.E();
}
public void StmtAnd3()
{
if (this.F(0) && this.F(1) && this.F(2)) {
this.M1();
} else {
this.M2();
}
this.E();
}
public void StmtOr3()
{
if (this.F(0) || this.F(1) || this.F(3)) {
this.M1();
} else {
this.M2();
}
this.E();
}
public void StmtComplex()
{
if (this.F(0) && this.F(1) && !this.F(2) && (this.F(3) || this.F(4))) {
this.M1();
} else {
this.M2();
}
this.E();
}
}
}

398
ICSharpCode.Decompiler/Tests/TestCases/Pretty/ShortCircuit.il

@ -0,0 +1,398 @@ @@ -0,0 +1,398 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.18020
// Copyright (c) Microsoft Corporation. All rights reserved.
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly '0hc4wf1j'
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module '0hc4wf1j.dll'
// MVID: {BB9907D8-9A9B-40EA-99C2-170F6DA15820}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x017B0000
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance void B(bool b) cil managed
{
} // end of method ShortCircuit::B
.method public hidebysig newslot abstract virtual
instance bool F(int32 i) cil managed
{
} // end of method ShortCircuit::F
.method public hidebysig newslot abstract virtual
instance void M1() cil managed
{
} // end of method ShortCircuit::M1
.method public hidebysig newslot abstract virtual
instance void M2() cil managed
{
} // end of method ShortCircuit::M2
.method public hidebysig newslot abstract virtual
instance void E() cil managed
{
} // end of method ShortCircuit::E
.method public hidebysig instance void
ExprAnd() cil managed
{
// Code size 29 (0x1d)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldc.i4.0
IL_0004: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0009: brfalse.s IL_0014
IL_000b: ldarg.0
IL_000c: ldc.i4.1
IL_000d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0012: br.s IL_0015
IL_0014: ldc.i4.0
IL_0015: nop
IL_0016: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::B(bool)
IL_001b: nop
IL_001c: ret
} // end of method ShortCircuit::ExprAnd
.method public hidebysig instance void
ExprOr() cil managed
{
// Code size 29 (0x1d)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldc.i4.0
IL_0004: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0009: brtrue.s IL_0014
IL_000b: ldarg.0
IL_000c: ldc.i4.1
IL_000d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0012: br.s IL_0015
IL_0014: ldc.i4.1
IL_0015: nop
IL_0016: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::B(bool)
IL_001b: nop
IL_001c: ret
} // end of method ShortCircuit::ExprOr
.method public hidebysig instance void
ExprCond() cil managed
{
// Code size 35 (0x23)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldc.i4.0
IL_0004: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0009: brtrue.s IL_0014
IL_000b: ldarg.0
IL_000c: ldc.i4.2
IL_000d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0012: br.s IL_001b
IL_0014: ldarg.0
IL_0015: ldc.i4.1
IL_0016: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_001b: nop
IL_001c: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::B(bool)
IL_0021: nop
IL_0022: ret
} // end of method ShortCircuit::ExprCond
.method public hidebysig instance void
StmtAnd2() cil managed
{
// Code size 56 (0x38)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0008: brfalse.s IL_0016
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0011: ldc.i4.0
IL_0012: ceq
IL_0014: br.s IL_0017
IL_0016: ldc.i4.1
IL_0017: nop
IL_0018: stloc.0
IL_0019: ldloc.0
IL_001a: brtrue.s IL_0027
IL_001c: nop
IL_001d: ldarg.0
IL_001e: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0023: nop
IL_0024: nop
IL_0025: br.s IL_0030
IL_0027: nop
IL_0028: ldarg.0
IL_0029: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_002e: nop
IL_002f: nop
IL_0030: ldarg.0
IL_0031: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0036: nop
IL_0037: ret
} // end of method ShortCircuit::StmtAnd2
.method public hidebysig instance void
StmtOr2() cil managed
{
// Code size 56 (0x38)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0008: brtrue.s IL_0016
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0011: ldc.i4.0
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_0027
IL_001c: nop
IL_001d: ldarg.0
IL_001e: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0023: nop
IL_0024: nop
IL_0025: br.s IL_0030
IL_0027: nop
IL_0028: ldarg.0
IL_0029: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_002e: nop
IL_002f: nop
IL_0030: ldarg.0
IL_0031: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0036: nop
IL_0037: ret
} // end of method ShortCircuit::StmtOr2
.method public hidebysig instance void
StmtAnd3() cil managed
{
// Code size 65 (0x41)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0008: brfalse.s IL_001f
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0011: brfalse.s IL_001f
IL_0013: ldarg.0
IL_0014: ldc.i4.2
IL_0015: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_001a: ldc.i4.0
IL_001b: ceq
IL_001d: br.s IL_0020
IL_001f: ldc.i4.1
IL_0020: nop
IL_0021: stloc.0
IL_0022: ldloc.0
IL_0023: brtrue.s IL_0030
IL_0025: nop
IL_0026: ldarg.0
IL_0027: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_002c: nop
IL_002d: nop
IL_002e: br.s IL_0039
IL_0030: nop
IL_0031: ldarg.0
IL_0032: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_0037: nop
IL_0038: nop
IL_0039: ldarg.0
IL_003a: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_003f: nop
IL_0040: ret
} // end of method ShortCircuit::StmtAnd3
.method public hidebysig instance void
StmtOr3() cil managed
{
// Code size 65 (0x41)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0008: brtrue.s IL_001f
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0011: brtrue.s IL_001f
IL_0013: ldarg.0
IL_0014: ldc.i4.3
IL_0015: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_001a: ldc.i4.0
IL_001b: ceq
IL_001d: br.s IL_0020
IL_001f: ldc.i4.0
IL_0020: nop
IL_0021: stloc.0
IL_0022: ldloc.0
IL_0023: brtrue.s IL_0030
IL_0025: nop
IL_0026: ldarg.0
IL_0027: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_002c: nop
IL_002d: nop
IL_002e: br.s IL_0039
IL_0030: nop
IL_0031: ldarg.0
IL_0032: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_0037: nop
IL_0038: nop
IL_0039: ldarg.0
IL_003a: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_003f: nop
IL_0040: ret
} // end of method ShortCircuit::StmtOr3
.method public hidebysig instance void
StmtComplex() cil managed
{
// Code size 87 (0x57)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0008: brfalse.s IL_0035
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0011: brfalse.s IL_0035
IL_0013: ldarg.0
IL_0014: ldc.i4.2
IL_0015: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_001a: brtrue.s IL_0035
IL_001c: ldarg.0
IL_001d: ldc.i4.3
IL_001e: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0023: brtrue.s IL_0031
IL_0025: ldarg.0
IL_0026: ldc.i4.4
IL_0027: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_002c: ldc.i4.0
IL_002d: ceq
IL_002f: br.s IL_0032
IL_0031: ldc.i4.0
IL_0032: nop
IL_0033: br.s IL_0036
IL_0035: ldc.i4.1
IL_0036: nop
IL_0037: stloc.0
IL_0038: ldloc.0
IL_0039: brtrue.s IL_0046
IL_003b: nop
IL_003c: ldarg.0
IL_003d: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0042: nop
IL_0043: nop
IL_0044: br.s IL_004f
IL_0046: nop
IL_0047: ldarg.0
IL_0048: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_004d: nop
IL_004e: nop
IL_004f: ldarg.0
IL_0050: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0055: nop
IL_0056: ret
} // end of method ShortCircuit::StmtComplex
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method ShortCircuit::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file ../../Tests/TestCases/Pretty\ShortCircuit.res

300
ICSharpCode.Decompiler/Tests/TestCases/Pretty/ShortCircuit.opt.il

@ -0,0 +1,300 @@ @@ -0,0 +1,300 @@
// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Copyright (c) Microsoft Corporation. All rights reserved.
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly ShortCircuit.opt
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 )
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module ShortCircuit.opt.dll
// MVID: {B2A8B996-539C-419F-B01A-1DC6A75F40BA}
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x00C70000
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance void B(bool b) cil managed
{
} // end of method ShortCircuit::B
.method public hidebysig newslot abstract virtual
instance bool F(int32 i) cil managed
{
} // end of method ShortCircuit::F
.method public hidebysig newslot abstract virtual
instance void M1() cil managed
{
} // end of method ShortCircuit::M1
.method public hidebysig newslot abstract virtual
instance void M2() cil managed
{
} // end of method ShortCircuit::M2
.method public hidebysig newslot abstract virtual
instance void E() cil managed
{
} // end of method ShortCircuit::E
.method public hidebysig instance void
ExprAnd() cil managed
{
// Code size 26 (0x1a)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0008: brfalse.s IL_0013
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0011: br.s IL_0014
IL_0013: ldc.i4.0
IL_0014: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::B(bool)
IL_0019: ret
} // end of method ShortCircuit::ExprAnd
.method public hidebysig instance void
ExprOr() cil managed
{
// Code size 26 (0x1a)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0008: brtrue.s IL_0013
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0011: br.s IL_0014
IL_0013: ldc.i4.1
IL_0014: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::B(bool)
IL_0019: ret
} // end of method ShortCircuit::ExprOr
.method public hidebysig instance void
ExprCond() cil managed
{
// Code size 32 (0x20)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0008: brtrue.s IL_0013
IL_000a: ldarg.0
IL_000b: ldc.i4.2
IL_000c: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0011: br.s IL_001a
IL_0013: ldarg.0
IL_0014: ldc.i4.1
IL_0015: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_001a: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::B(bool)
IL_001f: ret
} // end of method ShortCircuit::ExprCond
.method public hidebysig instance void
StmtAnd2() cil managed
{
// Code size 39 (0x27)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0007: brfalse.s IL_001a
IL_0009: ldarg.0
IL_000a: ldc.i4.1
IL_000b: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0010: brfalse.s IL_001a
IL_0012: ldarg.0
IL_0013: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0018: br.s IL_0020
IL_001a: ldarg.0
IL_001b: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_0020: ldarg.0
IL_0021: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0026: ret
} // end of method ShortCircuit::StmtAnd2
.method public hidebysig instance void
StmtOr2() cil managed
{
// Code size 39 (0x27)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0007: brtrue.s IL_0012
IL_0009: ldarg.0
IL_000a: ldc.i4.1
IL_000b: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0010: brfalse.s IL_001a
IL_0012: ldarg.0
IL_0013: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0018: br.s IL_0020
IL_001a: ldarg.0
IL_001b: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_0020: ldarg.0
IL_0021: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0026: ret
} // end of method ShortCircuit::StmtOr2
.method public hidebysig instance void
StmtAnd3() cil managed
{
// Code size 48 (0x30)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0007: brfalse.s IL_0023
IL_0009: ldarg.0
IL_000a: ldc.i4.1
IL_000b: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0010: brfalse.s IL_0023
IL_0012: ldarg.0
IL_0013: ldc.i4.2
IL_0014: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0019: brfalse.s IL_0023
IL_001b: ldarg.0
IL_001c: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0021: br.s IL_0029
IL_0023: ldarg.0
IL_0024: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_0029: ldarg.0
IL_002a: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_002f: ret
} // end of method ShortCircuit::StmtAnd3
.method public hidebysig instance void
StmtOr3() cil managed
{
// Code size 48 (0x30)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0007: brtrue.s IL_001b
IL_0009: ldarg.0
IL_000a: ldc.i4.1
IL_000b: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0010: brtrue.s IL_001b
IL_0012: ldarg.0
IL_0013: ldc.i4.3
IL_0014: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0019: brfalse.s IL_0023
IL_001b: ldarg.0
IL_001c: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0021: br.s IL_0029
IL_0023: ldarg.0
IL_0024: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_0029: ldarg.0
IL_002a: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_002f: ret
} // end of method ShortCircuit::StmtOr3
.method public hidebysig instance void
StmtComplex() cil managed
{
// Code size 66 (0x42)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0007: brfalse.s IL_0035
IL_0009: ldarg.0
IL_000a: ldc.i4.1
IL_000b: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0010: brfalse.s IL_0035
IL_0012: ldarg.0
IL_0013: ldc.i4.2
IL_0014: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0019: brtrue.s IL_0035
IL_001b: ldarg.0
IL_001c: ldc.i4.3
IL_001d: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_0022: brtrue.s IL_002d
IL_0024: ldarg.0
IL_0025: ldc.i4.4
IL_0026: callvirt instance bool ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::F(int32)
IL_002b: brfalse.s IL_0035
IL_002d: ldarg.0
IL_002e: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M1()
IL_0033: br.s IL_003b
IL_0035: ldarg.0
IL_0036: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::M2()
IL_003b: ldarg.0
IL_003c: callvirt instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit::E()
IL_0041: ret
} // end of method ShortCircuit::StmtComplex
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method ShortCircuit::.ctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.ShortCircuit
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

2
NRefactory

@ -1 +1 @@ @@ -1 +1 @@
Subproject commit 89ef9706523059f0a39b04b15ebcd4dea87e0e08
Subproject commit 85cf91fe5138252a44b8e1d14a10366f90a5a10d
Loading…
Cancel
Save