Skip to content

Commit 0e30a6f

Browse files
On 64 bit platforms, "stelem.ref" and "ldelema" ignore the high bits of a native int index (#71571)
Add support for native int indices in stelem.ref and ldelema helper functions. This required changing the abi of these functions, which required bumping the major R2R version number. As we have already done that for .NET 7, this is a minor cost. Note that this is still broken on Mono, and that bug is #71656 Fixes #52817
1 parent f29ae44 commit 0e30a6f

File tree

13 files changed

+148
-18
lines changed

13 files changed

+148
-18
lines changed

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ internal struct ArrayElement
553553
[StackTraceHidden]
554554
[DebuggerStepThrough]
555555
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
556-
private static ref object? LdelemaRef(Array array, int index, void* type)
556+
private static ref object? LdelemaRef(Array array, nint index, void* type)
557557
{
558558
// this will throw appropriate exceptions if array is null or access is out of range.
559559
ref object? element = ref Unsafe.As<ArrayElement[]>(array)[index].Value;
@@ -569,7 +569,7 @@ internal struct ArrayElement
569569
[StackTraceHidden]
570570
[DebuggerStepThrough]
571571
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
572-
private static void StelemRef(Array array, int index, object? obj)
572+
private static void StelemRef(Array array, nint index, object? obj)
573573
{
574574
// this will throw appropriate exceptions if array is null or access is out of range.
575575
ref object? element = ref Unsafe.As<ArrayElement[]>(array)[index].Value;

src/coreclr/inc/jiteeversionguid.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
4343
#define GUID_DEFINED
4444
#endif // !GUID_DEFINED
4545

46-
constexpr GUID JITEEVersionIdentifier = { /* f2faa5fc-a1ec-4244-aebb-5597bfd7153a */
47-
0xf2faa5fc,
48-
0xa1ec,
49-
0x4244,
50-
{0xae, 0xbb, 0x55, 0x97, 0xbf, 0xd7, 0x15, 0x3a}
46+
constexpr GUID JITEEVersionIdentifier = { /* 0d853657-7a01-421f-b1b0-d22a8e691441 */
47+
0x0d853657,
48+
0x7a01,
49+
0x421f,
50+
{0xb1, 0xb0, 0xd2, 0x2a, 0x8e, 0x69, 0x14, 0x41}
5151
};
5252

5353
//////////////////////////////////////////////////////////////////////////////////////////////////////////

src/coreclr/inc/readytorun.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
#define READYTORUN_SIGNATURE 0x00525452 // 'RTR'
1616

1717
// Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs
18-
#define READYTORUN_MAJOR_VERSION 0x0006
19-
#define READYTORUN_MINOR_VERSION 0x0003
18+
#define READYTORUN_MAJOR_VERSION 0x0007
19+
#define READYTORUN_MINOR_VERSION 0x0000
2020

2121
#define MINIMUM_READYTORUN_MAJOR_VERSION 0x006
2222

@@ -401,6 +401,10 @@ enum ReadyToRunHelper
401401
READYTORUN_HELPER_StackProbe = 0x111,
402402

403403
READYTORUN_HELPER_GetCurrentManagedThreadId = 0x112,
404+
405+
// Array helpers for use with native ints
406+
READYTORUN_HELPER_Stelem_Ref_I = 0x113,
407+
READYTORUN_HELPER_Ldelema_Ref_I = 0x114,
404408
};
405409

406410
#include "readytoruninstructionset.h"

src/coreclr/jit/importer.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13711,7 +13711,24 @@ void Compiler::impImportBlockCode(BasicBlock* block)
1371113711
GenTree* type = op1;
1371213712
GenTree* index = impPopStack().val;
1371313713
GenTree* arr = impPopStack().val;
13714-
op1 = gtNewHelperCallNode(CORINFO_HELP_LDELEMA_REF, TYP_BYREF, arr, index, type);
13714+
#ifdef TARGET_64BIT
13715+
// The CLI Spec allows an array to be indexed by either an int32 or a native int.
13716+
// The array helper takes a native int for array length.
13717+
// So if we have an int, explicitly extend it to be a native int.
13718+
if (genActualType(index->TypeGet()) != TYP_I_IMPL)
13719+
{
13720+
if (index->IsIntegralConst())
13721+
{
13722+
index->gtType = TYP_I_IMPL;
13723+
}
13724+
else
13725+
{
13726+
bool isUnsigned = false;
13727+
index = gtNewCastNode(TYP_I_IMPL, index, isUnsigned, TYP_I_IMPL);
13728+
}
13729+
}
13730+
#endif // TARGET_64BIT
13731+
op1 = gtNewHelperCallNode(CORINFO_HELP_LDELEMA_REF, TYP_BYREF, arr, index, type);
1371513732
}
1371613733

1371713734
impPushOnStack(op1, tiRetVal);
@@ -13852,7 +13869,24 @@ void Compiler::impImportBlockCode(BasicBlock* block)
1385213869

1385313870
impPopStack(3);
1385413871

13855-
// Else call a helper function to do the assignment
13872+
// Else call a helper function to do the assignment
13873+
#ifdef TARGET_64BIT
13874+
// The CLI Spec allows an array to be indexed by either an int32 or a native int.
13875+
// The array helper takes a native int for array length.
13876+
// So if we have an int, explicitly extend it to be a native int.
13877+
if (genActualType(index->TypeGet()) != TYP_I_IMPL)
13878+
{
13879+
if (index->IsIntegralConst())
13880+
{
13881+
index->gtType = TYP_I_IMPL;
13882+
}
13883+
else
13884+
{
13885+
bool isUnsigned = false;
13886+
index = gtNewCastNode(TYP_I_IMPL, index, isUnsigned, TYP_I_IMPL);
13887+
}
13888+
}
13889+
#endif // TARGET_64BIT
1385613890
op1 = gtNewHelperCallNode(CORINFO_HELP_ARRADDR_ST, TYP_VOID, array, index, value);
1385713891
goto SPILL_APPEND;
1385813892
}

src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/Unsafe.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ public static ref T Add<T>(ref T source, int elementOffset)
9191
return ref AddByteOffset(ref source, (IntPtr)(elementOffset * (nint)SizeOf<T>()));
9292
}
9393

94+
/// <summary>
95+
/// Adds an element offset to the given reference.
96+
/// </summary>
97+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
98+
public static ref T Add<T>(ref T source, IntPtr elementOffset)
99+
{
100+
return ref AddByteOffset(ref source, (IntPtr)((nint)elementOffset * (nint)SizeOf<T>()));
101+
}
102+
94103
/// <summary>
95104
/// Reinterprets the given location as a reference to a value of type <typeparamref name="T"/>.
96105
/// </summary>

src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ internal struct ArrayElement
743743
// Array stelem/ldelema helpers with RyuJIT conventions
744744
//
745745
[RuntimeExport("RhpStelemRef")]
746-
public static unsafe void StelemRef(Array array, int index, object obj)
746+
public static unsafe void StelemRef(Array array, nint index, object obj)
747747
{
748748
// This is supported only on arrays
749749
Debug.Assert(array.GetMethodTable()->IsArray, "first argument must be an array");
@@ -814,7 +814,7 @@ private static unsafe void StelemRef_Helper(ref object element, MethodTable* ele
814814
}
815815

816816
[RuntimeExport("RhpLdelemaRef")]
817-
public static unsafe ref object LdelemaRef(Array array, int index, IntPtr elementType)
817+
public static unsafe ref object LdelemaRef(Array array, nint index, IntPtr elementType)
818818
{
819819
Debug.Assert(array.GetMethodTable()->IsArray, "first argument must be an array");
820820

src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ struct ReadyToRunHeaderConstants
1010
{
1111
static const uint32_t Signature = 0x00525452; // 'RTR'
1212

13-
static const uint32_t CurrentMajorVersion = 6;
13+
static const uint32_t CurrentMajorVersion = 7;
1414
static const uint32_t CurrentMinorVersion = 0;
1515
};
1616

src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ internal struct ReadyToRunHeaderConstants
1414
{
1515
public const uint Signature = 0x00525452; // 'RTR'
1616

17-
public const ushort CurrentMajorVersion = 6;
18-
public const ushort CurrentMinorVersion = 3;
17+
public const ushort CurrentMajorVersion = 7;
18+
public const ushort CurrentMinorVersion = 0;
1919
}
2020

2121
#pragma warning disable 0169

src/coreclr/vm/corelib.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,8 +1226,8 @@ DEFINE_METHOD(CASTHELPERS, CHKCASTINTERFACE, ChkCastInterface, SM_Ptr
12261226
DEFINE_METHOD(CASTHELPERS, CHKCASTCLASS, ChkCastClass, SM_PtrVoid_Obj_RetObj)
12271227
DEFINE_METHOD(CASTHELPERS, CHKCASTCLASSSPECIAL, ChkCastClassSpecial, SM_PtrVoid_Obj_RetObj)
12281228
DEFINE_METHOD(CASTHELPERS, UNBOX, Unbox, SM_PtrVoid_Obj_RetRefByte)
1229-
DEFINE_METHOD(CASTHELPERS, STELEMREF, StelemRef, SM_Array_Int_Obj_RetVoid)
1230-
DEFINE_METHOD(CASTHELPERS, LDELEMAREF, LdelemaRef, SM_Array_Int_PtrVoid_RetRefObj)
1229+
DEFINE_METHOD(CASTHELPERS, STELEMREF, StelemRef, SM_Array_IntPtr_Obj_RetVoid)
1230+
DEFINE_METHOD(CASTHELPERS, LDELEMAREF, LdelemaRef, SM_Array_IntPtr_PtrVoid_RetRefObj)
12311231

12321232
DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData)
12331233
DEFINE_FIELD_U(_highMemoryLoadThresholdBytes, GCMemoryInfoData, highMemLoadThresholdBytes)

src/coreclr/vm/metasig.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,8 @@ DEFINE_METASIG(GM(RetT, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, _, M(0)))
604604
DEFINE_METASIG_T(SM(Array_Int_Array_Int_Int_RetVoid, C(ARRAY) i C(ARRAY) i i, v))
605605
DEFINE_METASIG_T(SM(Array_Int_Obj_RetVoid, C(ARRAY) i j, v))
606606
DEFINE_METASIG_T(SM(Array_Int_PtrVoid_RetRefObj, C(ARRAY) i P(v), r(j)))
607+
DEFINE_METASIG_T(SM(Array_IntPtr_Obj_RetVoid, C(ARRAY) I j, v))
608+
DEFINE_METASIG_T(SM(Array_IntPtr_PtrVoid_RetRefObj, C(ARRAY) I P(v), r(j)))
607609

608610
DEFINE_METASIG(SM(Obj_IntPtr_Bool_RetVoid, j I F, v))
609611
DEFINE_METASIG(SM(IntPtr_Obj_RetVoid, I j, v))

0 commit comments

Comments
 (0)