Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3744,6 +3744,24 @@ void InterpCompiler::EmitPushLdvirtftn(int thisVar, CORINFO_RESOLVED_TOKEN* pRes
m_pLastNewIns->info.pCallInfo->pCallArgs = callArgs;
}

static bool DisallowTailCall(CORINFO_SIG_INFO* callerSig, CORINFO_SIG_INFO* calleeSig)
{
// We allow only the return value types to differ between caller and callee as long as their stack types are the same.
// In principle we could allow more differences (e.g. I8 coercion to I4, or O to I) but for now we keep it simple.
if (callerSig->retType != calleeSig->retType)
{
if (g_stackTypeFromInterpType[GetInterpType(callerSig->retType)] != g_stackTypeFromInterpType[GetInterpType(calleeSig->retType)])
{
return true;
}
}
else if (callerSig->retType == CORINFO_TYPE_VALUECLASS && callerSig->retTypeClass != calleeSig->retTypeClass)
{
return true;
}
return false;
}

void InterpCompiler::EmitCalli(bool isTailCall, void* calliCookie, int callIFunctionPointerVar, CORINFO_SIG_INFO* callSiteSig)
{
AddIns(isTailCall ? INTOP_CALLI_TAIL : INTOP_CALLI);
Expand Down Expand Up @@ -4014,6 +4032,15 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
#endif
}

if (tailcall && DisallowTailCall(&m_methodInfo->args, &callInfo.sig))
{
if (isJmp)
{
BADCODE("Incompatible target for CEE_JMP tail call");
}
tailcall = false;
}

if (newObj && (callInfo.classFlags & CORINFO_FLG_VAROBJSIZE))
{
// This is a variable size object which means "System.String".
Expand Down
Loading