Я делаю небольшой язык, который очень похож на 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