From 8d01b3dedcb5506f030dd646a4b2309974626579 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 28 Feb 2024 16:49:19 +0100 Subject: [PATCH 01/32] Fix AV checks --- src/coreclr/nativeaot/Runtime/EHHelpers.cpp | 34 +++++++++++++++++++ .../nativeaot/Runtime/i386/StubDispatch.asm | 25 ++++++-------- 2 files changed, 45 insertions(+), 14 deletions(-) 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/i386/StubDispatch.asm b/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm index d5a1d1367ef09c..3901c883d9768d 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 byte ptr [ecx], 0 ;; 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 byte ptr [ecx], 0 jmp RhpInterfaceDispatchSlow FASTCALL_ENDFUNC From 59d83fb6cebd38884a42968b9eda9a4dedf8ae95 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 28 Feb 2024 16:49:41 +0100 Subject: [PATCH 02/32] Implement RhpLockCmpXchg64 --- .../nativeaot/Runtime/i386/Interlocked.asm | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) 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 From 456e06e5fc1ddf4de31bd63b0218b430441d03a3 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 28 Feb 2024 16:50:21 +0100 Subject: [PATCH 03/32] Fix accessing ThunkParamSlot --- src/coreclr/nativeaot/Runtime/i386/InteropThunksHelpers.asm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 From 2a0c2566f7465ad5ae32b63d5b4bd26ec1ff7616 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 28 Feb 2024 16:51:14 +0100 Subject: [PATCH 04/32] Implement P/Invoke asm helpers --- .../nativeaot/Runtime/i386/PInvoke.asm | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) 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 From 20fabf90b424aee047b991bf8d15e00a76f8bf46 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 28 Feb 2024 16:51:36 +0100 Subject: [PATCH 05/32] WIP: Math helpers --- .../nativeaot/Runtime/i386/MiscStubs.asm | 234 +++++++++++++++++- 1 file changed, 233 insertions(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm index d997859cc368da..410def8a9f3325 100644 --- a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm @@ -1,7 +1,8 @@ ;; Licensed to the .NET Foundation under one or more agreements. ;; The .NET Foundation licenses this file to you under the MIT license. - .586 + .686P + .XMM .model flat option casemap:none .code @@ -39,4 +40,235 @@ ProbeLoop: RhpStackProbe ENDP +;; *********************************************************************/ +;; llshl - long shift left +;; +;; Purpose: +;; Does a Long Shift Left (signed and unsigned are identical) +;; Shifts a long left any number of bits. +;; +;; NOTE: This routine has been adapted from the Microsoft CRTs. +;; +;; Entry: +;; EDX:EAX - long value to be shifted +;; ECX - number of bits to shift by +;; +;; Exit: +;; EDX:EAX - shifted value +;; +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. +;; +;; NOTE: This routine has been adapted from the Microsoft CRTs. +;; +;; Entry: +;; EDX:EAX - long value to be shifted +;; ECX - number of bits to shift by +;; +;; Exit: +;; EDX:EAX - shifted value +;; +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. +;; +;; NOTE: This routine has been adapted from the Microsoft CRTs. +;; +;; Entry: +;; EDX:EAX - long value to be shifted +;; ECX - number of bits to shift by +;; +;; Exit: +;; EDX:EAX - shifted value +;; +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 + +;; +;; Following helpers are unoptimized, forward to C library, and should +;; eventually be revisited. +;; + +EXTERN __dtol3 : PROC + +RhpDbl2Lng PROC public + movsd xmm0, qword ptr [esp+4] + call __dtol3 + ret 8 +RhpDbl2Lng ENDP + +RhpDbl2Int PROC public + movsd xmm0, qword ptr [esp+4] + cvttsd2si eax, xmm0 + ret 8 +RhpDbl2Int ENDP + +RhpDbl2UInt PROC public + movsd xmm0, qword ptr [esp+4] + call __dtol3 + ret 8 +RhpDbl2UInt ENDP + +;EXTERN __ltod3 : PROC + +RhpLng2Dbl PROC public + fild qword ptr [esp+4] + ;mov edx, dword ptr [esp+8] + ;mov ecx, dword ptr [esp+4] + ;call __ltod3 + ;movsd qword ptr [esp+4], xmm0 + ;fld qword ptr [esp+4] + ret 8 +RhpLng2Dbl ENDP + +EXTERN __ultod3 : PROC + +RhpULng2Dbl PROC public + mov edx, dword ptr [esp+8] + mov ecx, dword ptr [esp+4] + call __ultod3 + movsd qword ptr [esp+4], xmm0 + fld qword ptr [esp+4] + ret 8 +RhpULng2Dbl ENDP + +EXTERN __alldiv : PROC + +RhpLDiv PROC public + push dword ptr [esp+8] + push dword ptr [esp+8] + push dword ptr [esp+24] + push dword ptr [esp+24] + call __alldiv + ret 16 +RhpLDiv ENDP + +EXTERN __allrem : PROC + +RhpLMod PROC public + push dword ptr [esp+8] + push dword ptr [esp+8] + push dword ptr [esp+24] + push dword ptr [esp+24] + call __allrem + ret 16 +RhpLMod ENDP + +EXTERN __aulldiv : PROC + +RhpULDiv PROC public + push dword ptr [esp+8] + push dword ptr [esp+8] + push dword ptr [esp+24] + push dword ptr [esp+24] + call __aulldiv + ret 16 +RhpULDiv ENDP + +EXTERN __aullrem : PROC + +RhpULMod PROC public + push dword ptr [esp+8] + push dword ptr [esp+8] + push dword ptr [esp+24] + push dword ptr [esp+24] + call __aullrem + ret 16 +RhpULMod ENDP + +EXTERN __allmul : PROC + +RhpLMul PROC public + push dword ptr [esp+8] + push dword ptr [esp+8] + push dword ptr [esp+24] + push dword ptr [esp+24] + call __allmul + ret 16 +RhpLMul ENDP + +;; +;; https://github.com/dotnet/runtime/pull/98858 moves the following helpers to +;; managed code, so no need to optimize this +;; + +REDIRECT_FUNC macro ExportName, ImportName + EXTERN ImportName : PROC + + public ExportName + ExportName proc + jmp ImportName + ExportName endp +endm + +REDIRECT_FUNC RhpDbl2ULng, @RhpDbl2ULng@8 +REDIRECT_FUNC RhpFltRem, @RhpFltRem@8 +REDIRECT_FUNC RhpDblRem, @RhpDblRem@16 + end From e91de7169efb69c85eb624bee10a992074db4735 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 26 Feb 2024 10:42:43 +0100 Subject: [PATCH 06/32] Update runtime tests to work in win-x86 configuration Use explicit .def file to force the linker to strip the name mangling. Disable CFG test, the JIT doesn't support it on x86. --- .../SmokeTests/ComWrappers/CMakeLists.txt | 4 ++ .../ComWrappers/ComWrappersNative.def | 6 ++ .../ControlFlowGuard/ControlFlowGuard.csproj | 2 +- .../SmokeTests/PInvoke/CMakeLists.txt | 4 ++ .../SmokeTests/PInvoke/PInvokeNative.def | 56 +++++++++++++++++++ 5 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.def create mode 100644 src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.def diff --git a/src/tests/nativeaot/SmokeTests/ComWrappers/CMakeLists.txt b/src/tests/nativeaot/SmokeTests/ComWrappers/CMakeLists.txt index a631acce2c89d0..78d1de4ea17ee6 100644 --- a/src/tests/nativeaot/SmokeTests/ComWrappers/CMakeLists.txt +++ b/src/tests/nativeaot/SmokeTests/ComWrappers/CMakeLists.txt @@ -3,5 +3,9 @@ include_directories(${INC_PLATFORM_DIR}) add_library (ComWrappersNative SHARED ComWrappersNative.cpp) +if(CLR_CMAKE_HOST_WIN32) + target_link_options(ComWrappersNative PRIVATE /DEF:${CMAKE_CURRENT_SOURCE_DIR}/ComWrappersNative.def) +endif(CLR_CMAKE_HOST_WIN32) + # add the install targets install (TARGETS ComWrappersNative DESTINATION bin) diff --git a/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.def b/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.def new file mode 100644 index 00000000000000..a9168c4ebcaf6a --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.def @@ -0,0 +1,6 @@ +EXPORTS + BuildComPointer + CaptureComPointer + IsNULL + ReleaseComPointer + RetrieveCapturedComPointer diff --git a/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj b/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj index 0ea909b29cb70b..96a2ae3365db9c 100644 --- a/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj +++ b/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj @@ -5,7 +5,7 @@ true Guard true - true + true diff --git a/src/tests/nativeaot/SmokeTests/PInvoke/CMakeLists.txt b/src/tests/nativeaot/SmokeTests/PInvoke/CMakeLists.txt index 7aabb442144009..042053525c8b51 100644 --- a/src/tests/nativeaot/SmokeTests/PInvoke/CMakeLists.txt +++ b/src/tests/nativeaot/SmokeTests/PInvoke/CMakeLists.txt @@ -10,5 +10,9 @@ endif(CLR_CMAKE_HOST_WIN32) add_library (PInvokeNative SHARED PInvokeNative.cpp) target_link_libraries(PInvokeNative PRIVATE ${LINK_LIBRARIES_ADDITIONAL}) +if(CLR_CMAKE_HOST_WIN32) + target_link_options(PInvokeNative PRIVATE /DEF:${CMAKE_CURRENT_SOURCE_DIR}/PInvokeNative.def) +endif(CLR_CMAKE_HOST_WIN32) + # add the install targets install (TARGETS PInvokeNative DESTINATION bin) diff --git a/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.def b/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.def new file mode 100644 index 00000000000000..ef3262e7e63f63 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.def @@ -0,0 +1,56 @@ +EXPORTS + AllocateMemory + Callback + CheckIncremental + CheckIncremental_Foo + DecimalTest + GetDelegate + GetFunctionPointer + GetNativeFuncFunctionPointer + GetNextChar + Inc + InlineArrayTest + InlineStringTest + IsNULL + IsTrue + LastErrorTest + NativeFunc + RegisterCallbacks + ReleaseMemory + ReversePInvoke_Array + ReversePInvoke_DelegateField + ReversePInvoke_Int + ReversePInvoke_OutString + ReversePInvoke_String + ReversePInvoke_Unused + SafeHandleOutTest + SafeHandleRefTest + SafeHandleTest + SetLastErrorFunc + Square + StructTest + StructTest_Array + StructTest_ByOut + StructTest_ByRef + StructTest_Explicit + StructTest_Nested + StructTest_Sequential2 + ToUpper + ValidateIntResult + ValidateSuccessCall + VerifyAnsiCharArrayIn + VerifyAnsiCharArrayOut + VerifyAnsiString + VerifyAnsiStringArray + VerifyAnsiStringBuilder + VerifyAnsiStringBuilderOut + VerifyAnsiStringOut + VerifyAnsiStringRef + VerifyByRefFoo + VerifyByRefFooReturn + VerifySizeParamIndex + VerifyUnicodeString + VerifyUnicodeStringBuilder + VerifyUnicodeStringBuilderOut + VerifyUnicodeStringOut + VerifyUnicodeStringRef From 79b6075566cf8b05c5ebf6d6ed7721d1eb42ba63 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 28 Feb 2024 16:10:40 +0100 Subject: [PATCH 07/32] Enable win-x86 NativeAOT build --- eng/Subsets.props | 4 +++- src/coreclr/CMakeLists.txt | 2 +- src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj | 1 + src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) 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/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 From ddf5055d21e626767a8a733b157c33337c0337f5 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 8 Mar 2024 04:36:45 +0100 Subject: [PATCH 08/32] Replace InternalCalls.memmove with Unsafe.CopyBlock --- .../Runtime.Base/src/System/Runtime/InternalCalls.cs | 4 ---- .../Runtime.Base/src/System/Runtime/RuntimeExports.cs | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) 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..706dad38534c36 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs @@ -116,7 +116,7 @@ public static unsafe object RhBox(MethodTable* pEEType, ref byte data) { fixed (byte* pFields = &result.GetRawData()) fixed (byte* pData = &dataAdjustedForNullable) - InternalCalls.memmove(pFields, pData, pEEType->ValueTypeSize); + Unsafe.CopyBlock(pFields, pData, pEEType->ValueTypeSize); } return result; @@ -272,8 +272,8 @@ public static unsafe void RhUnbox(object? obj, ref byte data, MethodTable* pUnbo { // Copy the boxed fields into the new location. fixed (byte *pData = &data) - fixed (byte* pFields = &fields) - InternalCalls.memmove(pData, pFields, pEEType->ValueTypeSize); + fixed (byte* pFields = &fields) + Unsafe.CopyBlock(pData, pFields, pEEType->ValueTypeSize); } } From 27da448ec7a3ee40a63ab5e768f26781ce6f7f9b Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 8 Mar 2024 10:38:23 +0100 Subject: [PATCH 09/32] Use ref version of Unsafe.CopyBlock --- .../src/System/Runtime/CompilerServices/Unsafe.cs | 10 ++++++++++ .../Runtime.Base/src/System/Runtime/RuntimeExports.cs | 8 ++------ 2 files changed, 12 insertions(+), 6 deletions(-) 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/RuntimeExports.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs index 706dad38534c36..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) - Unsafe.CopyBlock(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) - Unsafe.CopyBlock(pData, pFields, pEEType->ValueTypeSize); + Unsafe.CopyBlock(ref data, ref fields, pEEType->ValueTypeSize); } } From 7b664a1f4b10ebee217912fe2b511934713b669f Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 8 Mar 2024 12:49:26 +0100 Subject: [PATCH 10/32] Add support for P/Invoke resolution with mangled stdcall signatures --- .../Runtime/CompilerHelpers/InteropHelpers.cs | 55 ++++++++++++------ .../TypeSystem/IL/Stubs/PInvokeILEmitter.cs | 13 ++++- .../IL/Stubs/PInvokeLazyFixupField.cs | 6 +- .../TypeSystem/Interop/InteropStateManager.cs | 23 ++++---- .../PInvokeMethodFixupNode.cs | 8 +++ .../SmokeTests/ComWrappers/CMakeLists.txt | 4 -- .../ComWrappers/ComWrappersNative.def | 6 -- .../SmokeTests/PInvoke/CMakeLists.txt | 4 -- .../SmokeTests/PInvoke/PInvokeNative.def | 56 ------------------- 9 files changed, 76 insertions(+), 99 deletions(-) delete mode 100644 src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.def delete mode 100644 src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.def 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..c5472a3c3115bc 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,42 @@ internal static unsafe void FixupMethodCell(IntPtr hModule, MethodFixupCell* pCe } #if TARGET_WINDOWS - private static unsafe IntPtr GetProcAddressWithSuffix(IntPtr hModule, byte* methodName, byte suffix) +#if TARGET_X86 + private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* methodName, 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++) + IntPtr pMethod = Interop.Kernel32.GetProcAddress(hModule, methodName); + if (pMethod == IntPtr.Zero && pCell->SignatureBytes >= 0) { - probedMethodName[i] = methodName[i]; + int nameLength = string.strlen(methodName); + // We need to add an extra bytes for the prefix, null terminator and stack size suffix ('@' and up to 10 digits) + 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); } + return pMethod; + } +#else + private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* methodName, MethodFixupCell* pCell) + { + return Interop.Kernel32.GetProcAddress(hModule, methodName); + } +#endif - probedMethodName[nameLength + 1] = 0; + 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]; + 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 @@ -626,6 +644,9 @@ internal unsafe struct MethodFixupCell public IntPtr MethodName; public ModuleFixupCell* Module; private int Flags; +#if TARGET_WINDOWS && TARGET_X86 + public int SignatureBytes; +#endif public CharSet CharSetMangling => (CharSet)(Flags & MethodFixupCellFlagsConstants.CharSetMask); public bool IsObjectiveCMessageSend => (Flags & MethodFixupCellFlagsConstants.IsObjectiveCMessageSendMask) != 0; diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs index e9d7adc4ad0e72..c61b427a51928d 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs @@ -300,8 +300,19 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) if (!_pInvokeILEmitterConfiguration.GenerateDirectCall(_targetMethod, out _)) { + int signatureBytes = -1; + if (context.Target.IsWindows && context.Target.Architecture == TargetArchitecture.X86 && + (_targetMethod.GetPInvokeMethodCallingConventions() & UnmanagedCallingConventions.CallingConventionMask) == UnmanagedCallingConventions.Stdcall) + { + signatureBytes = 0; + foreach (var p in nativeParameterTypes) + { + signatureBytes += AlignmentHelper.AlignUp(p.GetElementSize().AsInt, context.Target.PointerSize); + } + } + MetadataType lazyHelperType = context.GetHelperType("InteropHelpers"); - FieldDesc lazyDispatchCell = _interopStateManager.GetPInvokeLazyFixupField(_targetMethod); + FieldDesc lazyDispatchCell = _interopStateManager.GetPInvokeLazyFixupField(_targetMethod, signatureBytes); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs index b74dc75b46dee7..f11c14d2898011 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 int _signatureBytes; - public PInvokeLazyFixupField(DefType owningType, MethodDesc targetMethod) + public PInvokeLazyFixupField(DefType owningType, MethodDesc targetMethod, int signatureBytes) { Debug.Assert(targetMethod.IsPInvoke); _owningType = owningType; _targetMethod = targetMethod; + _signatureBytes = signatureBytes; } public MethodDesc TargetMethod @@ -32,6 +34,8 @@ public MethodDesc TargetMethod } } + public int SignatureBytes => _signatureBytes; + public PInvokeMetadata PInvokeMetadata { get diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs index f8a3ea39640662..7716766627a324 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs @@ -180,9 +180,10 @@ public TypeDesc GetInlineArrayType(InlineArrayCandidate candidate) return _inlineArrayHashtable.GetOrCreateValue(candidate); } - public FieldDesc GetPInvokeLazyFixupField(MethodDesc method) + public FieldDesc GetPInvokeLazyFixupField(MethodDesc method, int signatureBytes) { - return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method); + var methodKey = new PInvokeLazyFixupFieldKey(method, signatureBytes); + return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(methodKey); } public MethodDesc GetPInvokeCalliStub(MethodSignature signature, ModuleDesc moduleContext) @@ -446,11 +447,13 @@ public PInvokeDelegateWrapperHashtable(InteropStateManager interopStateManager, } } - private sealed class PInvokeLazyFixupFieldHashtable : LockFreeReaderHashtable + private readonly record struct PInvokeLazyFixupFieldKey(MethodDesc Method, int SignatureBytes); + + private sealed class PInvokeLazyFixupFieldHashtable : LockFreeReaderHashtable { - protected override int GetKeyHashCode(MethodDesc key) + protected override int GetKeyHashCode(PInvokeLazyFixupFieldKey key) { - return key.GetHashCode(); + return key.Method.GetHashCode(); } protected override int GetValueHashCode(PInvokeLazyFixupField value) @@ -458,19 +461,19 @@ 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 && key.SignatureBytes == value.SignatureBytes; } protected override bool CompareValueToValue(PInvokeLazyFixupField value1, PInvokeLazyFixupField value2) { - return value1.TargetMethod == value2.TargetMethod; + return value1.TargetMethod == value2.TargetMethod && value1.SignatureBytes == value2.SignatureBytes; } - protected override PInvokeLazyFixupField CreateValueFromKey(MethodDesc key) + protected override PInvokeLazyFixupField CreateValueFromKey(PInvokeLazyFixupFieldKey key) { - return new PInvokeLazyFixupField(_owningType, key); + return new PInvokeLazyFixupField(_owningType, key.Method, key.SignatureBytes); } 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..8a5d8dee9a0cab 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs @@ -97,6 +97,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) builder.EmitInt(flags); + if (factory.Target.IsWindows && factory.Target.Architecture == TargetArchitecture.X86) + { + builder.EmitInt(_pInvokeMethodData.SignatureBytes); + } + return builder.ToObjectData(); } @@ -113,6 +118,7 @@ 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) { @@ -167,6 +173,8 @@ public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField) charSetMangling = isAnsi ? CharSet.Ansi : CharSet.Unicode; } CharSetMangling = charSetMangling; + + SignatureBytes = pInvokeLazyFixupField.SignatureBytes; } public bool Equals(PInvokeMethodData other) diff --git a/src/tests/nativeaot/SmokeTests/ComWrappers/CMakeLists.txt b/src/tests/nativeaot/SmokeTests/ComWrappers/CMakeLists.txt index 78d1de4ea17ee6..a631acce2c89d0 100644 --- a/src/tests/nativeaot/SmokeTests/ComWrappers/CMakeLists.txt +++ b/src/tests/nativeaot/SmokeTests/ComWrappers/CMakeLists.txt @@ -3,9 +3,5 @@ include_directories(${INC_PLATFORM_DIR}) add_library (ComWrappersNative SHARED ComWrappersNative.cpp) -if(CLR_CMAKE_HOST_WIN32) - target_link_options(ComWrappersNative PRIVATE /DEF:${CMAKE_CURRENT_SOURCE_DIR}/ComWrappersNative.def) -endif(CLR_CMAKE_HOST_WIN32) - # add the install targets install (TARGETS ComWrappersNative DESTINATION bin) diff --git a/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.def b/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.def deleted file mode 100644 index a9168c4ebcaf6a..00000000000000 --- a/src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.def +++ /dev/null @@ -1,6 +0,0 @@ -EXPORTS - BuildComPointer - CaptureComPointer - IsNULL - ReleaseComPointer - RetrieveCapturedComPointer diff --git a/src/tests/nativeaot/SmokeTests/PInvoke/CMakeLists.txt b/src/tests/nativeaot/SmokeTests/PInvoke/CMakeLists.txt index 042053525c8b51..7aabb442144009 100644 --- a/src/tests/nativeaot/SmokeTests/PInvoke/CMakeLists.txt +++ b/src/tests/nativeaot/SmokeTests/PInvoke/CMakeLists.txt @@ -10,9 +10,5 @@ endif(CLR_CMAKE_HOST_WIN32) add_library (PInvokeNative SHARED PInvokeNative.cpp) target_link_libraries(PInvokeNative PRIVATE ${LINK_LIBRARIES_ADDITIONAL}) -if(CLR_CMAKE_HOST_WIN32) - target_link_options(PInvokeNative PRIVATE /DEF:${CMAKE_CURRENT_SOURCE_DIR}/PInvokeNative.def) -endif(CLR_CMAKE_HOST_WIN32) - # add the install targets install (TARGETS PInvokeNative DESTINATION bin) diff --git a/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.def b/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.def deleted file mode 100644 index ef3262e7e63f63..00000000000000 --- a/src/tests/nativeaot/SmokeTests/PInvoke/PInvokeNative.def +++ /dev/null @@ -1,56 +0,0 @@ -EXPORTS - AllocateMemory - Callback - CheckIncremental - CheckIncremental_Foo - DecimalTest - GetDelegate - GetFunctionPointer - GetNativeFuncFunctionPointer - GetNextChar - Inc - InlineArrayTest - InlineStringTest - IsNULL - IsTrue - LastErrorTest - NativeFunc - RegisterCallbacks - ReleaseMemory - ReversePInvoke_Array - ReversePInvoke_DelegateField - ReversePInvoke_Int - ReversePInvoke_OutString - ReversePInvoke_String - ReversePInvoke_Unused - SafeHandleOutTest - SafeHandleRefTest - SafeHandleTest - SetLastErrorFunc - Square - StructTest - StructTest_Array - StructTest_ByOut - StructTest_ByRef - StructTest_Explicit - StructTest_Nested - StructTest_Sequential2 - ToUpper - ValidateIntResult - ValidateSuccessCall - VerifyAnsiCharArrayIn - VerifyAnsiCharArrayOut - VerifyAnsiString - VerifyAnsiStringArray - VerifyAnsiStringBuilder - VerifyAnsiStringBuilderOut - VerifyAnsiStringOut - VerifyAnsiStringRef - VerifyByRefFoo - VerifyByRefFooReturn - VerifySizeParamIndex - VerifyUnicodeString - VerifyUnicodeStringBuilder - VerifyUnicodeStringBuilderOut - VerifyUnicodeStringOut - VerifyUnicodeStringRef From 1a0e39936a74a050cbcaf5841ed65cfefdaff7f7 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Fri, 8 Mar 2024 14:07:35 +0100 Subject: [PATCH 11/32] Fix build. --- .../src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs | 1 + 1 file changed, 1 insertion(+) 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 c5472a3c3115bc..ec50ba49dd78a6 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 @@ -411,6 +411,7 @@ private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* me #else private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* methodName, MethodFixupCell* pCell) { + _ = pCell; return Interop.Kernel32.GetProcAddress(hModule, methodName); } #endif From 610d40c29947bd9f86472d5c807edb2eaba7aeda Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 11:04:52 +0100 Subject: [PATCH 12/32] Move SignatureBytes into Flags in MethodFixupCell --- .../Runtime/CompilerHelpers/InteropHelpers.cs | 22 +++++++++---------- .../Internal/Runtime/RuntimeConstants.cs | 3 +++ .../TypeSystem/Interop/IL/MarshalHelpers.cs | 12 +++++----- .../PInvokeMethodFixupNode.cs | 21 ++++++++++-------- 4 files changed, 31 insertions(+), 27 deletions(-) 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 ec50ba49dd78a6..d8817133eb18bd 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 @@ -390,11 +390,11 @@ internal static unsafe void FixupMethodCell(IntPtr hModule, MethodFixupCell* pCe } #if TARGET_WINDOWS -#if TARGET_X86 private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* methodName, MethodFixupCell* pCell) { IntPtr pMethod = Interop.Kernel32.GetProcAddress(hModule, methodName); - if (pMethod == IntPtr.Zero && pCell->SignatureBytes >= 0) +#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 ('@' and up to 10 digits) @@ -406,15 +406,11 @@ private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* me probedMethodName[nameLength + 2 + bytesWritten] = 0; pMethod = Interop.Kernel32.GetProcAddress(hModule, probedMethodName); } - return pMethod; - } #else - private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* methodName, MethodFixupCell* pCell) - { _ = pCell; - return Interop.Kernel32.GetProcAddress(hModule, methodName); - } #endif + return pMethod; + } private static unsafe IntPtr GetProcAddressWithSuffix(IntPtr hModule, byte* methodName, byte suffix, MethodFixupCell* pCell) { @@ -644,14 +640,16 @@ internal unsafe struct MethodFixupCell public IntPtr Target; public IntPtr MethodName; public ModuleFixupCell* Module; - private int Flags; -#if TARGET_WINDOWS && TARGET_X86 - public int SignatureBytes; -#endif + 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; +#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/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/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/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs index 8a5d8dee9a0cab..acaf128383f417 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs @@ -77,31 +77,34 @@ 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; } - - builder.EmitInt(flags); - - if (factory.Target.IsWindows && factory.Target.Architecture == TargetArchitecture.X86) + else if (factory.Target.IsWindows && factory.Target.Architecture == TargetArchitecture.X86) { - builder.EmitInt(_pInvokeMethodData.SignatureBytes); + if (_pInvokeMethodData.SignatureBytes >= 0) + { + flags |= MethodFixupCellFlagsConstants.IsStdcall; + flags |= ((uint)_pInvokeMethodData.SignatureBytes << 16); + } } + builder.EmitUInt(flags); + return builder.ToObjectData(); } From cf69135a1ad4832aff03c2d8c304a3bc518ad7cd Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 11:19:06 +0100 Subject: [PATCH 13/32] Attempt to remove the non-sense key in PInvokeLazyFixupFieldHashtable --- .../IL/Stubs/PInvokeLazyFixupField.cs | 16 +++++++++---- .../TypeSystem/Interop/InteropStateManager.cs | 23 +++++++++---------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs index f11c14d2898011..97ac7e5346f62a 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs @@ -16,14 +16,14 @@ public sealed partial class PInvokeLazyFixupField : FieldDesc { private readonly DefType _owningType; private readonly MethodDesc _targetMethod; - private readonly int _signatureBytes; + private int _signatureBytes; - public PInvokeLazyFixupField(DefType owningType, MethodDesc targetMethod, int signatureBytes) + public PInvokeLazyFixupField(DefType owningType, MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); _owningType = owningType; _targetMethod = targetMethod; - _signatureBytes = signatureBytes; + _signatureBytes = -1; } public MethodDesc TargetMethod @@ -34,7 +34,15 @@ public MethodDesc TargetMethod } } - public int SignatureBytes => _signatureBytes; + public int SignatureBytes + { + get => _signatureBytes; + set + { + Debug.Assert(_signatureBytes == -1 || _signatureBytes == value); + _signatureBytes = value; + } + } public PInvokeMetadata PInvokeMetadata { diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs index 7716766627a324..4dd67b7d4bb101 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs @@ -182,8 +182,9 @@ public TypeDesc GetInlineArrayType(InlineArrayCandidate candidate) public FieldDesc GetPInvokeLazyFixupField(MethodDesc method, int signatureBytes) { - var methodKey = new PInvokeLazyFixupFieldKey(method, signatureBytes); - return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(methodKey); + var fieldDesc = _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method); + fieldDesc.SignatureBytes = signatureBytes; + return fieldDesc; } public MethodDesc GetPInvokeCalliStub(MethodSignature signature, ModuleDesc moduleContext) @@ -447,13 +448,11 @@ public PInvokeDelegateWrapperHashtable(InteropStateManager interopStateManager, } } - private readonly record struct PInvokeLazyFixupFieldKey(MethodDesc Method, int SignatureBytes); - - private sealed class PInvokeLazyFixupFieldHashtable : LockFreeReaderHashtable + private sealed class PInvokeLazyFixupFieldHashtable : LockFreeReaderHashtable { - protected override int GetKeyHashCode(PInvokeLazyFixupFieldKey key) + protected override int GetKeyHashCode(MethodDesc key) { - return key.Method.GetHashCode(); + return key.GetHashCode(); } protected override int GetValueHashCode(PInvokeLazyFixupField value) @@ -461,19 +460,19 @@ protected override int GetValueHashCode(PInvokeLazyFixupField value) return value.TargetMethod.GetHashCode(); } - protected override bool CompareKeyToValue(PInvokeLazyFixupFieldKey key, PInvokeLazyFixupField value) + protected override bool CompareKeyToValue(MethodDesc key, PInvokeLazyFixupField value) { - return key.Method == value.TargetMethod && key.SignatureBytes == value.SignatureBytes; + return key == value.TargetMethod; } protected override bool CompareValueToValue(PInvokeLazyFixupField value1, PInvokeLazyFixupField value2) { - return value1.TargetMethod == value2.TargetMethod && value1.SignatureBytes == value2.SignatureBytes; + return value1.TargetMethod == value2.TargetMethod; } - protected override PInvokeLazyFixupField CreateValueFromKey(PInvokeLazyFixupFieldKey key) + protected override PInvokeLazyFixupField CreateValueFromKey(MethodDesc key) { - return new PInvokeLazyFixupField(_owningType, key.Method, key.SignatureBytes); + return new PInvokeLazyFixupField(_owningType, key); } private readonly DefType _owningType; From 392cce9d6c4bcd023c3ee9fa8c891e495a696d18 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 12:29:57 +0100 Subject: [PATCH 14/32] Cleanup the math helpers not to depend on CRT internals Change Rhp[U]L[Div/Mod] from FCall to QCall, affects only x86 and arm --- src/coreclr/nativeaot/Runtime/MathHelpers.cpp | 28 +-- .../nativeaot/Runtime/i386/MiscStubs.asm | 193 +++++++++--------- .../Runtime/CompilerHelpers/MathHelpers.cs | 27 +-- 3 files changed, 129 insertions(+), 119 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp index 930c200a344411..1bafd290bd9f6b 100644 --- a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp @@ -78,50 +78,52 @@ EXTERN_C double REDHAWK_CALLCONV RhpDblRem(double dividend, double divisor) return(fmod(dividend,divisor)); } -#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; } +#endif -EXTERN_C int32_t REDHAWK_CALLCONV RhpIMod(int32_t i, int32_t j) +#ifdef HOST_ARM +EXTERN_C int32_t REDHAWK_CALLCONV RhpIDiv(int32_t i, int32_t j) { ASSERT(j && "Divide by zero!"); - return i % j; + return i / j; } -EXTERN_C uint32_t REDHAWK_CALLCONV RhpUMod(uint32_t i, uint32_t j) +EXTERN_C uint32_t REDHAWK_CALLCONV RhpUDiv(uint32_t i, uint32_t j) { ASSERT(j && "Divide by zero!"); - return i % j; + return i / j; } -EXTERN_C int64_t REDHAWK_CALLCONV RhpLMod(int64_t i, int64_t j) +EXTERN_C int32_t REDHAWK_CALLCONV RhpIMod(int32_t i, int32_t j) { ASSERT(j && "Divide by zero!"); return i % j; } -EXTERN_C uint64_t REDHAWK_CALLCONV RhpULMod(uint64_t i, uint64_t j) +EXTERN_C uint32_t REDHAWK_CALLCONV RhpUMod(uint32_t i, uint32_t j) { ASSERT(j && "Divide by zero!"); return i % j; diff --git a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm index 410def8a9f3325..73a5ed878d974f 100644 --- a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm @@ -41,14 +41,12 @@ ProbeLoop: RhpStackProbe ENDP ;; *********************************************************************/ -;; llshl - long shift left +;; LLsh - long shift left ;; ;; Purpose: ;; Does a Long Shift Left (signed and unsigned are identical) ;; Shifts a long left any number of bits. ;; -;; NOTE: This routine has been adapted from the Microsoft CRTs. -;; ;; Entry: ;; EDX:EAX - long value to be shifted ;; ECX - number of bits to shift by @@ -56,6 +54,8 @@ RhpStackProbe ENDP ;; Exit: ;; EDX:EAX - shifted value ;; +;; NOTE: Adapted from JIT_LLsh in CoreCLR +;; RhpLLsh PROC public ;; Reduce shift amount mod 64 and ecx, 63 @@ -84,8 +84,6 @@ RhpLLsh ENDP ;; Does a signed Long Shift Right ;; Shifts a long right any number of bits. ;; -;; NOTE: This routine has been adapted from the Microsoft CRTs. -;; ;; Entry: ;; EDX:EAX - long value to be shifted ;; ECX - number of bits to shift by @@ -93,6 +91,8 @@ RhpLLsh ENDP ;; Exit: ;; EDX:EAX - shifted value ;; +;; NOTE: Adapted from JIT_LRsh in CoreCLR +;; RhpLRsh PROC public ;; Reduce shift amount mod 64 and ecx, 63 @@ -115,13 +115,12 @@ LRshMORE32: RhpLRsh ENDP ;; *********************************************************************/ -;; LRsz: +;; LRsz +;; ;; Purpose: ;; Does a unsigned Long Shift Right ;; Shifts a long right any number of bits. ;; -;; NOTE: This routine has been adapted from the Microsoft CRTs. -;; ;; Entry: ;; EDX:EAX - long value to be shifted ;; ECX - number of bits to shift by @@ -129,6 +128,8 @@ RhpLRsh ENDP ;; Exit: ;; EDX:EAX - shifted value ;; +;; NOTE: Adapted from JIT_LRsz in CoreCLR +;; RhpLRsz PROC public ;; Reduce shift amount mod 64 and ecx, 63 @@ -150,109 +151,115 @@ LRszMORE32: ret RhpLRsz ENDP +;; *********************************************************************/ +;; LMul ;; -;; Following helpers are unoptimized, forward to C library, and should -;; eventually be revisited. +;; 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 clang generated code +;; +RhpLMul PROC public + push esi + mov ecx, dword ptr [esp + 16] + mov esi, dword ptr [esp + 8] + mov eax, ecx + mul esi + imul ecx, dword ptr [esp + 12] + add edx, ecx + imul esi, dword ptr [esp + 20] + add edx, esi + pop esi + ret 16 +RhpLMul ENDP -EXTERN __dtol3 : PROC - +;; *********************************************************************/ +;; Dbl2Lng +;; +;; Purpose: +;; Converts a double to a long truncating toward zero (C semantics) +;; Uses stdcall calling conventions +;; +;; NOTE: Adapted from JIT_Dbl2LngP4x87 in CoreCLR +;; RhpDbl2Lng PROC public - movsd xmm0, qword ptr [esp+4] - call __dtol3 - ret 8 +ALTERNATE_ENTRY RhpDbl2UInt + sub esp, 8 ; get some local space + + fld qword ptr [esp+0Ch] ; fetch arg + fnstcw word ptr [esp+0Ch] ; store FPCW + movzx eax, word ptr [esp+0Ch] ; zero extend - wide + or ah, 0Ch ; turn on OE and DE flags + mov dword ptr [esp], eax ; store new FPCW bits + fldcw word ptr [esp] ; reload FPCW with new bits + fistp qword ptr [esp] ; convert + mov eax, dword ptr [esp] ; reload FP result + mov edx, dword ptr [esp+4] + fldcw word ptr [esp+0Ch] ; reload original FPCW value + + add esp, 8 ; restore stack + + ret 8 RhpDbl2Lng ENDP +;; *********************************************************************/ +;; Dbl2Int +;; +;; Purpose: +;; Converts a double to a long truncating toward zero (C semantics) +;; Uses stdcall calling conventions +;; RhpDbl2Int PROC public - movsd xmm0, qword ptr [esp+4] - cvttsd2si eax, xmm0 - ret 8 + cvttsd2si eax, qword ptr [esp+4] + ret 8 RhpDbl2Int ENDP -RhpDbl2UInt PROC public - movsd xmm0, qword ptr [esp+4] - call __dtol3 - ret 8 -RhpDbl2UInt ENDP - -;EXTERN __ltod3 : PROC - +;; *********************************************************************/ +;; Lng2Dbl +;; +;; Purpose: +;; Converts a long to a double (C semantics) +;; Uses stdcall calling conventions +;; RhpLng2Dbl PROC public fild qword ptr [esp+4] - ;mov edx, dword ptr [esp+8] - ;mov ecx, dword ptr [esp+4] - ;call __ltod3 - ;movsd qword ptr [esp+4], xmm0 - ;fld qword ptr [esp+4] ret 8 RhpLng2Dbl ENDP -EXTERN __ultod3 : PROC - +;; *********************************************************************/ +;; ULng2Dbl +;; +;; Purpose: +;; Converts an unsigned long to a double (C semantics) +;; Uses stdcall calling conventions +;; +;; NOTE: Adapted from GCC generated code +;; RhpULng2Dbl PROC public - mov edx, dword ptr [esp+8] - mov ecx, dword ptr [esp+4] - call __ultod3 - movsd qword ptr [esp+4], xmm0 - fld qword ptr [esp+4] + sub esp, 12 + mov eax, dword ptr [esp+20] + fild qword ptr [esp+16] + test eax, eax + jns L2 + fadd TWO_TO_64 +L2: + fstp qword ptr [esp] + fld qword ptr [esp] + add esp, 12 ret 8 +.data + TWO_TO_64 dd 5f800000h ;; 2^64 +.code RhpULng2Dbl ENDP -EXTERN __alldiv : PROC - -RhpLDiv PROC public - push dword ptr [esp+8] - push dword ptr [esp+8] - push dword ptr [esp+24] - push dword ptr [esp+24] - call __alldiv - ret 16 -RhpLDiv ENDP - -EXTERN __allrem : PROC - -RhpLMod PROC public - push dword ptr [esp+8] - push dword ptr [esp+8] - push dword ptr [esp+24] - push dword ptr [esp+24] - call __allrem - ret 16 -RhpLMod ENDP - -EXTERN __aulldiv : PROC - -RhpULDiv PROC public - push dword ptr [esp+8] - push dword ptr [esp+8] - push dword ptr [esp+24] - push dword ptr [esp+24] - call __aulldiv - ret 16 -RhpULDiv ENDP - -EXTERN __aullrem : PROC - -RhpULMod PROC public - push dword ptr [esp+8] - push dword ptr [esp+8] - push dword ptr [esp+24] - push dword ptr [esp+24] - call __aullrem - ret 16 -RhpULMod ENDP - -EXTERN __allmul : PROC - -RhpLMul PROC public - push dword ptr [esp+8] - push dword ptr [esp+8] - push dword ptr [esp+24] - push dword ptr [esp+24] - call __allmul - ret 16 -RhpLMul ENDP - ;; ;; https://github.com/dotnet/runtime/pull/98858 moves the following helpers to ;; managed code, so no need to optimize this 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) { From 1736ccf98135010e38f24297696b31d22c77c328 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 12:59:50 +0100 Subject: [PATCH 15/32] RhCpuIdEx is FCall, fix the import declaration --- .../src/System/Runtime/RuntimeImports.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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..663136bd28fddc 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 @@ -1130,8 +1130,9 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe internal static unsafe partial void* memset(byte* mem, int value, nuint size); #if TARGET_X86 || TARGET_AMD64 - [LibraryImport(RuntimeLibrary)] - internal static unsafe partial void RhCpuIdEx(int* cpuInfo, int functionId, int subFunctionId); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhCpuIdEx")] + internal static extern unsafe void RhCpuIdEx(int* cpuInfo, int functionId, int subFunctionId); #endif } } From 8638f5566484e64f5b8607177e0927ca3f172cad Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 13:00:33 +0100 Subject: [PATCH 16/32] Make sure that thunk allocation functions can be resolved by the linker --- src/coreclr/nativeaot/Runtime/i386/AsmMacros.inc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 From e5a4ca757ff736d2330a734bf14c2d09d1e87802 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 13:12:45 +0100 Subject: [PATCH 17/32] RhEnumerateConfigurationValues was incorrectly marked as FCall --- src/coreclr/nativeaot/Runtime/GCHelpers.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/GCHelpers.cpp b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp index 88ad22aa2e90d9..6259f0216f129f 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; From 514bee15f366710ca2800259931f5882a96aa33e Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 13:38:13 +0100 Subject: [PATCH 18/32] Fix Mac/iOS/tvOS build --- .../src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d8817133eb18bd..bba0720d691075 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 @@ -645,7 +645,7 @@ internal unsafe struct MethodFixupCell 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); From 1bf01b20d81ea11d7753e4dd685a161269d0e1a6 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 15:37:46 +0100 Subject: [PATCH 19/32] Add FCIMPL1_D/FCIMPL2_FF/FCIMPL2_DD macros and mark RhpDbl2ULng/RhpFltRem/RhpDblRem with it. --- src/coreclr/nativeaot/Runtime/CommonMacros.h | 25 +++++++++++++++++++ src/coreclr/nativeaot/Runtime/MathHelpers.cpp | 9 ++++--- .../nativeaot/Runtime/i386/MiscStubs.asm | 18 ------------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index 02473e873aaabe..20825b6441d059 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -219,6 +219,21 @@ 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_IMPL_ALTNAME(_method, _argSize)))) + +#define FCIMPL1_D(_rettype, _method, a) \ + FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (a) \ + { +#define FCIMPL2_FF(_rettype, _method, a, b) \ + FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (b, a) \ + { +#define FCIMPL2_DD(_rettype, _method, a, b) \ + FCIMPL_RENAME_ARGSIZE(_rettype, _method, 16) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (b, a) \ + { #else @@ -228,6 +243,16 @@ typedef uint8_t CODE_LOCATION; #define FCALL_METHOD_ARGS(dummy, ...) (__VA_ARGS__) #define FCALL_METHOD_ARGS_(tuple) FCALL_METHOD_ARGS tuple +#define FCIMPL1_D(_rettype, _method, a) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (a) \ + { +#define FCIMPL2_FF(_rettype, _method, a, b) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ + { +#define FCIMPL2_DD(_rettype, _method, a, b) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ + { + #endif #define FCDECL_(_rettype, ...) \ diff --git a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp index 1bafd290bd9f6b..afdbff4cd81ad0 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,6 +79,7 @@ EXTERN_C double REDHAWK_CALLCONV RhpDblRem(double dividend, double divisor) // else... return(fmod(dividend,divisor)); } +FCIMPLEND #ifndef HOST_64BIT EXTERN_C int64_t QCALLTYPE RhpLDiv(int64_t i, int64_t j) diff --git a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm index 73a5ed878d974f..6875c3ebd8c7a8 100644 --- a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm @@ -260,22 +260,4 @@ L2: .code RhpULng2Dbl ENDP -;; -;; https://github.com/dotnet/runtime/pull/98858 moves the following helpers to -;; managed code, so no need to optimize this -;; - -REDIRECT_FUNC macro ExportName, ImportName - EXTERN ImportName : PROC - - public ExportName - ExportName proc - jmp ImportName - ExportName endp -endm - -REDIRECT_FUNC RhpDbl2ULng, @RhpDbl2ULng@8 -REDIRECT_FUNC RhpFltRem, @RhpFltRem@8 -REDIRECT_FUNC RhpDblRem, @RhpDblRem@16 - end From 8ac691d894eb77473ee411b1931043a7bf5a978b Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 16:29:01 +0100 Subject: [PATCH 20/32] x86: Use FCalls for CRT math --- src/coreclr/nativeaot/Runtime/CommonMacros.h | 43 ++- src/coreclr/nativeaot/Runtime/MathHelpers.cpp | 196 ++++++++++++++ .../src/System/Runtime/RuntimeImports.cs | 252 ------------------ 3 files changed, 235 insertions(+), 256 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index 20825b6441d059..76c3f90954cf12 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -220,19 +220,39 @@ typedef uint8_t CODE_LOCATION; #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_IMPL_ALTNAME(_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 REDHAWK_CALLCONV _method##_FCall (a) \ + { #define FCIMPL1_D(_rettype, _method, a) \ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (a) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (a) \ { #define FCIMPL2_FF(_rettype, _method, a, b) \ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (b, a) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (b, a) \ { #define FCIMPL2_DD(_rettype, _method, a, b) \ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 16) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (b, a) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (b, a) \ + { +#define FCIMPL2_FI(_rettype, _method, a, b) \ + FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (a, b) \ + { +#define FCIMPL2_DI(_rettype, _method, a, b) \ + FCIMPL_RENAME_ARGSIZE(_rettype, _method, 12) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (a, b) \ + { +#define FCIMPL3_FFF(_rettype, _method, a, b, c) \ + FCIMPL_RENAME_ARGSIZE(_rettype, _method, 12) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (c, b, a) \ + { +#define FCIMPL3_DDD(_rettype, _method, a, b, c) \ + FCIMPL_RENAME_ARGSIZE(_rettype, _method, 24) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (c, b, a) \ { #else @@ -243,6 +263,9 @@ 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 REDHAWK_CALLCONV _method (a) \ + { #define FCIMPL1_D(_rettype, _method, a) \ EXTERN_C _rettype REDHAWK_CALLCONV _method (a) \ { @@ -252,6 +275,18 @@ typedef uint8_t CODE_LOCATION; #define FCIMPL2_DD(_rettype, _method, a, b) \ EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ { +#define FCIMPL2_FI(_rettype, _method, a, b) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ + { +#define FCIMPL2_DI(_rettype, _method, a, b) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ + { +#define FCIMPL3_FFF(_rettype, _method, a, b, c) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b, c) \ + { +#define FCIMPL3_DDD(_rettype, _method, a, b, c) \ + EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b, c) \ + { #endif diff --git a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp index afdbff4cd81ad0..76e96d195420a2 100644 --- a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp @@ -178,3 +178,199 @@ EXTERN_C double REDHAWK_CALLCONV RhpULng2Dbl(uint64_t val) } #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/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 663136bd28fddc..d7831c6eae4fa5 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)])] From d6ca24f0d729f26e10458c4dbab0168300b401e9 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 17:41:49 +0100 Subject: [PATCH 21/32] s/REDHAWK_CALLCONV/F_CALL_CONV/g --- src/coreclr/nativeaot/Runtime/CommonMacros.h | 38 +++++++++---------- src/coreclr/nativeaot/Runtime/GCHelpers.cpp | 4 +- src/coreclr/nativeaot/Runtime/MathHelpers.cpp | 26 ++++++------- .../nativeaot/Runtime/RestrictedCallouts.h | 2 +- .../nativeaot/Runtime/RuntimeInstance.cpp | 2 +- .../nativeaot/Runtime/interoplibinterface.h | 10 ++--- src/coreclr/nativeaot/Runtime/portable.cpp | 2 +- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index 76c3f90954cf12..6b7ff128fd6dde 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 @@ -224,35 +224,35 @@ typedef uint8_t CODE_LOCATION; #define FCIMPL1_F(_rettype, _method, a) \ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 4) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (a) \ + EXTERN_C _rettype F_CALL_CONV _method##_FCall (a) \ { #define FCIMPL1_D(_rettype, _method, a) \ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (a) \ + EXTERN_C _rettype F_CALL_CONV _method##_FCall (a) \ { #define FCIMPL2_FF(_rettype, _method, a, b) \ FCIMPL_RENAME_ARGSIZE(_rettype, _method, 8) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method##_FCall (b, a) \ + 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 REDHAWK_CALLCONV _method##_FCall (b, a) \ + 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 REDHAWK_CALLCONV _method##_FCall (a, b) \ + 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 REDHAWK_CALLCONV _method##_FCall (a, b) \ + 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 REDHAWK_CALLCONV _method##_FCall (c, b, a) \ + 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 REDHAWK_CALLCONV _method##_FCall (c, b, a) \ + EXTERN_C _rettype F_CALL_CONV _method##_FCall (c, b, a) \ { #else @@ -264,35 +264,35 @@ typedef uint8_t CODE_LOCATION; #define FCALL_METHOD_ARGS_(tuple) FCALL_METHOD_ARGS tuple #define FCIMPL1_F(_rettype, _method, a) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (a) \ + EXTERN_C _rettype F_CALL_CONV _method (a) \ { #define FCIMPL1_D(_rettype, _method, a) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (a) \ + EXTERN_C _rettype F_CALL_CONV _method (a) \ { #define FCIMPL2_FF(_rettype, _method, a, b) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ + EXTERN_C _rettype F_CALL_CONV _method (a, b) \ { #define FCIMPL2_DD(_rettype, _method, a, b) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ + EXTERN_C _rettype F_CALL_CONV _method (a, b) \ { #define FCIMPL2_FI(_rettype, _method, a, b) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ + EXTERN_C _rettype F_CALL_CONV _method (a, b) \ { #define FCIMPL2_DI(_rettype, _method, a, b) \ - EXTERN_C _rettype REDHAWK_CALLCONV _method (a, b) \ + EXTERN_C _rettype F_CALL_CONV _method (a, b) \ { #define FCIMPL3_FFF(_rettype, _method, a, b, c) \ - EXTERN_C _rettype REDHAWK_CALLCONV _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 REDHAWK_CALLCONV _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) @@ -302,7 +302,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/GCHelpers.cpp b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp index 6259f0216f129f..7f6b1a08627faa 100644 --- a/src/coreclr/nativeaot/Runtime/GCHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/GCHelpers.cpp @@ -562,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(); @@ -701,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 76e96d195420a2..a205f92b14246b 100644 --- a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp @@ -108,71 +108,71 @@ EXTERN_C uint64_t QCALLTYPE RhpULMod(uint64_t i, uint64_t j) #endif #ifdef HOST_ARM -EXTERN_C int32_t REDHAWK_CALLCONV RhpIDiv(int32_t i, int32_t j) +EXTERN_C int32_t F_CALL_CONV RhpIDiv(int32_t i, int32_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 uint32_t F_CALL_CONV RhpUDiv(uint32_t i, uint32_t j) { ASSERT(j && "Divide by zero!"); return i / j; } -EXTERN_C int32_t REDHAWK_CALLCONV RhpIMod(int32_t i, int32_t j) +EXTERN_C int32_t F_CALL_CONV RhpIMod(int32_t i, int32_t j) { ASSERT(j && "Divide by zero!"); return i % j; } -EXTERN_C uint32_t REDHAWK_CALLCONV RhpUMod(uint32_t i, uint32_t j) +EXTERN_C uint32_t F_CALL_CONV RhpUMod(uint32_t i, uint32_t j) { ASSERT(j && "Divide by zero!"); return i % j; } -EXTERN_C int64_t REDHAWK_CALLCONV RhpLMul(int64_t i, int64_t j) +EXTERN_C int64_t F_CALL_CONV RhpLMul(int64_t i, int64_t j) { return i * j; } -EXTERN_C uint64_t REDHAWK_CALLCONV RhpLRsz(uint64_t i, int32_t j) +EXTERN_C uint64_t F_CALL_CONV RhpLRsz(uint64_t i, int32_t j) { return i >> (j & 0x3f); } -EXTERN_C int64_t REDHAWK_CALLCONV RhpLRsh(int64_t i, int32_t j) +EXTERN_C int64_t F_CALL_CONV RhpLRsh(int64_t i, int32_t j) { return i >> (j & 0x3f); } -EXTERN_C int64_t REDHAWK_CALLCONV RhpLLsh(int64_t i, int32_t j) +EXTERN_C int64_t F_CALL_CONV RhpLLsh(int64_t i, int32_t j) { return i << (j & 0x3f); } -EXTERN_C int64_t REDHAWK_CALLCONV RhpDbl2Lng(double val) +EXTERN_C int64_t F_CALL_CONV RhpDbl2Lng(double val) { return (int64_t)val; } -EXTERN_C int32_t REDHAWK_CALLCONV RhpDbl2Int(double val) +EXTERN_C int32_t F_CALL_CONV RhpDbl2Int(double val) { return (int32_t)val; } -EXTERN_C uint32_t REDHAWK_CALLCONV RhpDbl2UInt(double val) +EXTERN_C uint32_t F_CALL_CONV RhpDbl2UInt(double val) { return (uint32_t)val; } -EXTERN_C double REDHAWK_CALLCONV RhpLng2Dbl(int64_t val) +EXTERN_C double F_CALL_CONV RhpLng2Dbl(int64_t val) { return (double)val; } -EXTERN_C double REDHAWK_CALLCONV RhpULng2Dbl(uint64_t val) +EXTERN_C double F_CALL_CONV RhpULng2Dbl(uint64_t val) { return (double)val; } 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/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) { From e168e24e99eeec4244e2f419688044f85d2a76c0 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 17:45:03 +0100 Subject: [PATCH 22/32] Make RhCpuIdEx a QCall --- src/coreclr/nativeaot/Runtime/MiscHelpers.cpp | 3 +-- .../src/System/Runtime/RuntimeImports.cs | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) 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/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index d7831c6eae4fa5..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 @@ -878,9 +878,8 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe internal static unsafe partial void* memset(byte* mem, int value, nuint size); #if TARGET_X86 || TARGET_AMD64 - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhCpuIdEx")] - internal static extern unsafe void RhCpuIdEx(int* cpuInfo, int functionId, int subFunctionId); + [LibraryImport(RuntimeLibrary)] + internal static unsafe partial void RhCpuIdEx(int* cpuInfo, int functionId, int subFunctionId); #endif } } From 44168a2997bced6e05aafb033dcbc775f5c2e928 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 18:21:14 +0100 Subject: [PATCH 23/32] PR feedback: Move SignatureBytes computation and fix up Equals/CompareTo --- .../TypeSystem/IL/Stubs/PInvokeILEmitter.cs | 19 +++---------- .../IL/Stubs/PInvokeLazyFixupField.cs | 12 +++------ .../TypeSystem/Interop/InteropStateManager.cs | 4 +-- .../PInvokeMethodFixupNode.cs | 27 +++++++++++++++---- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs index c61b427a51928d..4621ebc0e465e1 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs @@ -300,28 +300,17 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) if (!_pInvokeILEmitterConfiguration.GenerateDirectCall(_targetMethod, out _)) { - int signatureBytes = -1; - if (context.Target.IsWindows && context.Target.Architecture == TargetArchitecture.X86 && - (_targetMethod.GetPInvokeMethodCallingConventions() & UnmanagedCallingConventions.CallingConventionMask) == UnmanagedCallingConventions.Stdcall) - { - signatureBytes = 0; - foreach (var p in nativeParameterTypes) - { - signatureBytes += AlignmentHelper.AlignUp(p.GetElementSize().AsInt, context.Target.PointerSize); - } - } + 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, signatureBytes); + 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 97ac7e5346f62a..4bc816f2076499 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs @@ -16,14 +16,12 @@ public sealed partial class PInvokeLazyFixupField : FieldDesc { private readonly DefType _owningType; private readonly MethodDesc _targetMethod; - private int _signatureBytes; public PInvokeLazyFixupField(DefType owningType, MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); _owningType = owningType; _targetMethod = targetMethod; - _signatureBytes = -1; } public MethodDesc TargetMethod @@ -34,14 +32,10 @@ public MethodDesc TargetMethod } } - public int SignatureBytes + public MethodSignature NativeSignature { - get => _signatureBytes; - set - { - Debug.Assert(_signatureBytes == -1 || _signatureBytes == value); - _signatureBytes = value; - } + get; + set; } public PInvokeMetadata PInvokeMetadata diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs index 4dd67b7d4bb101..ce8cdcfb0cf94a 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs @@ -180,10 +180,10 @@ public TypeDesc GetInlineArrayType(InlineArrayCandidate candidate) return _inlineArrayHashtable.GetOrCreateValue(candidate); } - public FieldDesc GetPInvokeLazyFixupField(MethodDesc method, int signatureBytes) + public FieldDesc GetPInvokeLazyFixupField(MethodDesc method, MethodSignature nativeSig) { var fieldDesc = _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method); - fieldDesc.SignatureBytes = signatureBytes; + fieldDesc.NativeSignature = nativeSig; return fieldDesc; } 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 acaf128383f417..a737f448ed7f5d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs @@ -127,11 +127,13 @@ 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"); } @@ -162,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 @@ -177,14 +179,25 @@ public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField) } CharSetMangling = charSetMangling; - SignatureBytes = pInvokeLazyFixupField.SignatureBytes; + 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) @@ -207,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) From a0e279f6c50f816c8a03e42cd88a43fc26a3020d Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 23:47:22 +0100 Subject: [PATCH 24/32] Use existing C helpers for Int/UInt/Long to Double conversions --- src/coreclr/nativeaot/Runtime/CommonMacros.h | 2 + src/coreclr/nativeaot/Runtime/MathHelpers.cpp | 56 +++++++------ .../nativeaot/Runtime/i386/MiscStubs.asm | 82 +------------------ 3 files changed, 34 insertions(+), 106 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index 6b7ff128fd6dde..e9e62638813ba9 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -230,6 +230,7 @@ typedef uint8_t CODE_LOCATION; 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) \ @@ -269,6 +270,7 @@ typedef uint8_t CODE_LOCATION; #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) \ { diff --git a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp index a205f92b14246b..9c4220ef5a7eed 100644 --- a/src/coreclr/nativeaot/Runtime/MathHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MathHelpers.cpp @@ -105,6 +105,37 @@ EXTERN_C uint64_t QCALLTYPE RhpULMod(uint64_t i, uint64_t j) ASSERT(j && "Divide by zero!"); return i % j; } + +FCIMPL1_D(int64_t, RhpDbl2Lng, double val) +{ + return (int64_t)val; +} +FCIMPLEND + +FCIMPL1_D(int32_t, RhpDbl2Int, double val) +{ + return (int32_t)val; +} +FCIMPLEND + +FCIMPL1_D(uint32_t, RhpDbl2UInt, double val) +{ + return (uint32_t)val; +} +FCIMPLEND + +FCIMPL1_L(double, RhpLng2Dbl, int64_t val) +{ + return (double)val; +} +FCIMPLEND + +FCIMPL1_L(double, RhpULng2Dbl, uint64_t val) +{ + return (double)val; +} +FCIMPLEND + #endif #ifdef HOST_ARM @@ -152,31 +183,6 @@ EXTERN_C int64_t F_CALL_CONV RhpLLsh(int64_t i, int32_t j) return i << (j & 0x3f); } -EXTERN_C int64_t F_CALL_CONV RhpDbl2Lng(double val) -{ - return (int64_t)val; -} - -EXTERN_C int32_t F_CALL_CONV RhpDbl2Int(double val) -{ - return (int32_t)val; -} - -EXTERN_C uint32_t F_CALL_CONV RhpDbl2UInt(double val) -{ - return (uint32_t)val; -} - -EXTERN_C double F_CALL_CONV RhpLng2Dbl(int64_t val) -{ - return (double)val; -} - -EXTERN_C double F_CALL_CONV RhpULng2Dbl(uint64_t val) -{ - return (double)val; -} - #endif // HOST_ARM #ifdef HOST_X86 diff --git a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm index 6875c3ebd8c7a8..3029ff378621a7 100644 --- a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm @@ -1,8 +1,7 @@ ;; Licensed to the .NET Foundation under one or more agreements. ;; The .NET Foundation licenses this file to you under the MIT license. - .686P - .XMM + .586 .model flat option casemap:none .code @@ -181,83 +180,4 @@ RhpLMul PROC public ret 16 RhpLMul ENDP -;; *********************************************************************/ -;; Dbl2Lng -;; -;; Purpose: -;; Converts a double to a long truncating toward zero (C semantics) -;; Uses stdcall calling conventions -;; -;; NOTE: Adapted from JIT_Dbl2LngP4x87 in CoreCLR -;; -RhpDbl2Lng PROC public -ALTERNATE_ENTRY RhpDbl2UInt - sub esp, 8 ; get some local space - - fld qword ptr [esp+0Ch] ; fetch arg - fnstcw word ptr [esp+0Ch] ; store FPCW - movzx eax, word ptr [esp+0Ch] ; zero extend - wide - or ah, 0Ch ; turn on OE and DE flags - mov dword ptr [esp], eax ; store new FPCW bits - fldcw word ptr [esp] ; reload FPCW with new bits - fistp qword ptr [esp] ; convert - mov eax, dword ptr [esp] ; reload FP result - mov edx, dword ptr [esp+4] - fldcw word ptr [esp+0Ch] ; reload original FPCW value - - add esp, 8 ; restore stack - - ret 8 -RhpDbl2Lng ENDP - -;; *********************************************************************/ -;; Dbl2Int -;; -;; Purpose: -;; Converts a double to a long truncating toward zero (C semantics) -;; Uses stdcall calling conventions -;; -RhpDbl2Int PROC public - cvttsd2si eax, qword ptr [esp+4] - ret 8 -RhpDbl2Int ENDP - -;; *********************************************************************/ -;; Lng2Dbl -;; -;; Purpose: -;; Converts a long to a double (C semantics) -;; Uses stdcall calling conventions -;; -RhpLng2Dbl PROC public - fild qword ptr [esp+4] - ret 8 -RhpLng2Dbl ENDP - -;; *********************************************************************/ -;; ULng2Dbl -;; -;; Purpose: -;; Converts an unsigned long to a double (C semantics) -;; Uses stdcall calling conventions -;; -;; NOTE: Adapted from GCC generated code -;; -RhpULng2Dbl PROC public - sub esp, 12 - mov eax, dword ptr [esp+20] - fild qword ptr [esp+16] - test eax, eax - jns L2 - fadd TWO_TO_64 -L2: - fstp qword ptr [esp] - fld qword ptr [esp] - add esp, 12 - ret 8 -.data - TWO_TO_64 dd 5f800000h ;; 2^64 -.code -RhpULng2Dbl ENDP - end From 880d97f0154feed7b3b494a9d47e8dfafb559100 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 23:51:20 +0100 Subject: [PATCH 25/32] Update comment --- .../src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 bba0720d691075..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 @@ -397,7 +397,11 @@ private static unsafe IntPtr GetProcAddressWithMangling(IntPtr hModule, byte* me 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 ('@' and up to 10 digits) + // 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); From 37816aebed2fe10738beec317c1632536ac53582 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 9 Mar 2024 23:54:42 +0100 Subject: [PATCH 26/32] Apply suggestions from code review Co-authored-by: Aaron Robinson --- src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm b/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm index 3901c883d9768d..daa4041b38135f 100644 --- a/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm +++ b/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm @@ -41,7 +41,7 @@ StubAVLocation textequ @CatStr( _RhpInterfaceDispatchAVLocation, entries ) ;; and the push of ebx below is precisely so we can access a second register to hold the MethodTable ;; pointer). ALTERNATE_ENTRY StubAVLocation - cmp byte ptr [ecx], 0 + cmp dword ptr [ecx], 0 ;; eax currently contains the indirection cell address. We need to update it to point to the cache ;; block instead. @@ -118,7 +118,7 @@ ALTERNATE_ENTRY _RhpInitialInterfaceDispatch ;; 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 byte ptr [ecx], 0 + cmp dword ptr [ecx], 0 jmp RhpInterfaceDispatchSlow FASTCALL_ENDFUNC From a8d355e78ab2a9b1ee7d8a357c944413753f6918 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 10 Mar 2024 00:36:06 +0100 Subject: [PATCH 27/32] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm b/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm index daa4041b38135f..86dd2807fbc8aa 100644 --- a/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm +++ b/src/coreclr/nativeaot/Runtime/i386/StubDispatch.asm @@ -41,7 +41,7 @@ StubAVLocation textequ @CatStr( _RhpInterfaceDispatchAVLocation, entries ) ;; 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], 0 + cmp dword ptr [ecx], ecx ;; eax currently contains the indirection cell address. We need to update it to point to the cache ;; block instead. @@ -118,7 +118,7 @@ ALTERNATE_ENTRY _RhpInitialInterfaceDispatch ;; 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], 0 + cmp dword ptr [ecx], ecx jmp RhpInterfaceDispatchSlow FASTCALL_ENDFUNC From 30aae4b4df7c1c4929a6b5260429437ec3522e6b Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 10 Mar 2024 01:18:51 +0100 Subject: [PATCH 28/32] Copy CoreCLR version of LMul. --- .../nativeaot/Runtime/i386/MiscStubs.asm | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm index 3029ff378621a7..6d7103920ff0e5 100644 --- a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm @@ -164,19 +164,30 @@ RhpLRsz ENDP ;; Exit: ;; EDX:EAX - product of multiplier and multiplicand ;; -;; NOTE: Adapted from clang generated code +;; NOTE: Adapted from JIT_LMul in CoreCLR ;; RhpLMul PROC public - push esi - mov ecx, dword ptr [esp + 16] - mov esi, dword ptr [esp + 8] - mov eax, ecx - mul esi - imul ecx, dword ptr [esp + 12] - add edx, ecx - imul esi, dword ptr [esp + 20] - add edx, esi - pop esi + mov eax, dword ptr [esp + 8] ; AHI + mov ecx, dword ptr [esp + 16] ; BHI + or ecx, eax ; test for both hiwords zero. + mov ecx, [esp + 12] ; BLO + jnz LMul_hard ; both are zero, just mult ALO and BLO + + mov eax, [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 From 543a4c8e8cfb50d20c21c2f955385320e745967e Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 10 Mar 2024 01:20:40 +0100 Subject: [PATCH 29/32] Use consistent syntax --- src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm index 6d7103920ff0e5..ac4b9c511cef14 100644 --- a/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/i386/MiscStubs.asm @@ -170,10 +170,10 @@ 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, [esp + 12] ; BLO + mov ecx, dword ptr [esp + 12] ; BLO jnz LMul_hard ; both are zero, just mult ALO and BLO - mov eax, [esp + 4] + mov eax, dword ptr [esp + 4] mul ecx ret 16 From b8c9ae0626e46595318c64303f86b50f77409a09 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 10 Mar 2024 17:36:50 +0100 Subject: [PATCH 30/32] Fix issue compiling some runtime tests for interop marshallers where "atoi" is imported multiple times with different calling convention --- .../Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs | 4 ++++ 1 file changed, 4 insertions(+) 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 a737f448ed7f5d..866c5d0341bf55 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs @@ -237,6 +237,10 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append("__"); sb.Append(CharSetMangling.ToString()); } + if (SignatureBytes >= 0) + { + sb.Append($"@{SignatureBytes}"); + } } } } From 03efa0714d235adcfd887912004040aa50348249 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 11 Mar 2024 08:51:59 +0100 Subject: [PATCH 31/32] Update src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Strehovský --- .../SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj b/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj index 96a2ae3365db9c..1fd766631b4a98 100644 --- a/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj +++ b/src/tests/nativeaot/SmokeTests/ControlFlowGuard/ControlFlowGuard.csproj @@ -5,6 +5,7 @@ true Guard true + true From 9dd48661287df65e9aed95a8802e7034efa982b1 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 11 Mar 2024 09:46:39 +0100 Subject: [PATCH 32/32] Use PInvokeLazyFixupFieldKey to pass NativeSignature --- .../IL/Stubs/PInvokeLazyFixupField.cs | 10 ++++--- .../TypeSystem/Interop/InteropStateManager.cs | 26 ++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs index 4bc816f2076499..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 @@ -34,8 +36,10 @@ public MethodDesc TargetMethod public MethodSignature NativeSignature { - get; - set; + get + { + return _nativeSignature; + } } public PInvokeMetadata PInvokeMetadata diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs index ce8cdcfb0cf94a..7147f65cbb681f 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs @@ -182,9 +182,7 @@ public TypeDesc GetInlineArrayType(InlineArrayCandidate candidate) public FieldDesc GetPInvokeLazyFixupField(MethodDesc method, MethodSignature nativeSig) { - var fieldDesc = _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method); - fieldDesc.NativeSignature = nativeSig; - return fieldDesc; + return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(new (method, nativeSig)); } public MethodDesc GetPInvokeCalliStub(MethodSignature signature, ModuleDesc moduleContext) @@ -448,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) @@ -460,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) @@ -470,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;