I went through RuntimeImports looking for things that looked unnecessary. The rest of this PR is basically "stuff that came out after pulling on a loose thread of a sweater".
ASM_SIZEOF( 8, 10, InterfaceDispatchCacheEntry)
#endif
-#ifdef FEATURE_DYNAMIC_CODE
-ASM_OFFSET( 0, 0, CallDescrData, pSrc)
-ASM_OFFSET( 4, 8, CallDescrData, numStackSlots)
-ASM_OFFSET( 8, C, CallDescrData, fpReturnSize)
-ASM_OFFSET( C, 10, CallDescrData, pArgumentRegisters)
-ASM_OFFSET( 10, 18, CallDescrData, pFloatArgumentRegisters)
-ASM_OFFSET( 14, 20, CallDescrData, pTarget)
-ASM_OFFSET( 18, 28, CallDescrData, pReturnBuffer)
-#endif
-
// Undefine macros that are only used in this header for convenience.
#undef ASM_OFFSET
#undef ASM_SIZEOF
#include "RuntimeInstance.h"
#include "CachedInterfaceDispatch.h"
#include "shash.h"
-#include "CallDescr.h"
class AsmOffsets
{
list(APPEND RUNTIME_SOURCES_ARCH_ASM
${ARCH_SOURCES_DIR}/AllocFast.${ASM_SUFFIX}
- ${ARCH_SOURCES_DIR}/CallDescrWorker.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/ExceptionHandling.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/GcProbe.${ASM_SUFFIX}
${ARCH_SOURCES_DIR}/Interlocked.${ASM_SUFFIX}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-struct CallDescrData
-{
- uint8_t* pSrc;
- int numStackSlots;
- int fpReturnSize;
- uint8_t* pArgumentRegisters;
- uint8_t* pFloatArgumentRegisters;
- void* pTarget;
- void* pReturnBuffer;
-};
return NULL;
}
-COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleFromEEType, (MethodTable * pEEType))
-{
- return pEEType->GetTypeManagerPtr()->AsTypeManager()->GetOsModuleHandle();
-}
-
-COOP_PINVOKE_HELPER(TypeManagerHandle, RhGetModuleFromEEType, (MethodTable * pEEType))
-{
- return *pEEType->GetTypeManagerPtr();
-}
-
COOP_PINVOKE_HELPER(FC_BOOL_RET, RhFindBlob, (TypeManagerHandle *pTypeManagerHandle, uint32_t blobId, uint8_t ** ppbBlob, uint32_t * pcbBlob))
{
TypeManagerHandle typeManagerHandle = *pTypeManagerHandle;
return pCodeOrg;
}
-// Get the universal transition thunk. If the universal transition stub is called through
-// the normal PE static linkage model, a jump stub would be used which may interfere with
-// the custom calling convention of the universal transition thunk. So instead, a special
-// api just for getting the thunk address is needed.
-// TODO: On ARM this may still result in a jump stub that trashes R12. Determine if anything
-// needs to be done about that when we implement the stub for ARM.
-extern "C" void RhpUniversalTransition();
-COOP_PINVOKE_HELPER(void*, RhGetUniversalTransitionThunk, ())
-{
- return (void*)RhpUniversalTransition;
-}
-
extern CrstStatic g_ThunkPoolLock;
EXTERN_C NATIVEAOT_API void __cdecl RhpAcquireThunkPoolLock()
REDHAWK_PALIMPORT uint32_t REDHAWK_PALAPI PalEventWrite(REGHANDLE arg1, const EVENT_DESCRIPTOR * arg2, uint32_t arg3, EVENT_DATA_DESCRIPTOR * arg4);
#endif
-REDHAWK_PALIMPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer);
-
REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalAllocateThunksFromTemplate(_In_ HANDLE hTemplateModule, uint32_t templateRva, size_t templateSize, _Outptr_result_bytebuffer_(templateSize) void** newThunksOut);
REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalFreeThunksFromTemplate(_In_ void *pBaseAddress);
#include "shash.inl"
-#ifndef DACCESS_COMPILE
-COOP_PINVOKE_HELPER(uint8_t *, RhSetErrorInfoBuffer, (uint8_t * pNewBuffer))
-{
- return (uint8_t *) PalSetWerDataBuffer(pNewBuffer);
-}
-#endif // DACCESS_COMPILE
-
-
ThreadStore * RuntimeInstance::GetThreadStore()
{
return m_pThreadStore;
EXTERN_C PTR_VOID PointerToReturnFromUniversalTransition_DebugStepTailCall;
GVAL_IMPL_INIT(PTR_VOID, g_ReturnFromUniversalTransition_DebugStepTailCallAddr, PointerToReturnFromUniversalTransition_DebugStepTailCall);
-
-EXTERN_C PTR_VOID PointerToReturnFromCallDescrThunk;
-GVAL_IMPL_INIT(PTR_VOID, g_ReturnFromCallDescrThunkAddr, PointerToReturnFromCallDescrThunk);
#endif
#ifdef TARGET_X86
#define STACK_ALIGN_SIZE 4
#endif
-#ifdef TARGET_AMD64
-struct CALL_DESCR_CONTEXT
-{
- uintptr_t Rbp;
- uintptr_t Rsi;
- uintptr_t Rbx;
- uintptr_t IP;
-};
-#elif defined(TARGET_ARM)
-struct CALL_DESCR_CONTEXT
-{
- uintptr_t R4;
- uintptr_t R5;
- uintptr_t R7;
- uintptr_t IP;
-};
-#elif defined(TARGET_ARM64)
-struct CALL_DESCR_CONTEXT
-{
- uintptr_t FP;
- uintptr_t IP;
- uintptr_t X19;
- uintptr_t X20;
-};
-#elif defined(TARGET_X86)
-struct CALL_DESCR_CONTEXT
-{
- uintptr_t Rbx;
- uintptr_t Rbp;
- uintptr_t IP;
-};
-#elif defined (TARGET_WASM)
-struct CALL_DESCR_CONTEXT
-{
- uintptr_t IP;
-};
-#else
-#error NYI - For this arch
-#endif
-
-typedef DPTR(CALL_DESCR_CONTEXT) PTR_CALL_DESCR_CONTEXT;
-
-void StackFrameIterator::UnwindCallDescrThunk()
-{
- ASSERT((m_dwFlags & MethodStateCalculated) == 0);
-
-#if defined(USE_PORTABLE_HELPERS) // @TODO: Corresponding helper code is only defined in assembly code
- return;
-#else // defined(USE_PORTABLE_HELPERS)
- ASSERT(CategorizeUnadjustedReturnAddress(m_ControlPC) == InCallDescrThunk);
-
- uintptr_t newSP;
-#ifdef TARGET_AMD64
- // RBP points to the SP that we want to capture. (This arrangement allows for
- // the arguments from this function to be loaded into memory with an adjustment
- // to SP, like an alloca
- newSP = *(PTR_UIntNative)m_RegDisplay.pRbp;
-
- PTR_CALL_DESCR_CONTEXT pContext = (PTR_CALL_DESCR_CONTEXT)newSP;
-
- m_RegDisplay.pRbp = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rbp);
- m_RegDisplay.pRsi = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rsi);
- m_RegDisplay.pRbx = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rbx);
-
- // And adjust SP to be the state that it should be in just after returning from
- // the CallDescrFunction
- newSP += sizeof(CALL_DESCR_CONTEXT);
-#elif defined(TARGET_ARM)
- // R7 points to the SP that we want to capture. (This arrangement allows for
- // the arguments from this function to be loaded into memory with an adjustment
- // to SP, like an alloca
- newSP = *(PTR_UIntNative)m_RegDisplay.pR7;
- PTR_CALL_DESCR_CONTEXT pContext = (PTR_CALL_DESCR_CONTEXT)newSP;
-
- m_RegDisplay.pR4 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, R4);
- m_RegDisplay.pR5 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, R5);
- m_RegDisplay.pR7 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, R7);
-
- // And adjust SP to be the state that it should be in just after returning from
- // the CallDescrFunction
- newSP += sizeof(CALL_DESCR_CONTEXT);
-
-#elif defined(TARGET_ARM64)
- // pFP points to the SP that we want to capture. (This arrangement allows for
- // the arguments from this function to be loaded into memory with an adjustment
- // to SP, like an alloca
- newSP = *(PTR_UIntNative)m_RegDisplay.pFP;
- PTR_CALL_DESCR_CONTEXT pContext = (PTR_CALL_DESCR_CONTEXT)newSP;
-
- m_RegDisplay.pX19 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, X19);
- m_RegDisplay.pX20 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, X20);
-
- // And adjust SP to be the state that it should be in just after returning from
- // the CallDescrFunction
- newSP += sizeof(CALL_DESCR_CONTEXT);
-
-#elif defined(TARGET_X86)
- // RBP points to the SP that we want to capture. (This arrangement allows for
- // the arguments from this function to be loaded into memory with an adjustment
- // to SP, like an alloca
- newSP = *(PTR_UIntNative)m_RegDisplay.pRbp;
-
- PTR_CALL_DESCR_CONTEXT pContext = (PTR_CALL_DESCR_CONTEXT)(newSP - offsetof(CALL_DESCR_CONTEXT, Rbp));
-
- m_RegDisplay.pRbp = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rbp);
- m_RegDisplay.pRbx = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rbx);
-
- // And adjust SP to be the state that it should be in just after returning from
- // the CallDescrFunction
- newSP += sizeof(CALL_DESCR_CONTEXT) - offsetof(CALL_DESCR_CONTEXT, Rbp);
-
-#else
- PORTABILITY_ASSERT("UnwindCallDescrThunk");
- PTR_CALL_DESCR_CONTEXT pContext = NULL;
-#endif
-
- m_RegDisplay.SetAddrOfIP(PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, IP));
- m_RegDisplay.SetIP(pContext->IP);
- m_RegDisplay.SetSP(newSP);
- SetControlPC(dac_cast<PTR_VOID>(pContext->IP));
-
-#endif // defined(USE_PORTABLE_HELPERS)
-}
-
void StackFrameIterator::UnwindThrowSiteThunk()
{
ASSERT((m_dwFlags & MethodStateCalculated) == 0);
{
ASSERT(m_pConservativeStackRangeLowerBound == NULL);
- if (category == InCallDescrThunk)
- {
- UnwindCallDescrThunk();
- }
- else if (category == InUniversalTransitionThunk)
+ if (category == InUniversalTransitionThunk)
{
UnwindUniversalTransitionThunk();
ASSERT(m_pConservativeStackRangeLowerBound != NULL);
default:
return false;
case InUniversalTransitionThunk:
- case InCallDescrThunk:
return true;
}
}
#else // defined(USE_PORTABLE_HELPERS)
#if defined(FEATURE_DYNAMIC_CODE)
- if (EQUALS_RETURN_ADDRESS(returnAddress, ReturnFromCallDescrThunk))
- {
- return InCallDescrThunk;
- }
- else if (EQUALS_RETURN_ADDRESS(returnAddress, ReturnFromUniversalTransition) ||
+ if (EQUALS_RETURN_ADDRESS(returnAddress, ReturnFromUniversalTransition) ||
EQUALS_RETURN_ADDRESS(returnAddress, ReturnFromUniversalTransition_DebugStepTailCall))
{
return InUniversalTransitionThunk;
// NOTE: This function always publishes a non-NULL conservative stack range lower bound.
void UnwindUniversalTransitionThunk();
- // If our control PC indicates that we're in the call descr thunk that we use to call an arbitrary managed
- // function with an arbitrary signature from a normal managed function handle the stack walk specially.
- void UnwindCallDescrThunk();
-
void EnterInitialInvalidState(Thread * pThreadToWalk);
void InternalInit(Thread * pThreadToWalk, PTR_PInvokeTransitionFrame pFrame, uint32_t dwFlags); // GC stackwalk
InThrowSiteThunk,
InFuncletInvokeThunk,
InFilterFuncletInvokeThunk,
- InCallDescrThunk,
InUniversalTransitionThunk,
};
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-.intel_syntax noprefix
-#include <unixasmmacros.inc>
-
-NESTED_ENTRY RhCallDescrWorker, _TEXT, NoHandler
-
- EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk
-
- // UNIXTODO: Implement this function
- int 3
-NESTED_END RhCallDescrWorker, _TEXT
+++ /dev/null
-;; Licensed to the .NET Foundation under one or more agreements.
-;; The .NET Foundation licenses this file to you under the MIT license.
-
-include AsmMacros.inc
-
-
-;;;;;;;;;;;;;;;;;;;;;;; CallingConventionConverter Thunks Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;extern "C" void RhCallDescrWorker(CallDescrData * pCallDescrData);
-
- NESTED_ENTRY RhCallDescrWorker, _TEXT
-
- push_nonvol_reg rbx ; save nonvolatile registers
- push_nonvol_reg rsi ;
- push_nonvol_reg rbp ;
- set_frame rbp, 0 ; set frame pointer
-
- END_PROLOGUE
-
- mov rbx, rcx ; save pCallDescrData in rbx
-
- mov ecx, dword ptr [rbx + OFFSETOF__CallDescrData__numStackSlots]
-
- test ecx, 1
- jz StackAligned
- push rax
-StackAligned:
-
- mov rsi, [rbx + OFFSETOF__CallDescrData__pSrc] ; set source argument list address
- lea rsi, [rsi + 8 * rcx]
-
-StackCopyLoop: ; copy the arguments to stack top-down to carefully probe for sufficient
- ; stack space
- sub rsi, 8
- push qword ptr [rsi]
- dec ecx
- jnz StackCopyLoop
-
- ;
- ; N.B. All four argument registers are loaded regardless of the actual number
- ; of arguments.
- ;
-
- mov rax, [rbx + OFFSETOF__CallDescrData__pFloatArgumentRegisters] ; get floating pointer arg registers pointer
-
- mov rcx, 0[rsp] ; load first four argument registers
- mov rdx, 8[rsp] ;
- mov r8, 10h[rsp] ;
- mov r9, 18h[rsp] ;
- test rax, rax ;
- jz DoCall ;
- movdqa xmm0, [rax + 00h] ; load floating point registers if they are used
- movdqa xmm1, [rax + 10h] ;
- movdqa xmm2, [rax + 20h] ;
- movdqa xmm3, [rax + 30h] ;
-DoCall:
- call qword ptr [rbx + OFFSETOF__CallDescrData__pTarget] ; call target function
-
- EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk
-
- ; Symbol used to identify thunk call to managed function so the special
- ; case unwinder can unwind through this function. Sadly we cannot directly
- ; export this symbol right now because it confuses DIA unwinder to believe
- ; it's the beginning of a new method, therefore we export the address
- ; of an auxiliary variable holding the address instead.
-
- ; Save FP return value
-
- mov ecx, dword ptr [rbx + OFFSETOF__CallDescrData__fpReturnSize]
- test ecx, ecx
- jz ReturnsInt
-
- cmp ecx, 4
- je ReturnsFloat
- cmp ecx, 8
- je ReturnsDouble
- ; unexpected
- jmp Epilog
-
-ReturnsInt:
- mov rbx, [rbx + OFFSETOF__CallDescrData__pReturnBuffer]
- mov [rbx], rax
-
-Epilog:
- lea rsp, 0[rbp] ; deallocate argument list
- pop rbp ; restore nonvolatile register
- pop rsi ;
- pop rbx ;
- ret
-
-ReturnsFloat:
-; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
- mov rbx, [rbx + OFFSETOF__CallDescrData__pReturnBuffer]
- movss real4 ptr [rbx], xmm0
- jmp Epilog
-
-ReturnsDouble:
-; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
- mov rbx, [rbx + OFFSETOF__CallDescrData__pReturnBuffer]
- movsd real8 ptr [rbx], xmm0
- jmp Epilog
-
- NESTED_END RhCallDescrWorker, _TEXT
-
-end
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-.syntax unified
-.thumb
-
-#include <AsmOffsets.inc> // generated by the build from AsmOffsets.cpp
-#include <unixasmmacros.inc>
-
-// TODO: Implement Arm support
-
-NESTED_ENTRY RhCallDescrWorker, _TEXT, NoHandler
-LOCAL_LABEL(ReturnFromCallDescrThunk):
-
- EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk
-
- // UNIXTODO: Implement this function
- EMIT_BREAKPOINT
-NESTED_END RhCallDescrWorker, _TEXT
-
+++ /dev/null
-;; Licensed to the .NET Foundation under one or more agreements.
-;; The .NET Foundation licenses this file to you under the MIT license.
-
-#include "AsmMacros.h"
-
- TEXTAREA
-
-;;-----------------------------------------------------------------------------
-;; This helper routine enregisters the appropriate arguments and makes the
-;; actual call.
-;;-----------------------------------------------------------------------------
-;;void RhCallDescrWorker(CallDescrData * pCallDescrData);
- NESTED_ENTRY RhCallDescrWorker
- PROLOG_PUSH {r4,r5,r7,lr}
- PROLOG_STACK_SAVE r7
-
- mov r5,r0 ; save pCallDescrData in r5
-
- ldr r1, [r5,#OFFSETOF__CallDescrData__numStackSlots]
- cbz r1, Ldonestack
-
- ;; Add frame padding to ensure frame size is a multiple of 8 (a requirement of the OS ABI).
- ;; We push four registers (above) and numStackSlots arguments (below). If this comes to an odd number
- ;; of slots we must pad with another. This simplifies to "if the low bit of numStackSlots is set,
- ;; extend the stack another four bytes".
- lsls r2, r1, #2
- and r3, r2, #4
- sub sp, sp, r3
-
- ;; This loop copies numStackSlots words
- ;; from [pSrcEnd-4,pSrcEnd-8,...] to [sp-4,sp-8,...]
- ldr r0, [r5,#OFFSETOF__CallDescrData__pSrc]
- add r0,r0,r2
-Lstackloop
- ldr r2, [r0,#-4]!
- str r2, [sp,#-4]!
- subs r1, r1, #1
- bne Lstackloop
-Ldonestack
-
- ;; If FP arguments are supplied in registers (r3 != NULL) then initialize all of them from the pointer
- ;; given in r3. Do not use "it" since it faults in floating point even when the instruction is not executed.
- ldr r3, [r5,#OFFSETOF__CallDescrData__pFloatArgumentRegisters]
- cbz r3, LNoFloatingPoint
- vldm r3, {s0-s15}
-LNoFloatingPoint
-
- ;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 12]
- ;; into r0, ..., r3
-
- ldr r4, [r5,#OFFSETOF__CallDescrData__pArgumentRegisters]
- ldm r4, {r0-r3}
-
- CHECK_STACK_ALIGNMENT
-
- ;; call pTarget
- ;; Note that remoting expect target in r4.
- ldr r4, [r5,#OFFSETOF__CallDescrData__pTarget]
- blx r4
-
- EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk
-
- ;; Symbol used to identify thunk call to managed function so the special
- ;; case unwinder can unwind through this function. Sadly we cannot directly
- ;; export this symbol right now because it confuses DIA unwinder to believe
- ;; it's the beginning of a new method, therefore we export the address
- ;; of an auxiliary variable holding the address instead.
-
- ldr r3, [r5,#OFFSETOF__CallDescrData__fpReturnSize]
-
- ;; Save FP return value if appropriate
- cbz r3, LFloatingPointReturnDone
-
- ;; Float return case
- ;; Do not use "it" since it faults in floating point even when the instruction is not executed.
- cmp r3, #4
- bne LNoFloatReturn
- vmov r0, s0
- b LFloatingPointReturnDone
-LNoFloatReturn
-
- ;; Double return case
- ;; Do not use "it" since it faults in floating point even when the instruction is not executed.
- cmp r3, #8
- bne LNoDoubleReturn
- vmov r0, r1, s0, s1
- b LFloatingPointReturnDone
-LNoDoubleReturn
-; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
- ldr r2, [r5, #OFFSETOF__CallDescrData__pReturnBuffer]
-
- cmp r3, #16
- bne LNoFloatHFAReturn
- vstm r2, {s0-s3}
- b LReturnDone
-LNoFloatHFAReturn
-
- cmp r3, #32
- bne LNoDoubleHFAReturn
- vstm r2, {d0-d3}
- b LReturnDone
-LNoDoubleHFAReturn
-
- EMIT_BREAKPOINT ; Unreachable
-
-LFloatingPointReturnDone
-
-; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
- ldr r5, [r5, #OFFSETOF__CallDescrData__pReturnBuffer]
-
- ;; Save return value into retbuf
- str r0, [r5, #(0)]
- str r1, [r5, #(4)]
-
-LReturnDone
-
-#ifdef _DEBUG
- ;; trash the floating point registers to ensure that the HFA return values
- ;; won't survive by accident
- vldm sp, {d0-d3}
-#endif
-
- EPILOG_STACK_RESTORE r7
- EPILOG_POP {r4,r5,r7,pc}
-
- NESTED_END RhCallDescrWorker
-
- END
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#include <unixasmmacros.inc>
-#include "AsmOffsets.inc"
-
-//-----------------------------------------------------------------------------
-// This helper routine enregisters the appropriate arguments and makes the
-// actual call.
-//
-// INPUT: x0: pointer to CallDescrData struct
-//
-//-----------------------------------------------------------------------------
-//void RhCallDescrWorker(CallDescrData * pCallDescrData);
- NESTED_ENTRY RhCallDescrWorker, _TEXT, NoHandler
-
- PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32
- PROLOG_SAVE_REG_PAIR x19, x20, 16
-
- // Save the value of SP before we start pushing any arguments
- mov x20, sp
-
- mov x19, x0 // save pCallDescrData in x19
-
- ldr w1, [x19, #OFFSETOF__CallDescrData__numStackSlots]
- cbz w1, Ldonestack
-
- // Add frame padding to ensure frame size is a multiple of 16 (a requirement of the OS ABI).
- // We push two registers (above) and numStackSlots arguments (below). If this comes to an odd number
- // of slots we must pad with another. This simplifies to "if the low bit of numStackSlots is set,
- // extend the stack another eight bytes".
- ldr x0, [x19, #OFFSETOF__CallDescrData__pSrc]
- add x0, x0, x1, lsl #3 // pSrcEnd=pSrc+8*numStackSlots
- ands x2, x1, #1
- beq Lstackloop
-
- // This loop copies numStackSlots words
- // from [pSrcEnd-8,pSrcEnd-16,...] to [sp-8,sp-16,...]
-
- // Pad and store one stack slot as number of slots are odd
- ldr x4, [x0,#-8]!
- str x4, [sp,#-16]!
- subs x1, x1, #1
- beq Ldonestack
-Lstackloop:
- ldp x2, x4, [x0,#-16]!
- stp x2, x4, [sp,#-16]!
- subs x1, x1, #2
- bne Lstackloop
-Ldonestack:
-
- // If FP arguments are supplied in registers (x9 != NULL) then initialize all of them from the pointer
- // given in x9.
- ldr x9, [x19, #OFFSETOF__CallDescrData__pFloatArgumentRegisters]
- cbz x9, LNoFloatingPoint
- ldp d0, d1, [x9]
- ldp d2, d3, [x9, #16]
- ldp d4, d5, [x9, #32]
- ldp d6, d7, [x9, #48]
-LNoFloatingPoint:
-
- // Copy [pArgumentRegisters, ..., pArgumentRegisters + 64]
- // into x0, ..., x7, x8
-
- ldr x9, [x19, #OFFSETOF__CallDescrData__pArgumentRegisters]
- ldp x0, x1, [x9]
- ldp x2, x3, [x9, #16]
- ldp x4, x5, [x9, #32]
- ldp x6, x7, [x9, #48]
- ldr x8, [x9, #64]
-
- // call pTarget
- ldr x9, [x19, #OFFSETOF__CallDescrData__pTarget]
- blr x9
-
- EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk
-
- // Symbol used to identify thunk call to managed function so the special
- // case unwinder can unwind through this function. Sadly we cannot directly
- // export this symbol right now because it confuses DIA unwinder to believe
- // it's the beginning of a new method, therefore we export the address
- // of an auxiliary variable holding the address instead.
-
- ldr w3, [x19, #OFFSETOF__CallDescrData__fpReturnSize]
-
- // Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
- ldr x19, [x19, #OFFSETOF__CallDescrData__pReturnBuffer]
-
- // Int return case
- cbz w3, LIntReturn
-
- // Float return case
- cmp w3, #4
- beq LFloatOrDoubleReturn
-
- // Double return case
- cmp w3, #8
- bne LCheckHFAReturn
-
-LFloatOrDoubleReturn:
- str d0, [x19]
- b LReturnDone
-
-LCheckHFAReturn:
- cmp w3, #16
- beq LFloatOrDoubleHFAReturn
- cmp w3, #32
- beq LFloatOrDoubleHFAReturn
- b LNoHFAReturn
-
-LFloatOrDoubleHFAReturn:
- //Single/Double HFAReturn return case
- stp d0, d1, [x19, #00]
- stp d2, d3, [x19, #16]
- b LReturnDone
-
-LNoHFAReturn:
-
- EMIT_BREAKPOINT // Unreachable
-
-LIntReturn:
- // Save return value(s) into retbuf for int
- stp x0, x1, [x19]
-
-LReturnDone:
-
-#ifdef _DEBUG
- // Trash the floating point registers to ensure that the HFA return values
- // won't survive by accident
- ldp d0, d1, [sp]
- ldp d2, d3, [sp, #16]
-#endif
- // Restore the value of SP
- mov sp, x20
-
- EPILOG_RESTORE_REG_PAIR x19, x20, 16
- EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 32
- EPILOG_RETURN
-
- NESTED_END RhCallDescrWorker
+++ /dev/null
-;; Licensed to the .NET Foundation under one or more agreements.
-;; The .NET Foundation licenses this file to you under the MIT license.
-
-#include "AsmMacros.h"
-
- TEXTAREA
-
-;;-----------------------------------------------------------------------------
-;; This helper routine enregisters the appropriate arguments and makes the
-;; actual call.
-;;
-;; INPUT: x0: pointer to CallDescrData struct
-;;
-;;-----------------------------------------------------------------------------
-;;void RhCallDescrWorker(CallDescrData * pCallDescrData);
- NESTED_ENTRY RhCallDescrWorker
-
- PROLOG_SAVE_REG_PAIR fp, lr, #-32!
- PROLOG_SAVE_REG_PAIR x19, x20, #16
-
- ;; Save the value of SP before we start pushing any arguments
- mov x20, sp
-
- mov x19, x0 ; save pCallDescrData in x19
-
- ldr w1, [x19, #OFFSETOF__CallDescrData__numStackSlots]
- cbz w1, Ldonestack
-
- ;; Add frame padding to ensure frame size is a multiple of 16 (a requirement of the OS ABI).
- ;; We push two registers (above) and numStackSlots arguments (below). If this comes to an odd number
- ;; of slots we must pad with another. This simplifies to "if the low bit of numStackSlots is set,
- ;; extend the stack another eight bytes".
- ldr x0, [x19, #OFFSETOF__CallDescrData__pSrc]
- add x0, x0, x1 lsl #3 ; pSrcEnd=pSrc+8*numStackSlots
- ands x2, x1, #1
- beq Lstackloop
-
- ;; This loop copies numStackSlots words
- ;; from [pSrcEnd-8,pSrcEnd-16,...] to [sp-8,sp-16,...]
-
- ;; Pad and store one stack slot as number of slots are odd
- ldr x4, [x0,#-8]!
- str x4, [sp,#-16]!
- subs x1, x1, #1
- beq Ldonestack
-Lstackloop
- ldp x2, x4, [x0,#-16]!
- stp x2, x4, [sp,#-16]!
- subs x1, x1, #2
- bne Lstackloop
-Ldonestack
-
- ;; If FP arguments are supplied in registers (x9 != NULL) then initialize all of them from the pointer
- ;; given in x9.
- ldr x9, [x19, #OFFSETOF__CallDescrData__pFloatArgumentRegisters]
- cbz x9, LNoFloatingPoint
- ldp d0, d1, [x9]
- ldp d2, d3, [x9, #16]
- ldp d4, d5, [x9, #32]
- ldp d6, d7, [x9, #48]
-LNoFloatingPoint
-
- ;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 64]
- ;; into x0, ..., x7, x8
-
- ldr x9, [x19, #OFFSETOF__CallDescrData__pArgumentRegisters]
- ldp x0, x1, [x9]
- ldp x2, x3, [x9, #16]
- ldp x4, x5, [x9, #32]
- ldp x6, x7, [x9, #48]
- ldr x8, [x9, #64]
-
- ;; call pTarget
- ldr x9, [x19, #OFFSETOF__CallDescrData__pTarget]
- blr x9
-
- EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk
-
- ;; Symbol used to identify thunk call to managed function so the special
- ;; case unwinder can unwind through this function. Sadly we cannot directly
- ;; export this symbol right now because it confuses DIA unwinder to believe
- ;; it's the beginning of a new method, therefore we export the address
- ;; of an auxiliary variable holding the address instead.
-
- ldr w3, [x19, #OFFSETOF__CallDescrData__fpReturnSize]
-
- ;; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
- ldr x19, [x19, #OFFSETOF__CallDescrData__pReturnBuffer]
-
- ;; Int return case
- cbz w3, LIntReturn
-
- ;; Float return case
- cmp w3, #4
- beq LFloatOrDoubleReturn
-
- ;; Double return case
- cmp w3, #8
- bne LCheckHFAReturn
-
-LFloatOrDoubleReturn
- str d0, [x19]
- b LReturnDone
-
-LCheckHFAReturn
- cmp w3, #16
- beq LFloatOrDoubleHFAReturn
- cmp w3, #32
- beq LFloatOrDoubleHFAReturn
- b LNoHFAReturn
-
-LFloatOrDoubleHFAReturn
- ;;Single/Double HFAReturn return case
- stp d0, d1, [x19, #00]
- stp d2, d3, [x19, #16]
- b LReturnDone
-
-LNoHFAReturn
-
- EMIT_BREAKPOINT ; Unreachable
-
-LIntReturn
- ;; Save return value(s) into retbuf for int
- stp x0, x1, [x19]
-
-LReturnDone
-
-#ifdef _DEBUG
- ;; Trash the floating point registers to ensure that the HFA return values
- ;; won't survive by accident
- ldp d0, d1, [sp]
- ldp d2, d3, [sp, #16]
-#endif
- ;; Restore the value of SP
- mov sp, x20
-
- EPILOG_RESTORE_REG_PAIR x19, x20, #16
- EPILOG_RESTORE_REG_PAIR fp, lr, #32!
- EPILOG_RETURN
-
- NESTED_END RhCallDescrWorker
-
- END
+++ /dev/null
-;; Licensed to the .NET Foundation under one or more agreements.
-;; The .NET Foundation licenses this file to you under the MIT license.
-
- .586
- .model flat
- option casemap:none
- .code
-
-include AsmMacros.inc
-
-ifdef FEATURE_DYNAMIC_CODE
-;;;;;;;;;;;;;;;;;;;;;;; CallingConventionConverter Thunks Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;------------------------------------------------------------------------------
-; This helper routine enregisters the appropriate arguments and makes the
-; actual call.
-;------------------------------------------------------------------------------
-; void __fastcall CallDescrWorker(CallDescrWorkerParams * pParams)
-FASTCALL_FUNC RhCallDescrWorker, 4
- push ebp
- mov ebp, esp
- push ebx
- mov ebx, ecx
-
- mov ecx, [ebx + OFFSETOF__CallDescrData__numStackSlots]
- mov eax, [ebx + OFFSETOF__CallDescrData__pSrc] ; copy the stack
- test ecx, ecx
- jz donestack
- lea eax, [eax + 4 * ecx - 4] ; last argument
- push dword ptr [eax]
- dec ecx
- jz donestack
- sub eax, 4
- push dword ptr [eax]
- dec ecx
- jz donestack
-stackloop:
- sub eax, 4
- push dword ptr [eax]
- dec ecx
- jnz stackloop
-donestack:
-
- ; now we must push each field of the ArgumentRegister structure
- mov eax, [ebx + OFFSETOF__CallDescrData__pArgumentRegisters]
- mov edx, dword ptr [eax]
- mov ecx, dword ptr [eax + 4]
- mov eax,[ebx + OFFSETOF__CallDescrData__pTarget]
- call eax
-
- EXPORT_POINTER_TO_ADDRESS _PointerToReturnFromCallDescrThunk
-
- ; Symbol used to identify thunk call to managed function so the special
- ; case unwinder can unwind through this function. Sadly we cannot directly
- ; export this symbol right now because it confuses DIA unwinder to believe
- ; it's the beginning of a new method, therefore we export the address
- ; by means of an auxiliary variable.
-
- ; Save FP return value if necessary
- mov ecx, [ebx + OFFSETOF__CallDescrData__fpReturnSize]
- cmp ecx, 0
- je ReturnsInt
-
- cmp ecx, 4
- je ReturnsFloat
- cmp ecx, 8
- je ReturnsDouble
- ; unexpected
- jmp Epilog
-
-ReturnsInt:
-; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself
- mov ebx, [ebx + OFFSETOF__CallDescrData__pReturnBuffer]
- mov [ebx], eax
- mov [ebx + 4], edx
-
-Epilog:
- pop ebx
- pop ebp
- retn
-
-ReturnsFloat:
- mov ebx, [ebx + OFFSETOF__CallDescrData__pReturnBuffer]
- fstp dword ptr [ebx] ; Spill the Float return value
- jmp Epilog
-
-ReturnsDouble:
- mov ebx, [ebx + OFFSETOF__CallDescrData__pReturnBuffer]
- fstp qword ptr [ebx] ; Spill the Double return value
- jmp Epilog
-
-FASTCALL_ENDFUNC
-
-endif
-
-end
#endif // USE_PORTABLE_HELPERS
-// @TODO Implement CallDescrThunk
-EXTERN_C void * ReturnFromCallDescrThunk;
-#ifdef USE_PORTABLE_HELPERS
-void * ReturnFromCallDescrThunk;
-#endif
-
#if defined(USE_PORTABLE_HELPERS)
//
// Return address hijacking
return 0;
}
-COOP_PINVOKE_HELPER(void, RhCallDescrWorker, (void * callDescr))
-{
- ASSERT_UNCONDITIONALLY("NYI");
-}
-
COOP_PINVOKE_HELPER(void *, RhGetCommonStubAddress, ())
{
ASSERT_UNCONDITIONALLY("NYI");
#endif
}
-REDHAWK_PALEXPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer)
-{
- static void* pBuffer;
- return PalInterlockedExchangePointer(&pBuffer, pNewBuffer);
-}
-
extern "C" HANDLE GetCurrentProcess()
{
return (HANDLE)-1;
FlushInstructionCache(GetCurrentProcess(), pAddress, size);
}
-REDHAWK_PALEXPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer)
-{
- static void* pBuffer;
- return InterlockedExchangePointer(&pBuffer, pNewBuffer);
-}
-
#if defined(HOST_ARM64)
#include "IntrinsicConstants.h"
return typeHandle.ToEETypePtr().RawValue;
}
- public static TypeManagerHandle GetModuleFromTypeHandle(RuntimeTypeHandle typeHandle)
+ public static unsafe TypeManagerHandle GetModuleFromTypeHandle(RuntimeTypeHandle typeHandle)
{
- return RuntimeImports.RhGetModuleFromEEType(GetPointerFromTypeHandle(typeHandle));
+ return typeHandle.ToMethodTable()->TypeManager;
}
public static RuntimeTypeHandle CreateRuntimeTypeHandle(IntPtr ldTokenResult)
private static volatile ReflectionExecutionDomainCallbacks s_reflectionExecutionDomainCallbacks;
private static TypeLoaderCallbacks s_typeLoaderCallbacks;
- public static void ReportUnhandledException(Exception exception)
- {
- RuntimeExceptionHelpers.ReportUnhandledException(exception);
- }
-
- public static unsafe RuntimeTypeHandle GetRuntimeTypeHandleFromObjectReference(object obj)
- {
- return new RuntimeTypeHandle(obj.GetEETypePtr());
- }
-
- public static IntPtr GetUniversalTransitionThunk()
- {
- return RuntimeImports.RhGetUniversalTransitionThunk();
- }
-
public static object CreateThunksHeap(IntPtr commonStubAddress)
{
object newHeap = RuntimeImports.RhCreateThunksHeap(commonStubAddress);
return RuntimeImports.RhGetThunkSize();
}
- [DebuggerStepThrough]
- /* TEMP workaround due to bug 149078 */
- [MethodImpl(MethodImplOptions.NoInlining)]
- public static void CallDescrWorker(IntPtr callDescr)
- {
- RuntimeImports.RhCallDescrWorker(callDescr);
- }
-
- [DebuggerStepThrough]
- /* TEMP workaround due to bug 149078 */
- [MethodImpl(MethodImplOptions.NoInlining)]
- public static void CallDescrWorkerNative(IntPtr callDescr)
- {
- RuntimeImports.RhCallDescrWorkerNative(callDescr);
- }
-
public static Delegate CreateObjectArrayDelegate(Type delegateType, Func<object?[], object?> invoker)
{
return Delegate.CreateObjectArrayDelegate(delegateType, invoker);
[RuntimeImport(RuntimeLibrary, "RhBoxAny")]
internal static extern unsafe object RhBoxAny(ref byte pData, MethodTable* pEEType);
- internal static unsafe object RhBoxAny(ref byte pData, EETypePtr pEEType)
- => RhBoxAny(ref pData, pEEType.ToPointer());
-
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhNewObject")]
internal static extern unsafe object RhNewObject(MethodTable* pEEType);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhResolveDispatchOnType")]
- // For my life cannot figure out the ordering of modifiers this is expecting.
-#pragma warning disable IDE0036
internal static extern unsafe IntPtr RhResolveDispatchOnType(EETypePtr instanceType, EETypePtr interfaceType, ushort slot, EETypePtr* pGenericContext);
internal static unsafe IntPtr RhResolveDispatchOnType(EETypePtr instanceType, EETypePtr interfaceType, ushort slot)
internal static extern IntPtr RhGetOSModuleFromPointer(IntPtr pointerVal);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- [RuntimeImport(RuntimeLibrary, "RhGetModuleFromEEType")]
- internal static extern TypeManagerHandle RhGetModuleFromEEType(IntPtr pEEType);
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- [RuntimeImport(RuntimeLibrary, "RhGetOSModuleFromEEType")]
- internal static extern IntPtr RhGetOSModuleFromEEType(IntPtr pEEType);
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhGetThreadStaticStorage")]
internal static extern ref object[][] RhGetThreadStaticStorage();
internal static extern unsafe int RhGetModuleFileName(IntPtr moduleHandle, out char* moduleName);
#endif
- // returns the previous value.
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- [RuntimeImport(RuntimeLibrary, "RhSetErrorInfoBuffer")]
- internal static extern unsafe void* RhSetErrorInfoBuffer(void* pNewBuffer);
-
//
// StackTrace helper
//
[RuntimeImport(RuntimeLibrary, "RhSetThreadExitCallback")]
internal static extern unsafe void RhSetThreadExitCallback(delegate* unmanaged<void> pCallback);
- // Functions involved in thunks from managed to managed functions (Universal transition transitions
- // from an arbitrary method call into a defined function, and CallDescrWorker goes the other way.
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- [RuntimeImport(RuntimeLibrary, "RhGetUniversalTransitionThunk")]
- internal static extern IntPtr RhGetUniversalTransitionThunk();
-
- // For Managed to Managed calls
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- [RuntimeImport(RuntimeLibrary, "RhCallDescrWorker")]
- internal static extern void RhCallDescrWorker(IntPtr callDescr);
-
- // For Managed to Native calls
- [LibraryImport(RuntimeLibrary, EntryPoint = "RhCallDescrWorker")]
- internal static partial void RhCallDescrWorkerNative(IntPtr callDescr);
-
// Moves memory from smem to dmem. Size must be a positive value.
// This copy uses an intrinsic to be safe for copying arbitrary bits of
// heap memory