IL generation for double arrays

I am writing some IL institutes to create int and double arrays using the System.Reflection.Emit namespace.

To create an int array, I use the following code.

 LocalBuilder arr = gen.DeclareLocal(typeof(int)); gen.Emit(OpCodes.Ldc_I4_1); gen.Emit(OpCodes.Newarr, typeof(int)); gen.Emit(OpCodes.Stloc, arr); gen.Emit(OpCodes.Ldloc, arr); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ldc_I4, 500); gen.Emit(OpCodes.Stelem_I4); gen.Emit(OpCodes.Ldloc, arr); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ldelem_I4); gen.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[]{typeof(int)})); 

Works as expected and prints 500 on the console.

The same thing I tried to create a double array, as shown below.

 LocalBuilder arr = gen.DeclareLocal(typeof(double)); gen.Emit(OpCodes.Ldc_I4_1); gen.Emit(OpCodes.Newarr, typeof(double)); gen.Emit(OpCodes.Stloc, arr); gen.Emit(OpCodes.Ldloc, arr); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ldc_R8, 500D); gen.Emit(OpCodes.Stelem_R8); gen.Emit(OpCodes.Ldloc, arr); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ldelem_I8); gen.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[]{typeof(double)})); 

Unfortunately, this does not work, and when I check the generated assembly using pereview , it gave me the following error.

 Microsoft (R) .NET Framework PE Verifier. Version 4.0.30319.1 Copyright (c) Microsoft Corporation. All rights reserved. [IL]: Error: [C:\temp\Research\Research\bin\Debug\MyMod.exe : Foo::Main][offset 0x00000006][found ref array md array 'System.Double[]'][expected Double] Unexpected type on the stack. [IL]: Error: [C:\temp\Research\Research\bin\Debug\MyMod.exe : Foo::Main][offset 0x00000012] Expected single di mension array. 2 Error(s) Verifying MyMod.exe 

In addition, I checked the generated assembly using ildasm

 .method privatescope static void Main$PST06000001() cil managed { .entrypoint // Code size 28 (0x1c) .maxstack 3 .locals init (float64 V_0) IL_0000: ldc.i4.1 IL_0001: newarr [mscorlib]System.Double IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: ldc.i4.0 IL_0009: ldc.r8 500. IL_0012: stelem.r8 IL_0013: ldloc.0 IL_0014: ldc.i4.0 IL_0015: ldelem.i8 IL_0016: call void [mscorlib]System.Console::WriteLine(float64) IL_001b: ret } // end of method Foo::Main 

Do you have any ideas?

+7
source share
1 answer
 LocalBuilder arr = gen.DeclareLocal(typeof(int)); gen.Emit(OpCodes.Ldc_I4_1); gen.Emit(OpCodes.Newarr, typeof(int)); gen.Emit(OpCodes.Stloc, arr); 

Why is arr not of type int[] ?

I'm sure peverify will complain about both versions.

The fact that it launches for the first version is just "luck" *.

* The reason is much more complicated.

+6
source

All Articles