// 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)
{
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");
// 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
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);