summaryrefslogtreecommitdiff
path: root/src/jit/instr.cpp
diff options
context:
space:
mode:
authorPat Gavlin <pagavlin@microsoft.com>2017-07-21 16:43:25 -0700
committerPat Gavlin <pagavlin@microsoft.com>2017-07-21 16:43:25 -0700
commit1a70ba93318cf8081f7f433b793f03bc9c29e8b2 (patch)
treef565771f4a2d92209079774e54d798cc3a53ce21 /src/jit/instr.cpp
parent7b213c4c336383d281fcc3d3e7d811da54cb42ec (diff)
downloadcoreclr-1a70ba93318cf8081f7f433b793f03bc9c29e8b2.tar.gz
coreclr-1a70ba93318cf8081f7f433b793f03bc9c29e8b2.tar.bz2
coreclr-1a70ba93318cf8081f7f433b793f03bc9c29e8b2.zip
Lock the the dest reg in `inst_RV_TT` if necessary.
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.
Diffstat (limited to 'src/jit/instr.cpp')
-rw-r--r--src/jit/instr.cpp19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/jit/instr.cpp b/src/jit/instr.cpp
index c4e894bdc8..2b9780fcf3 100644
--- a/src/jit/instr.cpp
+++ b/src/jit/instr.cpp
@@ -2532,7 +2532,24 @@ AGAIN:
}
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