From d4c26281bd5859e318e245c371d8056a0bc51d28 Mon Sep 17 00:00:00 2001 From: Fadi Hanna Date: Mon, 3 Feb 2020 20:09:30 -0500 Subject: [PATCH] Save stack arguments size in InlinedCallFrame.m_Datum on x86 to handle callee's popping of arguments (#26834) * Save stack arguments size in InlinedCallFrame.m_Datum on x86 to handle callee's popping of arguments * Move stack arguments sizes logic to Windows-only --- src/coreclr/src/jit/lower.cpp | 19 ++++++++++++++----- src/coreclr/src/vm/i386/PInvokeStubs.asm | 8 ++++---- src/coreclr/src/vm/i386/cgenx86.cpp | 6 +++++- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/coreclr/src/jit/lower.cpp b/src/coreclr/src/jit/lower.cpp index 937d837..bf47b52 100644 --- a/src/coreclr/src/jit/lower.cpp +++ b/src/coreclr/src/jit/lower.cpp @@ -3240,8 +3240,8 @@ GenTree* Lowering::LowerDelegateInvoke(GenTreeCall* call) #else // !TARGET_X86 // In case of helper dispatched tail calls, "thisptr" will be the third arg. // The first two args are: real call target and addr of args copy routine. - const unsigned argNum = 2; -#endif // !TARGET_X86 + const unsigned argNum = 2; +#endif // !_TARGET_X86_ fgArgTabEntry* thisArgTabEntry = comp->gtArgEntryByArgNum(call, argNum); thisArgNode = thisArgTabEntry->GetNode(); @@ -3507,7 +3507,7 @@ void Lowering::InsertPInvokeMethodProlog() #if defined(TARGET_X86) || defined(TARGET_ARM) GenTreeCall::Use* argList = comp->gtNewCallArgs(frameAddr); #else - GenTreeCall::Use* argList = comp->gtNewCallArgs(frameAddr, PhysReg(REG_SECRET_STUB_PARAM)); + GenTreeCall::Use* argList = comp->gtNewCallArgs(frameAddr, PhysReg(REG_SECRET_STUB_PARAM)); #endif GenTree* call = comp->gtNewHelperCallNode(CORINFO_HELP_INIT_PINVOKE_FRAME, TYP_I_IMPL, argList); @@ -3688,9 +3688,18 @@ void Lowering::InsertPInvokeCallProlog(GenTreeCall* call) GenTree* frameAddr = new (comp, GT_LCL_VAR_ADDR) GenTreeLclVar(GT_LCL_VAR_ADDR, TYP_BYREF, comp->lvaInlinedPInvokeFrameVar); +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) + // On x86 targets, PInvoke calls need the size of the stack args in InlinedCallFrame.m_Datum. + // This is because the callee pops stack arguments, and we need to keep track of this during stack + // walking + const unsigned numStkArgBytes = call->fgArgInfo->GetNextSlotNum() * TARGET_POINTER_SIZE; + GenTree* stackBytes = comp->gtNewIconNode(numStkArgBytes, TYP_INT); + GenTreeCall::Use* args = comp->gtNewCallArgs(frameAddr, stackBytes); +#else + GenTreeCall::Use* args = comp->gtNewCallArgs(frameAddr); +#endif // Insert call to CORINFO_HELP_JIT_PINVOKE_BEGIN - GenTree* helperCall = - comp->gtNewHelperCallNode(CORINFO_HELP_JIT_PINVOKE_BEGIN, TYP_VOID, comp->gtNewCallArgs(frameAddr)); + GenTree* helperCall = comp->gtNewHelperCallNode(CORINFO_HELP_JIT_PINVOKE_BEGIN, TYP_VOID, args); comp->fgMorphTree(helperCall); BlockRange().InsertBefore(insertBefore, LIR::SeqTree(comp, helperCall)); diff --git a/src/coreclr/src/vm/i386/PInvokeStubs.asm b/src/coreclr/src/vm/i386/PInvokeStubs.asm index e85ac3b..6b7558c 100644 --- a/src/coreclr/src/vm/i386/PInvokeStubs.asm +++ b/src/coreclr/src/vm/i386/PInvokeStubs.asm @@ -32,9 +32,9 @@ extern @JIT_PInvokeEndRarePath@0:proc ; ; in: -; InlinedCallFrame (ecx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right -; before actual InlinedCallFrame data) -; +; InlinedCallFrame (ecx) = pointer to the InlinedCallFrame data, including the GS cookie slot (GS cookie right +; before actual InlinedCallFrame data) +; StackArgumentsSize (edx) = Number of argument bytes pushed on the stack, which will be popped by the callee ; _JIT_PInvokeBegin@4 PROC public @@ -46,7 +46,7 @@ _JIT_PInvokeBegin@4 PROC public lea eax,[??_7InlinedCallFrame@@6B@] mov dword ptr [ecx], eax - mov dword ptr [ecx + InlinedCallFrame__m_Datum], 0 + mov dword ptr [ecx + InlinedCallFrame__m_Datum], edx mov eax, esp diff --git a/src/coreclr/src/vm/i386/cgenx86.cpp b/src/coreclr/src/vm/i386/cgenx86.cpp index fb890e8..d03f335 100644 --- a/src/coreclr/src/vm/i386/cgenx86.cpp +++ b/src/coreclr/src/vm/i386/cgenx86.cpp @@ -612,7 +612,10 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD) return; } - DWORD stackArgSize = (DWORD) dac_cast(m_Datum); + DWORD stackArgSize = 0; + +#if !defined(UNIX_X86_ABI) + stackArgSize = (DWORD) dac_cast(m_Datum); if (stackArgSize & ~0xFFFF) { @@ -624,6 +627,7 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD) stackArgSize = pMD->GetStackArgumentSize(); } +#endif /* The return address is just above the "ESP" */ pRD->PCTAddr = PTR_HOST_MEMBER_TADDR(InlinedCallFrame, this, -- 2.7.4