Ошибка с краткими кодами операций в Reflection.Emit - PullRequest
3 голосов
/ 12 августа 2010

Я делаю небольшой язык, который очень похож на hlsl, но поддерживает только пиксельные шейдеры. Этот язык использует refle.emit для сборки сборок из точечной сети, которые реализуют ту же функциональность. В настоящее время я тестирую свою реализацию инструкции ветвления "if" и в одном из моих модульных тестов (большое if с внутренним if если-то еще) не получилось следующее сообщение об ошибке:

System.NotSupportedException: недопустимая однобайтовая ветвь в позиции: 32. Запрошенная ветвь была: 132.

Я проследил проблему до использования кратких инструкций формы в моем случае OpCodes.Br_S. Решение было простым, я заменил OpCodes.Br_S на OpCodes.Br, но у меня есть пара вопросов об этом решении:

Это решение влияет на производительность сгенерированного кода? Если я хочу правильно сгенерировать Br_S для одного байта и Br для других случаев, как я могу это сделать? Проблема здесь в том, что я использую шаблон посетителя и для инструкции перехода, такой как «если», я должен сначала вывести Br или Br_s, и в этот момент у меня нет никакого способа узнать, будет ли оставшийся код требовать более одного байта прыгать на этикетку. Чтобы лучше проиллюстрировать мой вопрос, это код, который я генерирую для следующих утверждений:

Мой язык:

int a = -1; if (1>1) { a=1; } else if(2>2) { a=2; }

IL:

.method public virtual final instance int32 Main() cil managed {</p> <pre><code>.maxstack 4 .locals init ( [0] int32 num) L_0000: ldc.i4.m1 L_0001: stloc.0 L_0002: ldc.i4.1 L_0003: ldc.i4.1 L_0004: ble.s L_000a L_0006: ldc.i4.1 L_0007: stloc.0 L_0008: br.s L_0010 L_000a: ldc.i4.2 L_000b: ldc.i4.2 L_000c: ble.s L_0010 L_000e: ldc.i4.2 L_000f: stloc.0 L_0010: ldloc.0 L_0011: ret

}

В этом случае я использую две краткие инструкции формы ble.s и br.s для реализации ifs так же, как это делает компилятор .net. Однако компилятор .NET может выбирать br.s или br в зависимости от ситуации, моя проблема в том, как мне сделать что-то подобное?

Tnks

1 Ответ

6 голосов
/ 12 августа 2010

Если вы хотите сделать это, вам нужно вычислить смещение до цели ветвления, прежде чем генерировать саму ветвь, а затем определить, является ли смещение достаточно маленьким, чтобы его можно было достичь с помощью короткой инструкции формы.Я не думаю, что есть особенно простой способ сделать это, используя библиотеку Reflection.Emit.

...