diff --git a/src/coreclr/src/jit/codegen.h b/src/coreclr/src/jit/codegen.h index 2c71468717624d..653cfa2bfbaeaf 100644 --- a/src/coreclr/src/jit/codegen.h +++ b/src/coreclr/src/jit/codegen.h @@ -1406,8 +1406,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void inst_SA_RV(instruction ins, unsigned ofs, regNumber reg, var_types type); void inst_SA_IV(instruction ins, unsigned ofs, int val, var_types type); - void inst_RV_ST( - instruction ins, regNumber reg, TempDsc* tmp, unsigned ofs, var_types type, emitAttr size = EA_UNKNOWN); void inst_FS_ST(instruction ins, emitAttr size, TempDsc* tmp, unsigned ofs); void inst_TT(instruction ins, GenTree* tree, unsigned offs = 0, int shfv = 0, emitAttr size = EA_UNKNOWN); diff --git a/src/coreclr/src/jit/emitarm.cpp b/src/coreclr/src/jit/emitarm.cpp index b5ed5e83e08ac8..bf586cb0353060 100644 --- a/src/coreclr/src/jit/emitarm.cpp +++ b/src/coreclr/src/jit/emitarm.cpp @@ -3510,11 +3510,22 @@ void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs) NYI("emitIns_S"); } -/***************************************************************************** - * - * Add an instruction referencing a register and a stack-based local variable. - */ -void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs) +//------------------------------------------------------------------------------------- +// emitIns_R_S: Add an instruction referencing a register and a stack-based local variable. +// +// Arguments: +// ins - The instruction to add. +// attr - Oeration size. +// varx - The variable to generate offset for. +// offs - The offset of variable or field in stack. +// pBaseReg - The base register that is used while calculating the offset. For example, if the offset +// with "stack pointer" can't be encoded in instruction, "frame pointer" can be used to get +// the offset of the field. In such case, pBaseReg will store the "fp". +// +// Return Value: +// The pBaseReg that holds the base register that was used to calculate the offset. +// +void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, regNumber* pBaseReg) { if (ins == INS_mov) { @@ -3547,6 +3558,7 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va insFormat fmt = IF_NONE; insFlags sf = INS_FLAGS_NOT_SET; regNumber reg2; + regNumber baseRegUsed; /* Figure out the variable's frame position */ int base; @@ -3555,6 +3567,10 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs, CodeGen::instIsFP(ins)); + if (pBaseReg != nullptr) + { + *pBaseReg = reg2; + } disp = base + offs; undisp = unsigned_abs(disp); @@ -3575,8 +3591,8 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va else { regNumber rsvdReg = codeGen->rsGetRsvdReg(); - emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ true); - emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2); + emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ true, &baseRegUsed); + emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, baseRegUsed); emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0); return; } @@ -3599,8 +3615,11 @@ 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, /* isFloatUsage */ false); + emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ false, &baseRegUsed); fmt = IF_T2_E0; + + // Ensure the baseReg calculated is correct. + assert(baseRegUsed == reg2); } } else if (ins == INS_add) @@ -3625,7 +3644,10 @@ 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, /* isFloatUsage */ false); + emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ false, &baseRegUsed); + + // Ensure the baseReg calculated is correct. + assert(baseRegUsed == reg2); emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg); return; } @@ -3662,8 +3684,24 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va appendToCurIG(id); } -// generate the offset of &varx + offs into a register -void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs, bool isFloatUsage) +//------------------------------------------------------------------------------------- +// emitIns_genStackOffset: Generate the offset of &varx + offs into a register +// +// Arguments: +// r - Register in which offset calculation result is stored. +// varx - The variable to generate offset for. +// offs - The offset of variable or field in stack. +// isFloatUsage - 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. +// pBaseReg - The base register that is used while calculating the offset. For example, if the offset with +// "stack pointer" can't be encoded in instruction, "frame pointer" can be used to get the offset +// of the field. In such case, pBaseReg will store the "fp". +// +// Return Value: +// The pBaseReg that holds the base register that was used to calculate the offset. +// +void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs, bool isFloatUsage, regNumber* pBaseReg) { regNumber regBase; int base; @@ -3673,11 +3711,13 @@ void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs, bool isFlo emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®Base, offs, isFloatUsage); disp = base + offs; - emitIns_R_S(INS_movw, EA_4BYTE, r, varx, offs); + emitIns_R_S(INS_movw, EA_4BYTE, r, varx, offs, pBaseReg); if ((disp & 0xffff) != disp) { - emitIns_R_S(INS_movt, EA_4BYTE, r, varx, offs); + regNumber regBaseUsedInMovT; + emitIns_R_S(INS_movt, EA_4BYTE, r, varx, offs, ®BaseUsedInMovT); + assert(*pBaseReg == regBaseUsedInMovT); } } @@ -3708,6 +3748,7 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va insFormat fmt = IF_NONE; insFlags sf = INS_FLAGS_NOT_SET; regNumber reg2; + regNumber baseRegUsed; /* Figure out the variable's frame position */ int base; @@ -3736,7 +3777,10 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va else { regNumber rsvdReg = codeGen->rsGetRsvdReg(); - emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ true); + emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ true, &baseRegUsed); + + // Ensure the baseReg calculated is correct. + assert(baseRegUsed == reg2); emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2); emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0); return; @@ -3758,8 +3802,11 @@ 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, /* isFloatUsage */ false); + emitIns_genStackOffset(rsvdReg, varx, offs, /* isFloatUsage */ false, &baseRegUsed); fmt = IF_T2_E0; + + // Ensure the baseReg calculated is correct. + assert(baseRegUsed == reg2); } assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_K1)); assert(sf != INS_FLAGS_DONT_CARE); diff --git a/src/coreclr/src/jit/emitarm.h b/src/coreclr/src/jit/emitarm.h index fe6a7a0c0790a7..8c9c77eec98d91 100644 --- a/src/coreclr/src/jit/emitarm.h +++ b/src/coreclr/src/jit/emitarm.h @@ -267,11 +267,11 @@ 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, bool isFloatUsage); +void emitIns_genStackOffset(regNumber r, int varx, int offs, bool isFloatUsage, regNumber* pBaseReg); void emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs); -void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs); +void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs, regNumber* pBaseReg = nullptr); void emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val); diff --git a/src/coreclr/src/jit/instr.cpp b/src/coreclr/src/jit/instr.cpp index ec776cbea9a911..364273efddc4aa 100644 --- a/src/coreclr/src/jit/instr.cpp +++ b/src/coreclr/src/jit/instr.cpp @@ -1308,40 +1308,6 @@ void CodeGen::inst_RV_ST(instruction ins, emitAttr size, regNumber reg, GenTree* inst_RV_TT(ins, reg, tree, 0, size); } -void CodeGen::inst_RV_ST(instruction ins, regNumber reg, TempDsc* tmp, unsigned ofs, var_types type, emitAttr size) -{ - if (size == EA_UNKNOWN) - { - size = emitActualTypeSize(type); - } - -#ifdef TARGET_ARM - switch (ins) - { - case INS_mov: - assert(!"Please call ins_Load(type) to get the load instruction"); - break; - - case INS_add: - case INS_ldr: - case INS_ldrh: - case INS_ldrb: - case INS_ldrsh: - case INS_ldrsb: - case INS_lea: - case INS_vldr: - GetEmitter()->emitIns_R_S(ins, size, reg, tmp->tdTempNum(), ofs); - break; - - default: - assert(!"Default inst_RV_ST case not supported for Arm"); - break; - } -#else // !TARGET_ARM - GetEmitter()->emitIns_R_S(ins, size, reg, tmp->tdTempNum(), ofs); -#endif // !TARGET_ARM -} - void CodeGen::inst_mov_RV_ST(regNumber reg, GenTree* tree) { /* Figure out the size of the value being loaded */ diff --git a/src/coreclr/tests/issues.targets b/src/coreclr/tests/issues.targets index ec07afb575c5a9..14a87203905912 100644 --- a/src/coreclr/tests/issues.targets +++ b/src/coreclr/tests/issues.targets @@ -557,18 +557,6 @@ https://github.com/dotnet/runtime/issues/12979 - - https://github.com/dotnet/runtime/issues/35501 - - - https://github.com/dotnet/runtime/issues/35501 - - - https://github.com/dotnet/runtime/issues/35501 - - - https://github.com/dotnet/runtime/issues/35501 -