@@ -2802,7 +2802,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
28022802XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
28032803*/
28042804
2805- #if !defined(TARGET_RISCV64)
28062805struct RegNode ;
28072806
28082807struct RegNodeEdge
@@ -3346,8 +3345,6 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed)
33463345 }
33473346}
33483347
3349- #endif
3350-
33513348// -----------------------------------------------------------------------------
33523349// genGetParameterHomingTempRegisterCandidates: Get the registers that are
33533350// usable during register homing.
@@ -4122,15 +4119,69 @@ void CodeGen::genEnregisterOSRArgsAndLocals()
41224119 }
41234120}
41244121
4122+ #if defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64)
4123+ // -----------------------------------------------------------------------------
4124+ // genHomeSwiftStructParameters: Move the incoming segment to the local stack frame.
4125+ //
4126+ // Arguments:
4127+ // lclNum - Number of local variable to home
4128+ // seg - Stack segment of the local variable to home
4129+ // initReg - Scratch register to use if needed
4130+ // initRegStillZeroed - Set to false if the scratch register was needed
4131+ //
4132+ void CodeGen::genHomeStackSegment (unsigned lclNum,
4133+ const ABIPassingSegment& seg,
4134+ regNumber initReg,
4135+ bool * initRegStillZeroed)
4136+ {
4137+ var_types loadType = TYP_UNDEF;
4138+ switch (seg.Size )
4139+ {
4140+ case 1 :
4141+ loadType = TYP_UBYTE;
4142+ break ;
4143+ case 2 :
4144+ loadType = TYP_USHORT;
4145+ break ;
4146+ case 3 :
4147+ case 4 :
4148+ loadType = TYP_INT;
4149+ break ;
4150+ case 5 :
4151+ case 6 :
4152+ case 7 :
4153+ case 8 :
4154+ loadType = TYP_LONG;
4155+ break ;
4156+ default :
4157+ assert (!" Unexpected segment size for struct parameter not passed implicitly by ref" );
4158+ return ;
4159+ }
4160+ emitAttr size = emitTypeSize (loadType);
4161+
4162+ int loadOffset =
4163+ -(isFramePointerUsed () ? genCallerSPtoFPdelta () : genCallerSPtoInitialSPdelta ()) + (int )seg.GetStackOffset ();
4164+ #ifdef TARGET_XARCH
4165+ GetEmitter ()->emitIns_R_AR (ins_Load (loadType), size, initReg, genFramePointerReg (), loadOffset);
4166+ #else
4167+ genInstrWithConstant (ins_Load (loadType), size, initReg, genFramePointerReg (), loadOffset, initReg);
4168+ #endif
4169+ GetEmitter ()->emitIns_S_R (ins_Store (loadType), size, initReg, lclNum, seg.Offset );
4170+
4171+ if (initRegStillZeroed)
4172+ *initRegStillZeroed = false ;
4173+ }
4174+ #endif // defined(SWIFT_SUPPORT) || defined(TARGET_RISCV64)
4175+
41254176#ifdef SWIFT_SUPPORT
41264177
41274178// -----------------------------------------------------------------------------
41284179// genHomeSwiftStructParameters:
4129- // Reassemble Swift struct parameters if necessary.
4180+ // Reassemble Swift struct parameters if necessary.
41304181//
4131- // Parameters :
4132- // handleStack - If true, reassemble the segments that were passed on the stack.
4133- // If false, reassemble the segments that were passed in registers.
4182+ // Arguments :
4183+ // handleStack - If true, reassemble the segments that were passed on the stack.
4184+ // If false, reassemble the segments that were passed in registers.
41344185//
41354186void CodeGen::genHomeSwiftStructParameters (bool handleStack)
41364187{
@@ -4176,59 +4227,54 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack)
41764227 }
41774228 else
41784229 {
4179- var_types loadType = TYP_UNDEF;
4180- switch (seg.Size )
4181- {
4182- case 1 :
4183- loadType = TYP_UBYTE;
4184- break ;
4185- case 2 :
4186- loadType = TYP_USHORT;
4187- break ;
4188- case 3 :
4189- case 4 :
4190- loadType = TYP_INT;
4191- break ;
4192- case 5 :
4193- case 6 :
4194- case 7 :
4195- case 8 :
4196- loadType = TYP_LONG;
4197- break ;
4198- default :
4199- assert (!" Unexpected segment size for struct parameter not passed implicitly by ref" );
4200- continue ;
4201- }
4230+ // We can use REG_SCRATCH as a temporary register here as we ensured that during LSRA build.
4231+ genHomeStackSegment (lclNum, seg, REG_SCRATCH, nullptr );
4232+ }
4233+ }
4234+ }
4235+ }
4236+ #endif
42024237
4203- int offset;
4204- if (isFramePointerUsed ())
4205- {
4206- offset = -genCallerSPtoFPdelta ();
4207- }
4208- else
4209- {
4210- offset = -genCallerSPtoInitialSPdelta ();
4211- }
4238+ // -----------------------------------------------------------------------------
4239+ // genHomeStackPartOfSplitParameter: Home the tail (stack) portion of a split parameter next to where the head
4240+ // (register) portion is homed.
4241+ //
4242+ // Arguments:
4243+ // initReg - scratch register to use if needed
4244+ // initRegStillZeroed - set to false if scratch register was needed
4245+ //
4246+ // Notes:
4247+ // No-op on platforms where argument registers are already homed to form a contiguous space with incoming stack.
4248+ //
4249+ void CodeGen::genHomeStackPartOfSplitParameter (regNumber initReg, bool * initRegStillZeroed)
4250+ {
4251+ #ifdef TARGET_RISCV64
4252+ unsigned lclNum = 0 ;
4253+ for (; lclNum < compiler->info .compArgsCount ; lclNum++)
4254+ {
4255+ LclVarDsc* var = compiler->lvaGetDesc (lclNum);
4256+ if (!var->lvIsSplit || !var->lvOnFrame )
4257+ continue ;
42124258
4213- offset += ( int )seg. GetStackOffset ( );
4259+ JITDUMP ( " Homing stack part of split parameter V%02u \n " , lclNum );
42144260
4215- // Move the incoming segment to the local stack frame. We can
4216- // use REG_SCRATCH as a temporary register here as we ensured
4217- // that during LSRA build.
4218- #ifdef TARGET_XARCH
4219- GetEmitter ()->emitIns_R_AR (ins_Load (loadType), emitTypeSize (loadType), REG_SCRATCH,
4220- genFramePointerReg (), offset);
4221- #else
4222- genInstrWithConstant (ins_Load (loadType), emitTypeSize (loadType), REG_SCRATCH, genFramePointerReg (),
4223- offset, REG_SCRATCH);
4224- #endif
4261+ assert (varTypeIsStruct (var));
4262+ assert (!compiler->lvaIsImplicitByRefLocal (lclNum));
4263+ const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo (lclNum);
4264+ assert (abiInfo.NumSegments == 2 );
4265+ assert (abiInfo.Segments [0 ].GetRegister () == REG_ARG_LAST);
4266+ const ABIPassingSegment& seg = abiInfo.Segments [1 ];
42254267
4226- GetEmitter ()->emitIns_S_R (ins_Store (loadType), emitTypeSize (loadType), REG_SCRATCH, lclNum, seg.Offset );
4227- }
4268+ genHomeStackSegment (lclNum, seg, initReg, initRegStillZeroed);
4269+
4270+ for (lclNum += 1 ; lclNum < compiler->info .compArgsCount ; lclNum++)
4271+ {
4272+ assert (!compiler->lvaGetDesc (lclNum)->lvIsSplit ); // There should be only one split parameter
42284273 }
4274+ break ;
42294275 }
4230- }
42314276#endif
4277+ }
42324278
42334279/* -----------------------------------------------------------------------------
42344280 *
@@ -5547,6 +5593,8 @@ void CodeGen::genFnProlog()
55475593 {
55485594 compiler->lvaUpdateArgsWithInitialReg ();
55495595
5596+ genHomeStackPartOfSplitParameter (initReg, &initRegZeroed);
5597+
55505598 if ((intRegState.rsCalleeRegArgMaskLiveIn | floatRegState.rsCalleeRegArgMaskLiveIn ) != RBM_NONE)
55515599 {
55525600 genHomeRegisterParams (initReg, &initRegZeroed);
0 commit comments