c# - How to emit LDC_I8 for a ulong.Parse call? -
i'm having issue emitting il set uint64 property value. below minimal code reproduce issue.
using system; using system.reflection; using system.reflection.emit; namespace consoleapplication1 { class program { static void main(string[] args) { assemblybuilder assemblybuilder = appdomain.currentdomain.definedynamicassembly( new assemblyname("test"), assemblybuilderaccess.runandsave); modulebuilder m_modulebuilder = assemblybuilder.definedynamicmodule("test.dll", "test.dll"); typebuilder typebuilder = m_modulebuilder.definetype("class1", typeattributes.public | typeattributes.class | typeattributes.autoclass | typeattributes.ansiclass | typeattributes.beforefieldinit | typeattributes.autolayout, null); fieldbuilder fieldbuilder = typebuilder.definefield("m_prop1", typeof(ulong), fieldattributes.private); methodbuilder getmethodbuilder = typebuilder.definemethod( "get_prop1", methodattributes.public | methodattributes.specialname | methodattributes.hidebysig, typeof(ulong), type.emptytypes); ilgenerator getilgen = getmethodbuilder.getilgenerator(); getilgen.emit(opcodes.ldarg_0); getilgen.emit(opcodes.ldfld, fieldbuilder); getilgen.emit(opcodes.ret); methodbuilder setmethodbuilder = typebuilder.definemethod( "set_prop1", methodattributes.public | methodattributes.specialname | methodattributes.hidebysig, null, new[] { typeof(ulong) }); ilgenerator setilgen = setmethodbuilder.getilgenerator(); setilgen.emit(opcodes.ldarg_0); setilgen.emit(opcodes.ldarg_1); setilgen.emit(opcodes.stfld, fieldbuilder); setilgen.emit(opcodes.ret); propertybuilder propertybuilder = typebuilder.defineproperty( "prop1", propertyattributes.hasdefault, typeof(ulong), null); propertybuilder.setgetmethod(getmethodbuilder); propertybuilder.setsetmethod(setmethodbuilder); constructorbuilder constructorbuilder = typebuilder.defineconstructor(methodattributes.public, callingconventions.standard, type.emptytypes); ilgenerator ilgenerator = constructorbuilder.getilgenerator(); ilgenerator.emit(opcodes.ldarg_0); ilgenerator.emit(opcodes.call, typebuilder.basetype.getconstructor(type.emptytypes)); ilgenerator.emit(opcodes.ldarg_0); ilgenerator.emit(opcodes.ldc_i8, ulong.parse("0")); ilgenerator.emit(opcodes.call, propertybuilder.getsetmethod()); ilgenerator.emit(opcodes.ret); type class1type = typebuilder.createtype(); assemblybuilder.save("test.dll"); } } }
if run peverify on created .dll following:
[il]: error: [c:\code\consoleapplication1\consoleapplication1\bin\debug\test.dl : class1::.ctor][offset 0x00000010] unrecognized local variable number. 1 error(s) verifying test.dll
if dissassemble constructor looks follows:
.method public specialname rtspecialname instance void .ctor() cil managed { // code size 18 (0x12) .maxstack 4 il_0000: ldarg.0 il_0001: call instance void [mscorlib]system.object::.ctor() il_0006: ldarg.0 il_0007: ldc.i8 0x22800000000 il_0010: ldloc.0 il_0011: ret } // end of method class1::.ctor
so why ilgenerator.emit(opcodes.ldc_i8, ulong.parse("0"));
being turned il_0007: ldc.i8 0x22800000000
, happened property set call?
changing ulong.parse long.parse gets create assembly without these errors long.parse crash if feed value greater long.maxvalue.
that particular call emit
ends using overload accepts float
, due lack of ulong
-aware overload, you've discovered since posting original question. funny-looking constant see in ildasm because overload have emitted 4 bytes 0 value, 8 byte constant expected, interpreted following opcodes higher order bytes of constant (which explains why property accessor call apparently replaced different opcode).
Comments
Post a Comment