For ARM32, `inst_RV_TT` may need to load the referenced lclVar into a
temporary register before emitting the requested instruction. The
chosen register *must not* be the instruction's destination register.
The existing code attempted to ensure this by masking the dest register
from the set of pickable registers, but this is not sufficient:
`rsPickReg` must return a valid register and will happily attempt to
spill and return the destination register even if it is not in the
recommended set. To prevent this, this change locks and unlocks the
destination register if necessary (i.e. if it was not locked upon
entry).
Fixes #12935.
}
else
{
- regTmp = regSet.rsPickReg(RBM_ALLINT & ~genRegMask(reg));
+ // Lock the destination register to ensure that rsPickReg does not choose it.
+ const regMaskTP regMask = genRegMask(reg);
+ if ((regMask & regSet.rsMaskUsed) == 0)
+ {
+ regSet.rsLockReg(regMask);
+ regTmp = regSet.rsPickReg(RBM_ALLINT);
+ regSet.rsUnlockReg(regMask);
+ }
+ else if ((regMask & regSet.rsMaskLock) == 0)
+ {
+ regSet.rsLockUsedReg(regMask);
+ regTmp = regSet.rsPickReg(RBM_ALLINT);
+ regSet.rsUnlockUsedReg(regMask);
+ }
+ else
+ {
+ regTmp = regSet.rsPickReg(RBM_ALLINT);
+ }
}
#endif // LEGACY_BACKEND