//
inline bool hasFixedRetBuffReg()
{
- // Disable this until the VM changes are also enabled
-#if 0 //def _TARGET_ARM64_
+#ifdef _TARGET_ARM64_
return true;
#else
return false;
bne Lstackloop
Ldonestack
- ;; If FP arguments are supplied in registers (x8 != NULL) then initialize all of them from the pointer
- ;; given in x8.
- ldr x8, [x19,#CallDescrData__pFloatArgumentRegisters]
- cbz x8, LNoFloatingPoint
- ldp d0, d1, [x8]
- ldp d2, d3, [x8, #16]
- ldp d4, d5, [x8, #32]
- ldp d6, d7, [x8, #48]
+ ;; If FP arguments are supplied in registers (x9 != NULL) then initialize all of them from the pointer
+ ;; given in x9.
+ ldr x9, [x19,#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 + 56]
- ;; into x0, ..., x7
+ ;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 64]
+ ;; into x0, ..., x7, x8
- ldr x8, [x19,#CallDescrData__pArgumentRegisters]
- ldp x0, x1, [x8]
- ldp x2, x3, [x8, #16]
- ldp x4, x5, [x8, #32]
- ldp x6, x7, [x8, #48]
+ ldr x9, [x19,#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]
;; ARM64TODO: => see if anything special needs to be done for remoting
;; call pTarget
- ldr x8, [x19,#CallDescrData__pTarget]
- blr x8
+ ldr x9, [x19,#CallDescrData__pTarget]
+ blr x9
ldr w3, [x19,#CallDescrData__fpReturnSize]
#define METHODDESC_REGISTER x12
-#define SIZEOF__ArgumentRegisters 0x40
+#define SIZEOF__ArgumentRegisters 0x48
ASMCONSTANTS_C_ASSERT(SIZEOF__ArgumentRegisters == sizeof(ArgumentRegisters))
#define SIZEOF__FloatArgumentRegisters 0x40
#ifdef FEATURE_COMINTEROP
-#define SIZEOF__ComMethodFrame 0x68
+#define SIZEOF__ComMethodFrame 0x70
ASMCONSTANTS_C_ASSERT(SIZEOF__ComMethodFrame == sizeof(ComMethodFrame));
#define UnmanagedToManagedFrame__m_pvDatum 0x10
; The call in ndirect import precode points to this function.
NESTED_ENTRY NDirectImportThunk
- PROLOG_SAVE_REG_PAIR fp, lr, #-144!
+ PROLOG_SAVE_REG_PAIR fp, lr, #-160!
SAVE_ARGUMENT_REGISTERS sp, 16
- SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80
+ SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88
mov x0, x12
bl NDirectImportWorker
mov x12, x0
; pop the stack and restore original register state
- RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80
+ RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88
RESTORE_ARGUMENT_REGISTERS sp, 16
- EPILOG_RESTORE_REG_PAIR fp, lr, #144!
+ EPILOG_RESTORE_REG_PAIR fp, lr, #160!
; If we got back from NDirectImportWorker, the MD has been successfully
; linked. Proceed to execute the original DLL call.
NESTED_ENTRY VirtualMethodFixupStub
; Save arguments and return address
- PROLOG_SAVE_REG_PAIR fp, lr, #-144!
+ PROLOG_SAVE_REG_PAIR fp, lr, #-160!
SAVE_ARGUMENT_REGISTERS sp, 16
- SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80
+ SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88
; Refer to ZapImportVirtualThunk::Save
; for details on this.
; pop the stack and restore original register state
RESTORE_ARGUMENT_REGISTERS sp, 16
- RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80
- EPILOG_RESTORE_REG_PAIR fp, lr, #144!
+ RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88
+ EPILOG_RESTORE_REG_PAIR fp, lr, #160!
PATCH_LABEL VirtualMethodFixupPatchLabel
GBLA ComCallPreStub_StackAlloc
GBLA ComCallPreStub_FrameOffset
GBLA ComCallPreStub_ErrorReturnOffset
+ GBLA ComCallPreStub_FirstStackAdjust
ComCallPreStub_FrameSize SETA (SIZEOF__GSCookie + SIZEOF__ComMethodFrame)
-ComCallPreStub_StackAlloc SETA ComCallPreStub_FrameSize - SIZEOF__ArgumentRegisters - 2 * 8 ; reg args , fp & lr already pushed
+ComCallPreStub_FirstStackAdjust SETA (SIZEOF__ArgumentRegisters + 2 * 8) ; reg args , fp & lr already pushed
+ComCallPreStub_StackAlloc SETA ComCallPreStub_FrameSize - ComCallPreStub_FirstStackAdjust
ComCallPreStub_StackAlloc SETA ComCallPreStub_StackAlloc + SIZEOF__FloatArgumentRegisters + 8; 8 for ErrorReturn
-
IF ComCallPreStub_StackAlloc:MOD:16 != 0
ComCallPreStub_StackAlloc SETA ComCallPreStub_StackAlloc + 8
ENDIF
-ComCallPreStub_FrameOffset SETA (ComCallPreStub_StackAlloc - (SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters - 2 * 8))
+ComCallPreStub_FrameOffset SETA (ComCallPreStub_StackAlloc - (SIZEOF__ComMethodFrame - ComCallPreStub_FirstStackAdjust))
ComCallPreStub_ErrorReturnOffset SETA SIZEOF__FloatArgumentRegisters
+ IF (ComCallPreStub_FirstStackAdjust):MOD:16 != 0
+ComCallPreStub_FirstStackAdjust SETA ComCallPreStub_FirstStackAdjust + 8
+ ENDIF
+
; Save arguments and return address
- PROLOG_SAVE_REG_PAIR fp, lr, #-80!
+ PROLOG_SAVE_REG_PAIR fp, lr, #-ComCallPreStub_FirstStackAdjust!
PROLOG_STACK_ALLOC ComCallPreStub_StackAlloc
SAVE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc)
RESTORE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc)
EPILOG_STACK_FREE ComCallPreStub_StackAlloc
- EPILOG_RESTORE_REG_PAIR fp, lr, #80!
+ EPILOG_RESTORE_REG_PAIR fp, lr, #ComCallPreStub_FirstStackAdjust!
; and tailcall to the actual method
EPILOG_BRANCH_REG x12
; pop the stack
EPILOG_STACK_FREE ComCallPreStub_StackAlloc
- EPILOG_RESTORE_REG_PAIR fp, lr, #80!
+ EPILOG_RESTORE_REG_PAIR fp, lr, #ComCallPreStub_FirstStackAdjust!
EPILOG_RETURN
GBLA GenericComCallStub_FrameSize
GBLA GenericComCallStub_StackAlloc
GBLA GenericComCallStub_FrameOffset
+ GBLA GenericComCallStub_FirstStackAdjust
GenericComCallStub_FrameSize SETA (SIZEOF__GSCookie + SIZEOF__ComMethodFrame)
-GenericComCallStub_StackAlloc SETA GenericComCallStub_FrameSize - SIZEOF__ArgumentRegisters - 2 * 8
+GenericComCallStub_FirstStackAdjust SETA (SIZEOF__ArgumentRegisters + 2 * 8)
+GenericComCallStub_StackAlloc SETA GenericComCallStub_FrameSize - GenericComCallStub_FirstStackAdjust
GenericComCallStub_StackAlloc SETA GenericComCallStub_StackAlloc + SIZEOF__FloatArgumentRegisters
- IF GenericComCallStub_StackAlloc:MOD:16 != 0
+ IF (GenericComCallStub_StackAlloc):MOD:16 != 0
GenericComCallStub_StackAlloc SETA GenericComCallStub_StackAlloc + 8
ENDIF
-GenericComCallStub_FrameOffset SETA (GenericComCallStub_StackAlloc - (SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters - 2 * 8))
+GenericComCallStub_FrameOffset SETA (GenericComCallStub_StackAlloc - (SIZEOF__ComMethodFrame - GenericComCallStub_FirstStackAdjust))
+
+ IF (GenericComCallStub_FirstStackAdjust):MOD:16 != 0
+GenericComCallStub_FirstStackAdjust SETA GenericComCallStub_FirstStackAdjust + 8
+ ENDIF
+
; Save arguments and return address
- PROLOG_SAVE_REG_PAIR fp, lr, #-80!
+ PROLOG_SAVE_REG_PAIR fp, lr, #-GenericComCallStub_FirstStackAdjust!
PROLOG_STACK_ALLOC GenericComCallStub_StackAlloc
SAVE_ARGUMENT_REGISTERS sp, (16+GenericComCallStub_StackAlloc)
; pop the stack
EPILOG_STACK_FREE GenericComCallStub_StackAlloc
- EPILOG_RESTORE_REG_PAIR fp, lr, #80!
+ EPILOG_RESTORE_REG_PAIR fp, lr, #GenericComCallStub_FirstStackAdjust!
EPILOG_RETURN
ldp x2, x3, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 16)]
ldp x4, x5, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 32)]
ldp x6, x7, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 48)]
+ ldr x8, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 64)]
ldr x1, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 8)]
NESTED_ENTRY TheUMEntryPrestub,,UMEntryPrestubUnwindFrameChainHandler
; Save arguments and return address
- PROLOG_SAVE_REG_PAIR fp, lr, #-144!
+ PROLOG_SAVE_REG_PAIR fp, lr, #-160!
SAVE_ARGUMENT_REGISTERS sp, 16
- SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80
+ SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88
mov x0, x12
bl TheUMEntryPrestubWorker
; pop the stack and restore original register state
RESTORE_ARGUMENT_REGISTERS sp, 16
- RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80
- EPILOG_RESTORE_REG_PAIR fp, lr, #144!
+ RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88
+ EPILOG_RESTORE_REG_PAIR fp, lr, #160!
; and tailcall to the actual method
EPILOG_BRANCH_REG x12
NESTED_ENTRY UMThunkStub,,UMThunkStubUnwindFrameChainHandler
; Save arguments and return address
- PROLOG_SAVE_REG_PAIR fp, lr, #-96! ; 64 for regArgs, 8 for x19 & 8 for x12
+ PROLOG_SAVE_REG_PAIR fp, lr, #-112! ; 72 for regArgs, 8 for x19 & 8 for x12 & 8 for 16-byte align
; save callee saved reg x19. x19 is used in the method to store thread*
- PROLOG_SAVE_REG x19, #88
+ PROLOG_SAVE_REG x19, #96
SAVE_ARGUMENT_REGISTERS sp, 16
GBLA UMThunkStub_HiddenArg ; offset of saved UMEntryThunk *
GBLA UMThunkStub_StackArgs ; offset of original stack args (total size of UMThunkStub frame)
-UMThunkStub_HiddenArg SETA 80
-UMThunkStub_StackArgs SETA 96
+UMThunkStub_HiddenArg SETA 88
+UMThunkStub_StackArgs SETA 112
; save UMEntryThunk*
str x12, [sp, #UMThunkStub_HiddenArg]
str w4, [x19, #Thread__m_fPreemptiveGCDisabled]
EPILOG_STACK_RESTORE
- EPILOG_RESTORE_REG x19, #88
- EPILOG_RESTORE_REG_PAIR fp, lr, #96!
+ EPILOG_RESTORE_REG x19, #96
+ EPILOG_RESTORE_REG_PAIR fp, lr, #112!
EPILOG_RETURN
NESTED_END ResolveWorkerChainLookupAsmStub
;; ------------------------------------------------------------------
-;; void ResolveWorkerAsmStub(args in regs x0-x7 & stack, x11:IndirectionCellAndFlags, x12:DispatchToken)
+;; void ResolveWorkerAsmStub(args in regs x0-x7 & stack and possibly retbuf arg in x8, x11:IndirectionCellAndFlags, x12:DispatchToken)
;;
;; The stub dispatch thunk which transfers control to VSD_ResolveWorker.
NESTED_ENTRY ResolveWorkerAsmStub
add x0, sp, #__PWTB_TransitionBlock ; pTransitionBlock
mov x1, x11 ; Indirection cell
- mov x2, x8 ; sectionIndex
- mov x3, x9 ; Module*
+ mov x2, x9 ; sectionIndex
+ mov x3, x10 ; Module*
bl ExternalMethodFixupWorker
mov x12, x0
add x0, sp, #__PWTB_TransitionBlock ; pTransitionBlock
mov x1, x11 ; Indirection cell
- mov x2, x8 ; sectionIndex
- mov x3, x9 ; Module*
+ mov x2, x9 ; sectionIndex
+ mov x3, x10 ; Module*
mov x4, $frameFlags
bl DynamicHelperWorker
cbnz x0, %FT0
#ifdef FEATURE_PREJIT
;; ------------------------------------------------------------------
-;; void StubDispatchFixupStub(args in regs x0-x7 & stack, x11:IndirectionCellAndFlags, x12:DispatchToken)
+;; void StubDispatchFixupStub(args in regs x0-x7 & stack and possibly retbuff arg in x8, x11:IndirectionCellAndFlags, x12:DispatchToken)
;;
;; The stub dispatch thunk which transfers control to StubDispatchFixupWorker.
NESTED_ENTRY StubDispatchFixupStub
__PWTB_StackAlloc SETA __PWTB_TransitionBlock
__PWTB_ArgumentRegisters SETA __PWTB_StackAlloc + 96
- PROLOG_SAVE_REG_PAIR fp, lr, #-160!
+ PROLOG_SAVE_REG_PAIR fp, lr, #-176!
; Spill callee saved registers
PROLOG_SAVE_REG_PAIR x19, x20, #16
PROLOG_SAVE_REG_PAIR x21, x22, #32
EPILOG_RESTORE_REG_PAIR x23, x24, #48
EPILOG_RESTORE_REG_PAIR x25, x26, #64
EPILOG_RESTORE_REG_PAIR x27, x28, #80
- EPILOG_RESTORE_REG_PAIR fp, lr, #160!
+ EPILOG_RESTORE_REG_PAIR fp, lr, #176!
EPILOG_RETURN
MEND
EPILOG_RESTORE_REG_PAIR x23, x24, #48
EPILOG_RESTORE_REG_PAIR x25, x26, #64
EPILOG_RESTORE_REG_PAIR x27, x28, #80
- EPILOG_RESTORE_REG_PAIR fp, lr, #160!
+ EPILOG_RESTORE_REG_PAIR fp, lr, #176!
MEND
;-----------------------------------------------------------------------------
; base address to be passed in $reg
;
-; Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS
+; Reserve 72 bytes of memory before calling SAVE_ARGUMENT_REGISTERS
MACRO
SAVE_ARGUMENT_REGISTERS $reg, $offset
stp x2, x3, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 16)]
stp x4, x5, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 32)]
stp x6, x7, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 48)]
+ str x8, [$reg, #(__PWTB_SAVE_ARGUMENT_REGISTERS_OFFSET + 64)]
MEND
; Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS
ldp x2, x3, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 16)]
ldp x4, x5, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 32)]
ldp x6, x7, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 48)]
+ ldr x8, [$reg, #(__PWTB_RESTORE_ARGUMENT_REGISTERS_OFFSET + 64)]
MEND
MACRO
//--------------------------------------------------------------------
typedef DPTR(struct ArgumentRegisters) PTR_ArgumentRegisters;
struct ArgumentRegisters {
- INT64 x[8]; // x0 ....x7
+ INT64 x[9]; // x0 ....x7 & x8 can contain return buffer address
};
-#define NUM_ARGUMENT_REGISTERS 8
+#define NUM_ARGUMENT_REGISTERS 9
#define ARGUMENTREGISTERS_SIZE sizeof(ArgumentRegisters)
struct NDirectImportPrecode {
- static const int Type = 0x88;
+ static const int Type = 0x8B;
- // adr x8, #16 ; Notice that x8 register is used to differentiate the stub from StubPrecode which uses x9
- // ldp x10,x12,[x8] ; =m_pTarget,m_pMethodDesc
+ // adr x11, #16 ; Notice that x11 register is used to differentiate the stub from StubPrecode which uses x9
+ // ldp x10,x12,[x11] ; =m_pTarget,m_pMethodDesc
// br x10
// 4 byte padding for 8 byte allignement
// dcd pTarget
int n = 0;
- m_rgCode[n++] = 0x10000088; // adr x8, #16
- m_rgCode[n++] = 0xA940310A; // ldp x10,x12,[x8]
+ m_rgCode[n++] = 0x1000008B; // adr x11, #16
+ m_rgCode[n++] = 0xA940316A; // ldp x10,x12,[x11]
m_rgCode[n++] = 0xD61F0140; // br x10
_ASSERTE(n+1 == _countof(m_rgCode));
#ifndef _VIRTUAL_CALL_STUB_ARM_H
#define _VIRTUAL_CALL_STUB_ARM_H
-#define DISPATCH_STUB_FIRST_DWORD 0xf9400008
+#define DISPATCH_STUB_FIRST_DWORD 0xf940000d
#define RESOLVE_STUB_FIRST_DWORD 0xF940000C
struct ARM64EncodeHelpers
void Initialize(PCODE implTarget, PCODE failTarget, size_t expectedMT)
{
- // ldr x8, [x0] ; methodTable from object in x0
+ // ldr x13, [x0] ; methodTable from object in x0
// adr x9, _expectedMT ; _expectedMT is at offset 28 from pc
// ldp x10, x12, [x9] ; x10 = _expectedMT & x12 = _implTarget
- // cmp x8, x10
+ // cmp x13, x10
// bne failLabel
// br x12
// failLabel
// _implTarget
// _failTarget
- _stub._entryPoint[0] = DISPATCH_STUB_FIRST_DWORD; // 0xf9400008
+ _stub._entryPoint[0] = DISPATCH_STUB_FIRST_DWORD; // 0xf940000d
_stub._entryPoint[1] = 0x100000e9;
_stub._entryPoint[2] = 0xa940312a;
- _stub._entryPoint[3] = 0xeb0a011f;
+ _stub._entryPoint[3] = 0xeb0a01bf;
_stub._entryPoint[4] = 0x54000041;
_stub._entryPoint[5] = 0xd61f0180;
_stub._entryPoint[6] = 0x580000c9;
// x9 = e = this._cacheAddress + i
// if (mt == e.pMT && this._token == e.token)
// {
- // (e.target)(x0, [x1,...,x7]);
+ // (e.target)(x0, [x1,...,x7 and x8]);
// }
// else
// {
// x12 = this._token;
- // (this._slowEntryPoint)(x0, [x1,.., x7], x9, x11, x12);
+ // (this._slowEntryPoint)(x0, [x1,.., x7 and x8], x9, x11, x12);
// }
// }
//
_ASSERTE(n == ResolveStub::resolveEntryPointLen);
_ASSERTE(_stub._resolveEntryPoint + n == _stub._slowEntryPoint);
- // ResolveStub._slowEntryPoint(x0:MethodToken, [x1..x7], x11:IndirectionCellAndFlags)
+ // ResolveStub._slowEntryPoint(x0:MethodToken, [x1..x7 and x8], x11:IndirectionCellAndFlags)
// {
// x12 = this._token;
- // this._resolveWorkerTarget(x0, [x1..x7], x9, x11, x12);
+ // this._resolveWorkerTarget(x0, [x1..x7 and x8], x9, x11, x12);
// }
#undef PC_REL_OFFSET
_stub._slowEntryPoint[n++] = 0xD61F01A0;
_ASSERTE(n == ResolveStub::slowEntryPointLen);
- // ResolveStub._failEntryPoint(x0:MethodToken, x1,.., x7, x11:IndirectionCellAndFlags)
+ // ResolveStub._failEntryPoint(x0:MethodToken, x1,.., x7 and x8, x11:IndirectionCellAndFlags)
// {
// if(--*(this._pCounter) < 0) x11 = x11 | SDF_ResolveBackPatch;
- // this._resolveEntryPoint(x0, [x1..x7]);
+ // this._resolveEntryPoint(x0, [x1..x7 and x8]);
// }
#undef PC_REL_OFFSET //NOTE Offset can be negative
DWORD firstDword = *((DWORD*) pInstr);
- if (firstDword == DISPATCH_STUB_FIRST_DWORD) // assembly of first instruction of DispatchStub : ldr x8, [x0]
+ if (firstDword == DISPATCH_STUB_FIRST_DWORD) // assembly of first instruction of DispatchStub : ldr x13, [x0]
{
stubKind = SK_DISPATCH;
}
#ifndef __CALLING_CONVENTION_INCLUDED
#define __CALLING_CONVENTION_INCLUDED
+BOOL IsRetBuffPassedAsFirstArg();
+
// Describes how a single argument is laid out in registers and/or stack locations when given as an input to a
// managed method as part of a larger signature.
//
};
};
ArgumentRegisters m_argumentRegisters;
+ TADDR padding; // Keep size of TransitionBlock as multiple of 16-byte. Simplifies code in PROLOG_WITH_TRANSITION_BLOCK
#else
PORTABILITY_ASSERT("TransitionBlock");
#endif
#if _TARGET_X86_
// x86 is special as always
ret += this->HasThis() ? offsetof(ArgumentRegisters, EDX) : offsetof(ArgumentRegisters, ECX);
+#elif _TARGET_ARM64_
+ ret += (int) offsetof(ArgumentRegisters, x[8]);
#else
if (this->HasThis())
ret += sizeof(void *);
ret += sizeof(void*);
}
- if (this->HasRetBuffArg())
+ if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
{
ret += sizeof(void*);
}
ret += sizeof(void*);
}
- if (this->HasRetBuffArg())
+ if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
{
ret += sizeof(void*);
}
if (this->HasThis())
numRegistersUsed++;
- if (this->HasRetBuffArg())
+ if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
numRegistersUsed++;
_ASSERTE(!this->IsVarArg() || !this->HasParamType());
if (this->HasThis())
numRegistersUsed++;
- if (this->HasRetBuffArg())
+ if (this->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
numRegistersUsed++;
if (this->IsVarArg())
return argit.HasRetBuffArg();
}
+inline BOOL IsRetBuffPassedAsFirstArg()
+{
+ WRAPPER_NO_CONTRACT;
+#ifndef _TARGET_ARM64_
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
#endif // __CALLING_CONVENTION_INCLUDED
EnsureWritablePages(pClass);
- if (!pTargetMeth->IsStatic() && pTargetMeth->HasRetBuffArg())
+ if (!pTargetMeth->IsStatic() && pTargetMeth->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
{
if (FastInterlockCompareExchangePointer(&pClass->m_pInstRetBuffCallStub, pShuffleThunk, NULL ) != NULL)
{
// Look for a thunk cached on the delegate class first. Note we need a different thunk for instance methods with a
// hidden return buffer argument because the extra argument switches place with the target when coming from the caller.
- if (!pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg())
+ if (!pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
pShuffleThunk = pDelegateClass->m_pInstRetBuffCallStub;
else
pShuffleThunk = pDelegateClass->m_pStaticCallStub;
pTargetCode = pTargetMethod->GetMultiCallableAddrOfVirtualizedCode(pRefFirstArg, pTargetMethod->GetMethodTable());
else
#ifdef HAS_THISPTR_RETBUF_PRECODE
- if (pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg())
+ if (pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
pTargetCode = pTargetMethod->GetLoaderAllocatorForCode()->GetFuncPtrStubs()->GetFuncPtrStub(pTargetMethod, PRECODE_THISPTR_RETBUF);
else
#endif // HAS_THISPTR_RETBUF_PRECODE
// set the shuffle thunk
Stub *pShuffleThunk = NULL;
- if (!pMeth->IsStatic() && pMeth->HasRetBuffArg())
+ if (!pMeth->IsStatic() && pMeth->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
pShuffleThunk = pDelCls->m_pInstRetBuffCallStub;
else
pShuffleThunk = pDelCls->m_pStaticCallStub;
}
}
#ifdef HAS_THISPTR_RETBUF_PRECODE
- else if (pMeth->HasRetBuffArg())
+ else if (pMeth->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
method = pMeth->GetLoaderAllocatorForCode()->GetFuncPtrStubs()->GetFuncPtrStub(pMeth, PRECODE_THISPTR_RETBUF);
#endif // HAS_THISPTR_RETBUF_PRECODE
pRealCtor = MscorlibBinder::GetMethod(METHOD__MULTICAST_DELEGATE__CTOR_OPENED);
}
Stub *pShuffleThunk = NULL;
- if (!pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg())
+ if (!pTargetMethod->IsStatic() && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
pShuffleThunk = pDelCls->m_pInstRetBuffCallStub;
else
pShuffleThunk = pDelCls->m_pStaticCallStub;
#ifdef HAS_THISPTR_RETBUF_PRECODE
// Force closed delegates over static methods with return buffer to go via
// the slow path to create ThisPtrRetBufPrecode
- if (isStatic && pTargetMethod->HasRetBuffArg())
+ if (isStatic && pTargetMethod->HasRetBuffArg() && IsRetBuffPassedAsFirstArg())
return NULL;
#endif
// x11 contains indirection cell
// Do nothing x11 contains our first param
- // movz x8, #index
+ // movz x9, #index
DWORD index = GetSectionIndex();
_ASSERTE(index <= 0x7F);
- *(DWORD*)p = 0xd2800008 | (index << 5);
+ *(DWORD*)p = 0xd2800009 | (index << 5);
p += 4;
- // move Module* -> x9
- // ldr x9, [PC+0x14]
- *(DWORD*)p = 0x580000A9;
+ // move Module* -> x10
+ // ldr x10, [PC+0x14]
+ *(DWORD*)p = 0x580000AA;
p += 4;
- //ldr x9, [x9]
- *(DWORD*)p = 0xf9400129;
+ //ldr x10, [x10]
+ *(DWORD*)p = 0xf940014A;
p += 4;
}
else