Cesium
Cesium copied to clipboard
Strange approach to `ldind`
Currently, PrimitiveType.cs
has the following code:
internal static readonly Dictionary<PrimitiveTypeKind, (OpCode load, OpCode store)> Opcodes = new()
{
{ PrimitiveTypeKind.Char, (OpCodes.Ldind_I1, OpCodes.Stind_I1) },
{ PrimitiveTypeKind.SignedChar, (OpCodes.Ldind_I1, OpCodes.Stind_I1) },
{ PrimitiveTypeKind.UnsignedChar, (OpCodes.Ldind_U1, OpCodes.Stind_I1) },
{ PrimitiveTypeKind.Short, (OpCodes.Ldind_I2, OpCodes.Stind_I2) },
{ PrimitiveTypeKind.UnsignedShort, (OpCodes.Ldind_I2, OpCodes.Stind_I2) },
{ PrimitiveTypeKind.Int, (OpCodes.Ldind_I4, OpCodes.Stind_I4) },
{ PrimitiveTypeKind.UnsignedInt, (OpCodes.Ldind_I4, OpCodes.Stind_I4) },
{ PrimitiveTypeKind.Float, (OpCodes.Ldind_R4, OpCodes.Stind_R4) },
{ PrimitiveTypeKind.Long, (OpCodes.Ldind_I8, OpCodes.Stind_I8) },
{ PrimitiveTypeKind.UnsignedLong, (OpCodes.Ldind_I8, OpCodes.Stind_I8) },
{ PrimitiveTypeKind.Double, (OpCodes.Ldind_R8, OpCodes.Stind_R8) }
};
Note how all the other unsigned types have same get operation as their signed counterparts, except UnsignedChar
that has OpCodes.Ldind_U1
.
In CIL, there are four unsigned ldind
operations: ldind.u1
, ldind.u2
, and ldind.u4
(notably, ldind.u8
is absent). And we don't use them and use the signed versions.
Another interesting part is that there are no stind.u*
operations: all the setters are always signed.
We should figure out if there's any visible difference between these operations, and either
- use the signed ones consistently for all the unsigned types
- or use the unsigned operations where available
A possible test case (in C# for explanation's sake, so we'll of course need to convert to C):
sbyte[] x = new[] { -1 };
sbyte y = x[0]; // 2
int z = (int)y; // 3
My hypothesis is that the int
cast in line 3 won't do anything actually, and thus its result will depend on whether the ldind
operation in line 2 does sign-extension or zero-extension of the sbyte
value in the array x
.