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