CLR中的本机浮点类型用法

时间:2012-12-19 21:07:50

标签: .net cil

我发现CIL compiller允许输入native float类型。但是,CLR不允许这样做。它有用吗?它的大小是多少?是否有相应的.NET类型?我试图将它实现为伪原始类型:

.class public sequential ansi serializable sealed beforefieldinit NativeFloat
  extends System.ValueType
{
  .field assembly native float m_value
}

但是,CLR不支持此类型。谢谢你的帮助。

编辑:如果你有兴趣,它的CorElementType是26(0x1a,R)。

2 个答案:

答案 0 :(得分:5)

来自CIL ECMA规范,I.12.1.1 Native size: native int, native unsigned int, O and &

  

本机大小类型(native int,native unsigned int,O和&)是   CLI中用于推迟选择值大小的机制。   这些数据类型以CIL类型存在;但是,CLI会将每个映射到   特定处理器的原生大小。 (例如,数据类型I会   在奔腾处理器上映射到int32,但在IA64上映射到int64   因此,大小的选择推迟到JIT编译   或者运行时,初始化CLI并且架构是   众所周知。这意味着字段和堆栈帧偏移也不是   在编译时已知。

现在,说过,native float(而不是native int)在ECMA规范中没有提到过一次。我能找到的唯一证据是在一些开源CIL汇编器中,他们抛出一个异常,说明他们无法为native float生成操作码。

如果微软的CIL编译器实际上确实接受了这种类型,我认为这是微软打算实现的一个功能,但最终并未最终投入MSIL(CIL的前身)。另外,如果汇编程序实际上产生了操作码而不是错误消息,我可以想象(尽管这也是猜测)可能存在Microsoft的CLR(可能是.NET Micro Framework或特定版本的Silverlight)的变体,或者什么)支持操作码。

另请注意,在上面的规范中,提到了CLI。 CLR仅仅是Microsoft的CLI实现。

ECMA规范 提及原生浮点类型,但它不是native float

  

F,浮点值(float32,float64或其他表示形式   由底层硬件支持)

答案 1 :(得分:5)

CLI规范Ecma 335定义了三种浮点类型。 Float32,float64和F.前两个是名义类型,第三个是代表性类型,IL中的“native float”类型。

第I.12.1.3节“浮点数据类型的处理”给出了基本原理:

  

浮点数(静态,数组元素和类的字段)的存储位置具有固定大小。支持的存储大小为float32和float64。其他地方(在评估堆栈上,作为参数,作为返回类型和作为局部变量)浮点数使用内部浮点类型表示。在每个这样的实例中,变量或表达式的标称类型是float32或float64,但其值可以在内部用额外的范围和/或精度表示。内部浮点表示的大小取决于实现,可以变化,并且其精度至少与表示的变量或表达式的精度一样大。

这在当前的jitter实现中实际上并不存在,参数和局部变量实际上是float32或float64。但是它有一些先例,并且他们首先考虑这个问题的可能原因是,英特尔处理器中的内部FPU寄存器是80位。这是英特尔设计8087协处理器时许多月前做出的设计决定。

这个想法在纸面上听起来非常好,它允许以更高的精度存储中间计算结果,因此计算的最终结果可能更准确。然而毫无疑问,英特尔的十亿美元错误,FPU无法优化,仍然允许一致的浮点结果。问题在于内部FPU寄存器是有限的资源,其中只有8个。它也被实现为堆栈,处理起来非常尴尬。如果涉及计算,则不可避免地需要将中间结果溢出到存储器中。将80位值截断为64位。如果计算容易丢失很多有效数字,那么对代码进行小的更改会在计算结果中产生很大的差异。或者通常会扰乱程序员,因为第16位不一样。

嗯,大错,以及SO的大量问题的根源。当英特尔实施下一代浮点硬件时,该想法被废弃,XMM和YMM寄存器为64位。真正的寄存器,而不是堆栈。 x64抖动使用它们。使程序在64位模式下运行会产生与在32位模式下运行时不同的结果。还需要十年才能停止伤害。