开发者

Error with short form opcodes in Reflection.Emit

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 开发者_如何学Gogenerated 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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜