@@ -5644,9 +5644,7 @@ void Compiler::lvaFixVirtualFrameOffsets()
56445644#endif
56455645
56465646 // The delta to be added to virtual offset to adjust it relative to frame pointer or SP
5647- int delta = 0 ;
5648- int frameLocalsDelta = 0 ;
5649- int frameBoundary = 0 ;
5647+ int delta = 0 ;
56505648
56515649#ifdef TARGET_XARCH
56525650 delta += REGSIZE_BYTES ; // pushed PC (return address) for x86/x64
@@ -5671,25 +5669,7 @@ void Compiler::lvaFixVirtualFrameOffsets()
56715669 // We set FP to be after LR, FP
56725670 delta += 2 * REGSIZE_BYTES ;
56735671 }
5674- #elif defined(TARGET_ARM64)
5675- else
5676- {
5677- // FP is used.
5678- delta += codeGen->genTotalFrameSize () - codeGen->genSPtoFPdelta ();
5679-
5680- // If we placed FP/LR at the bottom of the frame we need to shift all the variables
5681- // on the new frame to account for it. See lvaAssignVirtualFrameOffsetsToLocals.
5682- if (!codeGen->IsSaveFpLrWithAllCalleeSavedRegisters ())
5683- {
5684- // We set FP to be after LR, FP
5685- frameLocalsDelta = 2 * REGSIZE_BYTES ;
5686- frameBoundary = opts.IsOSR () ? -info.compPatchpointInfo ->TotalFrameSize () : 0 ;
5687- if (info.compIsVarArgs )
5688- frameBoundary -= MAX_REG_ARG * REGSIZE_BYTES ;
5689- }
5690- JITDUMP (" --- delta bump %d for FP frame, %d inside frame for FP/LR relocation\n " , delta, frameLocalsDelta);
5691- }
5692- #elif defined(TARGET_AMD64)
5672+ #elif defined(TARGET_AMD64) || defined(TARGET_ARM64)
56935673 else
56945674 {
56955675 // FP is used.
@@ -5757,7 +5737,7 @@ void Compiler::lvaFixVirtualFrameOffsets()
57575737
57585738#if defined(TARGET_X86)
57595739 // On x86, we set the stack offset for a promoted field
5760- // to match a struct parameter in lvaAssignFrameOffsetsToPromotedStructs .
5740+ // to match a struct parameter in lvAssignFrameOffsetsToPromotedStructs .
57615741 if ((!varDsc->lvIsParam || parentvarDsc->lvIsParam ) && promotionType == PROMOTION_TYPE_DEPENDENT )
57625742#else
57635743 if (!varDsc->lvIsParam && promotionType == PROMOTION_TYPE_DEPENDENT )
@@ -5777,23 +5757,15 @@ void Compiler::lvaFixVirtualFrameOffsets()
57775757
57785758 if (doAssignStkOffs)
57795759 {
5780- int localDelta = delta;
5781-
5782- if (frameLocalsDelta != 0 && varDsc->GetStackOffset () < frameBoundary)
5783- {
5784- localDelta += frameLocalsDelta;
5785- }
5786-
5787- JITDUMP (" -- V%02u was %d, now %d\n " , lclNum, varDsc->GetStackOffset (),
5788- varDsc->GetStackOffset () + localDelta);
5789- varDsc->SetStackOffset (varDsc->GetStackOffset () + localDelta);
5760+ JITDUMP (" -- V%02u was %d, now %d\n " , lclNum, varDsc->GetStackOffset (), varDsc->GetStackOffset () + delta);
5761+ varDsc->SetStackOffset (varDsc->GetStackOffset () + delta);
57905762
57915763#if DOUBLE_ALIGN
57925764 if (genDoubleAlign () && !codeGen->isFramePointerUsed ())
57935765 {
57945766 if (varDsc->lvFramePointerBased )
57955767 {
5796- varDsc->SetStackOffset (varDsc->GetStackOffset () - localDelta );
5768+ varDsc->SetStackOffset (varDsc->GetStackOffset () - delta );
57975769
57985770 // We need to re-adjust the offsets of the parameters so they are EBP
57995771 // relative rather than stack/frame pointer relative
@@ -5815,13 +5787,9 @@ void Compiler::lvaFixVirtualFrameOffsets()
58155787 assert (codeGen->regSet .tmpAllFree ());
58165788 for (TempDsc* temp = codeGen->regSet .tmpListBeg (); temp != nullptr ; temp = codeGen->regSet .tmpListNxt (temp))
58175789 {
5818- temp->tdAdjustTempOffs (delta + frameLocalsDelta );
5790+ temp->tdAdjustTempOffs (delta);
58195791 }
58205792
5821- if (lvaCachedGenericContextArgOffs < frameBoundary)
5822- {
5823- lvaCachedGenericContextArgOffs += frameLocalsDelta;
5824- }
58255793 lvaCachedGenericContextArgOffs += delta;
58265794
58275795#if FEATURE_FIXED_OUT_ARGS
@@ -6077,6 +6045,30 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
60776045 codeGen->setFramePointerUsed (codeGen->isFramePointerRequired ());
60786046 }
60796047
6048+ #ifdef TARGET_ARM64
6049+ // Decide where to save FP and LR registers. We store FP/LR registers at the bottom of the frame if there is
6050+ // a frame pointer used (so we get positive offsets from the frame pointer to access locals), but not if we
6051+ // need a GS cookie AND localloc is used, since we need the GS cookie to protect the saved return value,
6052+ // and also the saved frame pointer. See CodeGen::genPushCalleeSavedRegisters() for more details about the
6053+ // frame types. Since saving FP/LR at high addresses is a relatively rare case, force using it during stress.
6054+ // (It should be legal to use these frame types for every frame).
6055+
6056+ if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 0 )
6057+ {
6058+ // Default configuration
6059+ codeGen->SetSaveFpLrWithAllCalleeSavedRegisters ((getNeedsGSSecurityCookie () && compLocallocUsed) ||
6060+ opts.compDbgEnC || compStressCompile (STRESS_GENERIC_VARN , 20 ));
6061+ }
6062+ else if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 1 )
6063+ {
6064+ codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (false ); // Disable using new frames
6065+ }
6066+ else if ((opts.compJitSaveFpLrWithCalleeSavedRegisters == 2 ) || (opts.compJitSaveFpLrWithCalleeSavedRegisters == 3 ))
6067+ {
6068+ codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (true ); // Force using new frames
6069+ }
6070+ #endif // TARGET_ARM64
6071+
60806072#ifdef TARGET_XARCH
60816073 // On x86/amd64, the return address has already been pushed by the call instruction in the caller.
60826074 stkOffs -= TARGET_POINTER_SIZE ; // return address;
@@ -6125,13 +6117,9 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
61256117#endif // !TARGET_ARM
61266118
61276119#ifdef TARGET_ARM64
6128- // If the frame pointer is used, then we'll save FP/LR either at the bottom of the stack
6129- // or at the top of the stack depending on frame type. We make the decision after assigning
6130- // the variables on the frame and then fix up the offsets in lvaFixVirtualFrameOffsets.
6131- // For now, we proceed as if FP/LR were saved with the callee registers. If we later
6132- // decide to move the FP/LR to the bottom of the frame it shifts all the assigned
6133- // variables and temporaries by 16 bytes. The largest alignment we currently make is 16
6134- // bytes for SIMD.
6120+ // If the frame pointer is used, then we'll save FP/LR at the bottom of the stack.
6121+ // Otherwise, we won't store FP, and we'll store LR at the top, with the other callee-save
6122+ // registers (if any).
61356123
61366124 int initialStkOffs = 0 ;
61376125 if (info.compIsVarArgs )
@@ -6142,7 +6130,17 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
61426130 stkOffs -= initialStkOffs;
61436131 }
61446132
6145- stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES ;
6133+ if (codeGen->IsSaveFpLrWithAllCalleeSavedRegisters () || !isFramePointerUsed ()) // Note that currently we always have
6134+ // a frame pointer
6135+ {
6136+ stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES ;
6137+ }
6138+ else
6139+ {
6140+ // Subtract off FP and LR.
6141+ assert (compCalleeRegsPushed >= 2 );
6142+ stkOffs -= (compCalleeRegsPushed - 2 ) * REGSIZE_BYTES ;
6143+ }
61466144
61476145#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
61486146
@@ -6812,6 +6810,15 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
68126810 }
68136811#endif // TARGET_AMD64
68146812
6813+ #ifdef TARGET_ARM64
6814+ if (!codeGen->IsSaveFpLrWithAllCalleeSavedRegisters () && isFramePointerUsed ()) // Note that currently we always have
6815+ // a frame pointer
6816+ {
6817+ // Create space for saving FP and LR.
6818+ stkOffs -= 2 * REGSIZE_BYTES ;
6819+ }
6820+ #endif // TARGET_ARM64
6821+
68156822#if FEATURE_FIXED_OUT_ARGS
68166823 if (lvaOutgoingArgSpaceSize > 0 )
68176824 {
@@ -6849,44 +6856,6 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
68496856
68506857 noway_assert (compLclFrameSize + originalFrameSize ==
68516858 (unsigned )-(stkOffs + (pushedCount * (int )TARGET_POINTER_SIZE )));
6852-
6853- #ifdef TARGET_ARM64
6854- // Decide where to save FP and LR registers. We store FP/LR registers at the bottom of the frame if there is
6855- // a frame pointer used (so we get positive offsets from the frame pointer to access locals), but not if we
6856- // need a GS cookie AND localloc is used, since we need the GS cookie to protect the saved return value,
6857- // and also the saved frame pointer. See CodeGen::genPushCalleeSavedRegisters() for more details about the
6858- // frame types. Since saving FP/LR at high addresses is a relatively rare case, force using it during stress.
6859- // (It should be legal to use these frame types for every frame).
6860- //
6861- // For Apple NativeAOT ABI we try to save the FP/LR registers on top to get canonical frame layout that can
6862- // be represented with compact unwinding information. In order to maintain code quality we only do it when
6863- // we can use SP-based addressing (!isFramePointerRequired) through lvaFrameAddress optimization, or if the
6864- // whole frame is small enough that the negative FP-based addressing can address the whole frame.
6865-
6866- if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 0 )
6867- {
6868- if (IsTargetAbi (CORINFO_NATIVEAOT_ABI ) && TargetOS::IsApplePlatform &&
6869- (!codeGen->isFramePointerRequired () || codeGen->genTotalFrameSize () < 0x100 ))
6870- {
6871- codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (true );
6872- }
6873- else
6874- {
6875- // Default configuration
6876- codeGen->SetSaveFpLrWithAllCalleeSavedRegisters ((getNeedsGSSecurityCookie () && compLocallocUsed) ||
6877- opts.compDbgEnC ||
6878- compStressCompile (Compiler::STRESS_GENERIC_VARN , 20 ));
6879- }
6880- }
6881- else if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 1 )
6882- {
6883- codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (false ); // Disable using new frames
6884- }
6885- else if ((opts.compJitSaveFpLrWithCalleeSavedRegisters == 2 ) || (opts.compJitSaveFpLrWithCalleeSavedRegisters == 3 ))
6886- {
6887- codeGen->SetSaveFpLrWithAllCalleeSavedRegisters (true ); // Force using new frames
6888- }
6889- #endif // TARGET_ARM64
68906859}
68916860
68926861// ------------------------------------------------------------------------
0 commit comments