summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Forstall <brucefo@microsoft.com>2018-12-16 14:27:08 -0800
committerGitHub <noreply@github.com>2018-12-16 14:27:08 -0800
commitf5979429b345879b4a4b38caac23ad701e4ae49f (patch)
tree4b2be8b65bfa2086d917eebcfee6c8edb2d9be34 /src
parent3e06d9f5911ffe30894b3e08ef955f645df3acd9 (diff)
parentc153d9fc6627e5bb35e31eea6038f64f2a006022 (diff)
downloadcoreclr-f5979429b345879b4a4b38caac23ad701e4ae49f.tar.gz
coreclr-f5979429b345879b4a4b38caac23ad701e4ae49f.tar.bz2
coreclr-f5979429b345879b4a4b38caac23ad701e4ae49f.zip
Merge pull request #21400 from BruceForstall/FixArm32FloatRange
Fix arm32 local variable references
Diffstat (limited to 'src')
-rw-r--r--src/jit/compiler.cpp3
-rw-r--r--src/jit/compiler.h2
-rw-r--r--src/jit/compiler.hpp83
-rw-r--r--src/jit/emit.cpp3
-rw-r--r--src/jit/emitarm.cpp23
-rw-r--r--src/jit/emitarm.h2
-rw-r--r--src/jit/lclvars.cpp2
7 files changed, 66 insertions, 52 deletions
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index 43acab3ca8..8093a7defc 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -4200,7 +4200,8 @@ bool Compiler::compRsvdRegCheck(FrameLayoutState curState)
// Always do the layout even if returning early. Callers might
// depend on us to do the layout.
unsigned frameSize = lvaFrameSize(curState);
- JITDUMP("\ncompRsvdRegCheck\n"
+ JITDUMP("\n"
+ "compRsvdRegCheck\n"
" frame size = %6d\n"
" compArgSize = %6d\n",
frameSize, compArgSize);
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index a79d77e4e2..7b91d39e2a 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -3055,7 +3055,7 @@ public:
#endif
#ifdef _TARGET_ARM_
- int lvaFrameAddress(int varNum, bool mustBeFPBased, regNumber* pBaseReg, int addrModeOffset);
+ int lvaFrameAddress(int varNum, bool mustBeFPBased, regNumber* pBaseReg, int addrModeOffset, bool isFloatUsage);
#else
int lvaFrameAddress(int varNum, bool* pFPbased);
#endif
diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp
index 8461b1f2a0..29a79f862b 100644
--- a/src/jit/compiler.hpp
+++ b/src/jit/compiler.hpp
@@ -2066,25 +2066,37 @@ inline int Compiler::lvaCachedGenericContextArgOffset()
return lvaCachedGenericContextArgOffs;
}
-/*****************************************************************************
- *
- * Return the stack framed offset of the given variable; set *FPbased to
- * true if the variable is addressed off of FP, false if it's addressed
- * off of SP. Note that 'varNum' can be a negated spill-temporary var index.
- *
- * mustBeFPBased - strong about whether the base reg is FP. But it is also
- * strong about not being FPBased after FINAL_FRAME_LAYOUT. i.e.,
- * it enforces SP based.
- *
- * addrModeOffset - is the addressing mode offset, for example: v02 + 0x10
- * So, V02 itself is at offset sp + 0x10 and then addrModeOffset is what gets
- * added beyond that.
- */
-
+//------------------------------------------------------------------------
+// lvaFrameAddress: Determine the stack frame offset of the given variable,
+// and how to generate an address to that stack frame.
+//
+// Arguments:
+// varNum - The variable to inquire about. Positive for user variables
+// or arguments, negative for spill-temporaries.
+// mustBeFPBased - [_TARGET_ARM_ only] True if the base register must be FP.
+// After FINAL_FRAME_LAYOUT, if false, it also requires SP base register.
+// pBaseReg - [_TARGET_ARM_ only] Out arg. *pBaseReg is set to the base
+// register to use.
+// addrModeOffset - [_TARGET_ARM_ only] The mode offset within the variable that we need to address.
+// For example, for a large struct local, and a struct field reference, this will be the offset
+// of the field. Thus, for V02 + 0x28, if V02 itself is at offset SP + 0x10
+// then addrModeOffset is what gets added beyond that, here 0x28.
+// isFloatUsage - [_TARGET_ARM_ only] True if the instruction being generated is a floating
+// point instruction. This requires using floating-point offset restrictions.
+// Note that a variable can be non-float, e.g., struct, but accessed as a
+// float local field.
+// pFPbased - [non-_TARGET_ARM_] Out arg. Set *FPbased to true if the
+// variable is addressed off of FP, false if it's addressed
+// off of SP.
+//
+// Return Value:
+// Returns the variable offset from the given base register.
+//
inline
#ifdef _TARGET_ARM_
int
- Compiler::lvaFrameAddress(int varNum, bool mustBeFPBased, regNumber* pBaseReg, int addrModeOffset)
+ Compiler::lvaFrameAddress(
+ int varNum, bool mustBeFPBased, regNumber* pBaseReg, int addrModeOffset, bool isFloatUsage)
#else
int
Compiler::lvaFrameAddress(int varNum, bool* pFPbased)
@@ -2092,17 +2104,15 @@ inline
{
assert(lvaDoneFrameLayout != NO_FRAME_LAYOUT);
- int offset;
- bool FPbased;
- bool fConservative = false;
- var_types type = TYP_UNDEF;
+ int varOffset;
+ bool FPbased;
+ bool fConservative = false;
if (varNum >= 0)
{
LclVarDsc* varDsc;
assert((unsigned)varNum < lvaCount);
varDsc = lvaTable + varNum;
- type = varDsc->TypeGet();
bool isPrespilledArg = false;
#if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
isPrespilledArg = varDsc->lvIsParam && compIsProfilerHookNeeded() &&
@@ -2146,7 +2156,7 @@ inline
}
#endif // DEBUG
- offset = varDsc->lvStkOffs;
+ varOffset = varDsc->lvStkOffs;
}
else // Its a spill-temp
{
@@ -2160,8 +2170,7 @@ inline
tmpDsc = codeGen->regSet.tmpFindNum(varNum, RegSet::TEMP_USAGE_USED);
}
assert(tmpDsc != nullptr);
- offset = tmpDsc->tdTempOffs();
- type = tmpDsc->tdTempType();
+ varOffset = tmpDsc->tdTempOffs();
}
else
{
@@ -2188,7 +2197,6 @@ inline
// : :
// ---------------------------------------------------
- type = compFloatingPointUsed ? TYP_FLOAT : TYP_INT;
fConservative = true;
if (!FPbased)
{
@@ -2199,7 +2207,7 @@ inline
#else
int outGoingArgSpaceSize = 0;
#endif
- offset = outGoingArgSpaceSize + max(-varNum * TARGET_POINTER_SIZE, (int)lvaGetMaxSpillTempSize());
+ varOffset = outGoingArgSpaceSize + max(-varNum * TARGET_POINTER_SIZE, (int)lvaGetMaxSpillTempSize());
}
else
{
@@ -2207,9 +2215,9 @@ inline
CLANG_FORMAT_COMMENT_ANCHOR;
#ifdef _TARGET_ARM_
- offset = codeGen->genCallerSPtoInitialSPdelta() - codeGen->genCallerSPtoFPdelta();
+ varOffset = codeGen->genCallerSPtoInitialSPdelta() - codeGen->genCallerSPtoFPdelta();
#else
- offset = -(codeGen->genTotalFrameSize());
+ varOffset = -(codeGen->genTotalFrameSize());
#endif
}
}
@@ -2231,19 +2239,20 @@ inline
// we have already selected the instruction. MinOpts will always reserve R10, so
// for MinOpts always use SP-based offsets, using R10 as necessary, for simplicity.
- int spOffset = fConservative ? compLclFrameSize : offset + codeGen->genSPtoFPdelta();
- int actualOffset = spOffset + addrModeOffset;
- int encodingLimitUpper = varTypeIsFloating(type) ? 0x3FC : 0xFFF;
- int encodingLimitLower = varTypeIsFloating(type) ? -0x3FC : -0xFF;
+ int spVarOffset = fConservative ? compLclFrameSize : varOffset + codeGen->genSPtoFPdelta();
+ int actualSPOffset = spVarOffset + addrModeOffset;
+ int actualFPOffset = varOffset + addrModeOffset;
+ int encodingLimitUpper = isFloatUsage ? 0x3FC : 0xFFF;
+ int encodingLimitLower = isFloatUsage ? -0x3FC : -0xFF;
// Use SP-based encoding. During encoding, we'll pick the best encoding for the actual offset we have.
- if (opts.MinOpts() || (actualOffset <= encodingLimitUpper))
+ if (opts.MinOpts() || (actualSPOffset <= encodingLimitUpper))
{
- offset = spOffset;
+ varOffset = spVarOffset;
*pBaseReg = compLocallocUsed ? REG_SAVED_LOCALLOC_SP : REG_SPBASE;
}
// Use Frame Pointer (R11)-based encoding.
- else if ((encodingLimitLower <= offset) && (offset <= encodingLimitUpper))
+ else if ((encodingLimitLower <= actualFPOffset) && (actualFPOffset <= encodingLimitUpper))
{
*pBaseReg = REG_FPBASE;
}
@@ -2252,7 +2261,7 @@ inline
// the "reserved register", which will get used during encoding.
else
{
- offset = spOffset;
+ varOffset = spVarOffset;
*pBaseReg = compLocallocUsed ? REG_SAVED_LOCALLOC_SP : REG_SPBASE;
}
}
@@ -2265,7 +2274,7 @@ inline
*pFPbased = FPbased;
#endif
- return offset;
+ return varOffset;
}
inline bool Compiler::lvaIsParameter(unsigned varNum)
diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp
index 655f0e2bc8..4a3afc1ab0 100644
--- a/src/jit/emit.cpp
+++ b/src/jit/emit.cpp
@@ -6734,7 +6734,8 @@ target_ssize_t emitter::emitGetInsSC(instrDesc* id)
regNumber baseReg;
int offs = id->idAddr()->iiaLclVar.lvaOffset();
#if defined(_TARGET_ARM_)
- int adr = emitComp->lvaFrameAddress(varNum, id->idIsLclFPBase(), &baseReg, offs);
+ int adr =
+ emitComp->lvaFrameAddress(varNum, id->idIsLclFPBase(), &baseReg, offs, CodeGen::instIsFP(id->idIns()));
int dsp = adr + offs;
if ((id->idIns() == INS_sub) || (id->idIns() == INS_subw))
dsp = -dsp;
diff --git a/src/jit/emitarm.cpp b/src/jit/emitarm.cpp
index 1b8d2af77d..8098c60a41 100644
--- a/src/jit/emitarm.cpp
+++ b/src/jit/emitarm.cpp
@@ -3474,7 +3474,8 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
int disp;
unsigned undisp;
- base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &reg2, offs);
+ base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &reg2, offs,
+ CodeGen::instIsFP(ins));
disp = base + offs;
undisp = unsigned_abs(disp);
@@ -3495,7 +3496,7 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
else
{
regNumber rsvdReg = codeGen->rsGetRsvdReg();
- emitIns_genStackOffset(rsvdReg, varx, offs);
+ emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ true);
emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
return;
@@ -3519,7 +3520,7 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
{
// Load disp into a register
regNumber rsvdReg = codeGen->rsGetRsvdReg();
- emitIns_genStackOffset(rsvdReg, varx, offs);
+ emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ false);
fmt = IF_T2_E0;
}
}
@@ -3545,7 +3546,7 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
{
// Load disp into a register
regNumber rsvdReg = codeGen->rsGetRsvdReg();
- emitIns_genStackOffset(rsvdReg, varx, offs);
+ emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ false);
emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
return;
}
@@ -3583,13 +3584,14 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
}
// generate the offset of &varx + offs into a register
-void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs)
+void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs, bool isFloatUsage)
{
regNumber regBase;
int base;
int disp;
- base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &regBase, offs);
+ base =
+ emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &regBase, offs, isFloatUsage);
disp = base + offs;
emitIns_R_S(INS_movw, EA_4BYTE, r, varx, offs);
@@ -3633,7 +3635,8 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
int disp;
unsigned undisp;
- base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &reg2, offs);
+ base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &reg2, offs,
+ CodeGen::instIsFP(ins));
disp = base + offs;
undisp = unsigned_abs(disp);
@@ -3654,7 +3657,7 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
else
{
regNumber rsvdReg = codeGen->rsGetRsvdReg();
- emitIns_genStackOffset(rsvdReg, varx, offs);
+ emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ true);
emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
return;
@@ -3676,7 +3679,7 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
{
// Load disp into a register
regNumber rsvdReg = codeGen->rsGetRsvdReg();
- emitIns_genStackOffset(rsvdReg, varx, offs);
+ emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ false);
fmt = IF_T2_E0;
}
assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_K1));
@@ -6363,7 +6366,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
regNumber regBase;
- int adr = emitComp->lvaFrameAddress(varNum, true, &regBase, ofs);
+ int adr = emitComp->lvaFrameAddress(varNum, true, &regBase, ofs, /* isFloatUsage */ false); // no float GC refs
if (id->idGCref() != GCT_NONE)
{
emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
diff --git a/src/jit/emitarm.h b/src/jit/emitarm.h
index fe24007ef9..1e79af0fed 100644
--- a/src/jit/emitarm.h
+++ b/src/jit/emitarm.h
@@ -267,7 +267,7 @@ void emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fdlHnd, int
void emitIns_S(instruction ins, emitAttr attr, int varx, int offs);
-void emitIns_genStackOffset(regNumber r, int varx, int offs);
+void emitIns_genStackOffset(regNumber r, int varx, int offs, bool isFloatUsage);
void emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp
index 339f7a5ff7..e58130bd5b 100644
--- a/src/jit/lclvars.cpp
+++ b/src/jit/lclvars.cpp
@@ -6722,7 +6722,7 @@ void Compiler::lvaDumpFrameLocation(unsigned lclNum)
regNumber baseReg;
#ifdef _TARGET_ARM_
- offset = lvaFrameAddress(lclNum, compLocallocUsed, &baseReg, 0);
+ offset = lvaFrameAddress(lclNum, compLocallocUsed, &baseReg, 0, /* isFloatUsage */ false);
#else
bool EBPbased;
offset = lvaFrameAddress(lclNum, &EBPbased);