test rax, rax
jz GenericPInvokeCalliGenILStub
+ ;
+ ; We need to distinguish between a MethodDesc* and an unmanaged target.
+ ; The way we do this is to shift the managed target to the left by one bit and then set the
+ ; least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
+ ;
+ shl PINVOKE_CALLI_TARGET_REGISTER, 1
+ or PINVOKE_CALLI_TARGET_REGISTER, 1
+
;
; jump to existing IL stub
;
test rax, rax
jz C_FUNC(GenericPInvokeCalliGenILStub)
+ //
+ // We need to distinguish between a MethodDesc* and an unmanaged target.
+ // The way we do this is to shift the managed target to the left by one bit and then set the
+ // least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
+ //
+ shl PINVOKE_CALLI_TARGET_REGISTER, 1
+ or PINVOKE_CALLI_TARGET_REGISTER, 1
+
//
// jump to existing IL stub
//
; if null goto stub generation
cbz x9, %0
+ IF "$FuncPrefix" == "GenericPInvokeCalli"
+ ;
+ ; We need to distinguish between a MethodDesc* and an unmanaged target.
+ ; The way we do this is to shift the managed target to the left by one bit and then set the
+ ; least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
+ ;
+ lsl x9, x9, #1
+ orr x9, x9, #1
+ ENDIF
EPILOG_BRANCH_REG x9
// $VASigCookieReg : register which contains the VASigCookie
// $SaveFPArgs : "Yes" or "No" . For varidic functions FP Args are not present in FP regs
// So need not save FP Args registers for vararg Pinvoke
-.macro PINVOKE_STUB __PInvokeStubFuncName,__PInvokeGenStubFuncName,__PInvokeStubWorkerName,VASigCookieReg,HiddenArg,SaveFPArgs
+.macro PINVOKE_STUB __PInvokeStubFuncName,__PInvokeGenStubFuncName,__PInvokeStubWorkerName,VASigCookieReg,HiddenArg,SaveFPArgs,ShiftLeftAndOrSecret=0
NESTED_ENTRY \__PInvokeStubFuncName, _TEXT, NoHandler
// if null goto stub generation
cbz x9, LOCAL_LABEL(\__PInvokeStubFuncName\()_0)
+ .if (\ShiftLeftAndOrSecret == 1)
+ //
+ // We need to distinguish between a MethodDesc* and an unmanaged target.
+ // The way we do this is to shift the managed target to the left by one bit and then set the
+ // least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
+ //
+ lsl x9, x9, #1
+ orr x9, x9, #1
+ .endif
+
EPILOG_BRANCH_REG x9
LOCAL_LABEL(\__PInvokeStubFuncName\()_0):
// x15 = VASigCookie*
// x12 = Unmanaged target
//
-PINVOKE_STUB GenericPInvokeCalliHelper, GenericPInvokeCalliGenILStub, GenericPInvokeCalliStubWorker, x15, x12, 1
+PINVOKE_STUB GenericPInvokeCalliHelper, GenericPInvokeCalliGenILStub, GenericPInvokeCalliStubWorker, x15, x12, 1, 1
// ------------------------------------------------------------------
// VarargPInvokeStub_RetBuffArg & VarargPInvokeGenILStub_RetBuffArg
// for managed-to-unmanaged CALLI that requires marshaling, the target is passed
// as the secret argument to the stub by GenericPInvokeCalliHelper (asmhelpers.asm)
EmitLoadStubContext(pcsEmit, dwStubFlags);
+#ifdef _WIN64
+ // the secret arg has been shifted to left and ORed with 1 (see code:GenericPInvokeCalliHelper)
+ pcsEmit->EmitLDC(1);
+ pcsEmit->EmitSHR_UN();
+#endif
}
else
#ifdef FEATURE_COMINTEROP