From 415eadb134d4f38b80d739c0bddefb34ade35109 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 25 Nov 2025 00:19:11 +0100 Subject: [PATCH 1/2] Fix interpreter Unix x64 call stub generator The call stub generator is missing support for return buffer passing in RSI, only RDI was supported by mistake. This change fixes it. --- src/coreclr/vm/amd64/asmhelpers.S | 39 +++++++++++++++++++++++++--- src/coreclr/vm/callstubgenerator.cpp | 36 ++++++++++++++++++++----- src/coreclr/vm/callstubgenerator.h | 2 +- 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/coreclr/vm/amd64/asmhelpers.S b/src/coreclr/vm/amd64/asmhelpers.S index 7231750b6698b0..74cf5256b5873d 100644 --- a/src/coreclr/vm/amd64/asmhelpers.S +++ b/src/coreclr/vm/amd64/asmhelpers.S @@ -574,7 +574,7 @@ END_PROLOGUE ret NESTED_END InterpreterStubRetDoubleI8, _TEXT -NESTED_ENTRY InterpreterStubRetBuff, _TEXT, NoHandler +NESTED_ENTRY InterpreterStubRetBuffRDI, _TEXT, NoHandler push_register rax // stack alignment END_PROLOGUE mov rdi, rax // pTransitionBlock* @@ -586,7 +586,21 @@ END_PROLOGUE mov rax, qword ptr [rsp + 8 + 8 + __InterpreterStubArgumentRegistersOffset] pop_register rcx ret -NESTED_END InterpreterStubRetBuff, _TEXT +NESTED_END InterpreterStubRetBuffRDI, _TEXT + +NESTED_ENTRY InterpreterStubRetBuffRSI, _TEXT, NoHandler + push_register rax // stack alignment +END_PROLOGUE + mov rdi, rax // pTransitionBlock* + mov rsi, rbx // the IR bytecode pointer + // Load the return buffer address + // The 8 + 8 is for the push and the return address slot + mov rdx, qword ptr [rsp + 8 + 8 + __InterpreterStubArgumentRegistersOffset + 8] + call C_FUNC(ExecuteInterpretedMethod) + mov rax, qword ptr [rsp + 8 + 8 + __InterpreterStubArgumentRegistersOffset + 8] + pop_register rcx + ret +NESTED_END InterpreterStubRetBuffRSI, _TEXT // Routines for passing value type arguments by reference in general purpose registers RDI, RSI, RDX, RCX, R8, R9 // from native code to the interpreter @@ -1732,7 +1746,7 @@ END_PROLOGUE ret NESTED_END CallJittedMethodRetVoid, _TEXT -NESTED_ENTRY CallJittedMethodRetBuff, _TEXT, NoHandler +NESTED_ENTRY CallJittedMethodRetBuffRDI, _TEXT, NoHandler push_nonvol_reg rbp mov rbp, rsp alloc_stack 0x10 @@ -1747,7 +1761,24 @@ END_PROLOGUE mov rsp, rbp pop rbp ret -NESTED_END CallJittedMethodRetBuff, _TEXT +NESTED_END CallJittedMethodRetBuffRDI, _TEXT + +NESTED_ENTRY CallJittedMethodRetBuffRSI, _TEXT, NoHandler + push_nonvol_reg rbp + mov rbp, rsp + alloc_stack 0x10 + save_reg_postrsp r10, 0 +END_PROLOGUE + sub rsp, rcx // total stack space + mov r11, rdi // The routines list + mov r10, rsi // interpreter stack args + mov rsi, rdx // return buffer + call qword ptr [r11] + mov r10, [rsp] + mov rsp, rbp + pop rbp + ret +NESTED_END CallJittedMethodRetBuffRSI, _TEXT NESTED_ENTRY CallJittedMethodRetDouble, _TEXT, NoHandler push_nonvol_reg rbp diff --git a/src/coreclr/vm/callstubgenerator.cpp b/src/coreclr/vm/callstubgenerator.cpp index ce0c58a90fbd47..8d0fcb7620d839 100644 --- a/src/coreclr/vm/callstubgenerator.cpp +++ b/src/coreclr/vm/callstubgenerator.cpp @@ -1975,12 +1975,19 @@ extern "C" void InterpreterStubRetVoid(); extern "C" void InterpreterStubRetDouble(); extern "C" void InterpreterStubRetI8(); -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#ifdef TARGET_AMD64 +#ifdef TARGET_WINDOWS extern "C" void CallJittedMethodRetBuffRCX(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize); extern "C" void CallJittedMethodRetBuffRDX(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize); extern "C" void InterpreterStubRetBuffRCX(); extern "C" void InterpreterStubRetBuffRDX(); -#else // TARGET_WINDOWS && TARGET_AMD64 +#else // TARGET_WINDOWS +extern "C" void CallJittedMethodRetBuffRDI(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize); +extern "C" void CallJittedMethodRetBuffRSI(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize); +extern "C" void InterpreterStubRetBuffRDI(); +extern "C" void InterpreterStubRetBuffRSI(); +#endif // TARGET_WINDOWS +#else // TARGET_AMD64 extern "C" void CallJittedMethodRetBuff(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize); extern "C" void InterpreterStubRetBuff(); #endif // TARGET_WINDOWS && TARGET_AMD64 @@ -2060,12 +2067,19 @@ CallStubHeader::InvokeFunctionPtr CallStubGenerator::GetInvokeFunctionPtr(CallSt INVOKE_FUNCTION_PTR(CallJittedMethodRetDouble); case ReturnTypeI8: INVOKE_FUNCTION_PTR(CallJittedMethodRetI8); -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#ifdef TARGET_AMD64 +#ifdef TARGET_WINDOWS case ReturnTypeBuffArg1: INVOKE_FUNCTION_PTR(CallJittedMethodRetBuffRCX); case ReturnTypeBuffArg2: INVOKE_FUNCTION_PTR(CallJittedMethodRetBuffRDX); -#else // TARGET_WINDOWS && TARGET_AMD64 +#else // TARGET_WINDOWS + case ReturnTypeBuffArg1: + INVOKE_FUNCTION_PTR(CallJittedMethodRetBuffRDI); + case ReturnTypeBuffArg2: + INVOKE_FUNCTION_PTR(CallJittedMethodRetBuffRSI); +#endif // TARGET_WINDOWS +#else // TARGET_AMD64 case ReturnTypeBuff: INVOKE_FUNCTION_PTR(CallJittedMethodRetBuff); #endif // TARGET_WINDOWS && TARGET_AMD64 @@ -2147,12 +2161,20 @@ PCODE CallStubGenerator::GetInterpreterReturnTypeHandler(CallStubGenerator::Retu RETURN_TYPE_HANDLER(InterpreterStubRetDouble); case ReturnTypeI8: RETURN_TYPE_HANDLER(InterpreterStubRetI8); -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#ifdef TARGET_AMD64 case ReturnTypeBuffArg1: +#ifdef TARGET_WINDOWS RETURN_TYPE_HANDLER(InterpreterStubRetBuffRCX); +#else + RETURN_TYPE_HANDLER(InterpreterStubRetBuffRDI); +#endif case ReturnTypeBuffArg2: +#ifdef TARGET_WINDOWS RETURN_TYPE_HANDLER(InterpreterStubRetBuffRDX); -#else // TARGET_WINDOWS && TARGET_AMD64 +#else + RETURN_TYPE_HANDLER(InterpreterStubRetBuffRSI); +#endif +#else // TARGET_AMD64 case ReturnTypeBuff: RETURN_TYPE_HANDLER(InterpreterStubRetBuff); #endif // TARGET_WINDOWS && TARGET_AMD64 @@ -2799,7 +2821,7 @@ CallStubGenerator::ReturnType CallStubGenerator::GetReturnType(ArgIterator *pArg { if (pArgIt->HasRetBuffArg()) { -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#ifdef TARGET_AMD64 if (pArgIt->HasThis()) { return ReturnTypeBuffArg2; diff --git a/src/coreclr/vm/callstubgenerator.h b/src/coreclr/vm/callstubgenerator.h index da686ff9a76cec..84d46929361259 100644 --- a/src/coreclr/vm/callstubgenerator.h +++ b/src/coreclr/vm/callstubgenerator.h @@ -70,7 +70,7 @@ class CallStubGenerator ReturnTypeVoid, ReturnTypeI8, ReturnTypeDouble, -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#ifdef TARGET_AMD64 ReturnTypeBuffArg1, ReturnTypeBuffArg2, #else From a23a4c1e2d88d36c0ed595e1786bc6b9b37bd3d8 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 25 Nov 2025 01:17:08 +0100 Subject: [PATCH 2/2] Apply suggestions from code review Add / fix some comments on #endifs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Aaron R Robinson --- src/coreclr/vm/callstubgenerator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/vm/callstubgenerator.cpp b/src/coreclr/vm/callstubgenerator.cpp index 8d0fcb7620d839..5622140882a207 100644 --- a/src/coreclr/vm/callstubgenerator.cpp +++ b/src/coreclr/vm/callstubgenerator.cpp @@ -1990,7 +1990,7 @@ extern "C" void InterpreterStubRetBuffRSI(); #else // TARGET_AMD64 extern "C" void CallJittedMethodRetBuff(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize); extern "C" void InterpreterStubRetBuff(); -#endif // TARGET_WINDOWS && TARGET_AMD64 +#endif // TARGET_AMD64 #ifdef UNIX_AMD64_ABI extern "C" void CallJittedMethodRetI8I8(PCODE *routines, int8_t*pArgs, int8_t*pRet, int totalStackSize); @@ -2082,7 +2082,7 @@ CallStubHeader::InvokeFunctionPtr CallStubGenerator::GetInvokeFunctionPtr(CallSt #else // TARGET_AMD64 case ReturnTypeBuff: INVOKE_FUNCTION_PTR(CallJittedMethodRetBuff); -#endif // TARGET_WINDOWS && TARGET_AMD64 +#endif // TARGET_AMD64 #ifdef UNIX_AMD64_ABI case ReturnTypeI8I8: INVOKE_FUNCTION_PTR(CallJittedMethodRetI8I8); @@ -2177,7 +2177,7 @@ PCODE CallStubGenerator::GetInterpreterReturnTypeHandler(CallStubGenerator::Retu #else // TARGET_AMD64 case ReturnTypeBuff: RETURN_TYPE_HANDLER(InterpreterStubRetBuff); -#endif // TARGET_WINDOWS && TARGET_AMD64 +#endif // TARGET_AMD64 #ifdef UNIX_AMD64_ABI case ReturnTypeI8I8: RETURN_TYPE_HANDLER(InterpreterStubRetI8I8); @@ -2832,7 +2832,7 @@ CallStubGenerator::ReturnType CallStubGenerator::GetReturnType(ArgIterator *pArg } #else return ReturnTypeBuff; -#endif +#endif // TARGET_AMD64 } else {