Reflection.Emit 中的短格式操作码错误
Posted
技术标签:
【中文标题】Reflection.Emit 中的短格式操作码错误【英文标题】:Error with short form opcodes in Reflection.Emit 【发布时间】:2010-08-12 16:12:03 【问题描述】:我正在制作一种与hlsl
非常相似但仅支持像素着色器的小型语言。该语言使用reflection.emit
构建实现相同功能的.NET 程序集。我目前正在测试我的分支指令if
的实现,并且在我的一个单元测试(一个大的if
和内部if/else
s)中失败并出现以下错误消息:
System.NotSupportedException : 在位置非法的一字节分支:32。请求的分支是:132。
在我的案例OpCodes.Br_S
中,我已将问题追溯到使用短格式指令。解决方案很简单,我已将 OpCodes.Br_S
替换为 OpCodes.Br
但是我对此解决方案有几个问题:
这个解决方案对生成代码的性能有影响吗?
如果我想为单字节正确生成Br_S
,为其他情况正确生成Br
,我该怎么做?这里的问题是我正在使用访问者模式,对于像if
这样的分支指令,我必须首先输出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
.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
来实现 if
s,就像 .NET 编译器所做的那样。但是.NET编译器可以根据情况选择br.s
或br
,我的问题是我该怎么做类似的事情?
Tnk
【问题讨论】:
你的 IL 有点大,没什么大不了的。相信 JIT 编译器可以做到这一点。这些微优化不值得你花时间。 我想这样做,但我需要自己生成 IL,因为例如 silverlight 中没有 c# 编译器。我想在 silverlight 以及其他没有可用编译器的环境中使用它...... 我相信 Hans 建议您不要使用短格式(您遇到问题)并使用标准的长格式,因为这种优化将自动发生在 JIT(其中Silverlight 有,就像任何其他 CLR impl) 嗯?这很奇怪......如果是这样的话,为什么会有两个不同的操作码?如果 Jit 编译器足够聪明,可以进行这种优化,我就无法真正理解操作码的简短版本。任何人都知道它们为什么存在吗?还有很多库明确地处理类似的情况,例如他们做这样的事情 if (index 【参考方案1】:如果您想这样做,您需要在生成分支本身之前计算到分支目标的偏移量,然后确定偏移量是否小到足以让短格式指令达到。我认为使用Reflection.Emit
库没有特别简单的方法。
【讨论】:
拜托,我有兴趣了解此回复。我有一个类似的问题。你在说什么节日?你能用某种插图解释一下吗?您还可以向我指出我可以从中受益的其他资源。提前致谢。 @ColourBlend - 分支指令有一个目标,该目标在 IL 代码中指定为偏移量,即使ILGenerator
API 允许您只传入一个标签(并且框架会根据标签所在的位置)。 Br_S
(和其他短指令)要求偏移量可以放入一个字节(即指令流中的偏移量不超过 127 个字节)。这有帮助吗?
谢谢。这很有帮助。不过,在你回复之前,我调查了一下。 DynamicMethod 的运行速度是否比等效的静态方法(设计时方法)快?将设计时方法转换为 MSIL 会提高性能吗?
我目前正在为存储过程开发小型数据访问映射器。我有一个具有大部分基本功能的工作版本。我想优化它的性能,我想知道您是否可以提供帮助。
@ColourBlend - 我的建议是以两种方式实现事物并分析它们以查看哪个更快。如果您有具体问题,最好在这里提出一个新问题,而不是在 cmets 中提问。以上是关于Reflection.Emit 中的短格式操作码错误的主要内容,如果未能解决你的问题,请参考以下文章