Ошибка в IL-коде с использованием Reflection.Emit

1

Я пишу компилятор, который генерирует.NET IL. Я пишу его на Linux Mint, используя С#/Mono.

Существует проблема с некоторым кодом, который я генерирую с помощью Reflection.Emit. Извините за ужасные имена в сгенерированном коде. Ниже приведена соответствующая часть выхода из монодиса.

.method public static 
       default valuetype Argon.30 Argon.28313529 (valuetype Argon.35 A_0)  cil managed 
{
    // Method begins at RVA 0x215c
// Code size 73 (0x49)
.maxstack 10
.locals init (
    valuetype Argon.35  V_0,
    valuetype Argon.35  V_1)
IL_0000:  ldarg.0 
IL_0001:  stloc.0 
IL_0002:  ldloca.s 0
IL_0004:  ldc.i4.7 
IL_0005:  newobj instance void valuetype Argon.35::'.ctor'(int32)
IL_000a:  call instance valuetype Argon.35 valuetype Argon.35::'add'(valuetype Argon.35)
IL_000f:  stloc.0 
IL_0010:  ldloc.0 
IL_0011:  stloc.1 
IL_0012:  ldloca.s 1
IL_0014:  ldc.i4.2 
IL_0015:  newobj instance void valuetype Argon.35::'.ctor'(int32)
IL_001a:  call instance valuetype Argon.35 valuetype Argon.35::'sub'(valuetype Argon.35)
IL_001f:  stloc.0 
IL_0020:  ldsfld class Argon.747970655F30 Argon.747970655F30::'instance'
IL_0025:  call valuetype Argon.30 Argon.283129()
IL_002a:  pop 
IL_002b:  ldarg.0 
IL_002c:  call valuetype Argon.30 Argon.28313229(valuetype Argon.35)
IL_0031:  pop 
IL_0032:  ldstr " + 5 = "
IL_0037:  newobj instance void class Argon.32::'.ctor'(string)
IL_003c:  call valuetype Argon.30 Argon.28313129(class Argon.32)
IL_0041:  pop 
IL_0042:  ldloc.0 
IL_0043:  call valuetype Argon.30 Argon.28313229(valuetype Argon.35)
IL_0048:  ret 
} // end of global method Argon.28313529

Когда я запускаю это в моно, я получаю следующую ошибку.

System.InvalidProgramException: неверный код IL в: Argon.28313529 (Argon.35): IL_0048: ret

Кажется, что проблема не работает в Microsoft.NET. Насколько я понимаю, это связано с тем, что моно-проверка проверок перед оптимизацией.

Кроме того, предыдущая версия кода без ошибки приведена ниже.

.method public static 
       default valuetype Argon.30 Argon.28313529 (valuetype Argon.35 A_0)  cil managed 
{
    // Method begins at RVA 0x215c
// Code size 46 (0x2e)
.maxstack 6
.locals init (
    valuetype Argon.35  V_0)
IL_0000:  ldarg.0 
IL_0001:  stloc.0 
IL_0002:  ldloca.s 0
IL_0004:  ldc.i4.7 
IL_0005:  newobj instance void valuetype Argon.35::'.ctor'(int32)
IL_000a:  call instance valuetype Argon.35 valuetype Argon.35::'add'(valuetype Argon.35)
IL_000f:  stloc.0 
IL_0010:  ldarg.0 
IL_0011:  call valuetype Argon.30 Argon.28313229(valuetype Argon.35)
IL_0016:  pop 
IL_0017:  ldstr " + 5 = "
IL_001c:  newobj instance void class Argon.32::'.ctor'(string)
IL_0021:  call valuetype Argon.30 Argon.28313129(class Argon.32)
IL_0026:  pop 
IL_0027:  ldloc.0 
IL_0028:  call valuetype Argon.30 Argon.28313229(valuetype Argon.35)
IL_002d:  ret 
} // end of global method Argon.28313529
  • 4
    Попробуйте проверить код с помощью PEVerify.exe из .NET SDK. Это может дать вам лучшее сообщение об ошибке, чем верификатор Mono.
Теги:
reflection.emit
il

2 ответа

4
Лучший ответ

Не оставляете ли вы экземпляр Argon.747970655F30 в стеке IL_0020, в дополнение к экземпляру Argon.30 возвращаемому инструкцией на IL_0043? Это оставит 2 элемента в стеке, когда вы ret, а не один.

  • 0
    Это была проблема. Функция не создавалась как метод экземпляра.
4

Инструкция на IL_0020 несбалансирует стек, его не должно было испускать. Это похоже на ошибку в вашем парсере. Эквивалентно не сообщать о такой ошибке кодирования:

class Example {
    Example instance;
    static void Method() { }
    void Bug() {
        instance.Method();    // CS0176
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню