When adding an int32
to a 64-bit native int
, does the CLR sign-extend or zero-extend the 32-bit integer? And most importantly: based on what information does it make this choice?
I am writing a .NET compiler and have read the ECMA specification throughly, but could not find an answer.
The CLI supports only a subset of these types in its operations upon values stored on its evaluation stack:
int32
,int64
, andnative int
.
-- ECMA 335, Section I 12.1: Supported data types
Since the values on the evaluation stack have no information on their signedness, instructions for which the signedness of the operands matter have two variants: one for signed and one for unsigned integers. The add
, sub
and mul
instructions (those that don't check for overflow) don't need to care about the signedness of the operands as long as the operands are the same size, and therefore have only a single variant. However, the operands are not always the same size...
ECMA 335, Section III 1.5: Operand type table states that an int32
and a native int
can be added, subtracted, multiplied and divided. The result is again a native int
. On a 64-bit system, a native int
is 64 bits wide.
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
So what would be the result here? Note that, according to the specification, the runtime does not need to track the exact types or the signedness of the values on the stack: it knows only int32
, int64
and native int
(and some others that are not relevant here).
I would imagine that IntPtr
and UIntPtr
arithmetic, since it is internally represented as native ints, would also use this kind of addition. However, ILSpy shows that adding an IntPtr
and an Int32
in C# calls the overloaded + operator on the IntPtr
class, which accepts only a signed Int32
argument.
Doing it directly in CIL (using the add
instruction) also indicates that the integer is interpreted as being signed. It should also have been implemented in Mono, but I could not find any references to back my findings up.