Browse Source

Allow inline assignments to short integers when we can tell that there's no truncation.

pull/960/head
Daniel Grunwald 8 years ago
parent
commit
b0bf6326ad
  1. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs
  2. 67
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.il
  3. 64
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.opt.il
  4. 48
      ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

6
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.cs

@ -51,12 +51,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -51,12 +51,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine(InlineAssignmentTest.field2 = new InlineAssignmentTest());
Console.WriteLine(InlineAssignmentTest.field2);
this.UseShort(this.field4 = 6);
this.UseShort(this.field4 = -10000);
this.UseShort(this.field4 = (short)this.field1);
this.UseShort(this.field4 = this.UseShort(0));
Console.WriteLine(this.field4);
}
public void UseShort(short s)
public short UseShort(short s)
{
Console.WriteLine(s);
return s;
}
public void ReadLoop1(TextReader r)

67
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.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 uq03kalt
.assembly w1xqybg1
{
.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 uq03kalt.dll
// MVID: {D636DE2E-D2CD-4EDF-B87B-0B0985C6C0B8}
.module w1xqybg1.dll
// MVID: {1BE5829A-0D5E-43DC-8C02-E3012B1780A2}
.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: 0x018D0000
// Image base: 0x033B0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -93,7 +93,7 @@ @@ -93,7 +93,7 @@
.method public hidebysig instance void
SimpleInlineWithFields2() cil managed
{
// Code size 87 (0x57)
// Code size 154 (0x9a)
.maxstack 4
.locals init (int32 V_0,
int16 V_1)
@ -125,25 +125,62 @@ @@ -125,25 +125,62 @@
IL_003d: stloc.1
IL_003e: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0043: ldloc.1
IL_0044: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0049: nop
IL_0044: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0049: pop
IL_004a: ldarg.0
IL_004b: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0050: call void [mscorlib]System.Console::WriteLine(int32)
IL_0055: nop
IL_0056: ret
IL_004b: ldarg.0
IL_004c: ldc.i4 0xffffd8f0
IL_0051: dup
IL_0052: stloc.1
IL_0053: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0058: ldloc.1
IL_0059: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_005e: pop
IL_005f: ldarg.0
IL_0060: ldarg.0
IL_0061: ldarg.0
IL_0062: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0067: conv.i2
IL_0068: dup
IL_0069: stloc.1
IL_006a: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_006f: ldloc.1
IL_0070: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0075: pop
IL_0076: ldarg.0
IL_0077: ldarg.0
IL_0078: ldarg.0
IL_0079: ldc.i4.0
IL_007a: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_007f: dup
IL_0080: stloc.1
IL_0081: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0086: ldloc.1
IL_0087: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_008c: pop
IL_008d: ldarg.0
IL_008e: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0093: call void [mscorlib]System.Console::WriteLine(int32)
IL_0098: nop
IL_0099: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields2
.method public hidebysig instance void
.method public hidebysig instance int16
UseShort(int16 s) cil managed
{
// Code size 9 (0x9)
.maxstack 8
// Code size 14 (0xe)
.maxstack 1
.locals init (int16 V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call void [mscorlib]System.Console::WriteLine(int32)
IL_0007: nop
IL_0008: ret
IL_0008: ldarg.1
IL_0009: stloc.0
IL_000a: br.s IL_000c
IL_000c: ldloc.0
IL_000d: ret
} // end of method InlineAssignmentTest::UseShort
.method public hidebysig instance void

64
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InlineAssignmentTest.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 zztqnmi4
.assembly f1ibwsev
{
.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 zztqnmi4.dll
// MVID: {038F2DF5-AE7B-4B0A-B846-AC254CE46038}
.module f1ibwsev.dll
// MVID: {8DB4E6AA-A0C2-49F3-8E9C-A28CE30F145A}
.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: 0x006A0000
// Image base: 0x01400000
// =============== CLASS MEMBERS DECLARATION ===================
@ -85,10 +85,13 @@ @@ -85,10 +85,13 @@
.method public hidebysig instance void
SimpleInlineWithFields2() cil managed
{
// Code size 80 (0x50)
// Code size 150 (0x96)
.maxstack 4
.locals init (int32 V_0,
int16 V_1)
int16 V_1,
int16 V_2,
int16 V_3,
int16 V_4)
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: dup
@ -112,21 +115,54 @@ @@ -112,21 +115,54 @@
IL_0038: stloc.1
IL_0039: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_003e: ldloc.1
IL_003f: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0044: ldarg.0
IL_0045: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_004a: call void [mscorlib]System.Console::WriteLine(int32)
IL_004f: ret
IL_003f: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0044: pop
IL_0045: ldarg.0
IL_0046: ldarg.0
IL_0047: ldc.i4 0xffffd8f0
IL_004c: dup
IL_004d: stloc.2
IL_004e: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0053: ldloc.2
IL_0054: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0059: pop
IL_005a: ldarg.0
IL_005b: ldarg.0
IL_005c: ldarg.0
IL_005d: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field1
IL_0062: conv.i2
IL_0063: dup
IL_0064: stloc.3
IL_0065: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_006a: ldloc.3
IL_006b: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0070: pop
IL_0071: ldarg.0
IL_0072: ldarg.0
IL_0073: ldarg.0
IL_0074: ldc.i4.0
IL_0075: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_007a: dup
IL_007b: stloc.s V_4
IL_007d: stfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0082: ldloc.s V_4
IL_0084: call instance int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::UseShort(int16)
IL_0089: pop
IL_008a: ldarg.0
IL_008b: ldfld int16 ICSharpCode.Decompiler.Tests.TestCases.Pretty.InlineAssignmentTest::field4
IL_0090: call void [mscorlib]System.Console::WriteLine(int32)
IL_0095: ret
} // end of method InlineAssignmentTest::SimpleInlineWithFields2
.method public hidebysig instance void
.method public hidebysig instance int16
UseShort(int16 s) cil managed
{
// Code size 7 (0x7)
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call void [mscorlib]System.Console::WriteLine(int32)
IL_0006: ret
IL_0006: ldarg.1
IL_0007: ret
} // end of method InlineAssignmentTest::UseShort
.method public hidebysig instance void

48
ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

@ -268,9 +268,55 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -268,9 +268,55 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
/// <summary>
/// Gets whether 'stobj type(..., value)' would evaluate to a different value than 'value'
/// due to implicit truncation.
/// </summary>
bool IsImplicitTruncation(ILInstruction value, IType type)
{
return type.IsSmallIntegerType();
if (!type.IsSmallIntegerType()) {
// Implicit truncation in ILAst only happens for small integer types;
// other types of implicit truncation in IL cause the ILReader to insert
// conv instructions.
return false;
}
// With small integer types, test whether the value being stored
// is being truncated:
if (value.MatchLdcI4(out int val)) {
switch (type.GetEnumUnderlyingType().GetDefinition()?.KnownTypeCode) {
case KnownTypeCode.Boolean:
return !(val == 0 || val == 1);
case KnownTypeCode.Byte:
return !(val >= byte.MinValue && val <= byte.MaxValue);
case KnownTypeCode.SByte:
return !(val >= sbyte.MinValue && val <= sbyte.MaxValue);
case KnownTypeCode.Int16:
return !(val >= short.MinValue && val <= short.MaxValue);
case KnownTypeCode.UInt16:
case KnownTypeCode.Char:
return !(val >= ushort.MinValue && val <= ushort.MaxValue);
}
} else if (value is LdObj ldobj) {
return IsImplicitTruncation(ldobj.Type, type);
} else if (value is StObj stobj) {
return IsImplicitTruncation(stobj.Type, type);
} else if (value is LdLoc ldloc) {
return IsImplicitTruncation(ldloc.Variable.Type, type);
} else if (value is StLoc stloc) {
return IsImplicitTruncation(stloc.Variable.Type, type);
} else if (value is CallInstruction call) {
return IsImplicitTruncation(call.Method.ReturnType, type);
} else if (value is Conv conv) {
return conv.TargetType != type.ToPrimitiveType();
} else if (value is Comp) {
return false; // comp returns 0 or 1, which always fits
}
return true;
}
bool IsImplicitTruncation(IType fromType, IType toType)
{
return !(fromType.GetSize() <= toType.GetSize() && fromType.GetSign() == toType.GetSign());
}
/// <code>

Loading…
Cancel
Save