diff options
author | Bruce Forstall <brucefo@microsoft.com> | 2018-12-16 14:27:08 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-16 14:27:08 -0800 |
commit | f5979429b345879b4a4b38caac23ad701e4ae49f (patch) | |
tree | 4b2be8b65bfa2086d917eebcfee6c8edb2d9be34 /src | |
parent | 3e06d9f5911ffe30894b3e08ef955f645df3acd9 (diff) | |
parent | c153d9fc6627e5bb35e31eea6038f64f2a006022 (diff) | |
download | coreclr-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.cpp | 3 | ||||
-rw-r--r-- | src/jit/compiler.h | 2 | ||||
-rw-r--r-- | src/jit/compiler.hpp | 83 | ||||
-rw-r--r-- | src/jit/emit.cpp | 3 | ||||
-rw-r--r-- | src/jit/emitarm.cpp | 23 | ||||
-rw-r--r-- | src/jit/emitarm.h | 2 | ||||
-rw-r--r-- | src/jit/lclvars.cpp | 2 |
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, ®2, offs); + base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, 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, ®Base, offs); + base = + emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®Base, 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, ®2, offs); + base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, 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, ®Base, ofs); + int adr = emitComp->lvaFrameAddress(varNum, true, ®Base, 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); |