22 #include "../config.h"
24 #include "RMonoAPIFunctionWrap_Def.h"
26 #include <type_traits>
27 #include "RMonoAPIBase_Def.h"
29 #include "../asmutil.h"
32 using namespace blackbone;
70 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
71 asmjit::Label RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::compileWrap(blackbone::IAsmHelper& a)
73 asmjit::Label label = a->newLabel();
76 RMonoAPIBase* mono = getRemoteMonoAPI();
77 RMonoAPIDispatcher* apid = mono->getAPIDispatcher();
82 apid->apply([&](
auto& e) {
83 ctx.gchandleGetTargetAddr = e.api.gchandle_get_target.getRawFuncAddress();
84 ctx.gchandleNewAddr = e.api.gchandle_new.getRawFuncAddress();
85 ctx.objectGetClassAddr = e.api.object_get_class.getRawFuncAddress();
86 ctx.classIsValuetypeAddr = e.api.class_is_valuetype.getRawFuncAddress();
87 ctx.objectUnboxAddr = e.api.object_unbox.getRawFuncAddress();
90 if constexpr(needsWrapFunc()) {
91 generateWrapperAsm(ctx);
98 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
99 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::generateWrapperAsm(AsmBuildContext& ctx)
101 using namespace asmjit;
102 using namespace asmjit::host;
104 IAsmHelper& a = *ctx.a;
111 ptr_t rawFuncAddr =
static_cast<CommonT*
>(
this)->getRawFuncAddress();
114 Label& lFuncRet = a->newLabel();
116 ctx.x64 = (
sizeof(irmono_voidp) == 8);
117 ctx.regSize =
sizeof(irmono_voidp);
118 ctx.rawArgStackSize = 0;
129 std::vector<GpReg> savedRegisters = { a->zbp, a->zbx, a->zsi, a->zdi };
132 genWrapperSpillArgsToStackX64<0>(ctx);
135 for (GpReg reg : savedRegisters) {
142 int32_t miscStaticStackSize = 0;
145 miscStaticStackSize += ctx.regSize;
147 a->sub(a->zsp, miscStaticStackSize);
149 ctx.stackOffsRetval = 0;
154 a->mov(a->zbp, a->zsp);
157 ctx.stackOffsArgBase = int32_t(miscStaticStackSize + savedRegisters.size()*ctx.regSize + ctx.regSize);
169 a->and_(rsp, 0xFFFFFFFFFFFFFFF0);
171 a->and_(esp, 0xFFFFFFF8);
175 a->mov(a->zbx, a->zsp);
181 a->mov(ptr(a->zbp, ctx.stackOffsRetval), a->zbx);
191 genWrapperReserveStack(ctx);
193 genWrapperCalculateRawArgStackSize<0>(ctx);
197 if (ctx.rawArgStackSize < 32) {
198 ctx.rawArgStackSize = 32;
203 a->mov(a->zcx, a->zsp);
204 a->sub(a->zcx, ctx.rawArgStackSize);
205 a->and_(a->zcx, 0xF);
208 a->sub(a->zsp, a->zcx);
211 a->sub(a->zsp, ctx.rawArgStackSize);
225 genWrapperBuildRawArgs(ctx);
232 genWrapperMoveStackArgsToRegsX64<0>(ctx);
237 a->mov(a->zax, rawFuncAddr);
240 a->mov(a->zax, rawFuncAddr);
248 a->mov(a->zbx, ptr(a->zbp, ctx.stackOffsRetval));
253 genWrapperHandleRetAndOutParams(ctx);
256 a->mov(a->zax, ptr(a->zbp, ctx.stackOffsRetval));
267 a->mov(a->zsp, a->zbp);
269 a->add(a->zsp, miscStaticStackSize);
271 for (
auto it = savedRegisters.rbegin() ; it != savedRegisters.rend() ; it++) {
281 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
282 template <
size_t wrapArgIdx>
283 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperSpillArgsToStackX64(AsmBuildContext& ctx)
285 using namespace asmjit;
286 using namespace asmjit::host;
288 typedef typename RMonoAPIFunctionWrapTraits<CommonT>::WrapArgsTuple WrapArgsTuple;
290 IAsmHelper& a = *ctx.a;
294 && wrapArgIdx < std::tuple_size_v<WrapArgsTuple>
296 static const GpReg intRegs[] = { rcx, rdx, r8, r9 };
297 static const XmmReg floatRegs[] = { xmm0, xmm1, xmm2, xmm3 };
299 static_assert(
sizeof(std::tuple_element_t<wrapArgIdx, WrapArgsTuple>) <=
sizeof(irmono_voidp),
300 "Spilling large arguments is not supported in X64.");
302 if constexpr(std::is_floating_point_v<std::tuple_element_t<wrapArgIdx, WrapArgsTuple>>) {
303 a->movq(ptr(a->zsp, (wrapArgIdx+1) *
sizeof(irmono_voidp)), floatRegs[wrapArgIdx]);
305 a->mov(ptr(a->zsp, (wrapArgIdx+1) *
sizeof(irmono_voidp)), intRegs[wrapArgIdx]);
308 genWrapperSpillArgsToStackX64<wrapArgIdx+1>(ctx);
313 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
314 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperReserveStack(AsmBuildContext& ctx)
316 using namespace asmjit;
317 using namespace asmjit::host;
319 IAsmHelper& a = *ctx.a;
321 if constexpr(std::is_base_of_v<Variant, typename RetT::Type>) {
322 if constexpr(
sizeof...(ArgsT) != 0) {
324 genWrapperReserveArgStack<1, ArgsT...>(ctx, PackHelper<ArgsT>()...);
326 }
else if constexpr (
327 std::is_base_of_v<std::string, typename RetT::Type>
328 || std::is_base_of_v<std::u16string, typename RetT::Type>
329 || std::is_base_of_v<std::u32string, typename RetT::Type>
331 if constexpr(
sizeof...(ArgsT) != 0) {
333 genWrapperReserveArgStack<1, ArgsT...>(ctx, PackHelper<ArgsT>()...);
335 }
else if constexpr(
sizeof...(ArgsT) != 0) {
336 genWrapperReserveArgStack<0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
341 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
342 template <
size_t wrapArgIdx,
typename ArgT,
typename... RestT>
343 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperReserveArgStack (
344 AsmBuildContext& ctx,
346 PackHelper<RestT>... rest
348 using namespace asmjit;
349 using namespace asmjit::host;
351 IAsmHelper& a = *ctx.a;
356 if constexpr(std::is_base_of_v<Variant, typename ArgT::Type>) {
357 Label lReserveEnd = a->newLabel();
360 a->mov(a->zcx, ptrWrapFuncArg<wrapArgIdx>(ctx));
361 a->jecxz(a->zcx, lReserveEnd);
365 a->movzx(a->zcx, ptr(a->zcx, - (int32_t)
sizeof(variantflags_t),
sizeof(variantflags_t)));
368 a->test(a->zcx, ParamFlagMonoObjectPtr);
372 a->sub(a->zsp,
sizeof(IRMonoObjectPtrRaw));
375 a->bind(lReserveEnd);
378 else if constexpr(std::is_base_of_v<VariantArray, typename ArgT::Type>) {
386 Label lReserveEnd = a->newLabel();
389 a->mov(a->zcx, ptrWrapFuncArg<wrapArgIdx>(ctx));
392 a->jecxz(a->zcx, lReserveEnd);
395 a->mov(ecx, ptr(a->zcx));
402 a->shl(a->zcx, static_ilog2(2*
sizeof(IRMonoObjectPtrRaw)));
403 a->sub(a->zsp, a->zcx);
406 a->bind(lReserveEnd);
409 else if constexpr(std::is_base_of_v<RMonoObjectHandleTag, typename ArgT::Type>) {
410 if constexpr (tags::has_param_tag_v<ArgT, tags::ParamOutTag>) {
411 Label lReserveEnd = a->newLabel();
414 a->mov(a->zcx, ptrWrapFuncArg<wrapArgIdx>(ctx));
415 a->jecxz(a->zcx, lReserveEnd);
418 a->sub(a->zsp,
sizeof(IRMonoObjectPtrRaw));
421 a->bind(lReserveEnd);
425 genWrapperReserveArgStack<wrapArgIdx+1, RestT...>(ctx, rest...);
429 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
430 template <
size_t argIdx>
431 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperCalculateRawArgStackSize(AsmBuildContext& ctx)
433 if constexpr(argIdx < std::tuple_size_v<
typename RMonoAPIFunctionRawTraits<CommonT>::RawArgsTuple>) {
434 ctx.rawArgStackSize += static_align (
435 (int32_t)
sizeof(std::tuple_element_t<argIdx,
typename RMonoAPIFunctionRawTraits<CommonT>::RawArgsTuple>),
436 (int32_t)
sizeof(irmono_voidp)
439 genWrapperCalculateRawArgStackSize<argIdx+1>(ctx);
444 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
445 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperBuildRawArgs(AsmBuildContext& ctx)
447 if constexpr(std::is_base_of_v<Variant, typename RetT::Type>) {
448 if constexpr(
sizeof...(ArgsT) != 0) {
450 genWrapperBuildRawArg<1, 0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
452 }
else if constexpr (
453 std::is_base_of_v<std::string, typename RetT::Type>
454 || std::is_base_of_v<std::u16string, typename RetT::Type>
455 || std::is_base_of_v<std::u32string, typename RetT::Type>
457 if constexpr(
sizeof...(ArgsT) != 0) {
459 genWrapperBuildRawArg<1, 0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
461 }
else if constexpr(
sizeof...(ArgsT) != 0) {
462 genWrapperBuildRawArg<0, 0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
467 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
468 template <
size_t wrapArgIdx,
size_t rawArgIdx,
typename ArgT,
typename... RestT>
469 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperBuildRawArg (
470 AsmBuildContext& ctx,
472 PackHelper<RestT>... rest
474 using namespace asmjit;
475 using namespace asmjit::host;
477 IAsmHelper& a = *ctx.a;
479 if constexpr(std::is_base_of_v<Variant, typename ArgT::Type>) {
480 Label lBuildEnd = a->newLabel();
481 Label lNullPtr = a->newLabel();
482 Label lNotMonoObjectPtr = a->newLabel();
483 Label lNoAutoUnbox = a->newLabel();
484 Label lNotDirectPtr = a->newLabel();
485 Label lMonoObjectPtrNotOut = a->newLabel();
488 a->mov(a->zcx, ptrWrapFuncArg<wrapArgIdx>(ctx));
489 a->test(a->zcx, a->zcx);
494 a->movzx(a->zsi, ptr(a->zcx, - (int32_t)
sizeof(variantflags_t),
sizeof(variantflags_t)));
497 a->test(a->zsi, ParamFlagMonoObjectPtr);
498 a->jz(lNotMonoObjectPtr);
502 a->mov(ecx, ptr(a->zcx));
503 genGchandleGetTargetChecked(ctx);
504 a->mov(a->zdi, a->zax);
507 a->sub(a->zbx,
sizeof(IRMonoObjectPtrRaw));
510 a->mov(ptr(a->zbx), a->zdi);
513 a->test(a->zsi, ParamFlagDisableAutoUnbox);
514 a->jnz(lNoAutoUnbox);
515 a->mov(a->zcx, a->zdi);
516 genIsValueTypeInstance(ctx);
517 a->test(a->zax, a->zax);
521 a->mov(a->zcx, a->zdi);
525 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zax);
529 a->bind(lNoAutoUnbox);
532 a->test(a->zsi, ParamFlagOut);
533 a->jz(lMonoObjectPtrNotOut);
536 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zbx);
540 a->bind(lMonoObjectPtrNotOut);
543 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zdi);
551 a->bind(lNotMonoObjectPtr);
552 a->test(a->zsi, ParamFlagDirectPtr);
553 a->jz(lNotDirectPtr);
556 a->mov(a->zax, ptr(a->zcx));
557 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zax);
561 a->bind(lNotDirectPtr);
564 a->lea(a->zax, ptr(a->zcx));
565 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zax);
573 a->mov(ptrRawFuncArg<rawArgIdx>(ctx, 0,
sizeof(irmono_voidp)), 0);
579 else if constexpr(std::is_base_of_v<VariantArray, typename ArgT::Type>) {
580 Label lBuildEnd = a->newLabel();
581 Label lBlockPtrNull = a->newLabel();
582 Label lLoopStart = a->newLabel();
583 Label lLoopFinal = a->newLabel();
584 Label lLoopEnd = a->newLabel();
585 Label lNotMonoObjectPtr = a->newLabel();
586 Label lNotOut = a->newLabel();
587 Label lNoAutoUnbox = a->newLabel();
588 Label lNoAutoUnboxNotOut = a->newLabel();
591 a->mov(a->zcx, ptrWrapFuncArg<wrapArgIdx>(ctx));
594 a->test(a->zcx, a->zcx);
595 a->jz(lBlockPtrNull);
596 a->cmp(dword_ptr(a->zcx), 0);
597 a->jz(lBlockPtrNull);
600 a->mov(a->zdx, dword_ptr(a->zcx));
605 a->lea(a->zsi, ptr(a->zcx,
sizeof(uint32_t)));
606 if (
sizeof(irmono_voidp) == 8) {
608 a->mov(a->zax, a->zsi);
609 a->and_(a->zax, 0x7);
610 a->add(a->zsi, a->zax);
615 a->lea(a->zdi, ptr(a->zsi, a->zdx, static_ilog2(
sizeof(irmono_voidp))));
618 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zsi);
627 a->sub(a->zbx, 2*
sizeof(IRMonoObjectPtrRaw));
631 a->mov(ptr(a->zbx,
sizeof(IRMonoObjectPtrRaw),
sizeof(IRMonoObjectPtrRaw)), 0);
634 a->cmp(ptr(a->zsi, 0,
sizeof(irmono_voidp)), 0);
638 a->test(ptr(a->zdi, 0,
sizeof(variantflags_t)), ParamFlagMonoObjectPtr);
639 a->jz(lNotMonoObjectPtr);
643 a->mov(a->zcx, ptr(a->zsi));
644 a->mov(ecx, ptr(a->zcx));
645 genGchandleGetTargetChecked(ctx);
648 a->mov(ptr(a->zbx), a->zax);
651 a->test(ptr(a->zdi, 0,
sizeof(variantflags_t)), ParamFlagOut);
655 a->mov(a->zcx, ptr(a->zsi));
656 a->mov(ptr(a->zbx,
sizeof(IRMonoObjectPtrRaw)), a->zcx);
665 a->mov(ptr(a->zsi), a->zax);
668 a->test(ptr(a->zdi, 0,
sizeof(variantflags_t)), ParamFlagDisableAutoUnbox);
669 a->jnz(lNoAutoUnbox);
670 a->mov(a->zcx, a->zax);
671 genIsValueTypeInstance(ctx);
672 a->test(a->zax, a->zax);
673 a->mov(a->zax, ptr(a->zsi));
677 a->mov(a->zcx, a->zax);
681 a->mov(ptr(a->zsi), a->zax);
685 a->bind(lNoAutoUnbox);
688 a->test(ptr(a->zdi, 0,
sizeof(variantflags_t)), ParamFlagOut);
689 a->jz(lNoAutoUnboxNotOut);
692 a->mov(ptr(a->zsi), a->zbx);
695 a->bind(lNoAutoUnboxNotOut);
701 a->bind(lNotMonoObjectPtr);
702 a->test(ptr(a->zdi, 0,
sizeof(variantflags_t)), ParamFlagDirectPtr);
706 a->mov(a->zax, ptr(a->zsi));
707 a->mov(a->zax, ptr(a->zax));
708 a->mov(ptr(a->zsi), a->zax);
716 a->add(a->zsi,
sizeof(irmono_voidp));
719 a->mov(a->zcx, ptr(a->zdi, 0,
sizeof(variantflags_t)));
720 a->add(a->zdi,
sizeof(variantflags_t));
721 a->test(a->zcx, ParamFlagLastArrayElement);
727 a->bind(lBlockPtrNull);
730 a->mov(ptrRawFuncArg<rawArgIdx>(ctx, 0,
sizeof(irmono_voidp)), 0);
737 std::is_base_of_v<std::string_view, typename ArgT::Type>
738 || std::is_base_of_v<std::u16string_view, typename ArgT::Type>
739 || std::is_base_of_v<std::u32string_view, typename ArgT::Type>
742 a->mov(a->zcx, ptrWrapFuncArg<wrapArgIdx>(ctx));
743 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zcx);
746 else if constexpr(std::is_base_of_v<RMonoObjectHandleTag, typename ArgT::Type>) {
747 Label lBuildEnd = a->newLabel();
748 Label lNull = a->newLabel();
751 a->mov(a->zcx, ptrWrapFuncArg<wrapArgIdx>(ctx));
754 a->jecxz(a->zcx, lNull);
756 if constexpr (tags::has_param_tag_v<ArgT, tags::ParamOutTag>) {
759 a->mov(ecx, ptr(a->zcx));
760 genGchandleGetTargetChecked(ctx);
763 a->sub(a->zbx,
sizeof(IRMonoObjectPtrRaw));
766 a->mov(ptr(a->zbx), a->zax);
769 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zbx);
773 genGchandleGetTargetChecked(ctx);
774 a->mov(ptrRawFuncArg<rawArgIdx>(ctx), a->zax);
782 a->mov(ptrRawFuncArg<rawArgIdx>(ctx, 0,
sizeof(irmono_voidp)), 0);
789 constexpr int32_t argSize = (int32_t)
sizeof(std::tuple_element_t<rawArgIdx,
typename RMonoAPIFunctionRawTraits<CommonT>::RawArgsTuple>);
791 static_assert(argSize ==
sizeof(std::tuple_element_t<wrapArgIdx,
typename RMonoAPIFunctionWrapTraits<CommonT>::WrapArgsTuple>),
792 "Different non-special argument type size for wrap and raw functions is not supported.");
795 for (
size_t partIdx = 0 ; partIdx*
sizeof(irmono_voidp) < argSize ; partIdx++) {
796 a->mov(a->zcx, ptrWrapFuncArg<wrapArgIdx>(ctx, partIdx));
797 a->mov(ptrRawFuncArg<rawArgIdx>(ctx, partIdx), a->zcx);
801 genWrapperBuildRawArg<wrapArgIdx+1, rawArgIdx+1, RestT...>(ctx, rest...);
805 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
806 template <
size_t rawArgIdx>
807 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperMoveStackArgsToRegsX64 (
810 using namespace asmjit;
811 using namespace asmjit::host;
813 typedef typename RMonoAPIFunctionRawTraits<CommonT>::RawArgsTuple RawArgsTuple;
815 IAsmHelper& a = *ctx.a;
821 && rawArgIdx < std::tuple_size_v<
typename RMonoAPIFunctionRawTraits<CommonT>::RawArgsTuple>
823 static const GpReg intRegs[] = { rcx, rdx, r8, r9 };
824 static const XmmReg floatRegs[] = { xmm0, xmm1, xmm2, xmm3 };
826 static_assert(
sizeof(std::tuple_element_t<rawArgIdx, RawArgsTuple>) <=
sizeof(irmono_voidp),
827 "Raw argument larger than 8 bytes isn't supported for wrapper function on x64.");
829 if constexpr(std::is_floating_point_v<std::tuple_element_t<rawArgIdx, RawArgsTuple>>) {
830 a->movq(floatRegs[rawArgIdx], ptr(a->zsp, rawArgIdx*
sizeof(irmono_voidp)));
832 a->mov(intRegs[rawArgIdx], ptr(a->zsp, rawArgIdx*
sizeof(irmono_voidp)));
835 genWrapperMoveStackArgsToRegsX64<rawArgIdx+1>(ctx);
840 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
841 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperHandleRetAndOutParams(AsmBuildContext& ctx)
843 using namespace asmjit;
844 using namespace asmjit::host;
846 IAsmHelper& a = *ctx.a;
848 if constexpr(std::is_base_of_v<Variant, typename RetT::Type>) {
849 Label lHandleEnd = a->newLabel();
856 a->mov(a->zcx, ptrWrapFuncArg<0>(ctx));
859 a->test(a->zcx, ParamFlagMonoObjectPtr);
863 a->mov(a->zcx, ptr(a->zax));
866 genGchandleNewChecked(ctx);
872 a->mov(ptr(a->zbp, ctx.stackOffsRetval), a->zax);
875 genWrapperHandleOutParams<1, 0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
878 else if constexpr(std::is_base_of_v<RMonoObjectHandleTag, typename RetT::Type>) {
880 a->mov(a->zcx, a->zax);
881 genGchandleNewChecked(ctx);
882 a->mov(ptr(a->zbp, ctx.stackOffsRetval), a->zax);
884 genWrapperHandleOutParams<0, 0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
888 std::is_base_of_v<std::string, typename RetT::Type>
889 || std::is_base_of_v<std::u16string, typename RetT::Type>
890 || std::is_base_of_v<std::u32string, typename RetT::Type>
892 Label lHandleEnd = a->newLabel();
893 Label lNull = a->newLabel();
894 Label lStrlenLoopStart = a->newLabel();
895 Label lStrlenLoopEnd = a->newLabel();
900 a->test(a->zax, a->zax);
904 a->mov(a->zsi, a->zax);
907 a->bind(lStrlenLoopStart);
908 a->cmp(ptr(a->zsi, 0,
sizeof(
typename RetT::Type::value_type)), 0);
909 a->je(lStrlenLoopEnd);
912 if (
sizeof(
typename RetT::Type::value_type) == 1) {
915 a->add(a->zsi,
sizeof(
typename RetT::Type::value_type));
918 a->jmp(lStrlenLoopStart);
920 a->bind(lStrlenLoopEnd);
923 a->mov(a->zcx, ptrWrapFuncArg<0>(ctx));
926 a->sub(a->zsi, a->zax);
927 if (
sizeof(
typename RetT::Type::value_type) != 1) {
928 a->shr(a->zsi, static_ilog2(
sizeof(
typename RetT::Type::value_type)));
930 a->mov(dword_ptr(a->zcx), esi);
933 a->mov(ptr(a->zbp, ctx.stackOffsRetval), a->zax);
940 a->mov(ptr(a->zbp, ctx.stackOffsRetval,
sizeof(irmono_voidp)), 0);
946 genWrapperHandleOutParams<1, 0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
949 else if constexpr(std::is_same_v<
typename RMonoAPIFunctionWrapTraits<CommonT>::WrapRetType,
void>) {
952 genWrapperHandleOutParams<0, 0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
957 a->mov(ptr(a->zbp, ctx.stackOffsRetval), a->zax);
959 genWrapperHandleOutParams<0, 0, ArgsT...>(ctx, PackHelper<ArgsT>()...);
964 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
965 template <
size_t wrapArgIdx,
size_t rawArgIdx,
typename ArgT,
typename... RestT>
966 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genWrapperHandleOutParams (
967 AsmBuildContext& ctx,
969 PackHelper<RestT>... rest
971 using namespace asmjit;
972 using namespace asmjit::host;
974 IAsmHelper& a = *ctx.a;
976 if constexpr(std::is_base_of_v<Variant, typename ArgT::Type>) {
977 Label lHandleEnd = a->newLabel();
980 a->mov(a->zdi, ptrWrapFuncArg<wrapArgIdx>(ctx));
983 a->test(a->zdi, a->zdi);
988 a->movzx(a->zcx, ptr(a->zdi, - (int32_t)
sizeof(variantflags_t),
sizeof(variantflags_t)));
991 a->test(a->zcx, ParamFlagMonoObjectPtr);
995 a->sub(a->zbx,
sizeof(IRMonoObjectPtrRaw));
998 a->test(a->zcx, ParamFlagOut);
1002 tags::has_param_tag_v<ArgT, tags::ParamOutTag>
1003 || tags::has_param_tag_v<ArgT, tags::ParamOvwrInOutTag>
1006 a->mov(a->zcx, ptr(a->zbx));
1007 genGchandleNewChecked(ctx);
1010 a->mov(dword_ptr(a->zdi), eax);
1018 a->bind(lHandleEnd);
1021 else if constexpr(std::is_base_of_v<VariantArray, typename ArgT::Type>) {
1022 Label lHandleEnd = a->newLabel();
1023 Label lLoopStart = a->newLabel();
1024 Label lLoopFinal = a->newLabel();
1025 Label lLoopEnd = a->newLabel();
1028 a->mov(a->zdi, ptrWrapFuncArg<wrapArgIdx>(ctx));
1031 a->test(a->zdi, a->zdi);
1035 tags::has_param_tag_v<ArgT, tags::ParamOutTag>
1036 || tags::has_param_tag_v<ArgT, tags::ParamOvwrInOutTag>
1042 a->bind(lLoopStart);
1043 a->cmp(esi, dword_ptr(a->zdi));
1047 a->sub(a->zbx, 2*
sizeof(IRMonoObjectPtrRaw));
1050 a->cmp(ptr(a->zbx,
sizeof(IRMonoObjectPtrRaw),
sizeof(irmono_voidp)), 0);
1054 a->mov(a->zcx, ptr(a->zbx));
1055 genGchandleNewChecked(ctx);
1058 a->mov(a->zcx, ptr(a->zbx,
sizeof(IRMonoObjectPtrRaw)));
1059 a->mov(dword_ptr(a->zcx), eax);
1064 a->bind(lLoopFinal);
1072 a->mov(a->zcx, dword_ptr(a->zdi));
1073 a->shl(a->zcx, 2*
sizeof(IRMonoObjectPtrRaw));
1074 a->sub(a->zbx, a->zcx);
1078 a->bind(lHandleEnd);
1081 else if constexpr(std::is_base_of_v<RMonoObjectHandleTag, typename ArgT::Type>) {
1082 if constexpr (tags::has_param_tag_v<ArgT, tags::ParamOutTag>) {
1083 Label lHandleEnd = a->newLabel();
1086 a->mov(a->zdi, ptrWrapFuncArg<wrapArgIdx>(ctx));
1089 a->test(a->zdi, a->zdi);
1093 a->sub(a->zbx,
sizeof(IRMonoObjectPtrRaw));
1096 a->mov(a->zcx, ptr(a->zbx));
1097 genGchandleNewChecked(ctx);
1100 a->mov(dword_ptr(a->zdi), eax);
1103 a->bind(lHandleEnd);
1107 genWrapperHandleOutParams<wrapArgIdx+1, rawArgIdx+1, RestT...>(ctx, rest...);
1115 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
1116 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genGchandleGetTargetChecked(AsmBuildContext& ctx)
1120 AsmGenGchandleGetTargetChecked(*ctx.a, ctx.gchandleGetTargetAddr, ctx.x64);
1124 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
1125 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genGchandleNewChecked(AsmBuildContext& ctx)
1129 AsmGenGchandleNewChecked(*ctx.a, ctx.gchandleNewAddr, ctx.x64);
1133 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
1134 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genIsValueTypeInstance(AsmBuildContext& ctx)
1136 AsmGenIsValueTypeInstance(*ctx.a, ctx.objectGetClassAddr, ctx.classIsValuetypeAddr, ctx.x64);
1140 template <
typename CommonT,
typename ABI,
typename RetT,
typename... ArgsT>
1141 void RMonoAPIFunctionWrap<CommonT, ABI, RetT, ArgsT...>::genObjectUnbox(AsmBuildContext& ctx)
1143 AsmGenObjectUnbox(*ctx.a, ctx.objectUnboxAddr, ctx.x64);