diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index 10c649fa958f13..7cd22fd3464b3d 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -4318,11 +4318,29 @@ bool InterpCompiler::DisallowTailCall(CORINFO_SIG_INFO* callerSig, CORINFO_SIG_I void InterpCompiler::EmitCalli(bool isTailCall, void* calliCookie, int callIFunctionPointerVar, CORINFO_SIG_INFO* callSiteSig) { AddIns(isTailCall ? INTOP_CALLI_TAIL : INTOP_CALLI); - m_pLastNewIns->data[0] = GetDataItemIndex(calliCookie); // data[1] is set to 1 if the calli is calling a pinvoke, 0 otherwise bool suppressGCTransition = false; CorInfoCallConv callConv = (CorInfoCallConv)(callSiteSig->callConv & IMAGE_CEE_CS_CALLCONV_MASK); bool isPInvoke = (callConv != CORINFO_CALLCONV_DEFAULT && callConv != CORINFO_CALLCONV_VARARG); +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + // On portable entry point platforms, managed callis defer cookie resolution to + // execution time. Allocate two consecutive data items: the sig token (immutable) + // and a cache slot (initially NULL) for the resolved cookie. + // calliCookie is non-NULL only for IL calli instructions where it holds + // the signature token. CODE_POINTER / LDVIRTFTN callis pass NULL because + // their targets always carry a MethodDesc resolved at execution time. + bool deferredCookie = !isPInvoke && calliCookie != NULL; + if (deferredCookie) + { + m_pLastNewIns->data[0] = GetNewDataItemIndex(calliCookie); + int32_t cacheSlot = GetNewDataItemIndex(nullptr); + _ASSERTE(cacheSlot == m_pLastNewIns->data[0] + 1); + } + else +#endif + { + m_pLastNewIns->data[0] = GetDataItemIndex(calliCookie); + } if (isPInvoke) { if (m_compHnd->pInvokeMarshalingRequired(NULL, callSiteSig)) @@ -4334,7 +4352,11 @@ void InterpCompiler::EmitCalli(bool isTailCall, void* calliCookie, int callIFunc m_compHnd->getUnmanagedCallConv(nullptr, callSiteSig, &suppressGCTransition); } m_pLastNewIns->data[1] = (suppressGCTransition ? (int32_t)CalliFlags::SuppressGCTransition : 0) | - (isPInvoke ? (int32_t)CalliFlags::PInvoke : 0); + (isPInvoke ? (int32_t)CalliFlags::PInvoke : 0) +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + | (deferredCookie ? (int32_t)CalliFlags::DeferredCookie : 0) +#endif + ; m_pLastNewIns->SetSVars2(CALL_ARGS_SVAR, callIFunctionPointerVar); } @@ -4796,7 +4818,30 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re callIFunctionPointerVar = m_pStackPointer[-1].var; m_pStackPointer--; +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + // On platforms with portable entry points, managed calli targets are portable + // entry points. At execution time, if the portable entry point carries a MethodDesc, + // the call is dispatched via CALL_INTERP_METHOD which derives the cookie from the + // MethodDesc. Targets without a MethodDesc — JIT helper portable entry points such + // as object allocators (e.g. CORINFO_HELP_NEWFAST) called via delegate* from BCL + // code like ActivatorCache — fall through to deferred cookie resolution using the + // calli's signature token stored here. + { + CorInfoCallConv callConv = (CorInfoCallConv)(callInfo.sig.callConv & IMAGE_CEE_CS_CALLCONV_MASK); + bool isUnmanaged = (callConv != CORINFO_CALLCONV_DEFAULT && callConv != CORINFO_CALLCONV_VARARG); + if (isUnmanaged) + { + calliCookie = m_compHnd->GetCookieForInterpreterCalliSig(&callInfo.sig); + } + else + { + // Store the sig token for runtime cookie resolution. + calliCookie = (void*)(size_t)token; + } + } +#else calliCookie = m_compHnd->GetCookieForInterpreterCalliSig(&callInfo.sig); +#endif m_ip += 5; } else @@ -5445,7 +5490,11 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re m_pStackPointer--; int codePointerLookupResult = m_pStackPointer[0].var; +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + calliCookie = NULL; +#else calliCookie = m_compHnd->GetCookieForInterpreterCalliSig(&callInfo.sig); +#endif EmitCalli(tailcall, calliCookie, codePointerLookupResult, &callInfo.sig); @@ -5488,7 +5537,11 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re m_pStackPointer--; int synthesizedLdvirtftnPtrVar = m_pStackPointer[0].var; +#ifdef FEATURE_PORTABLE_ENTRYPOINTS + calliCookie = NULL; +#else calliCookie = m_compHnd->GetCookieForInterpreterCalliSig(&callInfo.sig); +#endif EmitCalli(tailcall, calliCookie, synthesizedLdvirtftnPtrVar, &callInfo.sig); } diff --git a/src/coreclr/interpreter/inc/interpretershared.h b/src/coreclr/interpreter/inc/interpretershared.h index 35b7c23f8ac9df..18d38062f069a0 100644 --- a/src/coreclr/interpreter/inc/interpretershared.h +++ b/src/coreclr/interpreter/inc/interpretershared.h @@ -188,6 +188,7 @@ enum class CalliFlags : int32_t None = 0, SuppressGCTransition = 1 << 1, // The call is marked by the SuppressGCTransition attribute PInvoke = 1 << 2, // The call is a PInvoke call + DeferredCookie = 1 << 3, // Cookie data item contains a sig token to be resolved at runtime }; struct InterpIntervalMapEntry diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index 7a5bee2d9cb2af..d0131af40943a0 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -208,6 +208,7 @@ void InvokeUnmanagedMethod(MethodDesc *targetMethod, int8_t *pArgs, int8_t *pRet void InvokeCalliStub(CalliStubParam* pParam); void InvokeUnmanagedCalli(PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet); void InvokeDelegateInvokeMethod(DelegateInvokeMethodParam* pParam); +void* GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD); extern "C" PCODE CID_VirtualOpenDelegateDispatch(TransitionBlock * pTransitionBlock); // Filter to ignore SEH exceptions representing C++ exceptions. @@ -3037,15 +3038,40 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr else { #ifdef FEATURE_PORTABLE_ENTRYPOINTS - // WASM-TODO: We may end up here with native JIT helper entrypoint without MethodDesc - // that CALL_INTERP_METHOD is not able to handle. This is a potential problem for - // interpreter<->native code stub generator. - // https://github.com/dotnet/runtime/pull/119516#discussion_r2337631271 - if (!PortableEntryPoint::HasNativeEntryPoint(calliFunctionPointer)) + // On portable entry point platforms, calli targets are portable entry points. + // If the portable entry point has a MethodDesc, route through + // CALL_INTERP_METHOD which derives the cookie at runtime. This covers + // both interpreted methods and FCalls (which have native code set but + // still carry a MethodDesc). + // JIT helper portable entry points (no MethodDesc) fall through to + // InvokeCalliStub — the cookie is resolved at runtime from the calli's + // signature token. + targetMethod = PortableEntryPoint::TryGetMethodDesc(calliFunctionPointer); + if (targetMethod != nullptr) { - targetMethod = PortableEntryPoint::GetMethodDesc(calliFunctionPointer); goto CALL_INTERP_METHOD; } + + if (flags & (int32_t)CalliFlags::DeferredCookie) + { + // pDataItems[calliCookie] = sig token (immutable) + // pDataItems[calliCookie + 1] = cached cookie (initially NULL) + cookie = VolatileLoadWithoutBarrier(&pMethod->pDataItems[calliCookie + 1]); + if (cookie == NULL) + { + mdToken sigToken = (mdToken)(size_t)pMethod->pDataItems[calliCookie]; + MethodDesc* pCallerMD = (MethodDesc*)pMethod->methodHnd; + Module* pModule = pCallerMD->GetModule(); + PCCOR_SIGNATURE pSig; + ULONG cbSig; + IfFailThrow(pModule->GetMDImport()->GetSigFromToken(sigToken, &cbSig, &pSig)); + // nullptr type context is safe here — this path is only reached for + // JIT helper portable entry points which are non-generic. + MetaSig sig(pSig, cbSig, pModule, nullptr); + cookie = GetCookieForCalliSig(sig, nullptr); + VolatileStoreWithoutBarrier(&pMethod->pDataItems[calliCookie + 1], cookie); + } + } #endif // FEATURE_PORTABLE_ENTRYPOINTS CalliStubParam param = { calliFunctionPointer, cookie, callArgsAddress, returnValueAddress, pInterpreterFrame->GetContinuationPtr() }; InvokeCalliStub(¶m); diff --git a/src/coreclr/vm/precode_portable.cpp b/src/coreclr/vm/precode_portable.cpp index 40c4bdce3958bb..3deb3cc9fd7861 100644 --- a/src/coreclr/vm/precode_portable.cpp +++ b/src/coreclr/vm/precode_portable.cpp @@ -57,6 +57,14 @@ MethodDesc* PortableEntryPoint::GetMethodDesc(PCODE addr) return portableEntryPoint->_pMD; } +MethodDesc* PortableEntryPoint::TryGetMethodDesc(PCODE addr) +{ + LIMITED_METHOD_CONTRACT; + + PortableEntryPoint* portableEntryPoint = ToPortableEntryPoint(addr); + return portableEntryPoint->_pMD; +} + void* PortableEntryPoint::GetInterpreterData(PCODE addr) { STANDARD_VM_CONTRACT; diff --git a/src/coreclr/vm/precode_portable.hpp b/src/coreclr/vm/precode_portable.hpp index 3884895f56e911..431c8a26076ecb 100644 --- a/src/coreclr/vm/precode_portable.hpp +++ b/src/coreclr/vm/precode_portable.hpp @@ -19,6 +19,7 @@ class PortableEntryPoint final static void* GetActualCode(PCODE addr); static void SetActualCode(PCODE addr, PCODE actualCode); static MethodDesc* GetMethodDesc(PCODE addr); + static MethodDesc* TryGetMethodDesc(PCODE addr); static void* GetInterpreterData(PCODE addr); static void SetInterpreterData(PCODE addr, PCODE interpreterData); diff --git a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index 950acbc6c0f5d3..2df58b868a5fec 100644 --- a/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -19,12 +19,6 @@ namespace { - static void CallFunc_Void_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - double (*fptr)() = (double (*)())pcode; - *((double*)pRet) = (*fptr)(); - } - static void CallFunc_F64_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { double (*fptr)(double) = (double (*)(double))pcode; @@ -49,30 +43,12 @@ namespace *((double*)pRet) = (*fptr)(ARG_F64(0), ARG_I32(1)); } - static void CallFunc_F64_I32_F64_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - double (*fptr)(double, int32_t, double) = (double (*)(double, int32_t, double))pcode; - *((double*)pRet) = (*fptr)(ARG_F64(0), ARG_I32(1), ARG_F64(2)); - } - static void CallFunc_I32_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { double (*fptr)(int32_t) = (double (*)(int32_t))pcode; *((double*)pRet) = (*fptr)(ARG_I32(0)); } - static void CallFunc_I32_I32_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - double (*fptr)(int32_t, int32_t) = (double (*)(int32_t, int32_t))pcode; - *((double*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1)); - } - - static void CallFunc_Void_RetF32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - float (*fptr)() = (float (*)())pcode; - *((float*)pRet) = (*fptr)(); - } - static void CallFunc_F32_RetF32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { float (*fptr)(float) = (float (*)(float))pcode; @@ -103,60 +79,12 @@ namespace *((int32_t*)pRet) = (*fptr)(); } - static void CallFunc_F64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(double) = (int32_t (*)(double))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_F64(0)); - } - - static void CallFunc_F64_F32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(double, float, int32_t) = (int32_t (*)(double, float, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_F64(0), ARG_F32(1), ARG_I32(2)); - } - - static void CallFunc_F64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(double, int32_t) = (int32_t (*)(double, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_F64(0), ARG_I32(1)); - } - - static void CallFunc_F32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(float) = (int32_t (*)(float))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_F32(0)); - } - - static void CallFunc_F32_F32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(float, float) = (int32_t (*)(float, float))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_F32(0), ARG_F32(1)); - } - static void CallFunc_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t) = (int32_t (*)(int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0)); } - static void CallFunc_I32_F64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, double) = (int32_t (*)(int32_t, double))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_F64(1)); - } - - static void CallFunc_I32_F32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, float) = (int32_t (*)(int32_t, float))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_F32(1)); - } - - static void CallFunc_I32_F32_I32_I32_F32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, float, int32_t, int32_t, float) = (int32_t (*)(int32_t, float, int32_t, int32_t, float))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_F32(1), ARG_I32(2), ARG_I32(3), ARG_F32(4)); - } - static void CallFunc_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; @@ -199,12 +127,6 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), ARG_I32(8), ARG_I32(9), ARG_I32(10), ARG_I32(11), ARG_I32(12), ARG_I32(13)); } - static void CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), ARG_I32(8), ARG_I32(9), ARG_I32(10), ARG_I32(11), ARG_I32(12), ARG_I32(13), ARG_I32(14), ARG_I32(15), ARG_I32(16)); - } - static void CallFunc_I32_I32_I32_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int64_t) = (int32_t (*)(int32_t, int32_t, int32_t, int64_t))pcode; @@ -265,12 +187,6 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I64(2), ARG_I32(3)); } - static void CallFunc_I32_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1)); - } - static void CallFunc_I32_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; @@ -283,24 +199,6 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); } - static void CallFunc_I32_IND_I32_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_IND(3), ARG_I32(4)); - } - - static void CallFunc_I32_IND_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_IND(2)); - } - - static void CallFunc_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int64_t) = (int32_t (*)(int64_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I64(0)); - } - static void CallFunc_I64_I32_I64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int64_t, int32_t, int64_t, int32_t) = (int32_t (*)(int64_t, int32_t, int64_t, int32_t))pcode; @@ -355,12 +253,6 @@ namespace *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_IND(2), ARG_IND(3)); } - static void CallFunc_IND_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_IND(1)); - } - static void CallFunc_IND_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; @@ -385,30 +277,12 @@ namespace *((int64_t*)pRet) = (*fptr)(); } - static void CallFunc_F64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int64_t (*fptr)(double) = (int64_t (*)(double))pcode; - *((int64_t*)pRet) = (*fptr)(ARG_F64(0)); - } - - static void CallFunc_F32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int64_t (*fptr)(float) = (int64_t (*)(float))pcode; - *((int64_t*)pRet) = (*fptr)(ARG_F32(0)); - } - static void CallFunc_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t) = (int64_t (*)(int32_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I32(0)); } - static void CallFunc_I32_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int64_t (*fptr)(int32_t, int32_t) = (int64_t (*)(int32_t, int32_t))pcode; - *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1)); - } - static void CallFunc_I32_I32_I32_I64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t, int32_t, int32_t, int64_t) = (int64_t (*)(int32_t, int32_t, int32_t, int64_t))pcode; @@ -433,104 +307,24 @@ namespace *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I64(2)); } - static void CallFunc_I64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int64_t (*fptr)(int64_t) = (int64_t (*)(int64_t))pcode; - *((int64_t*)pRet) = (*fptr)(ARG_I64(0)); - } - - static void CallFunc_I64_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int64_t (*fptr)(int64_t, int32_t) = (int64_t (*)(int64_t, int32_t))pcode; - *((int64_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I32(1)); - } - static void CallFunc_I64_I64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int64_t, int64_t) = (int64_t (*)(int64_t, int64_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I64(1)); } - static void CallFunc_Void_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)() = (int32_t (*)())pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(); - } - - static void CallFunc_I32_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t) = (int32_t (*)(int32_t))pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(ARG_I32(0)); - } - - static void CallFunc_I32_I32_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1)); - } - - static void CallFunc_I32_I32_I32_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2)); - } - - static void CallFunc_I32_IND_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1)); - } - - static void CallFunc_IND_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t) = (int32_t (*)(int32_t))pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(ARG_IND(0)); - } - - static void CallFunc_IND_I32_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1)); - } - - static void CallFunc_IND_IND_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_IND(1)); - } - static void CallFunc_Void_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)() = (void (*)())pcode; (*fptr)(); } - static void CallFunc_F64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(double) = (void (*)(double))pcode; - (*fptr)(ARG_F64(0)); - } - static void CallFunc_F64_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(double, int32_t, int32_t) = (void (*)(double, int32_t, int32_t))pcode; (*fptr)(ARG_F64(0), ARG_I32(1), ARG_I32(2)); } - static void CallFunc_F32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(float) = (void (*)(float))pcode; - (*fptr)(ARG_F32(0)); - } - static void CallFunc_F32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(float, int32_t, int32_t) = (void (*)(float, int32_t, int32_t))pcode; @@ -543,12 +337,6 @@ namespace (*fptr)(ARG_I32(0)); } - static void CallFunc_I32_F64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(int32_t, double) = (void (*)(int32_t, double))pcode; - (*fptr)(ARG_I32(0), ARG_F64(1)); - } - static void CallFunc_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t) = (void (*)(int32_t, int32_t))pcode; @@ -579,12 +367,6 @@ namespace (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5)); } - static void CallFunc_I32_I32_I32_I32_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6)); - } - static void CallFunc_I32_I32_I32_IND_IND_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; @@ -597,18 +379,6 @@ namespace (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_IND(3), ARG_IND(4), ARG_I32(5)); } - static void CallFunc_I32_I32_I64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(int32_t, int32_t, int64_t) = (void (*)(int32_t, int32_t, int64_t))pcode; - (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I64(2)); - } - - static void CallFunc_I32_I32_IND_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2)); - } - static void CallFunc_I32_I32_IND_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; @@ -621,30 +391,12 @@ namespace (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2), ARG_IND(3), ARG_I32(4), ARG_I32(5)); } - static void CallFunc_I32_I64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(int32_t, int64_t) = (void (*)(int32_t, int64_t))pcode; - (*fptr)(ARG_I32(0), ARG_I64(1)); - } - - static void CallFunc_I32_IND_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(int32_t, int32_t) = (void (*)(int32_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_IND(1)); - } - static void CallFunc_I32_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2)); } - static void CallFunc_I32_IND_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) - { - void (*fptr)(int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_IND(1), ARG_IND(2), ARG_I32(3)); - } - static void CallFunc_I64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int64_t) = (void (*)(int64_t))pcode; @@ -713,29 +465,17 @@ namespace } const StringToWasmSigThunk g_wasmThunks[] = { - { "d", (void*)&CallFunc_Void_RetF64 }, { "dd", (void*)&CallFunc_F64_RetF64 }, { "ddd", (void*)&CallFunc_F64_F64_RetF64 }, { "dddd", (void*)&CallFunc_F64_F64_F64_RetF64 }, { "ddi", (void*)&CallFunc_F64_I32_RetF64 }, - { "ddid", (void*)&CallFunc_F64_I32_F64_RetF64 }, { "di", (void*)&CallFunc_I32_RetF64 }, - { "dii", (void*)&CallFunc_I32_I32_RetF64 }, - { "f", (void*)&CallFunc_Void_RetF32 }, { "ff", (void*)&CallFunc_F32_RetF32 }, { "fff", (void*)&CallFunc_F32_F32_RetF32 }, { "ffff", (void*)&CallFunc_F32_F32_F32_RetF32 }, { "ffi", (void*)&CallFunc_F32_I32_RetF32 }, { "i", (void*)&CallFunc_Void_RetI32 }, - { "id", (void*)&CallFunc_F64_RetI32 }, - { "idfi", (void*)&CallFunc_F64_F32_I32_RetI32 }, - { "idi", (void*)&CallFunc_F64_I32_RetI32 }, - { "if", (void*)&CallFunc_F32_RetI32 }, - { "iff", (void*)&CallFunc_F32_F32_RetI32 }, { "ii", (void*)&CallFunc_I32_RetI32 }, - { "iid", (void*)&CallFunc_I32_F64_RetI32 }, - { "iif", (void*)&CallFunc_I32_F32_RetI32 }, - { "iifiif", (void*)&CallFunc_I32_F32_I32_I32_F32_RetI32 }, { "iii", (void*)&CallFunc_I32_I32_RetI32 }, { "iiii", (void*)&CallFunc_I32_I32_I32_RetI32 }, { "iiiii", (void*)&CallFunc_I32_I32_I32_I32_RetI32 }, @@ -743,7 +483,6 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "iiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetI32 }, { "iiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32 }, { "iiiiiiiiiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 }, - { "iiiiiiiiiiiiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 }, { "iiiil", (void*)&CallFunc_I32_I32_I32_I64_RetI32 }, { "iiiini", (void*)&CallFunc_I32_I32_I32_IND_I32_RetI32 }, { "iiil", (void*)&CallFunc_I32_I32_I64_RetI32 }, @@ -754,12 +493,8 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "iiliiil", (void*)&CallFunc_I32_I64_I32_I32_I32_I64_RetI32 }, { "iill", (void*)&CallFunc_I32_I64_I64_RetI32 }, { "iilli", (void*)&CallFunc_I32_I64_I64_I32_RetI32 }, - { "iin", (void*)&CallFunc_I32_IND_RetI32 }, { "iini", (void*)&CallFunc_I32_IND_I32_RetI32 }, { "iiniii", (void*)&CallFunc_I32_IND_I32_I32_I32_RetI32 }, - { "iinini", (void*)&CallFunc_I32_IND_I32_IND_I32_RetI32 }, - { "iinn", (void*)&CallFunc_I32_IND_IND_RetI32 }, - { "il", (void*)&CallFunc_I64_RetI32 }, { "ilili", (void*)&CallFunc_I64_I32_I64_I32_RetI32 }, { "in", (void*)&CallFunc_IND_RetI32 }, { "ini", (void*)&CallFunc_IND_I32_RetI32 }, @@ -769,53 +504,30 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "iniiiii", (void*)&CallFunc_IND_I32_I32_I32_I32_I32_RetI32 }, { "inini", (void*)&CallFunc_IND_I32_IND_I32_RetI32 }, { "ininn", (void*)&CallFunc_IND_I32_IND_IND_RetI32 }, - { "inn", (void*)&CallFunc_IND_IND_RetI32 }, { "inni", (void*)&CallFunc_IND_IND_I32_RetI32 }, { "innii", (void*)&CallFunc_IND_IND_I32_I32_RetI32 }, { "innin", (void*)&CallFunc_IND_IND_I32_IND_RetI32 }, { "l", (void*)&CallFunc_Void_RetI64 }, - { "ld", (void*)&CallFunc_F64_RetI64 }, - { "lf", (void*)&CallFunc_F32_RetI64 }, { "li", (void*)&CallFunc_I32_RetI64 }, - { "lii", (void*)&CallFunc_I32_I32_RetI64 }, { "liiil", (void*)&CallFunc_I32_I32_I32_I64_RetI64 }, { "lil", (void*)&CallFunc_I32_I64_RetI64 }, { "lili", (void*)&CallFunc_I32_I64_I32_RetI64 }, { "lill", (void*)&CallFunc_I32_I64_I64_RetI64 }, - { "ll", (void*)&CallFunc_I64_RetI64 }, - { "lli", (void*)&CallFunc_I64_I32_RetI64 }, { "lll", (void*)&CallFunc_I64_I64_RetI64 }, - { "n", (void*)&CallFunc_Void_RetIND }, - { "ni", (void*)&CallFunc_I32_RetIND }, - { "nii", (void*)&CallFunc_I32_I32_RetIND }, - { "niii", (void*)&CallFunc_I32_I32_I32_RetIND }, - { "nin", (void*)&CallFunc_I32_IND_RetIND }, - { "nn", (void*)&CallFunc_IND_RetIND }, - { "nni", (void*)&CallFunc_IND_I32_RetIND }, - { "nnn", (void*)&CallFunc_IND_IND_RetIND }, { "v", (void*)&CallFunc_Void_RetVoid }, - { "vd", (void*)&CallFunc_F64_RetVoid }, { "vdii", (void*)&CallFunc_F64_I32_I32_RetVoid }, - { "vf", (void*)&CallFunc_F32_RetVoid }, { "vfii", (void*)&CallFunc_F32_I32_I32_RetVoid }, { "vi", (void*)&CallFunc_I32_RetVoid }, - { "vid", (void*)&CallFunc_I32_F64_RetVoid }, { "vii", (void*)&CallFunc_I32_I32_RetVoid }, { "viii", (void*)&CallFunc_I32_I32_I32_RetVoid }, { "viiii", (void*)&CallFunc_I32_I32_I32_I32_RetVoid }, { "viiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_RetVoid }, { "viiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetVoid }, - { "viiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_RetVoid }, { "viiinn", (void*)&CallFunc_I32_I32_I32_IND_IND_RetVoid }, { "viiinni", (void*)&CallFunc_I32_I32_I32_IND_IND_I32_RetVoid }, - { "viil", (void*)&CallFunc_I32_I32_I64_RetVoid }, - { "viin", (void*)&CallFunc_I32_I32_IND_RetVoid }, { "viinni", (void*)&CallFunc_I32_I32_IND_IND_I32_RetVoid }, { "viinnii", (void*)&CallFunc_I32_I32_IND_IND_I32_I32_RetVoid }, - { "vil", (void*)&CallFunc_I32_I64_RetVoid }, - { "vin", (void*)&CallFunc_I32_IND_RetVoid }, { "vini", (void*)&CallFunc_I32_IND_I32_RetVoid }, - { "vinni", (void*)&CallFunc_I32_IND_IND_I32_RetVoid }, { "vl", (void*)&CallFunc_I64_RetVoid }, { "vn", (void*)&CallFunc_IND_RetVoid }, { "vni", (void*)&CallFunc_IND_I32_RetVoid }, diff --git a/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs index 88bddf47f040c6..b1722487c6a277 100644 --- a/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs +++ b/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs @@ -68,55 +68,6 @@ public override bool Execute() } } - // WASM-TODO: - // add missing signatures temporarily - // part is for runtime tests and delegates - // active issue https://github.com/dotnet/runtime/issues/121222 - private static readonly string[] missingCookies = - [ - "d", - "ddid", - "dii", - "f", - "id", - "idfi", - "idi", - "if", - "iff", - "iid", - "iif", - "iifiif", - "iiiiiiiiiiiiiiiiii", - "iin", - "iinini", - "iinn", - "il", - "inn", - "lii", - "ld", - "lf", - "ll", - "lli", - "n", - "ni", - "nii", - "niii", - "nin", - "nn", - "nni", - "nnn", - "vd", - "vf", - "viiiiiii", - "viin", - "vid", - "viil", - "vil", - "vin", - "vinni", - "iinini", - ]; - private void ExecuteInternal(LogAdapter log) { Dictionary _symbolNameFixups = new(); @@ -136,8 +87,7 @@ private void ExecuteInternal(LogAdapter log) IEnumerable cookies = Enumerable.Concat( pinvoke.Generate(PInvokeModules, PInvokeOutputPath, ReversePInvokeOutputPath), - Enumerable.Concat(icall.Generate(IcallOutputPath), - missingCookies)); + icall.Generate(IcallOutputPath)); var m2n = new InterpToNativeGenerator(log); m2n.Generate(cookies, InterpToNativeOutputPath);