Browse Source

Avoid unnecessary casts in pointer comparisons.

pull/924/head
Daniel Grunwald 8 years ago
parent
commit
74eb0d8d63
  1. 46
      ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs
  2. 25
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  3. 100
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il
  4. 83
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il
  5. 79
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il
  6. 96
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il
  7. 49
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  8. 7
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs

46
ICSharpCode.Decompiler.Tests/TestCases/Correctness/TrickyTypes.cs

@ -25,6 +25,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -25,6 +25,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
static void Main()
{
InterestingConstants();
TruncatedComp();
}
static void Print<T>(T val)
@ -46,5 +47,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -46,5 +47,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Print(val2);
Print(2147483648u);
}
static void TruncatedComp()
{
Console.WriteLine("TruncatedComp1(1):");
TruncatedComp1(1);
Console.WriteLine("TruncatedComp1(-1):");
TruncatedComp1(-1);
Console.WriteLine("TruncatedComp1(0x100000001):");
TruncatedComp1(0x100000001);
Console.WriteLine("TruncatedComp1(long.MinValue):");
TruncatedComp1(long.MinValue);
Console.WriteLine("TruncatedComp2(1):");
TruncatedComp2(1, 1);
Console.WriteLine("TruncatedComp2(-1):");
TruncatedComp2(-1, -1);
Console.WriteLine("TruncatedComp2(0x100000001):");
TruncatedComp2(0x100000001, 1);
Console.WriteLine("TruncatedComp2(long.MinValue):");
TruncatedComp2(long.MinValue, int.MinValue);
}
static void TruncatedComp1(long val)
{
Print((int)val == val);
Print(val == (int)val);
Print(val < (int)val);
Print((int)val >= val);
}
static void TruncatedComp2(long val1, int val2)
{
Print(val1 == val2);
Print((int)val1 == val2);
Print(val1 < val2);
Print((int)val1 < val2);
Print(val1 <= val2);
Print((int)val1 <= val2);
}
}
}

25
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -32,6 +32,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -32,6 +32,31 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
}
public unsafe int SizeOf()
{
return sizeof(SimpleStruct);
}
private static void UseBool(bool b)
{
}
public unsafe void PointerComparison(int* a, double* b)
{
UnsafeCode.UseBool(a == b);
UnsafeCode.UseBool(a != b);
UnsafeCode.UseBool(a < b);
UnsafeCode.UseBool(a > b);
UnsafeCode.UseBool(a <= b);
UnsafeCode.UseBool(a >= b);
}
public unsafe void PointerComparisonWithNull(int* a)
{
UnsafeCode.UseBool(a == null);
UnsafeCode.UseBool(a != null);
}
public unsafe int* PointerCast(long* p)
{
return (int*)p;

100
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly aaldze1a
.assembly '40okgik0'
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module aaldze1a.dll
// MVID: {70B2C372-F51A-4F0B-B8F4-F20FC0522B70}
.module '40okgik0.dll'
// MVID: {668B0983-7797-493E-81D1-A040A24E86AA}
.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: 0x015B0000
// Image base: 0x00C20000
// =============== CLASS MEMBERS DECLARATION ===================
@ -59,6 +59,98 @@ @@ -59,6 +59,98 @@
IL_0007: ret
} // end of method UnsafeCode::get_NullPointer
.method public hidebysig instance int32
SizeOf() cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init (int32 V_0)
IL_0000: nop
IL_0001: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method UnsafeCode::SizeOf
.method private hidebysig static void UseBool(bool b) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method UnsafeCode::UseBool
.method public hidebysig instance void
PointerComparison(int32* a,
float64* b) cil managed
{
// Code size 71 (0x47)
.maxstack 2
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: ceq
IL_0005: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_000a: nop
IL_000b: ldarg.1
IL_000c: ldarg.2
IL_000d: ceq
IL_000f: ldc.i4.0
IL_0010: ceq
IL_0012: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0017: nop
IL_0018: ldarg.1
IL_0019: ldarg.2
IL_001a: clt.un
IL_001c: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0021: nop
IL_0022: ldarg.1
IL_0023: ldarg.2
IL_0024: cgt.un
IL_0026: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_002b: nop
IL_002c: ldarg.1
IL_002d: ldarg.2
IL_002e: cgt.un
IL_0030: ldc.i4.0
IL_0031: ceq
IL_0033: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0038: nop
IL_0039: ldarg.1
IL_003a: ldarg.2
IL_003b: clt.un
IL_003d: ldc.i4.0
IL_003e: ceq
IL_0040: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0045: nop
IL_0046: ret
} // end of method UnsafeCode::PointerComparison
.method public hidebysig instance void
PointerComparisonWithNull(int32* a) cil managed
{
// Code size 27 (0x1b)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.0
IL_0003: conv.u
IL_0004: ceq
IL_0006: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_000b: nop
IL_000c: ldarg.1
IL_000d: ldc.i4.0
IL_000e: conv.u
IL_000f: ceq
IL_0011: ldc.i4.0
IL_0012: ceq
IL_0014: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0019: nop
IL_001a: ret
} // end of method UnsafeCode::PointerComparisonWithNull
.method public hidebysig instance int32*
PointerCast(int64* p) cil managed
{

83
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly puaa14mr
.assembly '0iyybovr'
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module puaa14mr.dll
// MVID: {CFE0F8E8-DA3C-494E-93C4-14BC506B54FF}
.module '0iyybovr.dll'
// MVID: {4E5B1C69-64A7-4276-A009-A657A9B697D4}
.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: 0x014E0000
// Image base: 0x02F80000
// =============== CLASS MEMBERS DECLARATION ===================
@ -53,6 +53,81 @@ @@ -53,6 +53,81 @@
IL_0002: ret
} // end of method UnsafeCode::get_NullPointer
.method public hidebysig instance int32
SizeOf() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0006: ret
} // end of method UnsafeCode::SizeOf
.method private hidebysig static void UseBool(bool b) cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method UnsafeCode::UseBool
.method public hidebysig instance void
PointerComparison(int32* a,
float64* b) cil managed
{
// Code size 64 (0x40)
.maxstack 2
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ceq
IL_0004: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0009: ldarg.1
IL_000a: ldarg.2
IL_000b: ceq
IL_000d: ldc.i4.0
IL_000e: ceq
IL_0010: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0015: ldarg.1
IL_0016: ldarg.2
IL_0017: clt.un
IL_0019: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_001e: ldarg.1
IL_001f: ldarg.2
IL_0020: cgt.un
IL_0022: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0027: ldarg.1
IL_0028: ldarg.2
IL_0029: cgt.un
IL_002b: ldc.i4.0
IL_002c: ceq
IL_002e: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0033: ldarg.1
IL_0034: ldarg.2
IL_0035: clt.un
IL_0037: ldc.i4.0
IL_0038: ceq
IL_003a: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_003f: ret
} // end of method UnsafeCode::PointerComparison
.method public hidebysig instance void
PointerComparisonWithNull(int32* a) cil managed
{
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: conv.u
IL_0003: ceq
IL_0005: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_000a: ldarg.1
IL_000b: ldc.i4.0
IL_000c: conv.u
IL_000d: ceq
IL_000f: ldc.i4.0
IL_0010: ceq
IL_0012: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0017: ret
} // end of method UnsafeCode::PointerComparisonWithNull
.method public hidebysig instance int32*
PointerCast(int64* p) cil managed
{

79
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il

@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module UnsafeCode.dll
// MVID: {858D67FE-2C39-4F0B-B696-FA10954BDC00}
// MVID: {98803778-6CDE-4C69-BDF2-64568153FD06}
.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: 0x01270000
// Image base: 0x02790000
// =============== CLASS MEMBERS DECLARATION ===================
@ -57,6 +57,81 @@ @@ -57,6 +57,81 @@
IL_0002: ret
} // end of method UnsafeCode::get_NullPointer
.method public hidebysig instance int32
SizeOf() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0006: ret
} // end of method UnsafeCode::SizeOf
.method private hidebysig static void UseBool(bool b) cil managed
{
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method UnsafeCode::UseBool
.method public hidebysig instance void
PointerComparison(int32* a,
float64* b) cil managed
{
// Code size 64 (0x40)
.maxstack 2
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: ceq
IL_0004: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0009: ldarg.1
IL_000a: ldarg.2
IL_000b: ceq
IL_000d: ldc.i4.0
IL_000e: ceq
IL_0010: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0015: ldarg.1
IL_0016: ldarg.2
IL_0017: clt.un
IL_0019: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_001e: ldarg.1
IL_001f: ldarg.2
IL_0020: cgt.un
IL_0022: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0027: ldarg.1
IL_0028: ldarg.2
IL_0029: cgt.un
IL_002b: ldc.i4.0
IL_002c: ceq
IL_002e: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0033: ldarg.1
IL_0034: ldarg.2
IL_0035: clt.un
IL_0037: ldc.i4.0
IL_0038: ceq
IL_003a: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_003f: ret
} // end of method UnsafeCode::PointerComparison
.method public hidebysig instance void
PointerComparisonWithNull(int32* a) cil managed
{
// Code size 24 (0x18)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: conv.u
IL_0003: ceq
IL_0005: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_000a: ldarg.1
IL_000b: ldc.i4.0
IL_000c: conv.u
IL_000d: ceq
IL_000f: ldc.i4.0
IL_0010: ceq
IL_0012: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0017: ret
} // end of method UnsafeCode::PointerComparisonWithNull
.method public hidebysig instance int32*
PointerCast(int64* p) cil managed
{

96
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il

@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module UnsafeCode.dll
// MVID: {BCDFA7E7-0E94-44F0-8A8C-85049FECA738}
// MVID: {8E29CB23-0809-4825-9EB4-4274E16E25C8}
.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: 0x01330000
// Image base: 0x00690000
// =============== CLASS MEMBERS DECLARATION ===================
@ -63,6 +63,98 @@ @@ -63,6 +63,98 @@
IL_0007: ret
} // end of method UnsafeCode::get_NullPointer
.method public hidebysig instance int32
SizeOf() cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init (int32 V_0)
IL_0000: nop
IL_0001: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method UnsafeCode::SizeOf
.method private hidebysig static void UseBool(bool b) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method UnsafeCode::UseBool
.method public hidebysig instance void
PointerComparison(int32* a,
float64* b) cil managed
{
// Code size 71 (0x47)
.maxstack 2
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: ceq
IL_0005: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_000a: nop
IL_000b: ldarg.1
IL_000c: ldarg.2
IL_000d: ceq
IL_000f: ldc.i4.0
IL_0010: ceq
IL_0012: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0017: nop
IL_0018: ldarg.1
IL_0019: ldarg.2
IL_001a: clt.un
IL_001c: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0021: nop
IL_0022: ldarg.1
IL_0023: ldarg.2
IL_0024: cgt.un
IL_0026: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_002b: nop
IL_002c: ldarg.1
IL_002d: ldarg.2
IL_002e: cgt.un
IL_0030: ldc.i4.0
IL_0031: ceq
IL_0033: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0038: nop
IL_0039: ldarg.1
IL_003a: ldarg.2
IL_003b: clt.un
IL_003d: ldc.i4.0
IL_003e: ceq
IL_0040: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0045: nop
IL_0046: ret
} // end of method UnsafeCode::PointerComparison
.method public hidebysig instance void
PointerComparisonWithNull(int32* a) cil managed
{
// Code size 27 (0x1b)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.0
IL_0003: conv.u
IL_0004: ceq
IL_0006: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_000b: nop
IL_000c: ldarg.1
IL_000d: ldc.i4.0
IL_000e: conv.u
IL_000f: ceq
IL_0011: ldc.i4.0
IL_0012: ceq
IL_0014: call void ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UseBool(bool)
IL_0019: nop
IL_001a: ret
} // end of method UnsafeCode::PointerComparisonWithNull
.method public hidebysig instance int32*
PointerCast(int64* p) cil managed
{

49
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -487,6 +487,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -487,6 +487,20 @@ namespace ICSharpCode.Decompiler.CSharp
return right;
}
}
// Handle comparisons between unsafe pointers and null:
if (left.Type.Kind == TypeKind.Pointer && inst.Right.MatchLdcI(0)) {
negateOutput = false;
right = new NullReferenceExpression().WithRR(new ConstantResolveResult(SpecialType.NullType, null))
.WithILInstruction(inst.Right);
return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right)
.WithILInstruction(inst);
} else if (right.Type.Kind == TypeKind.Pointer && inst.Left.MatchLdcI(0)) {
negateOutput = false;
left = new NullReferenceExpression().WithRR(new ConstantResolveResult(SpecialType.NullType, null))
.WithILInstruction(inst.Left);
return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right)
.WithILInstruction(inst);
}
// Special case comparisons with enum and char literals
left = AdjustConstantExpressionToType(left, right.Type);
@ -497,12 +511,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -497,12 +511,8 @@ namespace ICSharpCode.Decompiler.CSharp
{
// When comparing a delegate with null, the C# compiler generates a reference comparison.
negateOutput = false;
return new BinaryOperatorExpression(left.Expression, inst.Kind.ToBinaryOperatorType(), right.Expression)
.WithILInstruction(inst)
.WithRR(new OperatorResolveResult(
compilation.FindType(KnownTypeCode.Boolean),
inst.Kind == ComparisonKind.Equality ? ExpressionType.Equal : ExpressionType.NotEqual,
left.ResolveResult, right.ResolveResult));
return CreateBuiltinBinaryOperator(left, inst.Kind.ToBinaryOperatorType(), right)
.WithILInstruction(inst);
}
var rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(), left.ResolveResult, right.ResolveResult)
@ -514,7 +524,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -514,7 +524,15 @@ namespace ICSharpCode.Decompiler.CSharp
if (inst.InputType == StackType.O) {
targetType = compilation.FindType(KnownTypeCode.Object);
} else {
targetType = TypeUtils.GetLargerType(NullableType.GetUnderlyingType(left.Type), NullableType.GetUnderlyingType(right.Type));
var leftUType = NullableType.GetUnderlyingType(left.Type);
var rightUType = NullableType.GetUnderlyingType(right.Type);
if (leftUType.GetStackType() == inst.InputType) {
targetType = leftUType;
} else if (rightUType.GetStackType() == inst.InputType) {
targetType = rightUType;
} else {
targetType = compilation.FindType(inst.InputType.ToKnownTypeCode(leftUType.GetSign()));
}
}
if (inst.IsLifted) {
targetType = NullableType.Create(compilation, targetType);
@ -543,6 +561,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -543,6 +561,17 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(rr);
}
ExpressionWithResolveResult CreateBuiltinBinaryOperator(
TranslatedExpression left, BinaryOperatorType type, TranslatedExpression right,
bool checkForOverflow = false)
{
return new BinaryOperatorExpression(left.Expression, type, right.Expression)
.WithRR(new OperatorResolveResult(
compilation.FindType(KnownTypeCode.Boolean),
BinaryOperatorExpression.GetLinqNodeType(type, checkForOverflow),
left.ResolveResult, right.ResolveResult));
}
/// <summary>
/// Handle Comp instruction, operators other than equality/inequality.
/// </summary>
@ -551,6 +580,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -551,6 +580,12 @@ namespace ICSharpCode.Decompiler.CSharp
var op = inst.Kind.ToBinaryOperatorType();
var left = Translate(inst.Left);
var right = Translate(inst.Right);
if (left.Type.Kind == TypeKind.Pointer && right.Type.Kind == TypeKind.Pointer) {
return CreateBuiltinBinaryOperator(left, op, right)
.WithILInstruction(inst);
}
left = PrepareArithmeticArgument(left, inst.InputType, inst.Sign, inst.IsLifted);
right = PrepareArithmeticArgument(right, inst.InputType, inst.Sign, inst.IsLifted);

7
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs

@ -53,6 +53,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -53,6 +53,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return true;
}
public override bool VisitSizeOfExpression(SizeOfExpression sizeOfExpression)
{
// C# sizeof(MyStruct) requires unsafe{}
// (not for sizeof(int), but that gets constant-folded and thus decompiled to 4)
return true;
}
public override bool VisitComposedType(ComposedType composedType)
{
if (composedType.PointerRank > 0)

Loading…
Cancel
Save