From cf38c442ec10844282b2ada4ba489aa8d190277b Mon Sep 17 00:00:00 2001 From: Fadi Hanna Date: Tue, 10 Mar 2020 16:47:52 -0700 Subject: [PATCH] Save stack arguments size in InlinedCallFrame.m_Datum on x86 to handle callee's popping of arguments (#33249) * Save stack arguments size in InlinedCallFrame.m_Datum on x86 to handle callee's popping of arguments --- src/coreclr/src/jit/lower.cpp | 17 +++++++++++++---- src/coreclr/src/vm/i386/PInvokeStubs.asm | 8 ++++---- src/coreclr/src/vm/i386/cgenx86.cpp | 6 +++++- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/coreclr/src/jit/lower.cpp b/src/coreclr/src/jit/lower.cpp index f95e9e2..838ed6b 100644 --- a/src/coreclr/src/jit/lower.cpp +++ b/src/coreclr/src/jit/lower.cpp @@ -3172,7 +3172,7 @@ 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; + const unsigned argNum = 2; #endif // !TARGET_X86 fgArgTabEntry* thisArgTabEntry = comp->gtArgEntryByArgNum(call, argNum); @@ -3439,7 +3439,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); @@ -3620,9 +3620,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 0de1ab4..3563e8e 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