// first we load the immediate into tmpReg
instGen_Set_Reg_To_Imm(size, tmpReg, imm);
- regTracker.rsTrackRegTrash(tmpReg);
+ regSet.verifyRegUsed(tmpReg);
// when we are in an unwind code region
// we record the extra instructions using unwindPadding()
// Load the CallerSP of the main function (stored in the PSP of the dynamically containing funclet or function)
genInstrWithConstant(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_R1, REG_R1,
genFuncletInfo.fiCallerSP_to_PSP_slot_delta, REG_R2, false);
- regTracker.rsTrackRegTrash(REG_R1);
+ regSet.verifyRegUsed(REG_R1);
// Store the PSP value (aka CallerSP)
genInstrWithConstant(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_R1, REG_SPBASE,
// compute the CallerSP, given the frame pointer. x3 is scratch.
genInstrWithConstant(INS_add, EA_PTRSIZE, REG_R3, REG_FPBASE, -genFuncletInfo.fiFunction_CallerSP_to_FP_delta,
REG_R2, false);
- regTracker.rsTrackRegTrash(REG_R3);
+ regSet.verifyRegUsed(REG_R3);
genInstrWithConstant(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_R3, REG_SPBASE,
genFuncletInfo.fiSP_to_PSP_slot_delta, REG_R2, false);
}
}
- regTracker.rsTrackRegIntCns(reg, imm);
+ regSet.verifyRegUsed(reg);
}
/***********************************************************************************
if (con->ImmedValNeedsReloc(compiler))
{
instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal);
- regTracker.rsTrackRegTrash(targetReg);
+ regSet.verifyRegUsed(targetReg);
}
else
{
emitter::emitNoGChelper(helper));
regMaskTP killMask = compiler->compHelperCallKillSet((CorInfoHelpFunc)helper);
- regTracker.rsTrashRegSet(killMask);
+ regSet.verifyRegistersUsed(killMask);
}
#ifdef FEATURE_SIMD
maxNestedAlignment = 0;
#endif
- regTracker.rsTrackInit(compiler, ®Set);
gcInfo.regSet = ®Set;
m_cgEmitter = new (compiler->getAllocator()) emitter();
m_cgEmitter->codeGen = this;
noway_assert(varDscDest->lvArgReg == varDscSrc->lvRegNum);
getEmitter()->emitIns_R_R(INS_xchg, size, varDscSrc->lvRegNum, varDscSrc->lvArgReg);
- regTracker.rsTrackRegTrash(varDscSrc->lvRegNum);
- regTracker.rsTrackRegTrash(varDscSrc->lvArgReg);
+ regSet.verifyRegUsed(varDscSrc->lvRegNum);
+ regSet.verifyRegUsed(varDscSrc->lvArgReg);
/* mark both arguments as processed */
regArgTab[destReg].processed = true;
getEmitter()->emitIns_R_R(insCopy, size, xtraReg, begRegNum);
- regTracker.rsTrackRegCopy(xtraReg, begRegNum);
+ regSet.verifyRegUsed(xtraReg);
*pXtraRegClobbered = true;
getEmitter()->emitIns_R_R(insCopy, size, destRegNum, srcRegNum);
- regTracker.rsTrackRegCopy(destRegNum, srcRegNum);
+ regSet.verifyRegUsed(destRegNum);
/* mark 'src' as processed */
noway_assert(srcReg < argMax);
getEmitter()->emitIns_R_R(insCopy, size, destRegNum, xtraReg);
- regTracker.rsTrackRegCopy(destRegNum, xtraReg);
+ regSet.verifyRegUsed(destRegNum);
psiMoveToReg(varNumSrc);
assert(regNum != REG_STK);
getEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), regNum, varNum, 0);
- regTracker.rsTrackRegTrash(regNum);
+ regSet.verifyRegUsed(regNum);
psiMoveToReg(varNum);
}
#if CPU_LOAD_STORE_ARCH
instGen_Set_Reg_To_Imm(EA_PTRSIZE, initReg, -(ssize_t)pageSize);
getEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, initReg, REG_SPBASE, initReg);
- regTracker.rsTrackRegTrash(initReg);
+ regSet.verifyRegUsed(initReg);
*pInitRegZeroed = false; // The initReg does not contain zero
#else
getEmitter()->emitIns_AR_R(INS_TEST, EA_PTRSIZE, REG_EAX, REG_SPBASE, -(int)pageSize);
#if CPU_LOAD_STORE_ARCH
instGen_Set_Reg_To_Imm(EA_PTRSIZE, initReg, -2 * (ssize_t)pageSize);
getEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, initReg, REG_SPBASE, initReg);
- regTracker.rsTrackRegTrash(initReg);
+ regSet.verifyRegUsed(initReg);
#else
getEmitter()->emitIns_AR_R(INS_TEST, EA_PTRSIZE, REG_EAX, REG_SPBASE, -2 * (int)pageSize);
#endif
noway_assert((ssize_t)(int)frameSize == (ssize_t)frameSize); // make sure framesize safely fits within an int
instGen_Set_Reg_To_Imm(EA_PTRSIZE, rLimit, -(int)frameSize);
getEmitter()->emitIns_R_R_R(INS_ldr, EA_4BYTE, rTemp, REG_SPBASE, rOffset);
- regTracker.rsTrackRegTrash(rTemp);
+ regSet.verifyRegUsed(rTemp);
#if defined(_TARGET_ARM_)
getEmitter()->emitIns_R_I(INS_sub, EA_PTRSIZE, rOffset, pageSize);
#elif defined(_TARGET_ARM64_)
{
// pop eax
inst_RV(INS_pop, REG_SECRET_STUB_PARAM, TYP_I_IMPL);
- regTracker.rsTrackRegTrash(REG_SECRET_STUB_PARAM);
+ regSet.verifyRegUsed(REG_SECRET_STUB_PARAM);
}
#endif // _TARGET_XARCH_
{
noway_assert(regSet.rsRegsModified(RBM_R12));
inst_RV_RV(INS_mov, REG_R12, REG_RCX);
- regTracker.rsTrackRegTrash(REG_R12);
+ regSet.verifyRegUsed(REG_R12);
}
if (intRegState.rsCalleeRegArgMaskLiveIn & RBM_RDI)
{
noway_assert(regSet.rsRegsModified(RBM_R13));
inst_RV_RV(INS_mov, REG_R13, REG_RDI);
- regTracker.rsTrackRegTrash(REG_R13);
+ regSet.verifyRegUsed(REG_R13);
}
#else // !UNIX_AMD64_ABI
// For register arguments we may have to save ECX
{
noway_assert(regSet.rsRegsModified(RBM_ESI));
inst_RV_RV(INS_mov, REG_ESI, REG_ECX);
- regTracker.rsTrackRegTrash(REG_ESI);
+ regSet.verifyRegUsed(REG_ESI);
}
#endif // !UNIX_AMD64_ABI
noway_assert((intRegState.rsCalleeRegArgMaskLiveIn & RBM_EAX) == 0);
getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, REG_EDI, genFramePointerReg(), untrLclLo);
- regTracker.rsTrackRegTrash(REG_EDI);
+ regSet.verifyRegUsed(REG_EDI);
inst_RV_IV(INS_mov, REG_ECX, (untrLclHi - untrLclLo) / sizeof(int), EA_4BYTE);
instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EAX);
// mov reg, [compiler->info.compTypeCtxtArg]
getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, reg, genFramePointerReg(), varDsc->lvStkOffs);
- regTracker.rsTrackRegTrash(reg);
+ regSet.verifyRegUsed(reg);
}
#if CPU_LOAD_STORE_ARCH
#if CPU_LOAD_STORE_ARCH
instGen_Set_Reg_To_Imm(EA_PTR_DSP_RELOC, reg, (ssize_t)compiler->gsGlobalSecurityCookieAddr);
getEmitter()->emitIns_R_R_I(ins_Load(TYP_I_IMPL), EA_PTRSIZE, reg, reg, 0);
- regTracker.rsTrackRegTrash(reg);
+ regSet.verifyRegUsed(reg);
#else
// mov reg, dword ptr [compiler->gsGlobalSecurityCookieAddr]
// mov dword ptr [frame.GSSecurityCookie], reg
getEmitter()->emitIns_R_AI(INS_mov, EA_PTR_DSP_RELOC, reg, (ssize_t)compiler->gsGlobalSecurityCookieAddr);
- regTracker.rsTrackRegTrash(reg);
+ regSet.verifyRegUsed(reg);
#endif
getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, reg, compiler->lvaGSSecurityCookie, 0);
}
if (compiler->compProfilerMethHndIndirected)
{
getEmitter()->emitIns_R_AI(INS_ldr, EA_PTR_DSP_RELOC, argReg, (ssize_t)compiler->compProfilerMethHnd);
- regTracker.rsTrackRegTrash(argReg);
+ regSet.verifyRegUsed(argReg);
}
else
{
}
getEmitter()->emitIns_R_R(INS_mov, attr, REG_PROFILER_RET_SCRATCH, REG_ARG_0);
- regTracker.rsTrackRegTrash(REG_PROFILER_RET_SCRATCH);
+ regSet.verifyRegUsed(REG_PROFILER_RET_SCRATCH);
gcInfo.gcMarkRegSetNpt(RBM_ARG_0);
r0Trashed = true;
}
if (compiler->compProfilerMethHndIndirected)
{
getEmitter()->emitIns_R_AI(INS_ldr, EA_PTR_DSP_RELOC, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd);
- regTracker.rsTrackRegTrash(REG_ARG_0);
+ regSet.verifyRegUsed(REG_ARG_0);
}
else
{
if (r0Trashed)
{
getEmitter()->emitIns_R_R(INS_mov, attr, REG_ARG_0, REG_PROFILER_RET_SCRATCH);
- regTracker.rsTrackRegTrash(REG_ARG_0);
+ regSet.verifyRegUsed(REG_ARG_0);
gcInfo.gcMarkRegSetNpt(RBM_PROFILER_RET_SCRATCH);
}
if (compiler->compLocallocUsed)
{
getEmitter()->emitIns_R_R(INS_mov, EA_4BYTE, REG_SAVED_LOCALLOC_SP, REG_SPBASE);
- regTracker.rsTrackRegTrash(REG_SAVED_LOCALLOC_SP);
+ regSet.verifyRegUsed(REG_SAVED_LOCALLOC_SP);
compiler->unwindSetFrameReg(REG_SAVED_LOCALLOC_SP, 0);
}
#endif // _TARGET_ARMARCH_
// MOV EAX, <VARARGS HANDLE>
getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_EAX, compiler->info.compArgsCount - 1, 0);
- regTracker.rsTrackRegTrash(REG_EAX);
+ regSet.verifyRegUsed(REG_EAX);
// MOV EAX, [EAX]
getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_EAX, REG_EAX, 0);
if (varDsc->lvRegNum != REG_EAX)
{
getEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, varDsc->lvRegNum, REG_EAX);
- regTracker.rsTrackRegTrash(varDsc->lvRegNum);
+ regSet.verifyRegUsed(varDsc->lvRegNum);
}
}
else
if (addrInfo.accessType == IAT_PVALUE)
{
getEmitter()->emitIns_R_R_I(INS_ldr, EA_PTRSIZE, indCallReg, indCallReg, 0);
- regTracker.rsTrackRegTrash(indCallReg);
+ regSet.verifyRegUsed(indCallReg);
}
break;
if ((compiler->compLclFrameSize == TARGET_POINTER_SIZE) && !compiler->compJmpOpUsed)
{
inst_RV(INS_pop, REG_ECX, TYP_I_IMPL);
- regTracker.rsTrackRegTrash(REG_ECX);
+ regSet.verifyRegUsed(REG_ECX);
}
else
#endif // _TARGET_X86
{
// "pop ecx" will make ESP point to the callee-saved registers
inst_RV(INS_pop, REG_ECX, TYP_I_IMPL);
- regTracker.rsTrackRegTrash(REG_ECX);
+ regSet.verifyRegUsed(REG_ECX);
}
#endif // _TARGET_X86
else
getEmitter()->emitIns_R_R_I(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_R1, REG_R1,
genFuncletInfo.fiPSP_slot_CallerSP_offset);
- regTracker.rsTrackRegTrash(REG_R1);
+ regSet.verifyRegUsed(REG_R1);
getEmitter()->emitIns_R_R_I(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_R1, REG_SPBASE,
genFuncletInfo.fiPSP_slot_SP_offset);
getEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, REG_FPBASE, REG_R1,
// This is a non-filter funclet
getEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, REG_R3, REG_FPBASE,
genFuncletInfo.fiFunctionCallerSPtoFPdelta);
- regTracker.rsTrackRegTrash(REG_R3);
+ regSet.verifyRegUsed(REG_R3);
getEmitter()->emitIns_R_R_I(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_R3, REG_SPBASE,
genFuncletInfo.fiPSP_slot_SP_offset);
}
getEmitter()->emitIns_R_AR(INS_mov, EA_PTRSIZE, REG_FPBASE, REG_ARG_0, genFuncletInfo.fiPSP_slot_InitialSP_offset);
- regTracker.rsTrackRegTrash(REG_FPBASE);
+ regSet.verifyRegUsed(REG_FPBASE);
getEmitter()->emitIns_AR_R(INS_mov, EA_PTRSIZE, REG_FPBASE, REG_SPBASE, genFuncletInfo.fiPSP_slot_InitialSP_offset);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*/
+//------------------------------------------------------------------------
+// verifyRegUsed: verify that the register is marked as used.
+//
+// Arguments:
+// reg - The register to verify.
+//
+// Return Value:
+// None.
+//
+// Assumptions:
+// The caller must have ensured that the register is already marked
+// as used.
+//
+// Notes:
+// This method is intended to be called during code generation, and
+// should simply validate that the register (or registers) have
+// already been added to the modified set.
+
+void RegSet::verifyRegUsed(regNumber reg)
+{
+ // TODO-Cleanup: we need to identify the places where the register
+ // is not marked as used when this is called.
+ rsSetRegsModified(genRegMask(reg));
+}
+
+//------------------------------------------------------------------------
+// verifyRegistersUsed: verify that the registers are marked as used.
+//
+// Arguments:
+// regs - The registers to verify.
+//
+// Return Value:
+// None.
+//
+// Assumptions:
+// The caller must have ensured that the registers are already marked
+// as used.
+//
+// Notes:
+// This method is intended to be called during code generation, and
+// should simply validate that the register (or registers) have
+// already been added to the modified set.
+
+void RegSet::verifyRegistersUsed(regMaskTP regMask)
+{
+ if (m_rsCompiler->opts.MinOpts() || m_rsCompiler->opts.compDbgCode)
+ {
+ return;
+ }
+
+ // TODO-Cleanup: we need to identify the places where the registers
+ // are not marked as used when this is called.
+ rsSetRegsModified(regMask);
+}
+
void RegSet::rsClearRegsModified()
{
assert(m_rsCompiler->lvaDoneFrameLayout < Compiler::FINAL_FRAME_LAYOUT);
_rsMaskVars = newMaskVars;
}
-/*****************************************************************************
- *
- * Trash the rsRegValues associated with a register
- */
-
-// inline
-void RegTracker::rsTrackRegTrash(regNumber reg)
-{
- /* Keep track of which registers we ever touch */
-
- regSet->rsSetRegsModified(genRegMask(reg));
-}
-
-/*****************************************************************************/
-
-// inline
-void RegTracker::rsTrackRegIntCns(regNumber reg, ssize_t val)
-{
- assert(genIsValidIntReg(reg));
-
- /* Keep track of which registers we ever touch */
-
- regSet->rsSetRegsModified(genRegMask(reg));
-}
-
/*****************************************************************************/
RegSet::RegSet(Compiler* compiler, GCInfo& gcInfo) : m_rsCompiler(compiler), m_rsGCInfo(gcInfo)
return dsc;
}
-/*****************************************************************************
- *
- * Record the fact that the given register now contains the given local
- * variable. Pointers are handled specially since reusing the register
- * will extend the lifetime of a pointer register which is not a register
- * variable.
- */
-
-void RegTracker::rsTrackRegLclVar(regNumber reg, unsigned var)
-{
- LclVarDsc* varDsc = &compiler->lvaTable[var];
- assert(reg != REG_STK);
-#if CPU_HAS_FP_SUPPORT
- assert(varTypeIsFloating(varDsc->TypeGet()) == false);
-#endif
-
- if (compiler->lvaTable[var].lvAddrExposed)
- {
- return;
- }
-
- /* Keep track of which registers we ever touch */
-
- regSet->rsSetRegsModified(genRegMask(reg));
-}
-
-/*****************************************************************************/
-
-void RegTracker::rsTrackRegCopy(regNumber reg1, regNumber reg2)
-{
- /* Keep track of which registers we ever touch */
-
- assert(reg1 < REG_COUNT);
- assert(reg2 < REG_COUNT);
-
- regSet->rsSetRegsModified(genRegMask(reg1));
-}
-
//------------------------------------------------------------
// rsSpillTree: Spill the tree held in 'reg'.
//
tree->gtFlags |= GTF_SPILLED;
}
-/*****************************************************************************
- *
- * A little helper to trash the given set of registers.
- * Usually used after a call has been generated.
- */
-
-void RegTracker::rsTrashRegSet(regMaskTP regMask)
-{
- if (compiler->opts.MinOpts() || compiler->opts.compDbgCode)
- {
- return;
- }
- regMaskTP regBit = 1;
- for (regNumber regNum = REG_FIRST; regMask != 0; regNum = REG_NEXT(regNum), regBit <<= 1)
- {
- if (regBit & regMask)
- {
- rsTrackRegTrash(regNum);
- regMask -= regBit;
- }
- }
-}
-
/*****************************************************************************/
/*