Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/coreclr/jit/codegenwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2906,6 +2906,20 @@ void CodeGen::genCallInstruction(GenTreeCall* call)

params.wasmSignature = m_compiler->info.compCompHnd->getWasmTypeSymbol(typeStack.Data(), typeStack.Height());

// R2R keeps its shadow SP in a local and leaves the __stack_pointer global stale; the PInvoke
// prolog (JIT_PInvokeBegin) normally publishes the current SP to __stack_pointer before native
// code runs, but that prolog/epilog is skipped for SuppressGCTransition calls (see Lowering).
// Without a publish, the native SuppressGCTransition callee allocates its shadow frame from the
// stale global (our caller's SP, above our frame) and overlaps/clobbers our address-taken locals.
// Publish our shadow SP here so the callee allocates below our frame. This is a net-zero operation
// on the Wasm operand stack, so it is safe to emit with the call arguments already pushed.
if (call->IsUnmanaged() && call->IsSuppressGCTransition())
{
GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, GetStackPointerRegIndex());
GetEmitter()->emitIns_I(INS_global_set, EA_HANDLE_CNS_RELOC,
(cnsval_ssize_t)(size_t)m_compiler->eeGetWasmWellKnownGlobals()->stackPointer);
}

// A non-null target expression always indicates an indirect call on Wasm,
// as currently the only possible result of the target expression would be a
// table index which must be used via call_indirect
Expand Down
Loading