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