summaryrefslogtreecommitdiff
path: root/src/jit/unwindx86.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/unwindx86.cpp')
-rw-r--r--src/jit/unwindx86.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/jit/unwindx86.cpp b/src/jit/unwindx86.cpp
new file mode 100644
index 0000000..516155c
--- /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