From 38b7cfd610f9bfc84d141b9f56f8f73ada7b1865 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Wed, 24 Jun 2026 11:14:02 -0700 Subject: [PATCH] [wasm R2R] Align 8-byte stack locals and keep frames 16-aligned 8-byte locals were only 4-byte aligned on wasm, so JS interop reads through the 8-byte HEAP64/HEAPF64 views landed on the wrong word. Align >=8 byte locals to 8 and round the frame to STACK_ALIGN. Fixes #129802. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/jit/lclvars.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 0dc864bd54e00d..5ee0d44d8d374f 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -5753,7 +5753,9 @@ int Compiler::lvaAllocLocalAndSetVirtualOffset(unsigned lclNum, unsigned size, i noway_assert(lclNum != BAD_VAR_NUM); LclVarDsc* lcl = lvaGetDesc(lclNum); -#ifdef TARGET_64BIT +#if defined(TARGET_64BIT) || defined(TARGET_WASM) + // Align >=8 byte locals to 8 bytes. + // // Before final frame layout, assume the worst case, that every >=8 byte local will need // maximum padding to be aligned. This is because we generate code based on the stack offset // computed during tentative frame layout. These offsets cannot get bigger during final @@ -5825,7 +5827,7 @@ int Compiler::lvaAllocLocalAndSetVirtualOffset(unsigned lclNum, unsigned size, i } #endif } -#endif // TARGET_64BIT +#endif // TARGET_64BIT || TARGET_WASM /* Reserve space on the stack by bumping the frame size */ @@ -6046,8 +6048,17 @@ void Compiler::lvaAlignFrame() } } #elif defined(TARGET_WASM) - // TODO-WASM: decide what the stack alignment strategy should be. In the native ABI, the alignment is 16, but that - // may be suboptimal for the managed ABI, since it may imply zeroing the padding slots. + // Keep the stack aligned to STACK_ALIGN. + if ((compLclFrameSize % STACK_ALIGN) != 0) + { + lvaIncrementFrameSize(STACK_ALIGN - (compLclFrameSize % STACK_ALIGN)); + } + else if (lvaDoneFrameLayout != FINAL_FRAME_LAYOUT) + { + // Reserve a full STACK_ALIGN so the offsets computed now are upper bounds. + lvaIncrementFrameSize(STACK_ALIGN); + } + assert((compLclFrameSize % STACK_ALIGN) == 0); #else NYI("TARGET specific lvaAlignFrame"); #endif