From 0c6d6742fedf7c69034eccabe993d08b54adadd8 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 16 Oct 2017 23:06:35 +0200 Subject: [PATCH] Add support for fixed-size buffers. --- .../TestCases/Pretty/UnsafeCode.cs | 22 +++ .../TestCases/Pretty/UnsafeCode.il | 128 +++++++++++++++++- .../TestCases/Pretty/UnsafeCode.opt.il | 116 +++++++++++++++- .../TestCases/Pretty/UnsafeCode.opt.roslyn.il | 112 ++++++++++++++- .../TestCases/Pretty/UnsafeCode.roslyn.il | 124 ++++++++++++++++- .../CSharp/CSharpDecompiler.cs | 31 +++++ .../CSharp/ExpressionBuilder.cs | 38 ++++-- .../Transforms/IntroduceUnsafeModifier.cs | 7 + ICSharpCode.Decompiler/DecompilerSettings.cs | 15 ++ ICSharpCode.Decompiler/IL/Instructions.cs | 2 +- ICSharpCode.Decompiler/IL/Instructions.tt | 3 +- 11 files changed, 576 insertions(+), 22 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs index cd4b44a21..76effaa7f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; + namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { public class UnsafeCode @@ -26,6 +28,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public double Y; } + public struct StructWithFixedSizeMembers + { + public unsafe fixed int Integers[100]; + public int NormalMember; + public unsafe fixed double Doubles[200]; + + [Obsolete("another attribute")] + public unsafe fixed byte Old[1]; + } + public unsafe int* NullPointer { get { return null; @@ -235,6 +247,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty return p - q; } + public unsafe double FixedMemberAccess(StructWithFixedSizeMembers* m, int i) + { + return (double)m->Integers[i] + m->Doubles[i]; + } + + public unsafe double* FixedMemberBasePointer(StructWithFixedSizeMembers* m) + { + return m->Doubles; + } + unsafe ~UnsafeCode() { this.PassPointerAsRefParameter(this.NullPointer); diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il index b99639e21..776a499a2 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly p1cal2uj +.assembly '4mqlts3y' { .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 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module p1cal2uj.dll -// MVID: {BD577496-1116-4E18-AF25-DE99056CECA8} +.module '4mqlts3y.dll' +// MVID: {5733C4E7-C3DA-4F38-A641-CE223719D7AA} .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: 0x03220000 +// Image base: 0x01000000 // =============== CLASS MEMBERS DECLARATION =================== @@ -43,6 +43,71 @@ .field public float64 Y } // end of class SimpleStruct + .class sequential ansi sealed nested public beforefieldinit StructWithFixedSizeMembers + extends [mscorlib]System.ValueType + { + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer0' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 400 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public int32 FixedElementField + } // end of class 'e__FixedBuffer0' + + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer1' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 1600 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public float64 FixedElementField + } // end of class 'e__FixedBuffer1' + + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer2' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 1 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public uint8 FixedElementField + } // end of class 'e__FixedBuffer2' + + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer0' Integers + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 59 53 79 73 74 65 6D 2E 49 6E 74 33 32 2C // ..YSystem.Int32, + 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 // mscorlib, Versi + 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 // on=4.0.0.0, Cult + 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 // ure=neutral, Pub + 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 // licKeyToken=b77a + 35 63 35 36 31 39 33 34 65 30 38 39 64 00 00 00 // 5c561934e089d... + 00 00 ) + .field public int32 NormalMember + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1' Doubles + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 5A 53 79 73 74 65 6D 2E 44 6F 75 62 6C 65 // ..ZSystem.Double + 2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 // , mscorlib, Vers + 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C // ion=4.0.0.0, Cul + 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 // ture=neutral, Pu + 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 // blicKeyToken=b77 + 61 35 63 35 36 31 39 33 34 65 30 38 39 C8 00 00 // a5c561934e089... + 00 00 00 ) + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer2' Old + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 58 53 79 73 74 65 6D 2E 42 79 74 65 2C 20 // ..XSystem.Byte, + 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F // mscorlib, Versio + 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 // n=4.0.0.0, Cultu + 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C // re=neutral, Publ + 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 // icKeyToken=b77a5 + 63 35 36 31 39 33 34 65 30 38 39 01 00 00 00 00 // c561934e089..... + 00 ) + .custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 11 61 6E 6F 74 68 65 72 20 61 74 74 72 69 // ...another attri + 62 75 74 65 00 00 ) // bute.. + } // end of class StructWithFixedSizeMembers + .method public hidebysig specialname instance int32* get_NullPointer() cil managed { @@ -860,6 +925,61 @@ IL_0010: ret } // end of method UnsafeCode::PointerSubtraction5 + .method public hidebysig instance float64 + FixedMemberAccess(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m, + int32 i) cil managed + { + // Code size 44 (0x2c) + .maxstack 4 + .locals init (float64 V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer0' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Integers + IL_0007: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer0'::FixedElementField + IL_000c: conv.u + IL_000d: ldarg.2 + IL_000e: conv.i + IL_000f: ldc.i4.4 + IL_0010: mul + IL_0011: add + IL_0012: ldind.i4 + IL_0013: conv.r8 + IL_0014: ldarg.1 + IL_0015: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles + IL_001a: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1'::FixedElementField + IL_001f: conv.u + IL_0020: ldarg.2 + IL_0021: conv.i + IL_0022: ldc.i4.8 + IL_0023: mul + IL_0024: add + IL_0025: ldind.r8 + IL_0026: add + IL_0027: stloc.0 + IL_0028: br.s IL_002a + + IL_002a: ldloc.0 + IL_002b: ret + } // end of method UnsafeCode::FixedMemberAccess + + .method public hidebysig instance float64* + FixedMemberBasePointer(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m) cil managed + { + // Code size 18 (0x12) + .maxstack 1 + .locals init (float64* V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles + IL_0007: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1'::FixedElementField + IL_000c: conv.u + IL_000d: stloc.0 + IL_000e: br.s IL_0010 + + IL_0010: ldloc.0 + IL_0011: ret + } // end of method UnsafeCode::FixedMemberBasePointer + .method family hidebysig virtual instance void Finalize() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il index 8e08fb072..60032b332 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.il @@ -10,7 +10,7 @@ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 4:0:0:0 } -.assembly '0mxa1uxq' +.assembly '4wfrzmwx' { .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 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 } -.module '0mxa1uxq.dll' -// MVID: {EDB443DE-1443-48F8-8E42-03BAFC654447} +.module '4wfrzmwx.dll' +// MVID: {1CBCDACC-05B6-4B2D-BF36-5845CD657180} .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: 0x00B60000 +// Image base: 0x00520000 // =============== CLASS MEMBERS DECLARATION =================== @@ -43,6 +43,71 @@ .field public float64 Y } // end of class SimpleStruct + .class sequential ansi sealed nested public beforefieldinit StructWithFixedSizeMembers + extends [mscorlib]System.ValueType + { + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer0' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 400 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public int32 FixedElementField + } // end of class 'e__FixedBuffer0' + + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer1' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 1600 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public float64 FixedElementField + } // end of class 'e__FixedBuffer1' + + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer2' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 1 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public uint8 FixedElementField + } // end of class 'e__FixedBuffer2' + + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer0' Integers + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 59 53 79 73 74 65 6D 2E 49 6E 74 33 32 2C // ..YSystem.Int32, + 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 // mscorlib, Versi + 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 // on=4.0.0.0, Cult + 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 // ure=neutral, Pub + 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 // licKeyToken=b77a + 35 63 35 36 31 39 33 34 65 30 38 39 64 00 00 00 // 5c561934e089d... + 00 00 ) + .field public int32 NormalMember + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1' Doubles + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 5A 53 79 73 74 65 6D 2E 44 6F 75 62 6C 65 // ..ZSystem.Double + 2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 // , mscorlib, Vers + 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C // ion=4.0.0.0, Cul + 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 // ture=neutral, Pu + 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 // blicKeyToken=b77 + 61 35 63 35 36 31 39 33 34 65 30 38 39 C8 00 00 // a5c561934e089... + 00 00 00 ) + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer2' Old + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 58 53 79 73 74 65 6D 2E 42 79 74 65 2C 20 // ..XSystem.Byte, + 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F // mscorlib, Versio + 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 // n=4.0.0.0, Cultu + 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C // re=neutral, Publ + 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 // icKeyToken=b77a5 + 63 35 36 31 39 33 34 65 30 38 39 01 00 00 00 00 // c561934e089..... + 00 ) + .custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 11 61 6E 6F 74 68 65 72 20 61 74 74 72 69 // ...another attri + 62 75 74 65 00 00 ) // bute.. + } // end of class StructWithFixedSizeMembers + .method public hidebysig specialname instance int32* get_NullPointer() cil managed { @@ -657,6 +722,49 @@ IL_000b: ret } // end of method UnsafeCode::PointerSubtraction5 + .method public hidebysig instance float64 + FixedMemberAccess(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m, + int32 i) cil managed + { + // Code size 39 (0x27) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer0' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Integers + IL_0006: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer0'::FixedElementField + IL_000b: conv.u + IL_000c: ldarg.2 + IL_000d: conv.i + IL_000e: ldc.i4.4 + IL_000f: mul + IL_0010: add + IL_0011: ldind.i4 + IL_0012: conv.r8 + IL_0013: ldarg.1 + IL_0014: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles + IL_0019: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1'::FixedElementField + IL_001e: conv.u + IL_001f: ldarg.2 + IL_0020: conv.i + IL_0021: ldc.i4.8 + IL_0022: mul + IL_0023: add + IL_0024: ldind.r8 + IL_0025: add + IL_0026: ret + } // end of method UnsafeCode::FixedMemberAccess + + .method public hidebysig instance float64* + FixedMemberBasePointer(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m) cil managed + { + // Code size 13 (0xd) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles + IL_0006: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer1'::FixedElementField + IL_000b: conv.u + IL_000c: ret + } // end of method UnsafeCode::FixedMemberBasePointer + .method family hidebysig virtual instance void Finalize() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il index 78e67655f..42df3166e 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.opt.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module UnsafeCode.dll -// MVID: {921693A0-E269-428D-8AB1-E3B34745B42B} +// MVID: {C46FA0A4-EE31-4A04-9894-41AA162DD602} .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: 0x033D0000 +// Image base: 0x00DE0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -47,6 +47,71 @@ .field public float64 Y } // end of class SimpleStruct + .class sequential ansi sealed nested public beforefieldinit StructWithFixedSizeMembers + extends [mscorlib]System.ValueType + { + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 400 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public int32 FixedElementField + } // end of class 'e__FixedBuffer' + + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 1600 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public float64 FixedElementField + } // end of class 'e__FixedBuffer' + + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 1 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public uint8 FixedElementField + } // end of class 'e__FixedBuffer' + + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' Integers + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 59 53 79 73 74 65 6D 2E 49 6E 74 33 32 2C // ..YSystem.Int32, + 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 // mscorlib, Versi + 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 // on=4.0.0.0, Cult + 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 // ure=neutral, Pub + 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 // licKeyToken=b77a + 35 63 35 36 31 39 33 34 65 30 38 39 64 00 00 00 // 5c561934e089d... + 00 00 ) + .field public int32 NormalMember + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' Doubles + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 5A 53 79 73 74 65 6D 2E 44 6F 75 62 6C 65 // ..ZSystem.Double + 2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 // , mscorlib, Vers + 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C // ion=4.0.0.0, Cul + 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 // ture=neutral, Pu + 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 // blicKeyToken=b77 + 61 35 63 35 36 31 39 33 34 65 30 38 39 C8 00 00 // a5c561934e089... + 00 00 00 ) + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' Old + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 58 53 79 73 74 65 6D 2E 42 79 74 65 2C 20 // ..XSystem.Byte, + 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F // mscorlib, Versio + 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 // n=4.0.0.0, Cultu + 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C // re=neutral, Publ + 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 // icKeyToken=b77a5 + 63 35 36 31 39 33 34 65 30 38 39 01 00 00 00 00 // c561934e089..... + 00 ) + .custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 11 61 6E 6F 74 68 65 72 20 61 74 74 72 69 // ...another attri + 62 75 74 65 00 00 ) // bute.. + } // end of class StructWithFixedSizeMembers + .method public hidebysig specialname instance int32* get_NullPointer() cil managed { @@ -663,6 +728,49 @@ IL_000b: ret } // end of method UnsafeCode::PointerSubtraction5 + .method public hidebysig instance float64 + FixedMemberAccess(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m, + int32 i) cil managed + { + // Code size 39 (0x27) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Integers + IL_0006: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer'::FixedElementField + IL_000b: conv.u + IL_000c: ldarg.2 + IL_000d: conv.i + IL_000e: ldc.i4.4 + IL_000f: mul + IL_0010: add + IL_0011: ldind.i4 + IL_0012: conv.r8 + IL_0013: ldarg.1 + IL_0014: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles + IL_0019: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer'::FixedElementField + IL_001e: conv.u + IL_001f: ldarg.2 + IL_0020: conv.i + IL_0021: ldc.i4.8 + IL_0022: mul + IL_0023: add + IL_0024: ldind.r8 + IL_0025: add + IL_0026: ret + } // end of method UnsafeCode::FixedMemberAccess + + .method public hidebysig instance float64* + FixedMemberBasePointer(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m) cil managed + { + // Code size 13 (0xd) + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles + IL_0006: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer'::FixedElementField + IL_000b: conv.u + IL_000c: ret + } // end of method UnsafeCode::FixedMemberBasePointer + .method family hidebysig virtual instance void Finalize() cil managed { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il index 311e55695..3dd5bea97 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.roslyn.il @@ -25,14 +25,14 @@ .ver 0:0:0:0 } .module UnsafeCode.dll -// MVID: {7BB1F8C9-F0A0-4D87-9A69-19FAC9915AFA} +// MVID: {A389E3D9-8350-4463-A41E-65C50B6E19ED} .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: 0x01620000 // =============== CLASS MEMBERS DECLARATION =================== @@ -47,6 +47,71 @@ .field public float64 Y } // end of class SimpleStruct + .class sequential ansi sealed nested public beforefieldinit StructWithFixedSizeMembers + extends [mscorlib]System.ValueType + { + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 400 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public int32 FixedElementField + } // end of class 'e__FixedBuffer' + + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 1600 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public float64 FixedElementField + } // end of class 'e__FixedBuffer' + + .class sequential ansi sealed nested public beforefieldinit 'e__FixedBuffer' + extends [mscorlib]System.ValueType + { + .pack 0 + .size 1 + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.UnsafeValueTypeAttribute::.ctor() = ( 01 00 00 00 ) + .field public uint8 FixedElementField + } // end of class 'e__FixedBuffer' + + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' Integers + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 59 53 79 73 74 65 6D 2E 49 6E 74 33 32 2C // ..YSystem.Int32, + 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 // mscorlib, Versi + 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 // on=4.0.0.0, Cult + 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 // ure=neutral, Pub + 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 // licKeyToken=b77a + 35 63 35 36 31 39 33 34 65 30 38 39 64 00 00 00 // 5c561934e089d... + 00 00 ) + .field public int32 NormalMember + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' Doubles + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 5A 53 79 73 74 65 6D 2E 44 6F 75 62 6C 65 // ..ZSystem.Double + 2C 20 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 // , mscorlib, Vers + 69 6F 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C // ion=4.0.0.0, Cul + 74 75 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 // ture=neutral, Pu + 62 6C 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 // blicKeyToken=b77 + 61 35 63 35 36 31 39 33 34 65 30 38 39 C8 00 00 // a5c561934e089... + 00 00 00 ) + .field public valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' Old + .custom instance void [mscorlib]System.Runtime.CompilerServices.FixedBufferAttribute::.ctor(class [mscorlib]System.Type, + int32) = ( 01 00 58 53 79 73 74 65 6D 2E 42 79 74 65 2C 20 // ..XSystem.Byte, + 6D 73 63 6F 72 6C 69 62 2C 20 56 65 72 73 69 6F // mscorlib, Versio + 6E 3D 34 2E 30 2E 30 2E 30 2C 20 43 75 6C 74 75 // n=4.0.0.0, Cultu + 72 65 3D 6E 65 75 74 72 61 6C 2C 20 50 75 62 6C // re=neutral, Publ + 69 63 4B 65 79 54 6F 6B 65 6E 3D 62 37 37 61 35 // icKeyToken=b77a5 + 63 35 36 31 39 33 34 65 30 38 39 01 00 00 00 00 // c561934e089..... + 00 ) + .custom instance void [mscorlib]System.ObsoleteAttribute::.ctor(string) = ( 01 00 11 61 6E 6F 74 68 65 72 20 61 74 74 72 69 // ...another attri + 62 75 74 65 00 00 ) // bute.. + } // end of class StructWithFixedSizeMembers + .method public hidebysig specialname instance int32* get_NullPointer() cil managed { @@ -866,6 +931,61 @@ IL_0010: ret } // end of method UnsafeCode::PointerSubtraction5 + .method public hidebysig instance float64 + FixedMemberAccess(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m, + int32 i) cil managed + { + // Code size 44 (0x2c) + .maxstack 4 + .locals init (float64 V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Integers + IL_0007: ldflda int32 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer'::FixedElementField + IL_000c: conv.u + IL_000d: ldarg.2 + IL_000e: conv.i + IL_000f: ldc.i4.4 + IL_0010: mul + IL_0011: add + IL_0012: ldind.i4 + IL_0013: conv.r8 + IL_0014: ldarg.1 + IL_0015: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles + IL_001a: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer'::FixedElementField + IL_001f: conv.u + IL_0020: ldarg.2 + IL_0021: conv.i + IL_0022: ldc.i4.8 + IL_0023: mul + IL_0024: add + IL_0025: ldind.r8 + IL_0026: add + IL_0027: stloc.0 + IL_0028: br.s IL_002a + + IL_002a: ldloc.0 + IL_002b: ret + } // end of method UnsafeCode::FixedMemberAccess + + .method public hidebysig instance float64* + FixedMemberBasePointer(valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers* m) cil managed + { + // Code size 18 (0x12) + .maxstack 1 + .locals init (float64* V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldflda valuetype ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer' ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers::Doubles + IL_0007: ldflda float64 ICSharpCode.Decompiler.Tests.TestCases.Pretty.UnsafeCode/StructWithFixedSizeMembers/'e__FixedBuffer'::FixedElementField + IL_000c: conv.u + IL_000d: stloc.0 + IL_000e: br.s IL_0010 + + IL_0010: ldloc.0 + IL_0011: ret + } // end of method UnsafeCode::FixedMemberBasePointer + .method family hidebysig virtual instance void Finalize() cil managed { diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 801b95b7c..1a2524dd9 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -30,6 +30,7 @@ using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.ControlFlow; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.Decompiler.Semantics; namespace ICSharpCode.Decompiler.CSharp { @@ -200,6 +201,8 @@ namespace ICSharpCode.Decompiler.CSharp return true; if (settings.AsyncAwait && AsyncAwaitDecompiler.IsCompilerGeneratedStateMachine(type)) return true; + if (settings.FixedBuffers && type.Name.StartsWith("<", StringComparison.Ordinal) && type.Name.Contains("__FixedBuffer")) + return true; } else if (type.IsCompilerGenerated()) { if (type.Name.StartsWith("", StringComparison.Ordinal)) return true; @@ -735,9 +738,37 @@ namespace ICSharpCode.Decompiler.CSharp } var fieldDecl = typeSystemAstBuilder.ConvertEntity(field); SetNewModifier(fieldDecl); + if (settings.FixedBuffers && IsFixedField(field, out var elementType, out var elementCount)) { + var fixedFieldDecl = new FixedFieldDeclaration(); + fieldDecl.Attributes.MoveTo(fixedFieldDecl.Attributes); + fixedFieldDecl.Modifiers = fieldDecl.Modifiers; + fixedFieldDecl.ReturnType = typeSystemAstBuilder.ConvertType(elementType); + fixedFieldDecl.Variables.Add(new FixedVariableInitializer(field.Name, new PrimitiveExpression(elementCount))); + fixedFieldDecl.Variables.Single().CopyAnnotationsFrom(((FieldDeclaration)fieldDecl).Variables.Single()); + fixedFieldDecl.CopyAnnotationsFrom(fieldDecl); + RemoveAttribute(fixedFieldDecl, fixedBufferAttributeTypeName); + return fixedFieldDecl; + } return fieldDecl; } + static readonly FullTypeName fixedBufferAttributeTypeName = new TopLevelTypeName("System.Runtime.CompilerServices", "FixedBufferAttribute"); + + internal static bool IsFixedField(IField field, out IType type, out int elementCount) + { + type = null; + elementCount = 0; + IAttribute attr = field.GetAttribute(fixedBufferAttributeTypeName, inherit: false); + if (attr != null && attr.PositionalArguments.Count == 2) { + if (attr.PositionalArguments[0] is TypeOfResolveResult trr && attr.PositionalArguments[1].ConstantValue is int length) { + type = trr.ReferencedType; + elementCount = length; + return true; + } + } + return false; + } + EntityDeclaration DoDecompile(PropertyDefinition propertyDefinition, IProperty property, ITypeResolveContext decompilationContext) { Debug.Assert(decompilationContext.CurrentMember == property); diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 677ea14c3..118a02862 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1450,10 +1450,16 @@ namespace ICSharpCode.Decompiler.CSharp result = target.UnwrapChild(dirExpr.Expression); result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation } else if (target.Type is PointerType pointerType) { - // Dereference the existing pointer - result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression) - .WithILInstruction(inst) - .WithRR(new ResolveResult(pointerType.ElementType)); + if (target.Expression is UnaryOperatorExpression uoe && uoe.Operator == UnaryOperatorType.AddressOf) { + // We can dereference the pointer by stripping away the '&' + result = target.UnwrapChild(uoe.Expression); + result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation + } else { + // Dereference the existing pointer + result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression) + .WithILInstruction(inst) + .WithRR(new ResolveResult(pointerType.ElementType)); + } } else { // reference type behind non-DirectionExpression? // this case should be impossible, but we can use a pointer cast @@ -1518,14 +1524,30 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override TranslatedExpression VisitLdFlda(LdFlda inst, TranslationContext context) { - var expr = ConvertField(inst.Field, inst.Target); - return new DirectionExpression(FieldDirection.Ref, expr) - .WithoutILInstruction().WithRR(new ResolveResult(new ByReferenceType(expr.Type))); + if (settings.FixedBuffers && inst.Field.Name == "FixedElementField" + && inst.Target is LdFlda nestedLdFlda + && CSharpDecompiler.IsFixedField(nestedLdFlda.Field, out var elementType, out _)) + { + Expression result = ConvertField(nestedLdFlda.Field, nestedLdFlda.Target); + result.RemoveAnnotations(); + return result.WithRR(new ResolveResult(new PointerType(elementType))) + .WithILInstruction(inst); + } + var expr = ConvertField(inst.Field, inst.Target).WithILInstruction(inst); + if (inst.ResultType == StackType.I) { + // ldflda producing native pointer + return new UnaryOperatorExpression(UnaryOperatorType.AddressOf, expr) + .WithoutILInstruction().WithRR(new ResolveResult(new PointerType(expr.Type))); + } else { + // ldflda producing managed pointer + return new DirectionExpression(FieldDirection.Ref, expr) + .WithoutILInstruction().WithRR(new ResolveResult(new ByReferenceType(expr.Type))); + } } protected internal override TranslatedExpression VisitLdsFlda(LdsFlda inst, TranslationContext context) { - var expr = ConvertField(inst.Field); + var expr = ConvertField(inst.Field).WithILInstruction(inst); return new DirectionExpression(FieldDirection.Ref, expr) .WithoutILInstruction().WithRR(new ResolveResult(new ByReferenceType(expr.Type))); } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs index cf759f9e2..942970409 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs @@ -57,6 +57,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { // C# sizeof(MyStruct) requires unsafe{} // (not for sizeof(int), but that gets constant-folded and thus decompiled to 4) + base.VisitSizeOfExpression(sizeOfExpression); return true; } @@ -126,5 +127,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return true; return result; } + + public override bool VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer) + { + base.VisitFixedVariableInitializer(fixedVariableInitializer); + return true; + } } } diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs index 50f744e6d..fc3abcb23 100644 --- a/ICSharpCode.Decompiler/DecompilerSettings.cs +++ b/ICSharpCode.Decompiler/DecompilerSettings.cs @@ -103,6 +103,21 @@ namespace ICSharpCode.Decompiler } } + bool fixedBuffers = true; + + /// + /// Decompile C# 1.0 'public unsafe fixed int arr[10];' members. + /// + public bool FixedBuffers { + get { return fixedBuffers; } + set { + if (fixedBuffers != value) { + fixedBuffers = value; + OnPropertyChanged(); + } + } + } + bool liftNullables = true; /// diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 2afb023df..c27b25f8c 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -3242,7 +3242,7 @@ namespace ICSharpCode.Decompiler.IL readonly IField field; /// Returns the field operand. public IField Field { get { return field; } } - public override StackType ResultType { get { return StackType.Ref; } } + public override StackType ResultType { get { return target.ResultType.IsIntegerType() ? StackType.I : StackType.Ref; } } protected override InstructionFlags ComputeFlags() { return target.Flags | (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow); diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 598763260..a3a2d2fea 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -192,7 +192,8 @@ SupportsVolatilePrefix, SupportsUnalignedPrefix, ResultType("Void")), new OpCode("ldflda", "Load address of instance field", - CustomClassName("LdFlda"), CustomArguments("target"), MayThrowIfNotDelayed, HasFieldOperand, ResultType("Ref")), + CustomClassName("LdFlda"), CustomArguments("target"), MayThrowIfNotDelayed, HasFieldOperand, + ResultType("target.ResultType.IsIntegerType() ? StackType.I : StackType.Ref")), new OpCode("ldsflda", "Load static field address", CustomClassName("LdsFlda"), NoArguments, ResultType("Ref"), HasFieldOperand),