diff options
Diffstat (limited to 'src/jit/unwindx86.cpp')
-rw-r--r-- | src/jit/unwindx86.cpp | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/src/jit/unwindx86.cpp b/src/jit/unwindx86.cpp new file mode 100644 index 0000000000..516155c6a2 --- /dev/null +++ b/src/jit/unwindx86.cpp @@ -0,0 +1,249 @@ +// 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 + +#ifndef _TARGET_X86_ +#error "This should be included only for x86" +#endif // _TARGET_X86_ + +void Compiler::unwindBegProlog() +{ +} + +void Compiler::unwindEndProlog() +{ +} + +void Compiler::unwindBegEpilog() +{ +} + +void Compiler::unwindEndEpilog() +{ +} + +void Compiler::unwindPush(regNumber reg) +{ +} + +void Compiler::unwindAllocStack(unsigned size) +{ +} + +void Compiler::unwindSetFrameReg(regNumber reg, unsigned offset) +{ +} + +void Compiler::unwindSaveReg(regNumber reg, unsigned offset) +{ +} + +//------------------------------------------------------------------------ +// Compiler::unwindReserve: Ask the VM to reserve space for the unwind information +// for the function and all its funclets. Called once, just before asking the VM +// for memory and emitting the generated code. Calls unwindReserveFunc() to handle +// the main function and each of the funclets, in turn. +// +void Compiler::unwindReserve() +{ +#if FEATURE_EH_FUNCLETS + assert(!compGeneratingProlog); + assert(!compGeneratingEpilog); + + assert(compFuncInfoCount > 0); + for (unsigned funcIdx = 0; funcIdx < compFuncInfoCount; funcIdx++) + { + unwindReserveFunc(funGetFunc(funcIdx)); + } +#endif +} + +//------------------------------------------------------------------------ +// Compiler::unwindEmit: Report all the unwind information to the VM. +// +// Arguments: +// pHotCode - Pointer to the beginning of the memory with the function and funclet hot code. +// pColdCode - Pointer to the beginning of the memory with the function and funclet cold code. +// +void Compiler::unwindEmit(void* pHotCode, void* pColdCode) +{ +#if FEATURE_EH_FUNCLETS + assert(!compGeneratingProlog); + assert(!compGeneratingEpilog); + + assert(compFuncInfoCount > 0); + for (unsigned funcIdx = 0; funcIdx < compFuncInfoCount; funcIdx++) + { + unwindEmitFunc(funGetFunc(funcIdx), pHotCode, pColdCode); + } +#endif // FEATURE_EH_FUNCLETS +} + +#if FEATURE_EH_FUNCLETS +//------------------------------------------------------------------------ +// Compiler::unwindReserveFunc: Reserve the unwind information from the VM for a +// given main function or funclet. +// +// Arguments: +// func - The main function or funclet to reserve unwind info for. +// +void Compiler::unwindReserveFunc(FuncInfoDsc* func) +{ + unwindReserveFuncHelper(func, true); + + if (fgFirstColdBlock != nullptr) + { + unwindReserveFuncHelper(func, false); + } +} + +//------------------------------------------------------------------------ +// Compiler::unwindReserveFuncHelper: Reserve the unwind information from the VM for a +// given main function or funclet, for either the hot or the cold section. +// +// Arguments: +// func - The main function or funclet to reserve unwind info for. +// isHotCode - 'true' to reserve the hot section, 'false' to reserve the cold section. +// +void Compiler::unwindReserveFuncHelper(FuncInfoDsc* func, bool isHotCode) +{ + BOOL isFunclet = (func->funKind != FUNC_ROOT); + BOOL isColdCode = isHotCode ? FALSE : TRUE; + + eeReserveUnwindInfo(isFunclet, isColdCode, sizeof(UNWIND_INFO)); +} + +//------------------------------------------------------------------------ +// Compiler::unwindEmitFunc: Report the unwind information to the VM for a +// given main function or funclet. Reports the hot section, then the cold +// section if necessary. +// +// Arguments: +// func - The main function or funclet to reserve unwind info for. +// pHotCode - Pointer to the beginning of the memory with the function and funclet hot code. +// pColdCode - Pointer to the beginning of the memory with the function and funclet cold code. +// +void Compiler::unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode) +{ + // Verify that the JIT enum is in sync with the JIT-EE interface enum + static_assert_no_msg(FUNC_ROOT == (FuncKind)CORJIT_FUNC_ROOT); + static_assert_no_msg(FUNC_HANDLER == (FuncKind)CORJIT_FUNC_HANDLER); + static_assert_no_msg(FUNC_FILTER == (FuncKind)CORJIT_FUNC_FILTER); + + unwindEmitFuncHelper(func, pHotCode, pColdCode, true); + + if (pColdCode != nullptr) + { + unwindEmitFuncHelper(func, pHotCode, pColdCode, false); + } +} + +//------------------------------------------------------------------------ +// Compiler::unwindEmitFuncHelper: Report the unwind information to the VM for a +// given main function or funclet, for either the hot or cold section. +// +// Arguments: +// func - The main function or funclet to reserve unwind info for. +// pHotCode - Pointer to the beginning of the memory with the function and funclet hot code. +// pColdCode - Pointer to the beginning of the memory with the function and funclet cold code. +// Ignored if 'isHotCode' is true. +// isHotCode - 'true' to report the hot section, 'false' to report the cold section. +// +void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode) +{ + UNATIVE_OFFSET startOffset; + UNATIVE_OFFSET endOffset; + + if (isHotCode) + { + emitLocation* startLoc; + emitLocation* endLoc; + + unwindGetFuncLocations(func, true, &startLoc, &endLoc); + + if (startLoc == nullptr) + { + startOffset = 0; + } + else + { + startOffset = startLoc->CodeOffset(genEmitter); + } + + if (endLoc == nullptr) + { + endOffset = info.compNativeCodeSize; + } + else + { + endOffset = endLoc->CodeOffset(genEmitter); + } + } + else + { + emitLocation* coldStartLoc; + emitLocation* coldEndLoc; + + assert(fgFirstColdBlock != nullptr); + assert(func->funKind == FUNC_ROOT); // No splitting of funclets. + + unwindGetFuncLocations(func, false, &coldStartLoc, &coldEndLoc); + + if (coldStartLoc == nullptr) + { + startOffset = 0; + } + else + { + startOffset = coldStartLoc->CodeOffset(genEmitter); + } + + if (coldEndLoc == nullptr) + { + endOffset = info.compNativeCodeSize; + } + else + { + endOffset = coldEndLoc->CodeOffset(genEmitter); + } + } + + // Adjust for cold or hot code: + // 1. The VM doesn't want the cold code pointer unless this is cold code. + // 2. The startOffset and endOffset need to be from the base of the hot section for hot code + // and from the base of the cold section for cold code + + if (isHotCode) + { + assert(endOffset <= info.compTotalHotCodeSize); + pColdCode = nullptr; + } + else + { + assert(startOffset >= info.compTotalHotCodeSize); + startOffset -= info.compTotalHotCodeSize; + endOffset -= info.compTotalHotCodeSize; + } + + UNWIND_INFO unwindInfo; + + unwindInfo.FunctionLength = (ULONG)(endOffset - startOffset); + + eeAllocUnwindInfo((BYTE*)pHotCode, (BYTE*)pColdCode, startOffset, endOffset, sizeof(UNWIND_INFO), + (BYTE*)&unwindInfo, (CorJitFuncKind)func->funKind); +} +#endif // FEATURE_EH_FUNCLETS |