Помощь с InvalidProgramException (Неверный код IL?) - PullRequest
2 голосов
/ 25 февраля 2011

Я получаю странную ошибку в сборке, экспортированной с System.Reflection.Emit с моно.При попытке запустить мою сборку я получаю InvalidProgramException: недействительный код IL.

monodis дает мне этот результат CIL (что соответствует тому, что я экспортирую с Emit):

.method public static hidebysig 
       default void f_main (class [Pine.Core]Pine.Core.Function A_0, class [Pine.Core]Pine.Core.ValueList A_1)  cil managed 
{
    // Method begins at RVA 0x2144
    // Code size 26 (0x1a)
    .maxstack 4
    .locals init (
        class [Pine.Core]Pine.Core.Function V_0,
        class [Pine.Core]Pine.Core.IScope   V_1,
        class [Pine.Core]Pine.Core.ValueList    V_2,
        class [Pine.Core]Pine.Core.IScope   V_3)
    IL_0000:  ldarg.0 
    IL_0001:  stloc.0 
    IL_0002:  ldarg.1 
    IL_0003:  stloc.2 
    IL_0004:  ldloc.0 
    IL_0005:  ldftn instance class [Pine.Core]Pine.Core.IScope class [Pine.Core]Pine.Core.Function::get_Scope()
    IL_000b:  stloc.1 
    IL_000c:  ldloc.1 
    IL_000d:  newobj instance void class [Pine.Core]Pine.Core.BlockScope::'.ctor'(class [Pine.Core]Pine.Core.IScope)
    IL_0012:  stloc.3 
    IL_0013:  ldloc.2 
    IL_0014:  call instance void class [Pine.Core]Pine.Core.ValueList::Clear()
    IL_0019:  ret 
} // end of method PineType::f_main

Ошибка возникает в IL_000b: stloc.1 Я понятия не имею, почему.

Я пытался заменить stloc.1 инструкцией pop.Когда я делаю это, ошибка происходит в IL_0019: ret

Я действительно не знаю, почему это ведет себя так.Есть идеи?

Дополнительная информация:

  • IScope - это интерфейс
  • BlockScope реализует IScope
  • Function имеетa public IScope Scope { get; private set; }
  • Я получаю эту ошибку как с Mono 2.6.7 (Boehm, AMD64), так и с Mono 2.8 (Boehm с типизированным GC и Parallel Mark, AMD64)

1 Ответ

5 голосов
/ 25 февраля 2011

Редактировать: судя по коду, возможно, IL_0005 предназначен для вызова / callvirt, а не для ldftn? Возможно, эмитент использует неправильный код операции?

Local 1 - это IScope. ldftn помещает указатель функции (native int) в стек оценки. Инструкция сохранения в IL_000b не поддается проверке, так как нативный int не может быть назначен для верификатора IScope.

Что касается вашей второй проблемы, вы разбалансировали стек оценки с помощью инструкции на IL_0004. Переход стека ldftn - "... -> ..., ftn". Это означает, что он не принимает аргумент стека оценки, только токен метаданных. Изменяя IL_000b на pop, вы выводите то, что ldftn нажал, но не то, что IL_0004 нажал.

Что мне не понятно, это то, что вы пытаетесь сделать. Вы не можете рассматривать единственный указатель на функцию как интерфейс (о котором вы могли бы думать, по крайней мере, концептуально, как указатель на v-таблицу). Вам необходимо создать экземпляр типа, который реализует интерфейс. То, что вы могли бы сделать с указателем на функцию, это создать делегата из него - Delegate имеет перегрузку (object, native int) для .ctor. Это было бы, где я предполагаю, что ссылка на объект, выдвинутая IL_0004, вступит в игру (первый аргумент этого .ctor). Конечно, вы также можете напрямую вызывать указатель на функцию. Поскольку я не знаком с этой объектной моделью, с которой вы взаимодействуете, я не могу сказать, каков правильный подход.

...