Browse Source

Fix #1078: Eliminate redundant variable in fixed statements.

pull/1108/head
Daniel Grunwald 7 years ago
parent
commit
7b8389dca5
  1. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  2. 275
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il
  3. 272
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il
  4. 40
      ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

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

@ -350,7 +350,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public unsafe string StackAllocStruct(int count)
{
SimpleStruct* ptr = stackalloc SimpleStruct[checked(count * 2)];
#if !(ROSLYN && OPT)
// unused stackalloc gets optimized out by roslyn
SimpleStruct* ptr2 = stackalloc SimpleStruct[10];
#endif
ptr->X = count;
ptr[1].X = ptr->X;
for (int i = 2; i < 10; i++) {

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

@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module UnsafeCode.dll
// MVID: {9580E5D9-4B71-43EE-9D33-75C7E9062150}
// MVID: {9AB968B1-31DB-4AAC-9C2B-5A258F68F90D}
.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: 0x048C0000
// Image base: 0x00BD0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -372,20 +372,23 @@
.method public hidebysig instance void
PassRefParameterAsPointer(int32& p) cil managed
{
// Code size 15 (0xf)
// Code size 17 (0x11)
.maxstack 2
.locals init (int32& pinned V_0)
.locals init (int32* V_0,
int32& pinned V_1)
IL_0000: ldarg.1
IL_0001: stloc.0
IL_0002: ldarg.0
IL_0003: ldloc.0
IL_0004: conv.i
IL_0005: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(int32*)
IL_000a: pop
IL_000b: ldc.i4.0
IL_000c: conv.u
IL_000d: stloc.0
IL_000e: ret
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: conv.u
IL_0004: stloc.0
IL_0005: ldarg.0
IL_0006: ldloc.0
IL_0007: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(int32*)
IL_000c: pop
IL_000d: ldc.i4.0
IL_000e: conv.u
IL_000f: stloc.1
IL_0010: ret
} // end of method UnsafeCode::PassRefParameterAsPointer
.method public hidebysig instance void
@ -413,29 +416,31 @@
.method public hidebysig instance void
AddressInMultiDimensionalArray(float64[0...,0...] matrix) cil managed
{
// Code size 31 (0x1f)
// Code size 32 (0x20)
.maxstack 3
.locals init (float64& pinned V_0)
.locals init (float64* V_0,
float64& pinned V_1)
IL_0000: ldarg.1
IL_0001: ldc.i4.1
IL_0002: ldc.i4.2
IL_0003: call instance float64& float64[0...,0...]::Address(int32,
int32)
IL_0008: stloc.0
IL_0009: ldarg.0
IL_000a: ldloc.0
IL_000b: conv.i
IL_000c: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_0011: pop
IL_0012: ldarg.0
IL_0013: ldloc.0
IL_0014: conv.i
IL_0015: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_001a: pop
IL_001b: ldc.i4.0
IL_001c: conv.u
IL_001d: stloc.0
IL_001e: ret
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: conv.u
IL_000b: stloc.0
IL_000c: ldarg.0
IL_000d: ldloc.0
IL_000e: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_0013: pop
IL_0014: ldarg.0
IL_0015: ldloc.0
IL_0016: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_001b: pop
IL_001c: ldc.i4.0
IL_001d: conv.u
IL_001e: stloc.1
IL_001f: ret
} // end of method UnsafeCode::AddressInMultiDimensionalArray
.method public hidebysig instance void
@ -449,7 +454,7 @@
IL_0000: ldarg.1
IL_0001: stloc.1
IL_0002: ldloc.1
IL_0003: conv.i
IL_0003: conv.u
IL_0004: stloc.0
IL_0005: ldloc.0
IL_0006: brfalse.s IL_0010
@ -484,10 +489,10 @@
int32 index,
float64 val) cil managed
{
// Code size 36 (0x24)
// Code size 35 (0x23)
.maxstack 3
.locals init (int64& pinned V_0,
int64[] V_1)
.locals init (int64* V_0,
int64[] pinned V_1)
IL_0000: ldarg.1
IL_0001: dup
IL_0002: stloc.1
@ -501,14 +506,14 @@
IL_000a: ldc.i4.0
IL_000b: conv.u
IL_000c: stloc.0
IL_000d: br.s IL_0017
IL_000d: br.s IL_0018
IL_000f: ldloc.1
IL_0010: ldc.i4.0
IL_0011: ldelema [mscorlib]System.Int64
IL_0016: stloc.0
IL_0017: ldloc.0
IL_0018: conv.i
IL_0016: conv.u
IL_0017: stloc.0
IL_0018: ldloc.0
IL_0019: ldarg.2
IL_001a: conv.i
IL_001b: ldc.i4.8
@ -516,10 +521,9 @@
IL_001d: add
IL_001e: ldarg.3
IL_001f: stind.r8
IL_0020: ldc.i4.0
IL_0021: conv.u
IL_0022: stloc.0
IL_0023: ret
IL_0020: ldnull
IL_0021: stloc.1
IL_0022: ret
} // end of method UnsafeCode::PutDoubleIntoLongArray1
.method public hidebysig instance void
@ -535,7 +539,7 @@
IL_0002: ldelema [mscorlib]System.Int64
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: conv.i
IL_0009: conv.u
IL_000a: ldarg.3
IL_000b: stind.r8
IL_000c: ldc.i4.0
@ -920,22 +924,25 @@
.method public hidebysig instance void
PinFixedMember(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers& m) cil managed
{
// Code size 25 (0x19)
// Code size 27 (0x1b)
.maxstack 2
.locals init (int32& pinned V_0)
.locals init (int32* V_0,
int32*& pinned V_1)
IL_0000: ldarg.1
IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Integers
IL_0006: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer'::FixedElementField
IL_000b: stloc.0
IL_000c: ldarg.0
IL_000d: ldloc.0
IL_000e: conv.i
IL_000f: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(int32*)
IL_0014: pop
IL_0015: ldc.i4.0
IL_0016: conv.u
IL_0017: stloc.0
IL_0018: ret
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: conv.u
IL_000e: stloc.0
IL_000f: ldarg.0
IL_0010: ldloc.0
IL_0011: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(int32*)
IL_0016: pop
IL_0017: ldc.i4.0
IL_0018: conv.u
IL_0019: stloc.1
IL_001a: ret
} // end of method UnsafeCode::PinFixedMember
.method private hidebysig instance void
@ -969,7 +976,7 @@
.method public hidebysig instance string
StackAlloc(int32 count) cil managed
{
// Code size 52 (0x34)
// Code size 53 (0x35)
.maxstack 3
.locals init (char* V_0,
char* V_1,
@ -980,51 +987,49 @@
IL_0003: mul.ovf.un
IL_0004: localloc
IL_0006: stloc.0
IL_0007: ldc.i4.s 100
IL_0009: conv.u
IL_000a: ldc.i4.2
IL_000b: mul.ovf.un
IL_000c: localloc
IL_000e: stloc.1
IL_000f: ldc.i4.0
IL_0010: stloc.2
IL_0011: br.s IL_0028
IL_0013: ldloc.0
IL_0014: ldloc.2
IL_0015: conv.i
IL_0016: ldc.i4.2
IL_0017: mul
IL_0018: add
IL_0019: ldloc.2
IL_001a: conv.u2
IL_001b: stind.i2
IL_001c: ldloc.1
IL_001d: ldloc.2
IL_001e: conv.i
IL_001f: ldc.i4.2
IL_0020: mul
IL_0021: add
IL_0022: ldc.i4.0
IL_0023: stind.i2
IL_0024: ldloc.2
IL_0025: ldc.i4.1
IL_0026: add
IL_0027: stloc.2
IL_0028: ldloc.2
IL_0029: ldarg.1
IL_002a: blt.s IL_0013
IL_002c: ldarg.0
IL_002d: ldloc.0
IL_002e: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_0033: ret
IL_0007: ldc.i4 0xc8
IL_000c: conv.u
IL_000d: localloc
IL_000f: stloc.1
IL_0010: ldc.i4.0
IL_0011: stloc.2
IL_0012: br.s IL_0029
IL_0014: ldloc.0
IL_0015: ldloc.2
IL_0016: conv.i
IL_0017: ldc.i4.2
IL_0018: mul
IL_0019: add
IL_001a: ldloc.2
IL_001b: conv.u2
IL_001c: stind.i2
IL_001d: ldloc.1
IL_001e: ldloc.2
IL_001f: conv.i
IL_0020: ldc.i4.2
IL_0021: mul
IL_0022: add
IL_0023: ldc.i4.0
IL_0024: stind.i2
IL_0025: ldloc.2
IL_0026: ldc.i4.1
IL_0027: add
IL_0028: stloc.2
IL_0029: ldloc.2
IL_002a: ldarg.1
IL_002b: blt.s IL_0014
IL_002d: ldarg.0
IL_002e: ldloc.0
IL_002f: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_0034: ret
} // end of method UnsafeCode::StackAlloc
.method public hidebysig instance string
StackAllocStruct(int32 count) cil managed
{
// Code size 97 (0x61)
// Code size 84 (0x54)
.maxstack 3
.locals init (valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct* V_0,
int32 V_1)
@ -1036,47 +1041,41 @@
IL_000a: mul.ovf.un
IL_000b: localloc
IL_000d: stloc.0
IL_000e: ldc.i4.s 10
IL_0010: conv.u
IL_0011: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0017: mul.ovf.un
IL_0018: localloc
IL_001a: pop
IL_001b: ldloc.0
IL_001c: ldarg.1
IL_001d: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_0022: ldloc.0
IL_0023: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0029: add
IL_002a: ldloc.0
IL_002b: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_0030: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_0035: ldc.i4.2
IL_0036: stloc.1
IL_0037: br.s IL_004e
IL_0039: ldloc.0
IL_003a: ldloc.1
IL_003b: conv.i
IL_003c: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0042: mul
IL_0043: add
IL_0044: ldarg.1
IL_0045: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_004a: ldloc.1
IL_004b: ldc.i4.1
IL_004c: add
IL_004d: stloc.1
IL_004e: ldloc.1
IL_004f: ldc.i4.s 10
IL_0051: blt.s IL_0039
IL_0053: ldarg.0
IL_0054: ldloc.0
IL_0055: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
IL_005a: conv.u
IL_005b: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_0060: ret
IL_000e: ldloc.0
IL_000f: ldarg.1
IL_0010: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_0015: ldloc.0
IL_0016: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_001c: add
IL_001d: ldloc.0
IL_001e: ldfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_0023: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_0028: ldc.i4.2
IL_0029: stloc.1
IL_002a: br.s IL_0041
IL_002c: ldloc.0
IL_002d: ldloc.1
IL_002e: conv.i
IL_002f: sizeof ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct
IL_0035: mul
IL_0036: add
IL_0037: ldarg.1
IL_0038: stfld int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::X
IL_003d: ldloc.1
IL_003e: ldc.i4.1
IL_003f: add
IL_0040: stloc.1
IL_0041: ldloc.1
IL_0042: ldc.i4.s 10
IL_0044: blt.s IL_002c
IL_0046: ldarg.0
IL_0047: ldloc.0
IL_0048: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/SimpleStruct::Y
IL_004d: conv.u
IL_004e: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_0053: ret
} // end of method UnsafeCode::StackAllocStruct
.method family hidebysig virtual instance void

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

@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module UnsafeCode.dll
// MVID: {34429304-3762-4E40-977B-76B197A03CDA}
// MVID: {0BE01D88-6EEB-4339-823F-1A46FF374EA2}
.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: 0x00C50000
// Image base: 0x035E0000
// =============== CLASS MEMBERS DECLARATION ===================
@ -174,17 +174,11 @@
.method public hidebysig specialname instance int32*
get_NullPointer() cil managed
{
// Code size 8 (0x8)
.maxstack 1
.locals init (int32* V_0)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: conv.u
IL_0003: stloc.0
IL_0004: br.s IL_0006
IL_0006: ldloc.0
IL_0007: ret
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.0
IL_0001: conv.u
IL_0002: ret
} // end of method UnsafeCode::get_NullPointer
.method private hidebysig specialname rtspecialname static
@ -442,23 +436,26 @@
.method public hidebysig instance void
PassRefParameterAsPointer(int32& p) cil managed
{
// Code size 18 (0x12)
// Code size 20 (0x14)
.maxstack 2
.locals init (int32& pinned V_0)
.locals init (int32* V_0,
int32& pinned V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: stloc.0
IL_0003: nop
IL_0004: ldarg.0
IL_0005: ldloc.0
IL_0006: conv.i
IL_0007: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(int32*)
IL_000c: pop
IL_000d: nop
IL_000e: ldc.i4.0
IL_000f: conv.u
IL_0010: stloc.0
IL_0011: ret
IL_0002: stloc.1
IL_0003: ldloc.1
IL_0004: conv.u
IL_0005: stloc.0
IL_0006: nop
IL_0007: ldarg.0
IL_0008: ldloc.0
IL_0009: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(int32*)
IL_000e: pop
IL_000f: nop
IL_0010: ldc.i4.0
IL_0011: conv.u
IL_0012: stloc.1
IL_0013: ret
} // end of method UnsafeCode::PassRefParameterAsPointer
.method public hidebysig instance void
@ -490,32 +487,34 @@
.method public hidebysig instance void
AddressInMultiDimensionalArray(float64[0...,0...] matrix) cil managed
{
// Code size 34 (0x22)
// Code size 35 (0x23)
.maxstack 3
.locals init (float64& pinned V_0)
.locals init (float64* V_0,
float64& pinned V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.1
IL_0003: ldc.i4.2
IL_0004: call instance float64& float64[0...,0...]::Address(int32,
int32)
IL_0009: stloc.0
IL_000a: nop
IL_000b: ldarg.0
IL_000c: ldloc.0
IL_000d: conv.i
IL_000e: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_0013: pop
IL_0014: ldarg.0
IL_0015: ldloc.0
IL_0016: conv.i
IL_0017: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_001c: pop
IL_001d: nop
IL_001e: ldc.i4.0
IL_001f: conv.u
IL_0020: stloc.0
IL_0021: ret
IL_0009: stloc.1
IL_000a: ldloc.1
IL_000b: conv.u
IL_000c: stloc.0
IL_000d: nop
IL_000e: ldarg.0
IL_000f: ldloc.0
IL_0010: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_0015: pop
IL_0016: ldarg.0
IL_0017: ldloc.0
IL_0018: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::PointerReferenceExpression(float64*)
IL_001d: pop
IL_001e: nop
IL_001f: ldc.i4.0
IL_0020: conv.u
IL_0021: stloc.1
IL_0022: ret
} // end of method UnsafeCode::AddressInMultiDimensionalArray
.method public hidebysig instance void
@ -531,7 +530,7 @@
IL_0001: ldarg.1
IL_0002: stloc.1
IL_0003: ldloc.1
IL_0004: conv.i
IL_0004: conv.u
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: brfalse.s IL_0011
@ -573,10 +572,10 @@
int32 index,
float64 val) cil managed
{
// Code size 39 (0x27)
// Code size 38 (0x26)
.maxstack 3
.locals init (int64& pinned V_0,
int64[] V_1)
.locals init (int64* V_0,
int64[] pinned V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: dup
@ -591,15 +590,15 @@
IL_000b: ldc.i4.0
IL_000c: conv.u
IL_000d: stloc.0
IL_000e: br.s IL_0018
IL_000e: br.s IL_0019
IL_0010: ldloc.1
IL_0011: ldc.i4.0
IL_0012: ldelema [mscorlib]System.Int64
IL_0017: stloc.0
IL_0018: nop
IL_0019: ldloc.0
IL_001a: conv.i
IL_0017: conv.u
IL_0018: stloc.0
IL_0019: nop
IL_001a: ldloc.0
IL_001b: ldarg.2
IL_001c: conv.i
IL_001d: ldc.i4.8
@ -608,10 +607,9 @@
IL_0020: ldarg.3
IL_0021: stind.r8
IL_0022: nop
IL_0023: ldc.i4.0
IL_0024: conv.u
IL_0025: stloc.0
IL_0026: ret
IL_0023: ldnull
IL_0024: stloc.1
IL_0025: ret
} // end of method UnsafeCode::PutDoubleIntoLongArray1
.method public hidebysig instance void
@ -619,24 +617,27 @@
int32 index,
float64 val) cil managed
{
// Code size 19 (0x13)
// Code size 21 (0x15)
.maxstack 2
.locals init (int64& pinned V_0)
.locals init (int64* V_0,
int64& pinned V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: ldelema [mscorlib]System.Int64
IL_0008: stloc.0
IL_0009: nop
IL_000a: ldloc.0
IL_000b: conv.i
IL_000c: ldarg.3
IL_000d: stind.r8
IL_000e: nop
IL_000f: ldc.i4.0
IL_0010: conv.u
IL_0011: stloc.0
IL_0012: ret
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000a: conv.u
IL_000b: stloc.0
IL_000c: nop
IL_000d: ldloc.0
IL_000e: ldarg.3
IL_000f: stind.r8
IL_0010: nop
IL_0011: ldc.i4.0
IL_0012: conv.u
IL_0013: stloc.1
IL_0014: ret
} // end of method UnsafeCode::PutDoubleIntoLongArray2
.method public hidebysig instance string
@ -1151,25 +1152,28 @@
.method public hidebysig instance void
PinFixedMember(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers& m) cil managed
{
// Code size 28 (0x1c)
// Code size 30 (0x1e)
.maxstack 2
.locals init (int32& pinned V_0)
.locals init (int32* V_0,
int32*& pinned V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Integers
IL_0007: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'<Integers>e__FixedBuffer'::FixedElementField
IL_000c: stloc.0
IL_000d: nop
IL_000e: ldarg.0
IL_000f: ldloc.0
IL_0010: conv.i
IL_0011: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(int32*)
IL_0016: pop
IL_0017: nop
IL_0018: ldc.i4.0
IL_0019: conv.u
IL_001a: stloc.0
IL_001b: ret
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: conv.u
IL_000f: stloc.0
IL_0010: nop
IL_0011: ldarg.0
IL_0012: ldloc.0
IL_0013: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(int32*)
IL_0018: pop
IL_0019: nop
IL_001a: ldc.i4.0
IL_001b: conv.u
IL_001c: stloc.1
IL_001d: ret
} // end of method UnsafeCode::PinFixedMember
.method private hidebysig instance void
@ -1216,7 +1220,7 @@
.method public hidebysig instance string
StackAlloc(int32 count) cil managed
{
// Code size 65 (0x41)
// Code size 66 (0x42)
.maxstack 3
.locals init (char* V_0,
char* V_1,
@ -1230,54 +1234,52 @@
IL_0004: mul.ovf.un
IL_0005: localloc
IL_0007: stloc.0
IL_0008: ldc.i4.s 100
IL_000a: conv.u
IL_000b: ldc.i4.2
IL_000c: mul.ovf.un
IL_000d: localloc
IL_000f: stloc.1
IL_0010: ldc.i4.0
IL_0011: stloc.2
IL_0012: br.s IL_002b
IL_0014: nop
IL_0015: ldloc.0
IL_0016: ldloc.2
IL_0017: conv.i
IL_0018: ldc.i4.2
IL_0019: mul
IL_001a: add
IL_001b: ldloc.2
IL_001c: conv.u2
IL_001d: stind.i2
IL_001e: ldloc.1
IL_001f: ldloc.2
IL_0020: conv.i
IL_0021: ldc.i4.2
IL_0022: mul
IL_0023: add
IL_0024: ldc.i4.0
IL_0025: stind.i2
IL_0026: nop
IL_0027: ldloc.2
IL_0028: ldc.i4.1
IL_0029: add
IL_002a: stloc.2
IL_002b: ldloc.2
IL_002c: ldarg.1
IL_002d: clt
IL_002f: stloc.3
IL_0030: ldloc.3
IL_0031: brtrue.s IL_0014
IL_0033: ldarg.0
IL_0034: ldloc.0
IL_0035: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_003a: stloc.s V_4
IL_003c: br.s IL_003e
IL_003e: ldloc.s V_4
IL_0040: ret
IL_0008: ldc.i4 0xc8
IL_000d: conv.u
IL_000e: localloc
IL_0010: stloc.1
IL_0011: ldc.i4.0
IL_0012: stloc.2
IL_0013: br.s IL_002c
IL_0015: nop
IL_0016: ldloc.0
IL_0017: ldloc.2
IL_0018: conv.i
IL_0019: ldc.i4.2
IL_001a: mul
IL_001b: add
IL_001c: ldloc.2
IL_001d: conv.u2
IL_001e: stind.i2
IL_001f: ldloc.1
IL_0020: ldloc.2
IL_0021: conv.i
IL_0022: ldc.i4.2
IL_0023: mul
IL_0024: add
IL_0025: ldc.i4.0
IL_0026: stind.i2
IL_0027: nop
IL_0028: ldloc.2
IL_0029: ldc.i4.1
IL_002a: add
IL_002b: stloc.2
IL_002c: ldloc.2
IL_002d: ldarg.1
IL_002e: clt
IL_0030: stloc.3
IL_0031: ldloc.3
IL_0032: brtrue.s IL_0015
IL_0034: ldarg.0
IL_0035: ldloc.0
IL_0036: call instance string ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode::UsePointer(float64*)
IL_003b: stloc.s V_4
IL_003d: br.s IL_003f
IL_003f: ldloc.s V_4
IL_0041: ret
} // end of method UnsafeCode::StackAlloc
.method public hidebysig instance string

40
ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

@ -366,17 +366,28 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// C# doesn't support a "by reference" variable, so replace it with a native pointer
context.Step("Replace pinned ref-local with native pointer", pinnedRegion);
ILVariable oldVar = pinnedRegion.Variable;
IType elementType = ((ByReferenceType)oldVar.Type).ElementType;
if (elementType.Kind == TypeKind.Pointer && pinnedRegion.Init.MatchLdFlda(out _, out var field)
&& ((PointerType)elementType).ElementType.Equals(field.Type))
{
// Roslyn 2.6 (C# 7.2) uses type "int*&" for the pinned local referring to a
// fixed field of type "int".
// Remove the extra level of indirection.
elementType = ((PointerType)elementType).ElementType;
}
ILVariable newVar = new ILVariable(
VariableKind.PinnedLocal,
new PointerType(((ByReferenceType)oldVar.Type).ElementType),
new PointerType(elementType),
oldVar.Index);
newVar.Name = oldVar.Name;
newVar.HasGeneratedName = oldVar.HasGeneratedName;
oldVar.Function.Variables.Add(newVar);
ReplacePinnedVar(oldVar, newVar, pinnedRegion);
UseExistingVariableForPinnedRegion(pinnedRegion);
} else if (pinnedRegion.Variable.Type.Kind == TypeKind.Array) {
context.Step("Replace pinned array with native pointer", pinnedRegion);
MoveArrayToPointerToPinnedRegionInit(pinnedRegion);
UseExistingVariableForPinnedRegion(pinnedRegion);
} else if (pinnedRegion.Variable.Type.IsKnownType(KnownTypeCode.String)) {
// fixing a string
ILVariable nativeVar;
@ -526,6 +537,33 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
Call call = inst.UnwrapConv(ConversionKind.SignExtend) as Call;
return call != null && call.Method.FullName == "System.Runtime.CompilerServices.RuntimeHelpers.get_OffsetToStringData";
}
/// <summary>
/// Modifies a pinned region to eliminate an extra local variable that roslyn tends to generate.
/// </summary>
void UseExistingVariableForPinnedRegion(PinnedRegion pinnedRegion)
{
// PinnedRegion V_1(..., BlockContainer {
// Block IL_0000(incoming: 1) {
// stloc V_0(ldloc V_1)
// ...
if (!(pinnedRegion.Body is BlockContainer body))
return;
if (pinnedRegion.Variable.LoadCount != 1)
return;
if (!body.EntryPoint.Instructions[0].MatchStLoc(out var v, out var init))
return;
if (!init.MatchLdLoc(pinnedRegion.Variable))
return;
if (!(v.IsSingleDefinition && v.Type.Equals(pinnedRegion.Variable.Type)))
return;
if (v.Kind != VariableKind.Local)
return;
// replace V_1 with V_0
v.Kind = VariableKind.PinnedLocal;
pinnedRegion.Variable = v;
body.EntryPoint.Instructions.RemoveAt(0);
}
#endregion
}
}
Loading…
Cancel
Save