genRestoreCalleeSavedFltRegs(compiler->compLclFrameSize);
#endif // !FEATURE_STACK_FP_X87
+#ifdef JIT32_GCENCODER
+ // On IA32, we start the OS-reported portion of the epilog after restoring any callee-saved
+ // floating-point registers. This avoids the need to update the x86 unwinder and retains binary
+ // compatibility between later versions of the JIT and earlier versions of the runtime.
+ getEmitter()->emitStartEpilog();
+#endif
+
/* Compute the size in bytes we've pushed/popped */
if (!doubleAlignOrFramePointerUsed())
emitPlaceholderList = emitPlaceholderLast = nullptr;
#ifdef JIT32_GCENCODER
- emitEpilogList = emitEpilogLast = NULL;
+ emitEpilogList = emitEpilogLast = nullptr;
#endif // JIT32_GCENCODER
/* We don't have any jumps */
EpilogList* el;
size_t sz;
- for (el = emitEpilogList, sz = 0; el; el = el->elNext)
+ for (el = emitEpilogList, sz = 0; el != nullptr; el = el->elNext)
{
- assert(el->elIG->igFlags & IGF_EPILOG);
+ assert(el->elLoc.GetIG()->igFlags & IGF_EPILOG);
- UNATIVE_OFFSET ofs =
- el->elIG->igOffs; // The epilog starts at the beginning of the IG, so the IG offset is correct
-
- sz += fp(cp, ofs);
+ // The epilog starts at the location recorded in the epilog list.
+ sz += fp(cp, el->elLoc.CodeOffset(this));
}
return sz;
#ifdef JIT32_GCENCODER
- EpilogList* el = new (emitComp, CMK_GC) EpilogList;
- el->elNext = NULL;
- el->elIG = emitCurIG;
+ EpilogList* el = new (emitComp, CMK_GC) EpilogList();
- if (emitEpilogLast)
+ if (emitEpilogLast != nullptr)
+ {
emitEpilogLast->elNext = el;
+ }
else
+ {
emitEpilogList = el;
+ }
emitEpilogLast = el;
#endif // JIT32_GCENCODER
-
- /* Remember current position so that we can compute total epilog size */
-
- emitEpilogBegLoc.CaptureLocation(this);
}
/*****************************************************************************
{
emitEndPrologEpilog();
+#ifdef JIT32_GCENCODER
+ assert(emitEpilogLast != nullptr);
+
UNATIVE_OFFSET newSize;
- UNATIVE_OFFSET epilogBegCodeOffset = emitEpilogBegLoc.CodeOffset(this);
+ UNATIVE_OFFSET epilogBegCodeOffset = emitEpilogLast->elLoc.CodeOffset(this);
#ifdef _TARGET_XARCH_
UNATIVE_OFFSET epilogExitSeqStartCodeOffset = emitExitSeqBegLoc.CodeOffset(this);
#else
}
#endif // _TARGET_X86_
+#endif // JIT32_GCENCODER
}
#if FEATURE_EH_FUNCLETS
#endif // FEATURE_EH_FUNCLETS
+
#ifdef JIT32_GCENCODER
+//
+// emitter::emitStartEpilog:
+// Mark the current position so that we can later compute the total epilog size.
+//
+void emitter::emitStartEpilog()
+{
+ assert(emitEpilogLast != nullptr);
+ emitEpilogLast->elLoc.CaptureLocation(this);
+}
+
/*****************************************************************************
*
* Return non-zero if the current method only has one epilog, which is
// IG of the epilog, and use it to find the epilog offset at the end of code generation.
struct EpilogList
{
- EpilogList* elNext;
- insGroup* elIG;
+ EpilogList* elNext;
+ emitLocation elLoc;
+
+ EpilogList()
+ : elNext(nullptr), elLoc()
+ {
+ }
};
EpilogList* emitEpilogList; // per method epilog list - head
EpilogList* emitEpilogLast; // per method epilog list - tail
public:
+ void emitStartEpilog();
+
bool emitHasEpilogEnd();
size_t emitGenEpilogLst(size_t (*fp)(void*, unsigned), void* cp);
void emitBegPrologEpilog(insGroup* igPh);
void emitEndPrologEpilog();
- emitLocation emitEpilogBegLoc;
-
void emitBegFnEpilog(insGroup* igPh);
void emitEndFnEpilog();