diff options
Diffstat (limited to 'src/jit/unwind.cpp')
-rw-r--r-- | src/jit/unwind.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/jit/unwind.cpp b/src/jit/unwind.cpp new file mode 100644 index 0000000000..4568fed75a --- /dev/null +++ b/src/jit/unwind.cpp @@ -0,0 +1,171 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XX XX +XX UnwindInfo XX +XX XX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +*/ + +#include "jitpch.h" +#ifdef _MSC_VER +#pragma hdrstop +#endif + +#if FEATURE_EH_FUNCLETS + +//------------------------------------------------------------------------ +// Compiler::unwindGetFuncLocations: Get the start/end emitter locations for this +// function or funclet. If 'getHotSectionData' is true, get the start/end locations +// for the hot section. Otherwise, get the data for the cold section. +// +// Note that we grab these locations before the prolog and epilogs are generated, so the +// locations must remain correct after the prolog and epilogs are generated. +// +// For the prolog, instructions are put in the special, preallocated, prolog instruction group. +// We don't want to expose the emitPrologIG unnecessarily (locations are actually pointers to +// emitter instruction groups). Since we know the offset of the start of the function/funclet, +// where the prolog is, will be zero, we use a nullptr start location to indicate that. +// +// There is no instruction group beyond the end of the end of the function, so there is no +// location to indicate that. Once again, use nullptr for that. +// +// Intermediate locations point at the first instruction group of a funclet, which is a +// placeholder IG. These are converted to real IGs, not deleted and replaced, so the location +// remains valid. +// +// Arguments: +// func - main function or funclet to get locations for. +// getHotSectionData - 'true' to get the hot section data, 'false' to get the cold section data. +// ppStartLoc - OUT parameter. Set to the start emitter location. +// ppEndLoc - OUT parameter. Set to the end emitter location (the location immediately +// the range; the 'end' location is not inclusive). +// +// Notes: +// A start location of nullptr means the beginning of the code. +// An end location of nullptr means the end of the code. +// +void Compiler::unwindGetFuncLocations(FuncInfoDsc* func, + bool getHotSectionData, + /* OUT */ emitLocation** ppStartLoc, + /* OUT */ emitLocation** ppEndLoc) +{ + if (func->funKind == FUNC_ROOT) + { + // Since all funclets are pulled out of line, the main code size is everything + // up to the first handler. If the function is hot/cold split, we need to get the + // appropriate sub-range. + + if (getHotSectionData) + { + *ppStartLoc = nullptr; // nullptr emit location means the beginning of the code. This is to handle the first + // fragment prolog. + + if (fgFirstColdBlock != nullptr) + { + // The hot section only goes up to the cold section + assert(fgFirstFuncletBB == nullptr); + + *ppEndLoc = new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(fgFirstColdBlock)); + } + else + { + if (fgFirstFuncletBB != nullptr) + { + *ppEndLoc = new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(fgFirstFuncletBB)); + } + else + { + *ppEndLoc = nullptr; // nullptr end location means the end of the code + } + } + } + else + { + assert(fgFirstFuncletBB == nullptr); // TODO-CQ: support hot/cold splitting in functions with EH + assert(fgFirstColdBlock != nullptr); // There better be a cold section! + + *ppStartLoc = new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(fgFirstColdBlock)); + *ppEndLoc = nullptr; // nullptr end location means the end of the code + } + } + else + { + assert(getHotSectionData); // TODO-CQ: support funclets in cold section + + EHblkDsc* HBtab = ehGetDsc(func->funEHIndex); + + if (func->funKind == FUNC_FILTER) + { + assert(HBtab->HasFilter()); + *ppStartLoc = new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(HBtab->ebdFilter)); + *ppEndLoc = new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(HBtab->ebdHndBeg)); + } + else + { + assert(func->funKind == FUNC_HANDLER); + *ppStartLoc = new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(HBtab->ebdHndBeg)); + *ppEndLoc = (HBtab->ebdHndLast->bbNext == nullptr) + ? nullptr + : new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(HBtab->ebdHndLast->bbNext)); + } + } +} + +#endif // FEATURE_EH_FUNCLETS + +#if defined(_TARGET_AMD64_) + +// See unwindAmd64.cpp + +#elif defined(_TARGET_ARM64_) + +// See unwindArm64.cpp + +#elif defined(_TARGET_ARM_) + +// See unwindArm.cpp + +#elif defined(_TARGET_X86_) + +// Stub routines that do nothing +void Compiler::unwindBegProlog() +{ +} +void Compiler::unwindEndProlog() +{ +} +void Compiler::unwindBegEpilog() +{ +} +void Compiler::unwindEndEpilog() +{ +} +void Compiler::unwindReserve() +{ +} +void Compiler::unwindEmit(void* pHotCode, void* pColdCode) +{ +} +void Compiler::unwindPush(regNumber reg) +{ +} +void Compiler::unwindAllocStack(unsigned size) +{ +} +void Compiler::unwindSetFrameReg(regNumber reg, unsigned offset) +{ +} +void Compiler::unwindSaveReg(regNumber reg, unsigned offset) +{ +} + +#else // _TARGET_* + +#error Unsupported or unset target architecture + +#endif // _TARGET_* |