diff --git a/src/coreclr/jit/abi.cpp b/src/coreclr/jit/abi.cpp index 7a594f77f3912..7fa39d0464434 100644 --- a/src/coreclr/jit/abi.cpp +++ b/src/coreclr/jit/abi.cpp @@ -259,13 +259,17 @@ bool ABIPassingInformation::HasExactlyOneStackSegment() const bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const { if (NumSegments < 2) + { return false; + } bool isFirstInReg = Segments[0].IsPassedInRegister(); for (unsigned i = 1; i < NumSegments; i++) { if (isFirstInReg != Segments[i].IsPassedInRegister()) + { return true; + } } return false; } diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index c3608402d27ec..301b10b1de071 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -4119,7 +4119,7 @@ void CodeGen::genEnregisterOSRArgsAndLocals() } } -#if defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) +#if defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) //----------------------------------------------------------------------------- // genHomeSwiftStructParameters: Move the incoming segment to the local stack frame. // @@ -4159,8 +4159,16 @@ void CodeGen::genHomeStackSegment(unsigned lclNum, } emitAttr size = emitTypeSize(loadType); - int loadOffset = - -(isFramePointerUsed() ? genCallerSPtoFPdelta() : genCallerSPtoInitialSPdelta()) + (int)seg.GetStackOffset(); + int loadOffset = (int)seg.GetStackOffset(); + if (isFramePointerUsed()) + { + loadOffset -= genCallerSPtoFPdelta(); + } + else + { + loadOffset -= genCallerSPtoInitialSPdelta(); + } + #ifdef TARGET_XARCH GetEmitter()->emitIns_R_AR(ins_Load(loadType), size, initReg, genFramePointerReg(), loadOffset); #else @@ -4171,7 +4179,7 @@ void CodeGen::genHomeStackSegment(unsigned lclNum, if (initRegStillZeroed) *initRegStillZeroed = false; } -#endif // defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) +#endif // defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) #ifdef SWIFT_SUPPORT @@ -4248,32 +4256,41 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) // void CodeGen::genHomeStackPartOfSplitParameter(regNumber initReg, bool* initRegStillZeroed) { -#ifdef TARGET_RISCV64 +#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64) unsigned lclNum = 0; for (; lclNum < compiler->info.compArgsCount; lclNum++) { LclVarDsc* var = compiler->lvaGetDesc(lclNum); - if (!var->lvIsSplit || !var->lvOnFrame) + if (!var->lvOnFrame || !varTypeIsStruct(var)) + { continue; + } - JITDUMP("Homing stack part of split parameter V%02u\n", lclNum); - - assert(varTypeIsStruct(var)); - assert(!compiler->lvaIsImplicitByRefLocal(lclNum)); const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); - assert(abiInfo.NumSegments == 2); - assert(abiInfo.Segments[0].GetRegister() == REG_ARG_LAST); - const ABIPassingSegment& seg = abiInfo.Segments[1]; + if (abiInfo.IsSplitAcrossRegistersAndStack()) + { + assert(var->lvIsSplit); + JITDUMP("Homing stack part of split parameter V%02u\n", lclNum); - genHomeStackSegment(lclNum, seg, initReg, initRegStillZeroed); + assert(abiInfo.NumSegments == 2); + assert(abiInfo.Segments[0].GetRegister() == REG_ARG_LAST); + assert(abiInfo.Segments[1].GetStackOffset() == 0); + const ABIPassingSegment& seg = abiInfo.Segments[1]; - for (lclNum += 1; lclNum < compiler->info.compArgsCount; lclNum++) - { - assert(!compiler->lvaGetDesc(lclNum)->lvIsSplit); // There should be only one split parameter + genHomeStackSegment(lclNum, seg, initReg, initRegStillZeroed); + +#ifdef DEBUG + for (lclNum += 1; lclNum < compiler->info.compArgsCount; lclNum++) + { + const ABIPassingInformation& abiInfo2 = compiler->lvaGetParameterABIInfo(lclNum); + // There should be only one split parameter + assert(!abiInfo2.IsSplitAcrossRegistersAndStack()); + } +#endif + break; } - break; } -#endif +#endif // TARGET_RISCV64 || TARGET_LOONGARCH64 } /*-----------------------------------------------------------------------------