Save stack arguments size in InlinedCallFrame.m_Datum on x86 to handle callee's poppi...
authorFadi Hanna <fadim@microsoft.com>
Tue, 4 Feb 2020 01:09:30 +0000 (20:09 -0500)
committerGitHub <noreply@github.com>
Tue, 4 Feb 2020 01:09:30 +0000 (20:09 -0500)
* 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
src/coreclr/src/vm/i386/PInvokeStubs.asm
src/coreclr/src/vm/i386/cgenx86.cpp

index 937d837..bf47b52 100644 (file)
@@ -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));
index e85ac3b..6b7558c 100644 (file)
@@ -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
index fb890e8..d03f335 100644 (file)
@@ -612,7 +612,10 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
         return;
     }
 
-    DWORD stackArgSize = (DWORD) dac_cast<TADDR>(m_Datum);
+    DWORD stackArgSize = 0;
+
+#if !defined(UNIX_X86_ABI)
+    stackArgSize = (DWORD) dac_cast<TADDR>(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,