diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 6fadbfa9aede89..db875b45dd0c6d 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -1097,7 +1097,7 @@ class CodeGen final : public CodeGenInterface #if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS) void genConsumeMultiOpOperands(GenTreeMultiOp* tree); #endif - void genEmitGSCookieCheck(bool pushReg); + void genEmitGSCookieCheck(bool tailCall); void genCodeForShift(GenTree* tree); #if defined(TARGET_X86) || defined(TARGET_ARM) diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 96f01019ac0ecd..8d90b0d3766f10 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -613,7 +613,10 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) // genEmitGSCookieCheck: Generate code to check that the GS cookie // wasn't thrashed by a buffer overrun. // -void CodeGen::genEmitGSCookieCheck(bool pushReg) +// Parameters: +// tailCall - Whether or not this is being emitted for a tail call +// +void CodeGen::genEmitGSCookieCheck(bool tailCall) { noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal); @@ -623,8 +626,9 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) // We don't have any IR node representing this check, so LSRA can't communicate registers // for us to use. - regNumber regGSConst = REG_GSCOOKIE_TMP_0; - regNumber regGSValue = REG_GSCOOKIE_TMP_1; + regMaskTP tmpRegs = genGetGSCookieTempRegs(tailCall); + regNumber regGSConst = genFirstRegNumFromMaskAndToggle(tmpRegs); + regNumber regGSValue = genFirstRegNumFromMaskAndToggle(tmpRegs); if (compiler->gsGlobalSecurityCookieAddr == nullptr) { @@ -3266,12 +3270,12 @@ void CodeGen::genCallInstruction(GenTreeCall* call) { regMaskTP trashedByEpilog = RBM_CALLEE_SAVED; - // The epilog may use and trash REG_GSCOOKIE_TMP_0/1. Make sure we have no - // non-standard args that may be trash if this is a tailcall. + // The epilog may use and trash some registers for the GS cookie check. + // Make sure we have no non-standard args that may be trash if this is + // a tailcall. if (compiler->getNeedsGSSecurityCookie()) { - trashedByEpilog |= genRegMask(REG_GSCOOKIE_TMP_0); - trashedByEpilog |= genRegMask(REG_GSCOOKIE_TMP_1); + trashedByEpilog |= genGetGSCookieTempRegs(/* tailCall */ true); } for (CallArg& arg : call->gtArgs.Args()) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 0ffa6e8887f7cd..d673a0678ceee5 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1552,14 +1552,11 @@ void CodeGen::genExitCode(BasicBlock* block) Note that this may result in a duplicate IPmapping entry, and that this is ok */ - // For non-optimized debuggable code, there is only one epilog. genIPmappingAdd(IPmappingDscKind::Epilog, DebugInfo(), true); - bool jmpEpilog = block->HasFlag(BBF_HAS_JMP); - #ifdef DEBUG // For returnining epilogs do some validation that the GC info looks right. - if (!jmpEpilog) + if (!block->HasFlag(BBF_HAS_JMP)) { if (compiler->compMethodReturnsRetBufAddr()) { @@ -1583,7 +1580,7 @@ void CodeGen::genExitCode(BasicBlock* block) if (compiler->getNeedsGSSecurityCookie()) { - genEmitGSCookieCheck(jmpEpilog); + genEmitGSCookieCheck(block->HasFlag(BBF_HAS_JMP)); } genReserveEpilog(block); @@ -2508,6 +2505,47 @@ CorInfoHelpFunc CodeGenInterface::genWriteBarrierHelperForWriteBarrierForm(GCInf } } +// ----------------------------------------------------------------------------- +// genGetGSCookieTempRegs: +// Get a mask of registers to use for the GS cookie check generated in a +// block. +// +// Parameters: +// tailCall - Whether the block is a tailcall +// +// Returns: +// Mask of all the registers that can be used. Some targets may need more +// than one register. +// +regMaskTP CodeGenInterface::genGetGSCookieTempRegs(bool tailCall) +{ +#ifdef TARGET_XARCH + if (tailCall) + { + // If we are tailcalling then return registers are available for use + return RBM_RAX; + } + +#ifdef TARGET_AMD64 + // Otherwise on x64 (win-x64 and SysV) r8 is never used for return values + return RBM_R8; +#else + // On x86 it's more difficult: we have only eax, ecx and edx available as volatile + // registers, and all of them may be used for return values (longs + async continuation). + if (compiler->compIsAsync()) + { + // Just use a callee save for this rare async + gs cookie check case. + return RBM_ESI; + } + + // Outside async ecx is not used for returns. + return RBM_ECX; +#endif +#else + return RBM_GSCOOKIE_TMP; +#endif +} + //---------------------------------------------------------------------- // genGCWriteBarrier: Generate a write barrier for a node. // diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index 645948206d672f..5b5219f06d97d8 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -217,6 +217,8 @@ class CodeGenInterface bool genWriteBarrierUsed; #endif + regMaskTP genGetGSCookieTempRegs(bool tailCall); + // The following property indicates whether the current method sets up // an explicit stack frame or not. private: diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index c0ecf124ee1da6..36bc8f78b6dc01 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -4464,7 +4464,10 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) // genEmitGSCookieCheck: Generate code to check that the GS cookie // wasn't thrashed by a buffer overrun. // -void CodeGen::genEmitGSCookieCheck(bool pushReg) +// Parameters: +// tailCall - Whether or not this is being emitted for a tail call +// +void CodeGen::genEmitGSCookieCheck(bool tailCall) { noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal); @@ -4474,8 +4477,9 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) // We don't have any IR node representing this check, so LSRA can't communicate registers // for us to use. - regNumber regGSConst = REG_GSCOOKIE_TMP_0; - regNumber regGSValue = REG_GSCOOKIE_TMP_1; + regMaskTP tmpRegs = genGetGSCookieTempRegs(tailCall); + regNumber regGSConst = genFirstRegNumFromMaskAndToggle(tmpRegs); + regNumber regGSValue = genFirstRegNumFromMaskAndToggle(tmpRegs); if (compiler->gsGlobalSecurityCookieAddr == nullptr) { @@ -5691,12 +5695,11 @@ void CodeGen::genCallInstruction(GenTreeCall* call) { regMaskTP trashedByEpilog = RBM_CALLEE_SAVED; - // The epilog may use and trash REG_GSCOOKIE_TMP_0/1. Make sure we have no + // The epilog may use and trash REG_GSCOOKIE_TMP. Make sure we have no // non-standard args that may be trash if this is a tailcall. if (compiler->getNeedsGSSecurityCookie()) { - trashedByEpilog |= genRegMask(REG_GSCOOKIE_TMP_0); - trashedByEpilog |= genRegMask(REG_GSCOOKIE_TMP_1); + trashedByEpilog |= genGetGSCookieTempRegs(/* tailCall */ true); } for (CallArg& arg : call->gtArgs.Args()) diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 943cd62e137b30..7bc4c8dcba0397 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -4473,7 +4473,10 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) // genEmitGSCookieCheck: Generate code to check that the GS cookie // wasn't thrashed by a buffer overrun. // -void CodeGen::genEmitGSCookieCheck(bool pushReg) +// Parameters: +// tailCall - Whether or not this is being emitted for a tail call +// +void CodeGen::genEmitGSCookieCheck(bool tailCall) { noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal); @@ -4483,8 +4486,9 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) // We don't have any IR node representing this check, so LSRA can't communicate registers // for us to use. - regNumber regGSConst = REG_GSCOOKIE_TMP_0; - regNumber regGSValue = REG_GSCOOKIE_TMP_1; + regMaskTP tmpRegs = genGetGSCookieTempRegs(tailCall); + regNumber regGSConst = genFirstRegNumFromMaskAndToggle(tmpRegs); + regNumber regGSValue = genFirstRegNumFromMaskAndToggle(tmpRegs); if (compiler->gsGlobalSecurityCookieAddr == nullptr) { @@ -5748,12 +5752,12 @@ void CodeGen::genCallInstruction(GenTreeCall* call) { regMaskTP trashedByEpilog = RBM_CALLEE_SAVED; - // The epilog may use and trash REG_GSCOOKIE_TMP_0/1. Make sure we have no - // non-standard args that may be trash if this is a tailcall. + // The epilog may use and trash some registers for the GS cookie check. + // Make sure we have no non-standard args that may be trash if this is + // a tailcall. if (compiler->getNeedsGSSecurityCookie()) { - trashedByEpilog |= genRegMask(REG_GSCOOKIE_TMP_0); - trashedByEpilog |= genRegMask(REG_GSCOOKIE_TMP_1); + trashedByEpilog |= genGetGSCookieTempRegs(/* tailCall */ true); } for (CallArg& arg : call->gtArgs.Args()) diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index bde2493ab0d137..ea237262532ff3 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -84,64 +84,20 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) } } -/***************************************************************************** - * - * Generate code to check that the GS cookie wasn't thrashed by a buffer - * overrun. If pushReg is true, preserve all registers around code sequence. - * Otherwise ECX could be modified. - * - * Implementation Note: pushReg = true, in case of tail calls. - */ -void CodeGen::genEmitGSCookieCheck(bool pushReg) +//--------------------------------------------------------------------- +// genEmitGSCookieCheck: +// Emit the check that the GS cookie has its original value. +// +// Parameters: +// tailCall - Whether or not this is being emitted for a tail call +// +void CodeGen::genEmitGSCookieCheck(bool tailCall) { noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal); - regNumber regGSCheck; - regMaskTP regMaskGSCheck = RBM_NONE; - - if (!pushReg) - { - // Non-tail call: we can use any callee trash register that is not - // a return register or contain 'this' pointer (keep alive this), since - // we are generating GS cookie check after a GT_RETURN block. - // Note: On Amd64 System V RDX is an arg register - REG_ARG_2 - as well - // as return register for two-register-returned structs. -#ifdef TARGET_X86 - // Note: ARG_0 can be REG_ASYNC_CONTINUATION_RET - // we will check for that later if we end up saving/restoring this. - regGSCheck = REG_ARG_0; - regNumber regGSCheckAlternative = REG_ARG_1; -#else - // these cannot be a part of any kind of return - regGSCheck = REG_R8; - regNumber regGSCheckAlternative = REG_R9; -#endif - - if (compiler->lvaKeepAliveAndReportThis() && compiler->lvaGetDesc(compiler->info.compThisArg)->lvIsInReg() && - (compiler->lvaGetDesc(compiler->info.compThisArg)->GetRegNum() == regGSCheck)) - { - regGSCheck = regGSCheckAlternative; - } - } - else - { -#ifdef TARGET_X86 - // It doesn't matter which register we pick, since we're going to save and restore it - // around the check. - // TODO-CQ: Can we optimize the choice of register to avoid doing the push/pop sometimes? - regGSCheck = REG_EAX; - regMaskGSCheck = RBM_EAX; -#else // !TARGET_X86 - // Jmp calls: specify method handle using which JIT queries VM for its entry point - // address and hence it can neither be a VSD call nor PInvoke calli with cookie - // parameter. Therefore, in case of jmp calls it is safe to use R11. - regGSCheck = REG_R11; -#endif // !TARGET_X86 - } - - regMaskTP byrefPushedRegs = RBM_NONE; - regMaskTP norefPushedRegs = RBM_NONE; - regMaskTP pushedRegs = RBM_NONE; + regMaskTP tempRegs = genGetGSCookieTempRegs(tailCall); + assert(tempRegs != RBM_NONE); + regNumber regGSCheck = genFirstRegNumFromMask(tempRegs); if (compiler->gsGlobalSecurityCookieAddr == nullptr) { @@ -163,18 +119,6 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) } else { - // AOT case - GS cookie value needs to be accessed through an indirection. - - // if we use the continuation reg, the pop/push requires no-GC - // this can happen only when AOT supports async on x86 - if (compiler->compIsAsync() && (regGSCheck == REG_ASYNC_CONTINUATION_RET)) - { - regMaskGSCheck = RBM_ASYNC_CONTINUATION_RET; - GetEmitter()->emitDisableGC(); - } - - pushedRegs = genPushRegs(regMaskGSCheck, &byrefPushedRegs, &norefPushedRegs); - instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regGSCheck, (ssize_t)compiler->gsGlobalSecurityCookieAddr); GetEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, regGSCheck, regGSCheck, 0); GetEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie, 0); @@ -184,8 +128,6 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) inst_JMP(EJ_je, gsCheckBlk); genEmitHelperCall(CORINFO_HELP_FAIL_FAST, 0, EA_UNKNOWN); genDefineTempLabel(gsCheckBlk); - - genPopRegs(pushedRegs, byrefPushedRegs, norefPushedRegs); } BasicBlock* CodeGen::genCallFinally(BasicBlock* block) @@ -6043,24 +5985,6 @@ void CodeGen::genCall(GenTreeCall* call) // all virtuals should have been expanded into a control expression assert(!call->IsVirtual() || call->gtControlExpr || call->gtCallAddr); - // Insert a GS check if necessary - if (call->IsTailCallViaJitHelper()) - { - if (compiler->getNeedsGSSecurityCookie()) - { -#if FEATURE_FIXED_OUT_ARGS - // If either of the conditions below is true, we will need a temporary register in order to perform the GS - // cookie check. When FEATURE_FIXED_OUT_ARGS is disabled, we save and restore the temporary register using - // push/pop. When FEATURE_FIXED_OUT_ARGS is enabled, however, we need an alternative solution. For now, - // though, the tail prefix is ignored on all platforms that use fixed out args, so we should never hit this - // case. - assert(compiler->gsGlobalSecurityCookieAddr == nullptr); - assert((int)compiler->gsGlobalSecurityCookieVal == (ssize_t)compiler->gsGlobalSecurityCookieVal); -#endif - genEmitGSCookieCheck(true); - } - } - genCallPlaceRegArgs(call); #if defined(TARGET_X86) diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 73597ea88edffa..6e7625745cb2e0 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -3177,10 +3177,6 @@ void Lowering::LowerFastTailCall(GenTreeCall* call) assert(!call->IsUnmanaged()); // tail calls to unamanaged methods assert(!comp->compLocallocUsed); // tail call from methods that also do localloc -#ifdef TARGET_AMD64 - assert(!comp->getNeedsGSSecurityCookie()); // jit64 compat: tail calls from methods that need GS check -#endif // TARGET_AMD64 - // We expect to see a call that meets the following conditions assert(call->IsFastTailCall()); diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index 0c06c07f8e325f..cb062b91cc1b8e 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -174,8 +174,7 @@ int LinearScan::BuildCall(GenTreeCall* call) ctrlExprCandidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH.GetIntRegSet() & ~SRBM_LR; if (compiler->getNeedsGSSecurityCookie()) { - ctrlExprCandidates &= - ~(genSingleTypeRegMask(REG_GSCOOKIE_TMP_0) | genSingleTypeRegMask(REG_GSCOOKIE_TMP_1)); + ctrlExprCandidates &= ~compiler->codeGen->genGetGSCookieTempRegs(/* tailCall */ true).GetIntRegSet(); } assert(ctrlExprCandidates != RBM_NONE); } diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 11ac16713e3b10..c2b3ebd564399d 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2535,6 +2535,16 @@ void LinearScan::buildIntervals() currentLoc += 2; } + if (compiler->getNeedsGSSecurityCookie() && block->KindIs(BBJ_RETURN)) + { + // The cookie check will kill some registers that it is using. + // Model this to ensure values that are kept live throughout the + // method are properly made available. + bool isTailCall = block->HasFlag(BBF_HAS_JMP); + addKillForRegs(compiler->codeGen->genGetGSCookieTempRegs(isTailCall), currentLoc + 1); + currentLoc += 2; + } + if (localVarsEnregistered) { #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE diff --git a/src/coreclr/jit/lsraloongarch64.cpp b/src/coreclr/jit/lsraloongarch64.cpp index 470a561afbc8d5..36eeaf1ffb8404 100644 --- a/src/coreclr/jit/lsraloongarch64.cpp +++ b/src/coreclr/jit/lsraloongarch64.cpp @@ -726,8 +726,7 @@ int LinearScan::BuildCall(GenTreeCall* call) ctrlExprCandidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH.GetIntRegSet(); if (compiler->getNeedsGSSecurityCookie()) { - ctrlExprCandidates &= - ~(genSingleTypeRegMask(REG_GSCOOKIE_TMP_0) | genSingleTypeRegMask(REG_GSCOOKIE_TMP_1)); + ctrlExprCandidates &= ~compiler->codeGen->genGetGSCookieTempRegs(/* tailCall */ true).GetIntRegSet(); } assert(ctrlExprCandidates != RBM_NONE); } @@ -742,8 +741,7 @@ int LinearScan::BuildCall(GenTreeCall* call) candidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH.GetIntRegSet(); if (compiler->getNeedsGSSecurityCookie()) { - ctrlExprCandidates &= - ~(genSingleTypeRegMask(REG_GSCOOKIE_TMP_0) | genSingleTypeRegMask(REG_GSCOOKIE_TMP_1)); + ctrlExprCandidates &= ~compiler->codeGen->genGetGSCookieTempRegs(/* tailCall */ true).GetIntRegSet(); } assert(candidates != RBM_NONE); } diff --git a/src/coreclr/jit/lsrariscv64.cpp b/src/coreclr/jit/lsrariscv64.cpp index a2a6152309f121..8298151a0bb2ee 100644 --- a/src/coreclr/jit/lsrariscv64.cpp +++ b/src/coreclr/jit/lsrariscv64.cpp @@ -963,8 +963,7 @@ int LinearScan::BuildCall(GenTreeCall* call) ctrlExprCandidates = allRegs(TYP_INT) & RBM_INT_CALLEE_TRASH.GetIntRegSet(); if (compiler->getNeedsGSSecurityCookie()) { - ctrlExprCandidates &= - ~(genSingleTypeRegMask(REG_GSCOOKIE_TMP_0) | genSingleTypeRegMask(REG_GSCOOKIE_TMP_1)); + ctrlExprCandidates &= ~compiler->codeGen->genGetGSCookieTempRegs(/* tailCall */ true).GetIntRegSet(); } assert(ctrlExprCandidates != RBM_NONE); } diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 5fe3cf8f034bcc..03ed72a5552eec 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -1305,6 +1305,10 @@ int LinearScan::BuildCall(GenTreeCall* call) // Fast tail call - make sure that call target is always computed in volatile registers // that will not be restored in the epilog sequence. ctrlExprCandidates = RBM_INT_CALLEE_TRASH.GetIntRegSet(); + if (compiler->getNeedsGSSecurityCookie()) + { + ctrlExprCandidates &= ~compiler->codeGen->genGetGSCookieTempRegs(/* tailCall */ true).GetIntRegSet(); + } } #ifdef TARGET_X86 else if (call->IsVirtualStub() && (call->gtCallType == CT_INDIRECT) && diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index a4f09b64f6213a..bc7250a0d2b7b6 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -4210,18 +4210,6 @@ bool Compiler::fgCanFastTailCall(GenTreeCall* callee, const char** failReason) return false; } -#ifdef TARGET_AMD64 - // Needed for Jit64 compat. - // In future, enabling fast tail calls from methods that need GS cookie - // check would require codegen side work to emit GS cookie check before a - // tail call. - if (getNeedsGSSecurityCookie()) - { - reportFastTailCallDecision("GS Security cookie check required"); - return false; - } -#endif - // If the NextCallReturnAddress intrinsic is used we should do normal calls. if (info.compHasNextCallRetAddr) { diff --git a/src/coreclr/jit/targetarm.h b/src/coreclr/jit/targetarm.h index 0695d1146d857e..9cfd1077c72d52 100644 --- a/src/coreclr/jit/targetarm.h +++ b/src/coreclr/jit/targetarm.h @@ -105,8 +105,7 @@ #define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT*sizeof(float)) // Temporary registers used for the GS cookie check. - #define REG_GSCOOKIE_TMP_0 REG_R12 - #define REG_GSCOOKIE_TMP_1 REG_LR + #define RBM_GSCOOKIE_TMP (RBM_R12 | RBM_LR) // register to hold shift amount; no special register is required on the ARM #define REG_SHIFT REG_NA diff --git a/src/coreclr/jit/targetarm64.h b/src/coreclr/jit/targetarm64.h index fbc8e79b46dcaf..c00ac9aeefeb55 100644 --- a/src/coreclr/jit/targetarm64.h +++ b/src/coreclr/jit/targetarm64.h @@ -130,8 +130,7 @@ #define RBM_ENC_CALLEE_SAVED 0 // Temporary registers used for the GS cookie check. - #define REG_GSCOOKIE_TMP_0 REG_IP0 - #define REG_GSCOOKIE_TMP_1 REG_IP1 + #define RBM_GSCOOKIE_TMP (RBM_IP0 | RBM_IP1) // register to hold shift amount; no special register is required on ARM64. #define REG_SHIFT REG_NA diff --git a/src/coreclr/jit/targetloongarch64.h b/src/coreclr/jit/targetloongarch64.h index 30003308d84400..7ff82e51840811 100644 --- a/src/coreclr/jit/targetloongarch64.h +++ b/src/coreclr/jit/targetloongarch64.h @@ -116,8 +116,7 @@ #define REG_TMP_0 REG_T0 // Temporary registers used for the GS cookie check. - #define REG_GSCOOKIE_TMP_0 REG_T0 - #define REG_GSCOOKIE_TMP_1 REG_T1 + #define RBM_GSCOOKIE_TMP (RBM_T0 | RBM_T1) // register to hold shift amount; no special register is required on LOONGARCH64. #define REG_SHIFT REG_NA diff --git a/src/coreclr/jit/targetriscv64.h b/src/coreclr/jit/targetriscv64.h index 642cc8d3e5df00..b718951f1cf10d 100644 --- a/src/coreclr/jit/targetriscv64.h +++ b/src/coreclr/jit/targetriscv64.h @@ -111,8 +111,7 @@ #define REG_TMP_0 REG_T0 // Temporary registers used for the GS cookie check. - #define REG_GSCOOKIE_TMP_0 REG_T0 - #define REG_GSCOOKIE_TMP_1 REG_T1 + #define RBM_GSCOOKIE_TMP (RBM_T0 | RBM_T1) // register to hold shift amount; no special register is required on ARM64. #define REG_SHIFT REG_NA diff --git a/src/tests/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il b/src/tests/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il index f2fadbbb666e45..ab022c56862c61 100644 --- a/src/tests/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il +++ b/src/tests/JIT/opt/Tailcall/TailcallVerifyWithPrefix.il @@ -339,146 +339,6 @@ 00 ) } // end of class TailcallVerify.Unsafe -.class private auto ansi beforefieldinit TailcallVerify.Condition17 - extends [mscorlib]System.Object -{ - .field private static int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) zero - .field private static int32 Result - .method public hidebysig static int32 Test1() cil managed nooptimization - { - // Code size 162 (0xa2) - .maxstack 3 - .locals init ([0] valuetype TailcallVerify.Unsafe u, - [1] class [mscorlib]System.Exception e) - IL_0000: ldstr "Executing Condition17.Test1 - Caller: Arguments: N" - + "one - ReturnType: 3 byte struct; Callee: Arguments: None - ReturnType: " - + "void" - IL_0005: call void [System.Console]System.Console::WriteLine(string) - IL_000a: ldc.i4.s 100 - IL_000c: stsfld int32 TailcallVerify.Condition17::Result - .try - { - IL_0011: ldloca.s u - IL_0013: initobj TailcallVerify.Unsafe - IL_0019: ldloc.0 - IL_001a: call void TailcallVerify.Condition17::Caller1(valuetype TailcallVerify.Unsafe) - IL_001f: leave.s IL_0078 - - } // end .try - catch [mscorlib]System.Exception - { - IL_0021: stloc.1 - IL_0022: ldloc.1 - IL_0023: isinst [mscorlib]System.DivideByZeroException - IL_0028: brtrue.s IL_0033 - - IL_002a: ldc.i4.s 101 - IL_002c: stsfld int32 TailcallVerify.Condition17::Result - IL_0031: rethrow - IL_0033: ldloc.1 - IL_0034: callvirt instance string [mscorlib]System.Exception::get_StackTrace() - IL_0039: ldstr "Caller" - IL_003e: callvirt instance int32 [mscorlib]System.String::IndexOf(string) - IL_0043: ldc.i4.m1 - IL_0044: bne.un.s IL_0076 - - IL_0046: ldstr "FAILED: DID NOT find the word 'Caller' in the stac" - + "ktrace." - IL_004b: call void [System.Console]System.Console::WriteLine(string) - IL_0050: ldstr "------------------------------------------------" - IL_0055: call void [System.Console]System.Console::WriteLine(string) - IL_005a: call void [System.Console]System.Console::WriteLine() - IL_005f: ldloc.1 - IL_0060: callvirt instance string [mscorlib]System.Exception::get_StackTrace() - IL_0065: call void [System.Console]System.Console::WriteLine(string) - IL_006a: call void [System.Console]System.Console::WriteLine() - IL_006f: ldc.i4.s 101 - IL_0071: stsfld int32 TailcallVerify.Condition17::Result - IL_0076: leave.s IL_0078 - - } // end handler - IL_0078: ldstr "Execution finished - Test " - IL_007d: ldsfld int32 TailcallVerify.Condition17::Result - IL_0082: ldc.i4.s 100 - IL_0084: beq.s IL_008d - - IL_0086: ldstr "FAILED" - IL_008b: br.s IL_0092 - - IL_008d: ldstr "PASSED" - IL_0092: call string [mscorlib]System.String::Concat(string, - string) - IL_0097: call void [System.Console]System.Console::WriteLine(string) - IL_009c: ldsfld int32 TailcallVerify.Condition17::Result - IL_00a1: ret - } // end of method Condition17::Test1 - - .method private hidebysig static void Caller1(valuetype TailcallVerify.Unsafe u) cil managed - { - // Code size 74 (0x4a) - .maxstack 2 - IL_0000: ldc.i4.0 - IL_0001: newobj instance void [mscorlib]System.Diagnostics.StackFrame::.ctor(bool) - IL_0006: callvirt instance class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Diagnostics.StackFrame::GetMethod() - IL_000b: callvirt instance string [mscorlib]System.Reflection.MemberInfo::get_Name() - IL_0010: ldstr "Caller" - IL_0015: callvirt instance int32 [mscorlib]System.String::IndexOf(string) - IL_001a: ldc.i4.m1 - IL_001b: bne.un.s IL_002e - - IL_001d: ldstr "Failed, Method was inlined..." - IL_0022: call void [System.Console]System.Console::WriteLine(string) - IL_0027: ldc.i4.s 101 - IL_0029: stsfld int32 TailcallVerify.Condition17::Result - IL_002e: ldarga.s u - IL_0030: ldflda valuetype TailcallVerify.Unsafe/'e__FixedBuffer0' TailcallVerify.Unsafe::data - IL_0035: ldflda uint8 TailcallVerify.Unsafe/'e__FixedBuffer0'::FixedElementField - IL_003a: conv.u - IL_003b: volatile. - IL_003d: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) TailcallVerify.Condition17::zero - IL_0042: conv.u1 - IL_0043: stind.i1 - IL_0044: tail. call void TailcallVerify.Condition17::Callee1() - IL_0049: ret - } // end of method Condition17::Caller1 - - .method private hidebysig static void Callee1() cil managed noinlining - { - // Code size 11 (0xb) - .maxstack 8 - IL_0000: ldc.i4.1 - IL_0001: volatile. - IL_0003: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) TailcallVerify.Condition17::zero - IL_0008: div - IL_0009: pop - IL_000a: ret - } // end of method Condition17::Callee1 - - .method public hidebysig specialname rtspecialname - instance void .ctor() cil managed - { - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void [mscorlib]System.Object::.ctor() - IL_0006: ret - } // end of method Condition17::.ctor - - .method private hidebysig specialname rtspecialname static - void .cctor() cil managed - { - // Code size 16 (0x10) - .maxstack 8 - IL_0000: ldc.i4.0 - IL_0001: volatile. - IL_0003: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) TailcallVerify.Condition17::zero - IL_0008: ldc.i4.s 100 - IL_000a: stsfld int32 TailcallVerify.Condition17::Result - IL_000f: ret - } // end of method Condition17::.cctor - -} // end of class TailcallVerify.Condition17 - .class private auto ansi beforefieldinit TailcallVerify.Condition16 extends [mscorlib]System.Object { @@ -2093,24 +1953,10 @@ IL_054a: ldloc.0 IL_054b: call bool [mscorlib]System.String::op_Equality(string, string) - IL_0550: brfalse.s IL_055c + IL_0550: brfalse.s IL_057c IL_0552: call int32 TailcallVerify.Condition16::Test1() IL_0557: call void TailcallVerify.Program::set_Result(int32) - IL_055c: ldloc.1 - IL_055d: ldstr "Condition17.Test1" - IL_0562: call bool [mscorlib]System.String::op_Equality(string, - string) - IL_0567: brtrue.s IL_0572 - - IL_0569: ldloc.1 - IL_056a: ldloc.0 - IL_056b: call bool [mscorlib]System.String::op_Equality(string, - string) - IL_0570: brfalse.s IL_057c - - IL_0572: call int32 TailcallVerify.Condition17::Test1() - IL_0577: call void TailcallVerify.Program::set_Result(int32) IL_057c: ldloc.1 IL_057d: ldstr "Condition18.Test1" IL_0582: call bool [mscorlib]System.String::op_Equality(string, @@ -2325,9 +2171,6 @@ ldstr "Condition16.Test1" call int32 TailcallVerify.Program::Run(string) pop - ldstr "Condition17.Test1" - call int32 TailcallVerify.Program::Run(string) - pop ldstr "Condition18.Test1" call int32 TailcallVerify.Program::Run(string) pop