Я экспериментирую с разбором IL, чтобы испустить метод. Я получил код IL метода в строке [], где каждая строка является инструкцией IL. Я цикл по этому массиву и добавление Opcodes с помощью ILGenerator:Использование Br_S OpCode для указания следующей инструкции с использованием Reflection.Emit.Label
foreach (string ins in instructions) //string representations of IL
{
string opCode = ins.Split(':').ElementAt(1);
// other conditions omitted
if (opCode.Contains("br.s"))
{
Label targetInstruction = ilGenerator.DefineLabel();
ilGenerator.MarkLabel(targetInstruction);
ilGenerator.Emit(OpCodes.Br_S, targetInstruction);
}
Вот IL, что мне нужно воспроизвести:
Source IL:
IL_0000: nop
IL_0001: ldstr "Hello, World!"
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
А вот что я получаю в качестве вывода:
Target IL:
IL_0000: nop
IL_0001: ldstr "Hello, World!"
IL_0006: stloc.0
IL_0007: br.s IL_0007 // this is wrong -- needs to point to IL_0009
IL_0009: ldloc.0
IL_000a: ret
Как вы можете видеть, вызов br.s указывает на себя, что, конечно, вызывает бесконечный цикл. Как заставить его указать на следующую инструкцию, как в источнике? Это связано с использованием Reflection.Emit.Label, но я не уверен, как это работает.
EDIT Кстати IL видели выше, для этого простого метода,
public string HelloWorld()
{
return "Hello, World!";
}
Там должно быть что-то я не вижу здесь ... Почему вы хотите, чтобы перейти к следующей инструкции? Разве это не просто более дорогостоящий нет-op? Кроме того, почему вы отмечаете инструкцию ветки как цель метки, если вы не хотите, чтобы она была целью? –
Переместите вызов MarkLabel() после вызова Emit(). Или просто опустить ветвь полностью, она ничего не делает. –
@Sean Я думаю, вы скоро поймете, что находитесь у вас над головой. Если вы планируете реализовать полный ИЛ-ассемблер, вам нужно будет сделать намного лучше, чем «string.Contains» для инструкций филиала. Вам в основном нужно создать ярлык и * найти * нужное место для него. Не все ветви «для следующей строки». –