Reflection.Emit 中的短格式操作码错误

发布于 2024-09-13 22:08:20 字数 1492 浏览 7 评论 0原文

我正在制作一种与 hlsl 非常相似的小型语言,但仅支持像素着色器。该语言使用 reflection.emit 构建实现相同功能的 .NET 程序集。我目前正在测试分支指令 if 的实现以及我的一个单元测试(一个带有内部 if/else 的大型 if ) 失败并出现以下错误消息:

System.NotSupportedException:位置 32 处存在非法一字节分支。请求的分支为:132。

我已将问题追溯到我的案例 OpCodes.Br_S 中使用短格式指令。解决方案很简单,我已将 OpCodes.Br_S 替换为 OpCodes.Br,但是我对此解决方案有几个问题:

此解决方案对性能有影响吗生成的代码?

如果我想正确生成单字节的 Br_S 和其他情况的 Br 我该怎么做?这里的问题是,我使用的是访问者模式,对于像 if 这样的分支指令,我必须首先输出 BrBr_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
{

    .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.sbr。 s 来实现 if,就像 .NET 编译器所做的那样。然而.NET编译器可以根据情况选择br.sbr,我的问题是我该如何做类似的事情?

特恩克斯

I'm making a small language that is very similar to hlsl but supports only pixel shaders. This language uses reflection.emit to build .NET assemblies that implement the same functionality. I'm currently testing my implementation of the branch instruction if and in one of my unit tests (a large if with inner if/elses) failed with the following error message:

System.NotSupportedException : Illegal one-byte branch at position: 32. Requested branch was: 132.

I've traced the problem to the use of short form instructions in my case OpCodes.Br_S. The solution was simple, I've replaced OpCodes.Br_S with OpCodes.Br however I have a couple of questions about this solution:

Does this solution have an impact on the performance of the generated code?

If I want to correctly generate Br_S for single byte and Br for the other cases how can I do that? The problem here is that I'm using a visitor pattern and for a branch instruction like the if I have to output Br or Br_s first and at that point, I have no way of knowing if the remaining code will require more than a single byte to jump to the label. To better illustrate my question this is the code that I generate for the following statements:

My Language:

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

IL:

.method public virtual final instance int32 Main() cil managed
{

    .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 
}

In this case, I'm using two short form instructions ble.s and br.s to implement the ifs just like what the .NET compiler does. However .NET compiler is able to choose br.s or br according to the cases, my problem is how can I do something similar?

Tnks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

屋顶上的小猫咪 2024-09-20 22:08:20

如果要执行此操作,则需要在生成分支本身之前计算到分支目标的偏移量,然后确定偏移量是否足够小以可由短格式指令到达。我认为使用 Reflection.Emit 库没有特别简单的方法来做到这一点。

If you want to do this, you'll need to calculate the offset to the branch target before generating the branch itself, and then determine if the offset is small enough to be reached by the short form instruction. I don't think that there's a particularly easy way to do this using the Reflection.Emit library.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文