diff --git a/eng/Subsets.props b/eng/Subsets.props
index 29d7467e6b43e7..cbe9cfc7d73c99 100644
--- a/eng/Subsets.props
+++ b/eng/Subsets.props
@@ -119,7 +119,9 @@
- true
+ <_NativeAotSupportedOS Condition="'$(TargetOS)' == 'windows' or '$(TargetOS)' == 'linux' or '$(TargetOS)' == 'osx' or '$(TargetOS)' == 'maccatalyst' or '$(TargetOS)' == 'iossimulator' or '$(TargetOS)' == 'ios' or '$(TargetOS)' == 'tvossimulator' or '$(TargetOS)' == 'tvos' or '$(TargetOS)' == 'freebsd'">true
+ <_NativeAotSupportedArch Condition="'$(TargetArchitecture)' == 'x64' or '$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm' or ('$(TargetOS)' == 'windows' and '$(TargetArchitecture)' == 'x86')">true
+ true
true
diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt
index 1c314d9bf624e0..4aa45914ff54b0 100644
--- a/src/coreclr/CMakeLists.txt
+++ b/src/coreclr/CMakeLists.txt
@@ -147,7 +147,7 @@ add_subdirectory(tools/aot/jitinterface)
if(NOT CLR_CROSS_COMPONENTS_BUILD)
# NativeAOT only buildable for a subset of CoreCLR-supported configurations
- if(CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_AMD64 OR CLR_CMAKE_HOST_ARCH_ARM)
+ if(CLR_CMAKE_HOST_ARCH_ARM64 OR CLR_CMAKE_HOST_ARCH_AMD64 OR CLR_CMAKE_HOST_ARCH_ARM OR (CLR_CMAKE_HOST_ARCH_I386 AND CLR_CMAKE_HOST_WIN32))
add_subdirectory(nativeaot)
endif()
endif(NOT CLR_CROSS_COMPONENTS_BUILD)
diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/Unsafe.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/Unsafe.cs
index 7f3df7a7893a2b..341cd832604715 100644
--- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/Unsafe.cs
+++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/Unsafe.cs
@@ -129,5 +129,15 @@ public static void CopyBlock(void* destination, void* source, uint byteCount)
{
throw new PlatformNotSupportedException();
}
+
+ ///
+ /// Copies bytes from the source address to the destination address.
+ ///
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void CopyBlock(ref byte destination, ref readonly byte source, uint byteCount)
+ {
+ throw new PlatformNotSupportedException();
+ }
}
}
diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs
index 486e5c3e3b1c7f..8f5098ab31adcd 100644
--- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs
+++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs
@@ -156,10 +156,6 @@ internal static int RhEndNoGCRegion()
[RuntimeImport(Redhawk.BaseName, "RhpGcSafeZeroMemory")]
internal static extern unsafe ref byte RhpGcSafeZeroMemory(ref byte dmem, nuint size);
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- [RuntimeImport(Redhawk.BaseName, "memmove")]
- internal static extern unsafe void* memmove(byte* dmem, byte* smem, nuint size);
-
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(Redhawk.BaseName, "RhBulkMoveWithWriteBarrier")]
internal static extern unsafe void RhBulkMoveWithWriteBarrier(ref byte dmem, ref byte smem, nuint size);
diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs
index 31fb19ea36b995..378fabf56836f0 100644
--- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs
+++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs
@@ -114,9 +114,7 @@ public static unsafe object RhBox(MethodTable* pEEType, ref byte data)
}
else
{
- fixed (byte* pFields = &result.GetRawData())
- fixed (byte* pData = &dataAdjustedForNullable)
- InternalCalls.memmove(pFields, pData, pEEType->ValueTypeSize);
+ Unsafe.CopyBlock(ref result.GetRawData(), ref dataAdjustedForNullable, pEEType->ValueTypeSize);
}
return result;
@@ -271,9 +269,7 @@ public static unsafe void RhUnbox(object? obj, ref byte data, MethodTable* pUnbo
else
{
// Copy the boxed fields into the new location.
- fixed (byte *pData = &data)
- fixed (byte* pFields = &fields)
- InternalCalls.memmove(pData, pFields, pEEType->ValueTypeSize);
+ Unsafe.CopyBlock(ref data, ref fields, pEEType->ValueTypeSize);
}
}
diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h
index 02473e873aaabe..e9e62638813ba9 100644
--- a/src/coreclr/nativeaot/Runtime/CommonMacros.h
+++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h
@@ -17,7 +17,7 @@
#define STDCALL
#endif
-#define REDHAWK_CALLCONV FASTCALL
+#define F_CALL_CONV FASTCALL
#define QCALLTYPE
#ifdef _MSC_VER
@@ -219,6 +219,42 @@ typedef uint8_t CODE_LOCATION;
_Pragma(FCALL_XSTRINGIFY(comment (linker, FCALL_DECL_ALTNAME(FCALL_METHOD_NAME_((__VA_ARGS__)), FCALL_ARGHELPER_STACKSIZE(__VA_ARGS__)))))
#define FCIMPL_RENAME(_rettype, ...) \
_Pragma(FCALL_XSTRINGIFY(comment (linker, FCALL_IMPL_ALTNAME(FCALL_METHOD_NAME_((__VA_ARGS__)), FCALL_ARGHELPER_STACKSIZE(__VA_ARGS__)))))
+#define FCIMPL_RENAME_ARGSIZE(_rettype, _method, _argSize) \
+ _Pragma(FCALL_XSTRINGIFY(comment (linker, FCALL_XSTRINGIFY(/alternatename:_method=@_method##_FCall@_argSize))))
+
+#define FCIMPL1_F(_rettype, _method, a) \
+ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 4) \
+ EXTERN_C _rettype F_CALL_CONV _method##_FCall (a) \
+ {
+#define FCIMPL1_D(_rettype, _method, a) \
+ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \
+ EXTERN_C _rettype F_CALL_CONV _method##_FCall (a) \
+ {
+#define FCIMPL1_L FCIMPL1_D
+#define FCIMPL2_FF(_rettype, _method, a, b) \
+ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \
+ EXTERN_C _rettype F_CALL_CONV _method##_FCall (b, a) \
+ {
+#define FCIMPL2_DD(_rettype, _method, a, b) \
+ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 16) \
+ EXTERN_C _rettype F_CALL_CONV _method##_FCall (b, a) \
+ {
+#define FCIMPL2_FI(_rettype, _method, a, b) \
+ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \
+ EXTERN_C _rettype F_CALL_CONV _method##_FCall (a, b) \
+ {
+#define FCIMPL2_DI(_rettype, _method, a, b) \
+ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 12) \
+ EXTERN_C _rettype F_CALL_CONV _method##_FCall (a, b) \
+ {
+#define FCIMPL3_FFF(_rettype, _method, a, b, c) \
+ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 12) \
+ EXTERN_C _rettype F_CALL_CONV _method##_FCall (c, b, a) \
+ {
+#define FCIMPL3_DDD(_rettype, _method, a, b, c) \
+ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 24) \
+ EXTERN_C _rettype F_CALL_CONV _method##_FCall (c, b, a) \
+ {
#else
@@ -228,11 +264,37 @@ typedef uint8_t CODE_LOCATION;
#define FCALL_METHOD_ARGS(dummy, ...) (__VA_ARGS__)
#define FCALL_METHOD_ARGS_(tuple) FCALL_METHOD_ARGS tuple
+#define FCIMPL1_F(_rettype, _method, a) \
+ EXTERN_C _rettype F_CALL_CONV _method (a) \
+ {
+#define FCIMPL1_D(_rettype, _method, a) \
+ EXTERN_C _rettype F_CALL_CONV _method (a) \
+ {
+#define FCIMPL1_L FCIMPL1_D
+#define FCIMPL2_FF(_rettype, _method, a, b) \
+ EXTERN_C _rettype F_CALL_CONV _method (a, b) \
+ {
+#define FCIMPL2_DD(_rettype, _method, a, b) \
+ EXTERN_C _rettype F_CALL_CONV _method (a, b) \
+ {
+#define FCIMPL2_FI(_rettype, _method, a, b) \
+ EXTERN_C _rettype F_CALL_CONV _method (a, b) \
+ {
+#define FCIMPL2_DI(_rettype, _method, a, b) \
+ EXTERN_C _rettype F_CALL_CONV _method (a, b) \
+ {
+#define FCIMPL3_FFF(_rettype, _method, a, b, c) \
+ EXTERN_C _rettype F_CALL_CONV _method (a, b, c) \
+ {
+#define FCIMPL3_DDD(_rettype, _method, a, b, c) \
+ EXTERN_C _rettype F_CALL_CONV _method (a, b, c) \
+ {
+
#endif
#define FCDECL_(_rettype, ...) \
FCDECL_RENAME(_rettype, __VA_ARGS__) \
- EXTERN_C _rettype REDHAWK_CALLCONV FCALL_METHOD_NAME_((__VA_ARGS__)) FCALL_METHOD_ARGS_((__VA_ARGS__))
+ EXTERN_C _rettype F_CALL_CONV FCALL_METHOD_NAME_((__VA_ARGS__)) FCALL_METHOD_ARGS_((__VA_ARGS__))
#define FCDECL0(_rettype, _method) FCDECL_(_rettype, _method)
#define FCDECL1(_rettype, _method, a) FCDECL_(_rettype, _method, a)
#define FCDECL2(_rettype, _method, a, b) FCDECL_(_rettype, _method, a, b)
@@ -242,7 +304,7 @@ typedef uint8_t CODE_LOCATION;
#define FCIMPL_(_rettype, ...) \
FCIMPL_RENAME(_rettype, __VA_ARGS__) \
- EXTERN_C _rettype REDHAWK_CALLCONV FCALL_METHOD_NAME_((__VA_ARGS__)) FCALL_METHOD_ARGS_((__VA_ARGS__)) \
+ EXTERN_C _rettype F_CALL_CONV FCALL_METHOD_NAME_((__VA_ARGS__)) FCALL_METHOD_ARGS_((__VA_ARGS__)) \
{
#define FCIMPL0(_rettype, _method) FCIMPL_(_rettype, _method)
#define FCIMPL1(_rettype, _method, a) FCIMPL_(_rettype, _method, a)
diff --git a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp
index 6dbfb11b3e597e..c440aced22dd95 100644
--- a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp
+++ b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp
@@ -309,7 +309,23 @@ EXTERN_C void* RhpRethrow2 = NULL;
#endif
EXTERN_C CODE_LOCATION RhpAssignRefAVLocation;
+#if defined(HOST_X86)
+EXTERN_C CODE_LOCATION RhpAssignRefEAXAVLocation;
+EXTERN_C CODE_LOCATION RhpAssignRefECXAVLocation;
+EXTERN_C CODE_LOCATION RhpAssignRefEBXAVLocation;
+EXTERN_C CODE_LOCATION RhpAssignRefESIAVLocation;
+EXTERN_C CODE_LOCATION RhpAssignRefEDIAVLocation;
+EXTERN_C CODE_LOCATION RhpAssignRefEBPAVLocation;
+#endif
EXTERN_C CODE_LOCATION RhpCheckedAssignRefAVLocation;
+#if defined(HOST_X86)
+EXTERN_C CODE_LOCATION RhpCheckedAssignRefEAXAVLocation;
+EXTERN_C CODE_LOCATION RhpCheckedAssignRefECXAVLocation;
+EXTERN_C CODE_LOCATION RhpCheckedAssignRefEBXAVLocation;
+EXTERN_C CODE_LOCATION RhpCheckedAssignRefESIAVLocation;
+EXTERN_C CODE_LOCATION RhpCheckedAssignRefEDIAVLocation;
+EXTERN_C CODE_LOCATION RhpCheckedAssignRefEBPAVLocation;
+#endif
EXTERN_C CODE_LOCATION RhpCheckedLockCmpXchgAVLocation;
EXTERN_C CODE_LOCATION RhpCheckedXchgAVLocation;
#if !defined(HOST_AMD64) && !defined(HOST_ARM64)
@@ -335,13 +351,31 @@ static bool InWriteBarrierHelper(uintptr_t faultingIP)
static uintptr_t writeBarrierAVLocations[] =
{
(uintptr_t)&RhpAssignRefAVLocation,
+#if defined(HOST_X86)
+ (uintptr_t)&RhpAssignRefEAXAVLocation,
+ (uintptr_t)&RhpAssignRefECXAVLocation,
+ (uintptr_t)&RhpAssignRefEBXAVLocation,
+ (uintptr_t)&RhpAssignRefESIAVLocation,
+ (uintptr_t)&RhpAssignRefEDIAVLocation,
+ (uintptr_t)&RhpAssignRefEBPAVLocation,
+#endif
(uintptr_t)&RhpCheckedAssignRefAVLocation,
+#if defined(HOST_X86)
+ (uintptr_t)&RhpCheckedAssignRefEAXAVLocation,
+ (uintptr_t)&RhpCheckedAssignRefECXAVLocation,
+ (uintptr_t)&RhpCheckedAssignRefEBXAVLocation,
+ (uintptr_t)&RhpCheckedAssignRefESIAVLocation,
+ (uintptr_t)&RhpCheckedAssignRefEDIAVLocation,
+ (uintptr_t)&RhpCheckedAssignRefEBPAVLocation,
+#endif
(uintptr_t)&RhpCheckedLockCmpXchgAVLocation,
(uintptr_t)&RhpCheckedXchgAVLocation,
#if !defined(HOST_AMD64) && !defined(HOST_ARM64)
+#if !defined(HOST_X86)
(uintptr_t)&RhpLockCmpXchg8AVLocation,
(uintptr_t)&RhpLockCmpXchg16AVLocation,
(uintptr_t)&RhpLockCmpXchg32AVLocation,
+#endif
(uintptr_t)&RhpLockCmpXchg64AVLocation,
#endif
(uintptr_t)&RhpByRefAssignRefAVLocation1,
diff --git a/src/coreclr/nativeaot/Runtime/GCHelpers.cpp b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp
index 88ad22aa2e90d9..7f6b1a08627faa 100644
--- a/src/coreclr/nativeaot/Runtime/GCHelpers.cpp
+++ b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp
@@ -418,12 +418,11 @@ FCIMPL0(int64_t, RhGetTotalAllocatedBytes)
}
FCIMPLEND
-FCIMPL2(void, RhEnumerateConfigurationValues, void* configurationContext, ConfigurationValueFunc callback)
+EXTERN_C void QCALLTYPE RhEnumerateConfigurationValues(void* configurationContext, ConfigurationValueFunc callback)
{
IGCHeap* pHeap = GCHeapUtilities::GetGCHeap();
pHeap->EnumerateConfigurationValues(configurationContext, callback);
}
-FCIMPLEND
GCHeapHardLimitInfo g_gcHeapHardLimitInfo;
bool g_gcHeapHardLimitInfoSpecified = false;
@@ -563,7 +562,7 @@ static Object* GcAllocInternal(MethodTable* pEEType, uint32_t uFlags, uintptr_t
// numElements - number of array elements
// pTransitionFrame- transition frame to make stack crawlable
// Returns a pointer to the object allocated or NULL on failure.
-EXTERN_C void* REDHAWK_CALLCONV RhpGcAlloc(MethodTable* pEEType, uint32_t uFlags, uintptr_t numElements, PInvokeTransitionFrame* pTransitionFrame)
+EXTERN_C void* F_CALL_CONV RhpGcAlloc(MethodTable* pEEType, uint32_t uFlags, uintptr_t numElements, PInvokeTransitionFrame* pTransitionFrame)
{
Thread* pThread = ThreadStore::GetCurrentThread();
@@ -702,7 +701,7 @@ EXTERN_C UInt32_BOOL g_fGcStressStarted;
UInt32_BOOL g_fGcStressStarted = UInt32_FALSE; // UInt32_BOOL because asm code reads it
// static
-EXTERN_C void REDHAWK_CALLCONV RhpStressGc()
+EXTERN_C void F_CALL_CONV RhpStressGc()
{
// The GarbageCollect operation below may trash the last win32 error. We save the error here so that it can be
// restored after the GC operation;
diff --git a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp
index 930c200a344411..9c4220ef5a7eed 100644
--- a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp
+++ b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp
@@ -9,7 +9,7 @@
// Floating point and 64-bit integer math helpers.
//
-EXTERN_C uint64_t REDHAWK_CALLCONV RhpDbl2ULng(double val)
+FCIMPL1_D(uint64_t, RhpDbl2ULng, double val)
{
const double two63 = 2147483648.0 * 4294967296.0;
uint64_t ret;
@@ -24,12 +24,13 @@ EXTERN_C uint64_t REDHAWK_CALLCONV RhpDbl2ULng(double val)
}
return ret;
}
+FCIMPLEND
#undef min
#undef max
#include
-EXTERN_C float REDHAWK_CALLCONV RhpFltRem(float dividend, float divisor)
+FCIMPL2_FF(float, RhpFltRem, float dividend, float divisor)
{
//
// From the ECMA standard:
@@ -53,8 +54,9 @@ EXTERN_C float REDHAWK_CALLCONV RhpFltRem(float dividend, float divisor)
// else...
return fmodf(dividend,divisor);
}
+FCIMPLEND
-EXTERN_C double REDHAWK_CALLCONV RhpDblRem(double dividend, double divisor)
+FCIMPL2_DD(double, RhpDblRem, double dividend, double divisor)
{
//
// From the ECMA standard:
@@ -77,99 +79,304 @@ EXTERN_C double REDHAWK_CALLCONV RhpDblRem(double dividend, double divisor)
// else...
return(fmod(dividend,divisor));
}
+FCIMPLEND
-#ifdef HOST_ARM
-EXTERN_C int32_t REDHAWK_CALLCONV RhpIDiv(int32_t i, int32_t j)
+#ifndef HOST_64BIT
+EXTERN_C int64_t QCALLTYPE RhpLDiv(int64_t i, int64_t j)
{
ASSERT(j && "Divide by zero!");
return i / j;
}
-EXTERN_C uint32_t REDHAWK_CALLCONV RhpUDiv(uint32_t i, uint32_t j)
+EXTERN_C uint64_t QCALLTYPE RhpULDiv(uint64_t i, uint64_t j)
{
ASSERT(j && "Divide by zero!");
return i / j;
}
-EXTERN_C int64_t REDHAWK_CALLCONV RhpLDiv(int64_t i, int64_t j)
+EXTERN_C int64_t QCALLTYPE RhpLMod(int64_t i, int64_t j)
{
ASSERT(j && "Divide by zero!");
- return i / j;
+ return i % j;
}
-EXTERN_C uint64_t REDHAWK_CALLCONV RhpULDiv(uint64_t i, uint64_t j)
+EXTERN_C uint64_t QCALLTYPE RhpULMod(uint64_t i, uint64_t j)
{
ASSERT(j && "Divide by zero!");
- return i / j;
+ return i % j;
}
-EXTERN_C int32_t REDHAWK_CALLCONV RhpIMod(int32_t i, int32_t j)
+FCIMPL1_D(int64_t, RhpDbl2Lng, double val)
{
- ASSERT(j && "Divide by zero!");
- return i % j;
+ return (int64_t)val;
}
+FCIMPLEND
-EXTERN_C uint32_t REDHAWK_CALLCONV RhpUMod(uint32_t i, uint32_t j)
+FCIMPL1_D(int32_t, RhpDbl2Int, double val)
{
- ASSERT(j && "Divide by zero!");
- return i % j;
+ return (int32_t)val;
}
+FCIMPLEND
-EXTERN_C int64_t REDHAWK_CALLCONV RhpLMod(int64_t i, int64_t j)
+FCIMPL1_D(uint32_t, RhpDbl2UInt, double val)
{
- ASSERT(j && "Divide by zero!");
- return i % j;
+ return (uint32_t)val;
}
+FCIMPLEND
-EXTERN_C uint64_t REDHAWK_CALLCONV RhpULMod(uint64_t i, uint64_t j)
+FCIMPL1_L(double, RhpLng2Dbl, int64_t val)
{
- ASSERT(j && "Divide by zero!");
- return i % j;
+ return (double)val;
}
+FCIMPLEND
-EXTERN_C int64_t REDHAWK_CALLCONV RhpLMul(int64_t i, int64_t j)
+FCIMPL1_L(double, RhpULng2Dbl, uint64_t val)
{
- return i * j;
+ return (double)val;
}
+FCIMPLEND
+
+#endif
-EXTERN_C uint64_t REDHAWK_CALLCONV RhpLRsz(uint64_t i, int32_t j)
+#ifdef HOST_ARM
+EXTERN_C int32_t F_CALL_CONV RhpIDiv(int32_t i, int32_t j)
{
- return i >> (j & 0x3f);
+ ASSERT(j && "Divide by zero!");
+ return i / j;
}
-EXTERN_C int64_t REDHAWK_CALLCONV RhpLRsh(int64_t i, int32_t j)
+EXTERN_C uint32_t F_CALL_CONV RhpUDiv(uint32_t i, uint32_t j)
{
- return i >> (j & 0x3f);
+ ASSERT(j && "Divide by zero!");
+ return i / j;
}
-EXTERN_C int64_t REDHAWK_CALLCONV RhpLLsh(int64_t i, int32_t j)
+EXTERN_C int32_t F_CALL_CONV RhpIMod(int32_t i, int32_t j)
{
- return i << (j & 0x3f);
+ ASSERT(j && "Divide by zero!");
+ return i % j;
}
-EXTERN_C int64_t REDHAWK_CALLCONV RhpDbl2Lng(double val)
+EXTERN_C uint32_t F_CALL_CONV RhpUMod(uint32_t i, uint32_t j)
{
- return (int64_t)val;
+ ASSERT(j && "Divide by zero!");
+ return i % j;
}
-EXTERN_C int32_t REDHAWK_CALLCONV RhpDbl2Int(double val)
+EXTERN_C int64_t F_CALL_CONV RhpLMul(int64_t i, int64_t j)
{
- return (int32_t)val;
+ return i * j;
}
-EXTERN_C uint32_t REDHAWK_CALLCONV RhpDbl2UInt(double val)
+EXTERN_C uint64_t F_CALL_CONV RhpLRsz(uint64_t i, int32_t j)
{
- return (uint32_t)val;
+ return i >> (j & 0x3f);
}
-EXTERN_C double REDHAWK_CALLCONV RhpLng2Dbl(int64_t val)
+EXTERN_C int64_t F_CALL_CONV RhpLRsh(int64_t i, int32_t j)
{
- return (double)val;
+ return i >> (j & 0x3f);
}
-EXTERN_C double REDHAWK_CALLCONV RhpULng2Dbl(uint64_t val)
+EXTERN_C int64_t F_CALL_CONV RhpLLsh(int64_t i, int32_t j)
{
- return (double)val;
+ return i << (j & 0x3f);
}
#endif // HOST_ARM
+
+#ifdef HOST_X86
+
+FCIMPL1_D(double, acos, double x)
+ return std::acos(x);
+FCIMPLEND
+
+FCIMPL1_F(float, acosf, float x)
+ return std::acosf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, acosh, double x)
+ return std::acosh(x);
+FCIMPLEND
+
+FCIMPL1_F(float, acoshf, float x)
+ return std::acoshf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, asin, double x)
+ return std::asin(x);
+FCIMPLEND
+
+FCIMPL1_F(float, asinf, float x)
+ return std::asinf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, asinh, double x)
+ return std::asinh(x);
+FCIMPLEND
+
+FCIMPL1_F(float, asinhf, float x)
+ return std::asinhf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, atan, double x)
+ return std::atan(x);
+FCIMPLEND
+
+FCIMPL1_F(float, atanf, float x)
+ return std::atanf(x);
+FCIMPLEND
+
+FCIMPL2_DD(double, atan2, double x, double y)
+ return std::atan2(x, y);
+FCIMPLEND
+
+FCIMPL2_FF(float, atan2f, float x, float y)
+ return std::atan2f(x, y);
+FCIMPLEND
+
+FCIMPL1_D(double, atanh, double x)
+ return std::atanh(x);
+FCIMPLEND
+
+FCIMPL1_F(float, atanhf, float x)
+ return std::atanhf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, cbrt, double x)
+ return std::cbrt(x);
+FCIMPLEND
+
+FCIMPL1_F(float, cbrtf, float x)
+ return std::cbrtf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, ceil, double x)
+ return std::ceil(x);
+FCIMPLEND
+
+FCIMPL1_F(float, ceilf, float x)
+ return std::ceilf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, cos, double x)
+ return std::cos(x);
+FCIMPLEND
+
+FCIMPL1_F(float, cosf, float x)
+ return std::cosf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, cosh, double x)
+ return std::cosh(x);
+FCIMPLEND
+
+FCIMPL1_F(float, coshf, float x)
+ return std::coshf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, exp, double x)
+ return std::exp(x);
+FCIMPLEND
+
+FCIMPL1_F(float, expf, float x)
+ return std::expf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, floor, double x)
+ return std::floor(x);
+FCIMPLEND
+
+FCIMPL1_F(float, floorf, float x)
+ return std::floorf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, log, double x)
+ return std::log(x);
+FCIMPLEND
+
+FCIMPL1_F(float, logf, float x)
+ return std::logf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, log2, double x)
+ return std::log2(x);
+FCIMPLEND
+
+FCIMPL1_F(float, log2f, float x)
+ return std::log2f(x);
+FCIMPLEND
+
+FCIMPL1_D(double, log10, double x)
+ return std::log10(x);
+FCIMPLEND
+
+FCIMPL1_F(float, log10f, float x)
+ return std::log10f(x);
+FCIMPLEND
+
+FCIMPL2_DD(double, pow, double x, double y)
+ return std::pow(x, y);
+FCIMPLEND
+
+FCIMPL2_FF(float, powf, float x, float y)
+ return std::powf(x, y);
+FCIMPLEND
+
+FCIMPL1_D(double, sin, double x)
+ return std::sin(x);
+FCIMPLEND
+
+FCIMPL1_F(float, sinf, float x)
+ return std::sinf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, sinh, double x)
+ return std::sinh(x);
+FCIMPLEND
+
+FCIMPL1_F(float, sinhf, float x)
+ return std::sinhf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, sqrt, double x)
+ return std::sqrt(x);
+FCIMPLEND
+
+FCIMPL1_F(float, sqrtf, float x)
+ return std::sqrtf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, tan, double x)
+ return std::tan(x);
+FCIMPLEND
+
+FCIMPL1_F(float, tanf, float x)
+ return std::tanf(x);
+FCIMPLEND
+
+FCIMPL1_D(double, tanh, double x)
+ return std::tanh(x);
+FCIMPLEND
+
+FCIMPL1_F(float, tanhf, float x)
+ return std::tanhf(x);
+FCIMPLEND
+
+FCIMPL3_DDD(double, fma, double x, double y, double z)
+ return std::fma(x, y, z);
+FCIMPLEND
+
+FCIMPL3_FFF(float, fmaf, float x, float y, float z)
+ return std::fmaf(x, y, z);
+FCIMPLEND
+
+FCIMPL2_DI(double, modf, double x, double* intptr)
+ return std::modf(x, intptr);
+FCIMPLEND
+
+FCIMPL2_FI(float, modff, float x, float* intptr)
+ return std::modff(x, intptr);
+FCIMPLEND
+
+#endif
diff --git a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp
index 47f0decdcfd5fd..6189b606880105 100644
--- a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp
+++ b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp
@@ -411,9 +411,8 @@ FCIMPL2(uint32_t, RhGetKnobValues, char *** pResultKeys, char *** pResultValues)
FCIMPLEND
#if defined(TARGET_X86) || defined(TARGET_AMD64)
-FCIMPL3(void, RhCpuIdEx, int* cpuInfo, int functionId, int subFunctionId)
+EXTERN_C void QCALLTYPE RhCpuIdEx(int* cpuInfo, int functionId, int subFunctionId)
{
__cpuidex(cpuInfo, functionId, subFunctionId);
}
-FCIMPLEND
#endif
diff --git a/src/coreclr/nativeaot/Runtime/RestrictedCallouts.h b/src/coreclr/nativeaot/Runtime/RestrictedCallouts.h
index fe6a3977397a34..2c1a2e61e0951b 100644
--- a/src/coreclr/nativeaot/Runtime/RestrictedCallouts.h
+++ b/src/coreclr/nativeaot/Runtime/RestrictedCallouts.h
@@ -97,6 +97,6 @@ class RestrictedCallouts
static CrstStatic s_sLock;
// Prototypes for the callouts.
- typedef void (REDHAWK_CALLCONV * GcRestrictedCallbackFunction)(uint32_t uiCondemnedGeneration);
+ typedef void (F_CALL_CONV * GcRestrictedCallbackFunction)(uint32_t uiCondemnedGeneration);
typedef CLR_BOOL (* HandleTableRestrictedCallbackFunction)(Object * pObject);
};
diff --git a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp
index 0d827ad498129c..708356c2e3a909 100644
--- a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp
+++ b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp
@@ -350,7 +350,7 @@ bool RuntimeInstance::ShouldHijackCallsiteForGcStress(uintptr_t CallsiteIP)
}
#ifdef FEATURE_CACHED_INTERFACE_DISPATCH
-EXTERN_C void REDHAWK_CALLCONV RhpInitialDynamicInterfaceDispatch();
+EXTERN_C void F_CALL_CONV RhpInitialDynamicInterfaceDispatch();
FCIMPL2(void *, RhNewInterfaceDispatchCell, MethodTable * pInterface, int32_t slotNumber)
{
diff --git a/src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc b/src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc
index f5e0d73f20631a..896bf8e67dab53 100644
--- a/src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc
+++ b/src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc
@@ -160,6 +160,7 @@ RhpStressGc equ @RhpStressGc@0
RhpGcPoll2 equ @RhpGcPoll2@4
RhHandleGet equ @RhHandleGet@4
RhpGcSafeZeroMemory equ @RhpGcSafeZeroMemory@8
+RhpGetNumThunkBlocksPerMapping equ @RhpGetNumThunkBlocksPerMapping@0
ifdef FEATURE_GC_STRESS
THREAD__HIJACKFORGCSTRESS equ ?HijackForGcStress@Thread@@SGXPAUPAL_LIMITED_CONTEXT@@@Z
@@ -177,14 +178,15 @@ EXTERN RhThrowEx : PROC
EXTERN RhRethrow : PROC
EXTERN RhpGcPoll2 : PROC
-;; The following two imports are not used in the assembly helpers. Due to the
+;; The following imports are not used in the assembly helpers. Due to the
;; way the FCall mangling is handled in the C sources through linker directives
;; (see FCIMPL macro definitions in CommonMacros.h), we need to add dummy
-;; references to some methods in two object files (HandleTableHelpers and
-;; GCMemoryHelpers) to get the linker to see the #pragma comment(linker, ...)
-;; directives embedded in those files.
+;; references to some methods in few object files (HandleTableHelpers and
+;; GCMemoryHelpers, ThunkMapping) to get the linker to see the #pragma
+;; comment(linker, ...) directives embedded in those files.
EXTERN RhHandleGet : PROC
EXTERN RhpGcSafeZeroMemory : PROC
+EXTERN RhpGetNumThunkBlocksPerMapping : PROC
ifdef FEATURE_GC_STRESS
EXTERN THREAD__HIJACKFORGCSTRESS : PROC
diff --git a/src/coreclr/nativeaot/Runtime/i386/Interlocked.asm b/src/coreclr/nativeaot/Runtime/i386/Interlocked.asm
index f9599b1b8666e3..9bce4da5c223dc 100644
--- a/src/coreclr/nativeaot/Runtime/i386/Interlocked.asm
+++ b/src/coreclr/nativeaot/Runtime/i386/Interlocked.asm
@@ -1,3 +1,32 @@
-;; TODO: Implement
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+
+ .586
+ .xmm
+ .model flat
+ option casemap:none
+ .code
+
+include AsmMacros.inc
+
+FASTCALL_FUNC RhpLockCmpXchg64, 20
+
+_value$ = 16
+_comparand$ = 8
+
+ mov eax, DWORD PTR _comparand$[esp-4]
+ mov edx, DWORD PTR _comparand$[esp]
+ push ebx
+ mov ebx, DWORD PTR _value$[esp]
+ push esi
+ mov esi, ecx
+ mov ecx, DWORD PTR _value$[esp+8]
+ALTERNATE_ENTRY _RhpLockCmpXchg64AVLocation
+ lock cmpxchg8b QWORD PTR [esi]
+ pop esi
+ pop ebx
+ ret 16
+
+FASTCALL_ENDFUNC
end
diff --git a/src/coreclr/nativeaot/Runtime/i386/InteropThunksHelpers.asm b/src/coreclr/nativeaot/Runtime/i386/InteropThunksHelpers.asm
index c8181f34da8e6e..f786fa592987d9 100644
--- a/src/coreclr/nativeaot/Runtime/i386/InteropThunksHelpers.asm
+++ b/src/coreclr/nativeaot/Runtime/i386/InteropThunksHelpers.asm
@@ -68,7 +68,8 @@ LEAF_ENTRY RhCommonStub, _TEXT
;; store thunk address in thread static
mov edx, [eax]
mov eax, [eax + POINTER_SIZE] ;; eax <- target slot data
- mov [ecx + OFFSET ThunkParamSlot], edx ;; ThunkParamSlot <- context slot data
+ add ecx, SECTIONREL ThunkParamSlot
+ mov [ecx], edx ;; ThunkParamSlot <- context slot data
;; restore the regs we used
pop edx
@@ -95,7 +96,8 @@ FASTCALL_FUNC RhGetCurrentThunkContext, 0
mov ecx, [__tls_index]
mov edx, fs:[__tls_array]
mov ecx, [edx + ecx * POINTER_SIZE]
- mov eax, [ecx + OFFSET ThunkParamSlot] ;; eax <- ThunkParamSlot
+ add ecx, SECTIONREL ThunkParamSlot
+ mov eax, [ecx] ;; eax <- ThunkParamSlot
ret
FASTCALL_ENDFUNC
diff --git a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm
index d997859cc368da..ac4b9c511cef14 100644
--- a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm
+++ b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm
@@ -39,4 +39,156 @@ ProbeLoop:
RhpStackProbe ENDP
+;; *********************************************************************/
+;; LLsh - long shift left
+;;
+;; Purpose:
+;; Does a Long Shift Left (signed and unsigned are identical)
+;; Shifts a long left any number of bits.
+;;
+;; Entry:
+;; EDX:EAX - long value to be shifted
+;; ECX - number of bits to shift by
+;;
+;; Exit:
+;; EDX:EAX - shifted value
+;;
+;; NOTE: Adapted from JIT_LLsh in CoreCLR
+;;
+RhpLLsh PROC public
+ ;; Reduce shift amount mod 64
+ and ecx, 63
+
+ cmp ecx, 32
+ jae LLshMORE32
+
+ ;; Handle shifts of between bits 0 and 31
+ shld edx, eax, cl
+ shl eax, cl
+ ret
+
+LLshMORE32:
+ ;; Handle shifts of between bits 32 and 63
+ ;; The x86 shift instructions only use the lower 5 bits.
+ mov edx, eax
+ xor eax, eax
+ shl edx, cl
+ ret
+RhpLLsh ENDP
+
+;; *********************************************************************/
+;; LRsh - long shift right
+;;
+;; Purpose:
+;; Does a signed Long Shift Right
+;; Shifts a long right any number of bits.
+;;
+;; Entry:
+;; EDX:EAX - long value to be shifted
+;; ECX - number of bits to shift by
+;;
+;; Exit:
+;; EDX:EAX - shifted value
+;;
+;; NOTE: Adapted from JIT_LRsh in CoreCLR
+;;
+RhpLRsh PROC public
+ ;; Reduce shift amount mod 64
+ and ecx, 63
+
+ cmp ecx, 32
+ jae LRshMORE32
+
+ ;; Handle shifts of between bits 0 and 31
+ shrd eax, edx, cl
+ sar edx, cl
+ ret
+
+LRshMORE32:
+ ;; Handle shifts of between bits 32 and 63
+ ;; The x86 shift instructions only use the lower 5 bits.
+ mov eax, edx
+ sar edx, 31
+ sar eax, cl
+ ret
+RhpLRsh ENDP
+
+;; *********************************************************************/
+;; LRsz
+;;
+;; Purpose:
+;; Does a unsigned Long Shift Right
+;; Shifts a long right any number of bits.
+;;
+;; Entry:
+;; EDX:EAX - long value to be shifted
+;; ECX - number of bits to shift by
+;;
+;; Exit:
+;; EDX:EAX - shifted value
+;;
+;; NOTE: Adapted from JIT_LRsz in CoreCLR
+;;
+RhpLRsz PROC public
+ ;; Reduce shift amount mod 64
+ and ecx, 63
+
+ cmp ecx, 32
+ jae LRszMORE32
+
+ ;; Handle shifts of between bits 0 and 31
+ shrd eax, edx, cl
+ shr edx, cl
+ ret
+
+LRszMORE32:
+ ;; Handle shifts of between bits 32 and 63
+ ;; The x86 shift instructions only use the lower 5 bits.
+ mov eax, edx
+ xor edx, edx
+ shr eax, cl
+ ret
+RhpLRsz ENDP
+
+;; *********************************************************************/
+;; LMul
+;;
+;; Purpose:
+;; Does a long multiply (same for signed/unsigned)
+;;
+;; Entry:
+;; Parameters are passed on the stack:
+;; 1st pushed: multiplier (QWORD)
+;; 2nd pushed: multiplicand (QWORD)
+;;
+;; Exit:
+;; EDX:EAX - product of multiplier and multiplicand
+;;
+;; NOTE: Adapted from JIT_LMul in CoreCLR
+;;
+RhpLMul PROC public
+ mov eax, dword ptr [esp + 8] ; AHI
+ mov ecx, dword ptr [esp + 16] ; BHI
+ or ecx, eax ; test for both hiwords zero.
+ mov ecx, dword ptr [esp + 12] ; BLO
+ jnz LMul_hard ; both are zero, just mult ALO and BLO
+
+ mov eax, dword ptr [esp + 4]
+ mul ecx
+ ret 16
+
+LMul_hard:
+ push ebx
+ mul ecx ; eax has AHI, ecx has BLO, so AHI * BLO
+ mov ebx, eax ; save result
+ mov eax, dword ptr [esp + 8] ; ALO
+ mul dword ptr [esp + 20] ; ALO * BHI
+ add ebx, eax ; ebx = ((ALO * BHI) + (AHI * BLO))
+ mov eax, dword ptr [esp + 8] ; ALO ;ecx = BLO
+ mul ecx ; so edx:eax = ALO*BLO
+ add edx, ebx ; now edx has all the LO*HI stuff
+ pop ebx
+ ret 16
+RhpLMul ENDP
+
end
diff --git a/src/coreclr/nativeaot/Runtime/i386/PInvoke.asm b/src/coreclr/nativeaot/Runtime/i386/PInvoke.asm
index 90f0d083a842a2..7e03d12c580818 100644
--- a/src/coreclr/nativeaot/Runtime/i386/PInvoke.asm
+++ b/src/coreclr/nativeaot/Runtime/i386/PInvoke.asm
@@ -6,7 +6,34 @@
option casemap:none
.code
-
include AsmMacros.inc
+FASTCALL_FUNC RhpPInvoke, 4
+ INLINE_GETTHREAD eax, edx
+
+ mov edx, [esp] ; edx <- return address
+ mov dword ptr [ecx + OFFSETOF__PInvokeTransitionFrame__m_pThread], eax
+ mov dword ptr [ecx + OFFSETOF__PInvokeTransitionFrame__m_FramePointer], ebp
+ mov dword ptr [ecx + OFFSETOF__PInvokeTransitionFrame__m_RIP], edx
+
+ lea edx, [esp + 4] ; edx <- caller SP
+ mov dword ptr [ecx + OFFSETOF__PInvokeTransitionFrame__m_Flags], PTFF_SAVE_RSP
+ mov dword ptr [ecx + OFFSETOF__PInvokeTransitionFrame__m_PreservedRegs], edx
+
+ mov dword ptr [eax + OFFSETOF__Thread__m_pTransitionFrame], ecx
+
+ ret
+FASTCALL_ENDFUNC
+
+FASTCALL_FUNC RhpPInvokeReturn, 4
+ mov edx, [ecx + OFFSETOF__PInvokeTransitionFrame__m_pThread]
+ mov dword ptr [edx + OFFSETOF__Thread__m_pTransitionFrame], 0
+ cmp [RhpTrapThreads], TrapThreadsFlags_None
+ jne @F ; forward branch - predicted not taken
+ ret
+@@:
+ ; passing transition frame pointer in rcx
+ jmp RhpWaitForGC2
+FASTCALL_ENDFUNC
+
end
diff --git a/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm b/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm
index d5a1d1367ef09c..86dd2807fbc8aa 100644
--- a/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm
+++ b/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm
@@ -31,16 +31,17 @@ endm
DEFINE_INTERFACE_DISPATCH_STUB macro entries
StubName textequ @CatStr( _RhpInterfaceDispatch, entries, <@0> )
+StubAVLocation textequ @CatStr( _RhpInterfaceDispatchAVLocation, entries )
StubName proc public
;; Check the instance here to catch null references. We're going to touch it again below (to cache
;; the MethodTable pointer), but that's after we've pushed ebx below, and taking an A/V there will
- ;; mess up the stack trace for debugging. We also don't have a spare scratch register (eax holds
- ;; the cache pointer and the push of ebx below is precisely so we can access a second register
- ;; to hold the MethodTable pointer).
- test ecx, ecx
- je RhpInterfaceDispatchNullReference
+ ;; mess up the stack trace. We also don't have a spare scratch register (eax holds the cache pointer
+ ;; and the push of ebx below is precisely so we can access a second register to hold the MethodTable
+ ;; pointer).
+ ALTERNATE_ENTRY StubAVLocation
+ cmp dword ptr [ecx], ecx
;; eax currently contains the indirection cell address. We need to update it to point to the cache
;; block instead.
@@ -94,15 +95,6 @@ RhpInterfaceDispatchSlow proc
jmp _RhpUniversalTransition_DebugStepTailCall@0
RhpInterfaceDispatchSlow endp
-;; Out of line helper used when we try to interface dispatch on a null pointer. Sets up the stack so the
-;; debugger gives a reasonable stack trace.
-RhpInterfaceDispatchNullReference proc public
- push ebp
- mov ebp, esp
- mov ebx, [ecx] ;; This should A/V
- int 3
-RhpInterfaceDispatchNullReference endp
-
;; Stub dispatch routine for dispatch to a vtable slot
_RhpVTableOffsetDispatch@0 proc public
;; eax currently contains the indirection cell address. We need to update it to point to the vtable offset (which is in the m_pCache field)
@@ -122,6 +114,11 @@ _RhpVTableOffsetDispatch@0 endp
;; Initial dispatch on an interface when we don't have a cache yet.
FASTCALL_FUNC RhpInitialDynamicInterfaceDispatch, 0
ALTERNATE_ENTRY _RhpInitialInterfaceDispatch
+ ;; Trigger an AV if we're dispatching on a null this.
+ ;; The exception handling infrastructure is aware of the fact that this is the first
+ ;; instruction of RhpInitialInterfaceDispatch and uses it to translate an AV here
+ ;; to a NullReferenceException at the callsite.
+ cmp dword ptr [ecx], ecx
jmp RhpInterfaceDispatchSlow
FASTCALL_ENDFUNC
diff --git a/src/coreclr/nativeaot/Runtime/interoplibinterface.h b/src/coreclr/nativeaot/Runtime/interoplibinterface.h
index da57618b3f7896..fce04b81f90249 100644
--- a/src/coreclr/nativeaot/Runtime/interoplibinterface.h
+++ b/src/coreclr/nativeaot/Runtime/interoplibinterface.h
@@ -6,11 +6,11 @@
class ObjCMarshalNative
{
public:
- using TryGetCallback = void*(REDHAWK_CALLCONV *)(void);
- using TryGetTaggedMemoryCallback = CLR_BOOL(REDHAWK_CALLCONV *)(_In_ Object *, _Out_ void **);
- using BeginEndCallback = void(REDHAWK_CALLCONV *)(void);
- using IsReferencedCallback = int(REDHAWK_CALLCONV *)(_In_ void*);
- using EnteredFinalizationCallback = void(REDHAWK_CALLCONV *)(_In_ void*);
+ using TryGetCallback = void*(F_CALL_CONV *)(void);
+ using TryGetTaggedMemoryCallback = CLR_BOOL(F_CALL_CONV *)(_In_ Object *, _Out_ void **);
+ using BeginEndCallback = void(F_CALL_CONV *)(void);
+ using IsReferencedCallback = int(F_CALL_CONV *)(_In_ void*);
+ using EnteredFinalizationCallback = void(F_CALL_CONV *)(_In_ void*);
public: // Instance inspection
static bool IsTrackedReference(_In_ Object * pObject, _Out_ bool* isReferenced);
diff --git a/src/coreclr/nativeaot/Runtime/portable.cpp b/src/coreclr/nativeaot/Runtime/portable.cpp
index 7907791d4dbdfd..d797ad14687ba0 100644
--- a/src/coreclr/nativeaot/Runtime/portable.cpp
+++ b/src/coreclr/nativeaot/Runtime/portable.cpp
@@ -33,7 +33,7 @@
#include "GCMemoryHelpers.inl"
#if defined(USE_PORTABLE_HELPERS)
-EXTERN_C void* REDHAWK_CALLCONV RhpGcAlloc(MethodTable *pEEType, uint32_t uFlags, uintptr_t numElements, void * pTransitionFrame);
+EXTERN_C void* F_CALL_CONV RhpGcAlloc(MethodTable *pEEType, uint32_t uFlags, uintptr_t numElements, void * pTransitionFrame);
static Object* AllocateObject(MethodTable* pEEType, uint32_t uFlags, uintptr_t numElements)
{
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
index 9f597e151d550f..e5bfe42e497694 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
@@ -359,24 +359,23 @@ internal static unsafe void FixupMethodCell(IntPtr hModule, MethodFixupCell* pCe
if (charSetMangling == 0)
{
// Look for the user-provided entry point name only
- pTarget = Interop.Kernel32.GetProcAddress(hModule, methodName);
+ pTarget = GetProcAddressWithMangling(hModule, methodName, pCell);
}
- else
- if (charSetMangling == CharSet.Ansi)
+ else if (charSetMangling == CharSet.Ansi)
{
// For ANSI, look for the user-provided entry point name first.
// If that does not exist, try the charset suffix.
- pTarget = Interop.Kernel32.GetProcAddress(hModule, methodName);
+ pTarget = GetProcAddressWithMangling(hModule, methodName, pCell);
if (pTarget == IntPtr.Zero)
- pTarget = GetProcAddressWithSuffix(hModule, methodName, (byte)'A');
+ pTarget = GetProcAddressWithSuffix(hModule, methodName, (byte)'A', pCell);
}
else
{
// For Unicode, look for the entry point name with the charset suffix first.
// The 'W' API takes precedence over the undecorated one.
- pTarget = GetProcAddressWithSuffix(hModule, methodName, (byte)'W');
+ pTarget = GetProcAddressWithSuffix(hModule, methodName, (byte)'W', pCell);
if (pTarget == IntPtr.Zero)
- pTarget = Interop.Kernel32.GetProcAddress(hModule, methodName);
+ pTarget = GetProcAddressWithMangling(hModule, methodName, pCell);
}
#else
pTarget = Interop.Sys.GetProcAddress(hModule, methodName);
@@ -391,23 +390,43 @@ internal static unsafe void FixupMethodCell(IntPtr hModule, MethodFixupCell* pCe
}
#if TARGET_WINDOWS
- private static unsafe IntPtr GetProcAddressWithSuffix(IntPtr hModule, byte* methodName, byte suffix)
+ private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* methodName, MethodFixupCell* pCell)
+ {
+ IntPtr pMethod = Interop.Kernel32.GetProcAddress(hModule, methodName);
+#if TARGET_X86
+ if (pMethod == IntPtr.Zero && pCell->IsStdcall)
+ {
+ int nameLength = string.strlen(methodName);
+ // We need to add an extra bytes for the prefix, null terminator and stack size suffix:
+ // - 1 byte for '_' prefix
+ // - 1 byte for '@' suffix
+ // - up to 10 bytes for digits (maximum positive number representable by uint)
+ // - 1 byte for NULL termination character
+ byte* probedMethodName = stackalloc byte[nameLength + 13];
+ probedMethodName[0] = (byte)'_';
+ Unsafe.CopyBlock(probedMethodName + 1, methodName, (uint)nameLength);
+ probedMethodName[nameLength + 1] = (byte)'@';
+ pCell->SignatureBytes.TryFormat(new Span(probedMethodName + 2 + nameLength, 10), out int bytesWritten);
+ probedMethodName[nameLength + 2 + bytesWritten] = 0;
+ pMethod = Interop.Kernel32.GetProcAddress(hModule, probedMethodName);
+ }
+#else
+ _ = pCell;
+#endif
+ return pMethod;
+ }
+
+ private static unsafe IntPtr GetProcAddressWithSuffix(IntPtr hModule, byte* methodName, byte suffix, MethodFixupCell* pCell)
{
int nameLength = string.strlen(methodName);
// We need to add an extra byte for the suffix, and an extra byte for the null terminator
byte* probedMethodName = stackalloc byte[nameLength + 2];
-
- for (int i = 0; i < nameLength; i++)
- {
- probedMethodName[i] = methodName[i];
- }
-
- probedMethodName[nameLength + 1] = 0;
-
+ Unsafe.CopyBlock(probedMethodName, methodName, (uint)nameLength);
probedMethodName[nameLength] = suffix;
+ probedMethodName[nameLength + 1] = 0;
- return Interop.Kernel32.GetProcAddress(hModule, probedMethodName);
+ return GetProcAddressWithMangling(hModule, probedMethodName, pCell);
}
#endif
@@ -625,11 +644,16 @@ internal unsafe struct MethodFixupCell
public IntPtr Target;
public IntPtr MethodName;
public ModuleFixupCell* Module;
- private int Flags;
+ private uint Flags;
public CharSet CharSetMangling => (CharSet)(Flags & MethodFixupCellFlagsConstants.CharSetMask);
+#if FEATURE_OBJCMARSHAL
public bool IsObjectiveCMessageSend => (Flags & MethodFixupCellFlagsConstants.IsObjectiveCMessageSendMask) != 0;
- public int ObjectiveCMessageSendFunction => (Flags & MethodFixupCellFlagsConstants.ObjectiveCMessageSendFunctionMask) >> MethodFixupCellFlagsConstants.ObjectiveCMessageSendFunctionShift;
+ public int ObjectiveCMessageSendFunction => (int)((Flags & MethodFixupCellFlagsConstants.ObjectiveCMessageSendFunctionMask) >> MethodFixupCellFlagsConstants.ObjectiveCMessageSendFunctionShift);
+#elif TARGET_WINDOWS && TARGET_X86
+ public bool IsStdcall => (Flags & MethodFixupCellFlagsConstants.IsStdcall) != 0;
+ public ushort SignatureBytes => (ushort)(Flags >> 16);
+#endif
}
internal unsafe struct CustomMarshallerKey : IEquatable
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
index 7175ea9c00cbe2..85fef043acb0e1 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
@@ -4,6 +4,7 @@
using System;
using System.Runtime;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using Internal.Runtime;
@@ -13,7 +14,7 @@ namespace Internal.Runtime.CompilerHelpers
/// Math helpers for generated code. The helpers marked with [RuntimeExport] and the type
/// itself need to be public because they constitute a public contract with the .NET Native toolchain.
///
- internal static class MathHelpers
+ internal static partial class MathHelpers
{
#if !TARGET_64BIT
//
@@ -144,9 +145,9 @@ public static ulong ULMulOvf(ulong i, ulong j)
return ThrowULngOvf();
}
- [RuntimeImport(RuntimeLibrary, "RhpULMod")]
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern ulong RhpULMod(ulong i, ulong j);
+ [LibraryImport(RuntimeLibrary)]
+ [SuppressGCTransition]
+ private static partial ulong RhpULMod(ulong i, ulong j);
public static ulong ULMod(ulong i, ulong j)
{
@@ -156,9 +157,9 @@ public static ulong ULMod(ulong i, ulong j)
return RhpULMod(i, j);
}
- [RuntimeImport(RuntimeLibrary, "RhpLMod")]
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern long RhpLMod(long i, long j);
+ [LibraryImport(RuntimeLibrary)]
+ [SuppressGCTransition]
+ private static partial long RhpLMod(long i, long j);
public static long LMod(long i, long j)
{
@@ -170,9 +171,9 @@ public static long LMod(long i, long j)
return RhpLMod(i, j);
}
- [RuntimeImport(RuntimeLibrary, "RhpULDiv")]
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern ulong RhpULDiv(ulong i, ulong j);
+ [LibraryImport(RuntimeLibrary)]
+ [SuppressGCTransition]
+ private static partial ulong RhpULDiv(ulong i, ulong j);
public static ulong ULDiv(ulong i, ulong j)
{
@@ -182,9 +183,9 @@ public static ulong ULDiv(ulong i, ulong j)
return RhpULDiv(i, j);
}
- [RuntimeImport(RuntimeLibrary, "RhpLDiv")]
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern long RhpLDiv(long i, long j);
+ [LibraryImport(RuntimeLibrary)]
+ [SuppressGCTransition]
+ private static partial long RhpLDiv(long i, long j);
public static long LDiv(long i, long j)
{
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
index a07cbef77c58b6..98604bc58561be 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
@@ -669,257 +669,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe
[RuntimeImport(RuntimeLibrary, "RhpCheckedXchg")]
internal static extern object InterlockedExchange([NotNullIfNotNull(nameof(value))] ref object? location1, object? value);
-#if TARGET_X86
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double acos(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float acosf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double acosh(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float acoshf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double asin(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float asinf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double asinh(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float asinhf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double atan(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float atanf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double atan2(double y, double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float atan2f(float y, float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double atanh(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float atanhf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double cbrt(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float cbrtf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double ceil(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float ceilf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double cos(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float cosf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double cosh(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float coshf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double exp(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float expf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double floor(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float floorf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double log(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float logf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double log2(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float log2f(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double log10(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float log10f(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double pow(double x, double y);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float powf(float x, float y);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double sin(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float sinf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double sinh(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float sinhf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double sqrt(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float sqrtf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double tan(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float tanf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double tanh(double x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float tanhf(float x);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double fmod(double x, double y);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float fmodf(float x, float y);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial double fma(double x, double y, double z);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static partial float fmaf(float x, float y, float z);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static unsafe partial double modf(double x, double* intptr);
-
- [LibraryImport(RuntimeImports.RuntimeLibrary)]
- [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
- [SuppressGCTransition]
- internal static unsafe partial float modff(float x, float* intptr);
-#else
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "acos")]
internal static extern double acos(double x);
@@ -1119,7 +868,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "modff")]
internal static extern unsafe float modff(float x, float* intptr);
-#endif
[LibraryImport(RuntimeImports.RuntimeLibrary)]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
diff --git a/src/coreclr/tools/Common/Internal/Runtime/RuntimeConstants.cs b/src/coreclr/tools/Common/Internal/Runtime/RuntimeConstants.cs
index 1c4a195a21d3d2..8ce74a03072b4d 100644
--- a/src/coreclr/tools/Common/Internal/Runtime/RuntimeConstants.cs
+++ b/src/coreclr/tools/Common/Internal/Runtime/RuntimeConstants.cs
@@ -73,5 +73,8 @@ internal static class MethodFixupCellFlagsConstants
public const int IsObjectiveCMessageSendMask = 0x8;
public const int ObjectiveCMessageSendFunctionMask = 0x70;
public const int ObjectiveCMessageSendFunctionShift = 4;
+ // Uses the same bit as IsObjectiveCMessageSendMask since we never have
+ // TARGET_X86 and FEATURE_OBJCMARSHAL used at the same time.
+ public const int IsStdcall = 0x8;
}
}
diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
index e9d7adc4ad0e72..4621ebc0e465e1 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
@@ -300,17 +300,17 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams)
if (!_pInvokeILEmitterConfiguration.GenerateDirectCall(_targetMethod, out _))
{
+ MethodSignature nativeSig = new MethodSignature(
+ MethodSignatureFlags.Static | MethodSignatureFlags.UnmanagedCallingConvention, 0, nativeReturnType, nativeParameterTypes,
+ _targetMethod.GetPInvokeMethodCallingConventions().EncodeAsEmbeddedSignatureData(context));
+
MetadataType lazyHelperType = context.GetHelperType("InteropHelpers");
- FieldDesc lazyDispatchCell = _interopStateManager.GetPInvokeLazyFixupField(_targetMethod);
+ FieldDesc lazyDispatchCell = _interopStateManager.GetPInvokeLazyFixupField(_targetMethod, nativeSig);
fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell));
fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType
.GetKnownMethod("ResolvePInvoke", null)));
- MethodSignature nativeSig = new MethodSignature(
- MethodSignatureFlags.Static | MethodSignatureFlags.UnmanagedCallingConvention, 0, nativeReturnType, nativeParameterTypes,
- _targetMethod.GetPInvokeMethodCallingConventions().EncodeAsEmbeddedSignatureData(context));
-
ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(context
.GetWellKnownType(WellKnownType.IntPtr));
diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs
index b74dc75b46dee7..b14891312fa43d 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs
@@ -16,12 +16,14 @@ public sealed partial class PInvokeLazyFixupField : FieldDesc
{
private readonly DefType _owningType;
private readonly MethodDesc _targetMethod;
+ private readonly MethodSignature _nativeSignature;
- public PInvokeLazyFixupField(DefType owningType, MethodDesc targetMethod)
+ public PInvokeLazyFixupField(DefType owningType, MethodDesc targetMethod, MethodSignature nativeSignature)
{
Debug.Assert(targetMethod.IsPInvoke);
_owningType = owningType;
_targetMethod = targetMethod;
+ _nativeSignature = nativeSignature;
}
public MethodDesc TargetMethod
@@ -32,6 +34,14 @@ public MethodDesc TargetMethod
}
}
+ public MethodSignature NativeSignature
+ {
+ get
+ {
+ return _nativeSignature;
+ }
+ }
+
public PInvokeMetadata PInvokeMetadata
{
get
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
index 7b0cf61350ab7d..565a890b2de7b3 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
@@ -949,7 +949,7 @@ internal static bool ShouldCheckForPendingException(TargetDetails target, PInvok
&& metadata.Name.StartsWith(ObjectiveCMsgSend);
}
- internal static int? GetObjectiveCMessageSendFunction(TargetDetails target, string pinvokeModule, string pinvokeFunction)
+ internal static uint? GetObjectiveCMessageSendFunction(TargetDetails target, string pinvokeModule, string pinvokeFunction)
{
if (!target.IsApplePlatform || pinvokeModule != ObjectiveCLibrary)
return null;
@@ -957,11 +957,11 @@ internal static bool ShouldCheckForPendingException(TargetDetails target, PInvok
#pragma warning disable CA1416
return pinvokeFunction switch
{
- "objc_msgSend" => (int)ObjectiveCMarshal.MessageSendFunction.MsgSend,
- "objc_msgSend_fpret" => (int)ObjectiveCMarshal.MessageSendFunction.MsgSendFpret,
- "objc_msgSend_stret" => (int)ObjectiveCMarshal.MessageSendFunction.MsgSendStret,
- "objc_msgSendSuper" => (int)ObjectiveCMarshal.MessageSendFunction.MsgSendSuper,
- "objc_msgSendSuper_stret" => (int)ObjectiveCMarshal.MessageSendFunction.MsgSendSuperStret,
+ "objc_msgSend" => (uint)ObjectiveCMarshal.MessageSendFunction.MsgSend,
+ "objc_msgSend_fpret" => (uint)ObjectiveCMarshal.MessageSendFunction.MsgSendFpret,
+ "objc_msgSend_stret" => (uint)ObjectiveCMarshal.MessageSendFunction.MsgSendStret,
+ "objc_msgSendSuper" => (uint)ObjectiveCMarshal.MessageSendFunction.MsgSendSuper,
+ "objc_msgSendSuper_stret" => (uint)ObjectiveCMarshal.MessageSendFunction.MsgSendSuperStret,
_ => null,
};
#pragma warning restore CA1416
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs
index f8a3ea39640662..7147f65cbb681f 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs
@@ -180,9 +180,9 @@ public TypeDesc GetInlineArrayType(InlineArrayCandidate candidate)
return _inlineArrayHashtable.GetOrCreateValue(candidate);
}
- public FieldDesc GetPInvokeLazyFixupField(MethodDesc method)
+ public FieldDesc GetPInvokeLazyFixupField(MethodDesc method, MethodSignature nativeSig)
{
- return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method);
+ return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(new (method, nativeSig));
}
public MethodDesc GetPInvokeCalliStub(MethodSignature signature, ModuleDesc moduleContext)
@@ -446,11 +446,19 @@ public PInvokeDelegateWrapperHashtable(InteropStateManager interopStateManager,
}
}
- private sealed class PInvokeLazyFixupFieldHashtable : LockFreeReaderHashtable
+ private readonly struct PInvokeLazyFixupFieldKey
{
- protected override int GetKeyHashCode(MethodDesc key)
+ public readonly MethodDesc Method;
+ public readonly MethodSignature NativeSignature;
+ public PInvokeLazyFixupFieldKey(MethodDesc method, MethodSignature nativeSignature)
+ => (Method, NativeSignature) = (method, nativeSignature);
+ }
+
+ private sealed class PInvokeLazyFixupFieldHashtable : LockFreeReaderHashtable
+ {
+ protected override int GetKeyHashCode(PInvokeLazyFixupFieldKey key)
{
- return key.GetHashCode();
+ return key.Method.GetHashCode();
}
protected override int GetValueHashCode(PInvokeLazyFixupField value)
@@ -458,9 +466,9 @@ protected override int GetValueHashCode(PInvokeLazyFixupField value)
return value.TargetMethod.GetHashCode();
}
- protected override bool CompareKeyToValue(MethodDesc key, PInvokeLazyFixupField value)
+ protected override bool CompareKeyToValue(PInvokeLazyFixupFieldKey key, PInvokeLazyFixupField value)
{
- return key == value.TargetMethod;
+ return key.Method == value.TargetMethod;
}
protected override bool CompareValueToValue(PInvokeLazyFixupField value1, PInvokeLazyFixupField value2)
@@ -468,9 +476,9 @@ protected override bool CompareValueToValue(PInvokeLazyFixupField value1, PInvok
return value1.TargetMethod == value2.TargetMethod;
}
- protected override PInvokeLazyFixupField CreateValueFromKey(MethodDesc key)
+ protected override PInvokeLazyFixupField CreateValueFromKey(PInvokeLazyFixupFieldKey key)
{
- return new PInvokeLazyFixupField(_owningType, key);
+ return new PInvokeLazyFixupField(_owningType, key.Method, key.NativeSignature);
}
private readonly DefType _owningType;
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
index 5a477f9fd84f45..866c5d0341bf55 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
@@ -77,25 +77,33 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
// Module fixup cell
builder.EmitPointerReloc(factory.PInvokeModuleFixup(_pInvokeMethodData.ModuleData));
- int flags = 0;
+ uint flags = 0;
- int charsetFlags = (int)_pInvokeMethodData.CharSetMangling;
+ uint charsetFlags = (uint)_pInvokeMethodData.CharSetMangling;
Debug.Assert((charsetFlags & MethodFixupCellFlagsConstants.CharSetMask) == charsetFlags);
charsetFlags &= MethodFixupCellFlagsConstants.CharSetMask;
flags |= charsetFlags;
- int? objcFunction = MarshalHelpers.GetObjectiveCMessageSendFunction(factory.Target, _pInvokeMethodData.ModuleData.ModuleName, _pInvokeMethodData.EntryPointName);
+ uint? objcFunction = MarshalHelpers.GetObjectiveCMessageSendFunction(factory.Target, _pInvokeMethodData.ModuleData.ModuleName, _pInvokeMethodData.EntryPointName);
if (objcFunction.HasValue)
{
flags |= MethodFixupCellFlagsConstants.IsObjectiveCMessageSendMask;
- int objcFunctionFlags = objcFunction.Value << MethodFixupCellFlagsConstants.ObjectiveCMessageSendFunctionShift;
+ uint objcFunctionFlags = objcFunction.Value << MethodFixupCellFlagsConstants.ObjectiveCMessageSendFunctionShift;
Debug.Assert((objcFunctionFlags & MethodFixupCellFlagsConstants.ObjectiveCMessageSendFunctionMask) == objcFunctionFlags);
objcFunctionFlags &= MethodFixupCellFlagsConstants.ObjectiveCMessageSendFunctionMask;
flags |= objcFunctionFlags;
}
+ else if (factory.Target.IsWindows && factory.Target.Architecture == TargetArchitecture.X86)
+ {
+ if (_pInvokeMethodData.SignatureBytes >= 0)
+ {
+ flags |= MethodFixupCellFlagsConstants.IsStdcall;
+ flags |= ((uint)_pInvokeMethodData.SignatureBytes << 16);
+ }
+ }
- builder.EmitInt(flags);
+ builder.EmitUInt(flags);
return builder.ToObjectData();
}
@@ -113,16 +121,19 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer
public readonly PInvokeModuleData ModuleData;
public readonly string EntryPointName;
public readonly CharSet CharSetMangling;
+ public readonly int SignatureBytes;
public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField)
{
PInvokeMetadata metadata = pInvokeLazyFixupField.PInvokeMetadata;
ModuleDesc declaringModule = ((MetadataType)pInvokeLazyFixupField.TargetMethod.OwningType).Module;
+ TargetDetails target = declaringModule.Context.Target;
+ EcmaMethod method = pInvokeLazyFixupField.TargetMethod as EcmaMethod;
CustomAttributeValue? decodedAttr = null;
// Look for DefaultDllImportSearchPath on the method
- if (pInvokeLazyFixupField.TargetMethod is EcmaMethod method)
+ if (method is not null)
{
decodedAttr = method.GetDecodedCustomAttribute("System.Runtime.InteropServices", "DefaultDllImportSearchPathsAttribute");
}
@@ -153,7 +164,7 @@ public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField)
EntryPointName = metadata.Name;
CharSet charSetMangling = default;
- if (declaringModule.Context.Target.IsWindows && !metadata.Flags.ExactSpelling)
+ if (target.IsWindows && !metadata.Flags.ExactSpelling)
{
// Mirror CharSet normalization from Marshaller.CreateMarshaller
bool isAnsi = metadata.Flags.CharSet switch
@@ -167,13 +178,26 @@ public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField)
charSetMangling = isAnsi ? CharSet.Ansi : CharSet.Unicode;
}
CharSetMangling = charSetMangling;
+
+ int signatureBytes = -1;
+ if (target.IsWindows && target.Architecture == TargetArchitecture.X86 && method is not null &&
+ (method.GetPInvokeMethodCallingConventions() & UnmanagedCallingConventions.CallingConventionMask) == UnmanagedCallingConventions.Stdcall)
+ {
+ signatureBytes = 0;
+ foreach (var p in pInvokeLazyFixupField.NativeSignature)
+ {
+ signatureBytes += AlignmentHelper.AlignUp(p.GetElementSize().AsInt, target.PointerSize);
+ }
+ }
+ SignatureBytes = signatureBytes;
}
public bool Equals(PInvokeMethodData other)
{
return ModuleData.Equals(other.ModuleData) &&
EntryPointName == other.EntryPointName &&
- CharSetMangling == other.CharSetMangling;
+ CharSetMangling == other.CharSetMangling &&
+ SignatureBytes == other.SignatureBytes;
}
public override bool Equals(object obj)
@@ -196,7 +220,11 @@ public int CompareTo(PInvokeMethodData other, CompilerComparer comparer)
if (moduleCompare != 0)
return moduleCompare;
- return CharSetMangling.CompareTo(other.CharSetMangling);
+ var charsetCompare = CharSetMangling.CompareTo(other.CharSetMangling);
+ if (charsetCompare != 0)
+ return charsetCompare;
+
+ return SignatureBytes.CompareTo(other.SignatureBytes);
}
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
@@ -209,6 +237,10 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
sb.Append("__");
sb.Append(CharSetMangling.ToString());
}
+ if (SignatureBytes >= 0)
+ {
+ sb.Append($"@{SignatureBytes}");
+ }
}
}
}
diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj
index bea5a3d9dd80a4..750819fc1fe28d 100644
--- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj
+++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj
@@ -14,6 +14,7 @@
false
false
false
+ false
false
true
diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj
index 522561c9c8a366..40879007dabbd0 100644
--- a/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj
+++ b/src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj
@@ -11,6 +11,7 @@
false
false
false
+ false
false
true
diff --git a/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj b/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj
index 0ea909b29cb70b..1fd766631b4a98 100644
--- a/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj
+++ b/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj
@@ -5,7 +5,8 @@
true
Guard
true
- true
+
+ true