-
Notifications
You must be signed in to change notification settings - Fork 24
Open
Description
We are trying to emit Ldftn instruction. In some cases we see exception System.ArgumentException.
Look at this code:
public class Dummy
{
public static int Add10(int x)
{
return x + 10;
}
}[TestFixture]
public class Tests
{
[TestCase(true)]
[TestCase(false)]
public void TestLdftn(bool useDocumentWriter)
{
var id = $"asm-{Guid.NewGuid()}";
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(id), AssemblyBuilderAccess.RunAndCollect);
var module = assembly.DefineDynamicModule(name: id, fileName: id + ".dll", emitSymbolInfo: true);
var fooTypeBuilder = module.DefineType("Foo", TypeAttributes.Public | TypeAttributes.Class);
var symWriter = module.GetSymWriter();
var barMethod = fooTypeBuilder.DefineMethod("Bar", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new[] { typeof(int) });
var documentName = fooTypeBuilder.Name + "." + barMethod.Name + ".cil";
var documentWriter = symWriter.DefineDocument(documentName, SymDocumentType.Text, SymLanguageType.ILAssembly, Guid.Empty);
using (var il = useDocumentWriter
? new GroboIL(barMethod, documentWriter)
: new GroboIL(barMethod))
{
il.Ldnull(); // stack: [null]
il.Ldftn(typeof(Dummy).GetMethod("Add10")); // stack: [null, Add10*]
il.Newobj(typeof(Func<int, int>).GetConstructor(new[] { typeof(object), typeof(IntPtr) })); // stack: [func]
il.Ldc_I4(5); // stack: [func, 5]
il.Call(typeof(Func<int, int>).GetMethod("Invoke")); // stack: [int]
il.Ret();
}
var fooType = fooTypeBuilder.CreateType();
var result = fooType.GetMethod("Bar").Invoke(null, new object[] { 5 });
result.Should().Be(15);
}
}We can succesfully emit and run code without document writer. But we see that exception in opposite scenario:
System.ArgumentException : Не удается передать указанный код операции в метод EmitCall.
Имя параметра: opcode
в System.Reflection.Emit.ILGenerator.EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)
в GrEmit.GroboIL.Emit(OpCode opCode, ILInstructionParameter parameter) в C:\BuildAgent\work\249acc80a2fd7042\GrEmit\GrEmit\GroboIL.cs:строка 2000
в GrEmit.GroboIL.Dispose() в C:\BuildAgent\work\249acc80a2fd7042\GrEmit\GrEmit\GroboIL.cs:строка 147
в GremitBugs.Tests.TestLdftn(Boolean useDocumentWriter) в C:\Users\****\Documents\Visual Studio 2017\Projects\GremitWeaks\GremitBugs\Tests.cs:строка 45
We assume that bug is located here:
gremit/GrEmit/GrEmit/GroboIL.cs
Lines 1999 to 2000 in b08a146
| else if(parameter is MethodILInstructionParameter) | |
| il.EmitCall(opCode, ((MethodILInstructionParameter)parameter).Method, null); |
Sometimes MethodILInstructionParameter leads to emit non call opcodes :)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels