diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index b71d8efffefa13..1531987846f084 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -538,11 +538,11 @@ void CodeGen::genCodeForBBlist() nonVarPtrRegs &= ~RBM_ASYNC_CONTINUATION_RET; } - // For a tailcall arbitrary argument registers may be live into the + // For a tailcall arbitrary argument/target registers may be live into the // epilog. Skip validating those. if (block->HasFlag(BBF_HAS_JMP)) { - nonVarPtrRegs &= ~fullIntArgRegMask(CorInfoCallConvExtension::Managed); + nonVarPtrRegs = RBM_NONE; } if (nonVarPtrRegs) diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 320d53d7cef864..0f40fe6085d8c1 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -6052,6 +6052,21 @@ void CodeGen::genCall(GenTreeCall* call) if (target->isContainedIndir()) { genConsumeAddress(target->AsIndir()->Addr()); + + // Consuming these registers will ensure the registers containing the state we need are available here, + // but it assumes we will use them immediately and will thus kill the live state. Since these registers + // are live into the epilog we need to remark them as live. + // This logic is similar to what genCallPlaceRegArgs does above for argument registers. + GenTreeIndir* indir = target->AsIndir(); + if (indir->HasBase() && indir->Base()->TypeIs(TYP_BYREF, TYP_REF)) + { + gcInfo.gcMarkRegPtrVal(indir->Base()->GetRegNum(), indir->Base()->TypeGet()); + } + + if (indir->HasIndex() && indir->Index()->TypeIs(TYP_BYREF, TYP_REF)) + { + gcInfo.gcMarkRegPtrVal(indir->Index()->GetRegNum(), indir->Index()->TypeGet()); + } } else {