Reverse P/Invoke methods do not support tailcalls. (#33677)
authorAaron Robinson <arobins@microsoft.com>
Wed, 18 Mar 2020 01:48:32 +0000 (18:48 -0700)
committerGitHub <noreply@github.com>
Wed, 18 Mar 2020 01:48:32 +0000 (18:48 -0700)
* Disable tailcalls in all scenarios involving a Reverse P/Invoke

src/coreclr/src/jit/flowgraph.cpp
src/coreclr/src/jit/importer.cpp
src/coreclr/src/jit/lower.cpp
src/coreclr/src/jit/patchpoint.cpp

index 8ba6d2f..b7ccbcb 100644 (file)
@@ -4329,6 +4329,12 @@ bool Compiler::fgMayExplicitTailCall()
         return false;
     }
 
+    if (opts.IsReversePInvoke())
+    {
+        // Reverse P/Invoke
+        return false;
+    }
+
 #if !FEATURE_FIXED_OUT_ARGS
     if (info.compIsVarArgs)
     {
index 04079ba..331650c 100644 (file)
@@ -7344,11 +7344,18 @@ var_types Compiler::impImportCall(OPCODE                  opcode,
     // Also, popping arguments in a varargs function is more work and NYI
     // If we have a security object, we have to keep our frame around for callers
     // to see any imperative security.
+    // Reverse P/Invokes need a call to CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT
+    // at the end, so tailcalls should be disabled.
     if (info.compFlags & CORINFO_FLG_SYNCH)
     {
         canTailCall             = false;
         szCanTailCallFailReason = "Caller is synchronized";
     }
+    else if (opts.IsReversePInvoke())
+    {
+        canTailCall             = false;
+        szCanTailCallFailReason = "Caller is Reverse P/Invoke";
+    }
 #if !FEATURE_FIXED_OUT_ARGS
     else if (info.compIsVarArgs)
     {
@@ -11479,6 +11486,11 @@ void Compiler::impImportBlockCode(BasicBlock* block)
                     BADCODE("Jmp not allowed in protected region");
                 }
 
+                if (opts.IsReversePInvoke())
+                {
+                    BADCODE("Jmp not allowed in reverse P/Invoke");
+                }
+
                 if (verCurrentState.esStackDepth != 0)
                 {
                     BADCODE("Stack must be empty after CEE_JMPs");
index 838ed6b..f4d5b28 100644 (file)
@@ -1809,6 +1809,7 @@ void Lowering::LowerFastTailCall(GenTreeCall* call)
     // Most of these checks are already done by importer or fgMorphTailCall().
     // This serves as a double sanity check.
     assert((comp->info.compFlags & CORINFO_FLG_SYNCH) == 0); // tail calls from synchronized methods
+    assert(!comp->opts.IsReversePInvoke());                  // tail calls reverse pinvoke
     assert(!call->IsUnmanaged());                            // tail calls to unamanaged methods
     assert(!comp->compLocallocUsed);                         // tail call from methods that also do localloc
 
index e9aca3b..8527bd9 100644 (file)
@@ -231,6 +231,12 @@ void Compiler::fgTransformPatchpoints()
         return;
     }
 
+    if (opts.IsReversePInvoke())
+    {
+        JITDUMP(" -- unable to handle Reverse P/Invoke\n");
+        return;
+    }
+
     PatchpointTransformer ppTransformer(this);
     int                   count = ppTransformer.Run();
     JITDUMP("\n*************** After fgTransformPatchpoints() [%d patchpoints transformed]\n", count);