if (endLabel != nullptr)
genDefineTempLabel(endLabel);
- // Write the lvaLocAllocSPvar stack frame slot
- if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM)
- {
- getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, regCnt, compiler->lvaLocAllocSPvar, 0);
- }
-
#if STACK_PROBES
if (compiler->opts.compNeedStackProbes)
{
if (endLabel != nullptr)
genDefineTempLabel(endLabel);
- // Write the lvaLocAllocSPvar stack frame slot
- if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM)
- {
- getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, targetReg, compiler->lvaLocAllocSPvar, 0);
- }
-
#if STACK_PROBES
if (compiler->opts.compNeedStackProbes)
{
(compiler->lvaTable[compiler->lvaSecurityObject].lvOnFrame &&
compiler->lvaTable[compiler->lvaSecurityObject].lvMustInit));
- // Initialize any "hidden" slots/locals
-
+#ifdef JIT32_GCENCODER
+ // Initialize the LocalAllocSP slot if there is localloc in the function.
if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM)
{
-#ifdef _TARGET_ARM64_
- getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_FPBASE, compiler->lvaLocAllocSPvar, 0);
-#else
getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaLocAllocSPvar, 0);
-#endif
}
+#endif // JIT32_GCENCODER
// Set up the GS security cookie
// The ESP tracking is used to report stack pointer-relative GC info, which is not
// interesting while doing the localloc construction. Also, for functions with localloc,
// we have EBP frames, and EBP-relative locals, and ESP-relative accesses only for function
-// call arguments. We store the ESP after the localloc is complete in the LocAllocSP
+// call arguments.
+//
+// For x86, we store the ESP after the localloc is complete in the LocAllocSP
// variable. This variable is implicitly reported to the VM in the GC info (its position
// is defined by convention relative to other items), and is used by the GC to find the
// "base" stack pointer in functions with localloc.
BAILOUT:
- // Write the lvaLocAllocSPvar stack frame slot
+#ifdef JIT32_GCENCODER
if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM)
{
getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaLocAllocSPvar, 0);
}
+#endif // JIT32_GCENCODER
#if STACK_PROBES
if (compiler->opts.compNeedStackProbes)
int lvaCachedGenericContextArgOffset(); // For CORINFO_CALLCONV_PARAMTYPE and if generic context is passed as
// THIS pointer
- unsigned lvaLocAllocSPvar; // variable which has the result of the last alloca/localloc
+#ifdef JIT32_GCENCODER
+
+ unsigned lvaLocAllocSPvar; // variable which stores the value of ESP after the the last alloca/localloc
+
+#endif // JIT32_GCENCODER
unsigned lvaNewObjArrayArgs; // variable with arguments for new MD array helper
ilName = "EHSlots";
}
#endif // !FEATURE_EH_FUNCLETS
+#ifdef JIT32_GCENCODER
else if (lclNum == lvaLocAllocSPvar)
{
ilName = "LocAllocSP";
}
+#endif // JIT32_GCENCODER
#if FEATURE_EH_FUNCLETS
else if (lclNum == lvaPSPSym)
{
#ifdef _TARGET_ARM_
lvaPromotedStructAssemblyScratchVar = BAD_VAR_NUM;
#endif // _TARGET_ARM_
- lvaLocAllocSPvar = BAD_VAR_NUM;
+#ifdef JIT32_GCENCODER
+ lvaLocAllocSPvar = BAD_VAR_NUM;
+#endif // JIT32_GCENCODER
lvaNewObjArrayArgs = BAD_VAR_NUM;
lvaGSSecurityCookie = BAD_VAR_NUM;
#ifdef _TARGET_X86_
}
#endif // FEATURE_EH_FUNCLETS
- // TODO: LocAllocSPvar should be only required by the implicit frame layout expected by the VM on x86.
- // It should be removed on other platforms once we check there are no other implicit dependencies.
+#ifdef JIT32_GCENCODER
+ // LocAllocSPvar is only required by the implicit frame layout expected by the VM on x86. Whether
+ // a function contains a Localloc is conveyed in the GC information, in the InfoHdrSmall.localloc
+ // field. The function must have an EBP frame. Then, the VM finds the LocAllocSP slot by assuming
+ // the following stack layout:
+ //
+ // -- higher addresses --
+ // saved EBP <-- EBP points here
+ // other callee-saved registers // InfoHdrSmall.savedRegsCountExclFP specifies this size
+ // optional GS cookie // InfoHdrSmall.security is 1 if this exists
+ // LocAllocSP slot
+ // -- lower addresses --
+ //
+ // See also eetwain.cpp::GetLocallocSPOffset() and its callers.
if (compLocallocUsed)
{
lvaLocAllocSPvar = lvaGrabTempWithImplicitUse(false DEBUGARG("LocAllocSPvar"));
LclVarDsc* locAllocSPvar = &lvaTable[lvaLocAllocSPvar];
locAllocSPvar->lvType = TYP_I_IMPL;
}
+#endif // JIT32_GCENCODER
}
// Ref counting is now enabled normally.
stkOffs = lvaAllocLocalAndSetVirtualOffset(lvaSecurityObject, TARGET_POINTER_SIZE, stkOffs);
}
+#ifdef JIT32_GCENCODER
if (lvaLocAllocSPvar != BAD_VAR_NUM)
{
-#ifdef JIT32_GCENCODER
noway_assert(codeGen->isFramePointerUsed()); // else offsets of locals of frameless methods will be incorrect
-#endif
stkOffs = lvaAllocLocalAndSetVirtualOffset(lvaLocAllocSPvar, TARGET_POINTER_SIZE, stkOffs);
}
+#endif // JIT32_GCENCODER
if (lvaReportParamTypeArg())
{
#else
lclNum == lvaShadowSPslotsVar ||
#endif // FEATURE_EH_FUNCLETS
- lclNum == lvaLocAllocSPvar || lclNum == lvaSecurityObject)
+#ifdef JIT32_GCENCODER
+ lclNum == lvaLocAllocSPvar ||
+#endif // JIT32_GCENCODER
+ lclNum == lvaSecurityObject)
{
assert(varDsc->lvStkOffs != BAD_STK_OFFS);
continue;
/*****************************************************************************
*
* Dump the frame location assigned to a local.
- * For non-LSRA, this will only be valid if there is no assigned register.
- * For LSRA, it's the home location, even though the variable doesn't always live
+ * It's the home location, even though the variable doesn't always live
* in its home location.
*/