Skip to content

Commit 5d9e18e

Browse files
steveisokCopilot
andauthored
Fix HFA/HVA by-value argument marshalling on ARM64 in CallTargetWorker (#130580)
MethodDescCallSite::CallTargetWorker manually marshals arguments into the register save area. The branch that expands a struct-passed-in-registers into individual register slots was gated to UNIX_AMD64_ABI / LOONGARCH64 / RISCV64 only. On ARM64, HFA/HVA structs passed by value in FP registers fell through to the default packed CopyMemory, which lays the fields out contiguously instead of placing each field in its own NEON register slot. The callee then read {field0, field2, garbage, ...}. Add a TARGET_ARM64 branch that calls the existing ArgDestination::CopyHFAStructToRegister when the argument is an HFA, matching the pattern already used in CopyValueClassArgUnchecked. Non-HFA structs (and HFAs spilled to the stack) keep IsHFA() == false and fall through to the unchanged default copy. This manifested as "vector math broken in the debugger only" because normal JIT-emitted calls and reflection invoke stubs do not use this manual marshalling path, but debugger func-eval does. Fixes #126564 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 4d33abd commit 5d9e18e

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

src/coreclr/vm/callhelpers.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,15 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *
401401
argDest.CopyStructToRegisters(pSrc, th.AsMethodTable()->GetNumInstanceFieldBytes(), 0);
402402
}
403403
else
404+
#elif defined(TARGET_ARM64)
405+
if (argDest.IsHFA())
406+
{
407+
// An HFA/HVA struct argument is enregistered with each field in its own
408+
// floating-point/vector register. Expand the packed struct data into the
409+
// register slots instead of copying it verbatim.
410+
argDest.CopyHFAStructToRegister(pSrc, stackSize);
411+
}
412+
else
404413
#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
405414
if (argDest.IsStructPassedInRegs())
406415
{

0 commit comments

Comments
 (0)