int32
向64 位添加 时native int
,CLR 是对 32 位整数进行符号扩展还是零扩展?最重要的是:根据什么信息做出这个选择?
我正在编写一个 .NET 编译器并已通读 ECMA 规范,但找不到答案。
CLI 在其对存储在其评估堆栈上的值的操作中仅支持这些类型的子集:
int32
、int64
和native int
。
-- ECMA 335,第 I 节 12.1:支持的数据类型
由于评估堆栈上的值没有关于其符号性的信息,因此操作数的符号性重要的指令有两种变体:一种用于有符号整数,另一种用于无符号整数。add
,sub
和指令(那些不检查溢出的mul
指令)不需要关心操作数的符号性,只要操作数大小相同,因此只有一个变体。但是,操作数并不总是相同的大小......
ECMA 335,第 III 节 1.5:操作数类型表规定 anint32
和 anative int
可以相加、相减、相乘和相除。结果又是一个native int
。在 64 位系统上,anative int
为 64 位宽。
ldc.i4.0 // Load int32 0
conv.i // Convert to (64-bit) native int
ldc.i4.m1 // Load int32 -1
add // Add native int 0 and int32 0xFFFFFFFF together
那么这里的结果是什么?请注意,根据规范,运行时不需要跟踪堆栈上值的确切类型或符号:它只知道int32
,int64
和native int
(以及其他一些与此无关的内容)。
我想算术IntPtr
,UIntPtr
因为它在内部表示为本地整数,也会使用这种加法。但是,ILSpy 表明在 C# 中添加 anIntPtr
和 anInt32
会调用类上的重载 + 运算符,该运算符IntPtr
仅接受带符号的Int32
参数。
直接在 CIL 中执行(使用add
指令)也表明整数被解释为有符号。它也应该在 Mono 中实现,但我找不到任何参考资料来支持我的发现。