summaryrefslogtreecommitdiff
path: root/src/jit/jiteh.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/jiteh.h')
-rw-r--r--src/jit/jiteh.h180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/jit/jiteh.h b/src/jit/jiteh.h
new file mode 100644
index 0000000000..573116282c
--- /dev/null
+++ b/src/jit/jiteh.h
@@ -0,0 +1,180 @@
+// 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 Exception Handling XX
+XX XX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+*/
+
+/*****************************************************************************/
+#ifndef _EH_H_
+#define _EH_H_
+
+struct BasicBlock;
+class Compiler;
+
+/*****************************************************************************/
+
+// The following holds the table of exception handlers.
+
+enum EHHandlerType
+{
+ EH_HANDLER_CATCH = 0x1, // Don't use zero (to aid debugging uninitialized memory)
+ EH_HANDLER_FILTER,
+ EH_HANDLER_FAULT,
+ EH_HANDLER_FINALLY
+};
+
+// ToCORINFO_EH_CLAUSE_FLAGS: Convert an internal EHHandlerType to a CORINFO_EH_CLAUSE_FLAGS value
+// to pass back to the VM.
+inline CORINFO_EH_CLAUSE_FLAGS ToCORINFO_EH_CLAUSE_FLAGS(EHHandlerType type)
+{
+ switch (type)
+ {
+ case EH_HANDLER_CATCH:
+ return CORINFO_EH_CLAUSE_NONE;
+ case EH_HANDLER_FILTER:
+ return CORINFO_EH_CLAUSE_FILTER;
+ case EH_HANDLER_FAULT:
+ return CORINFO_EH_CLAUSE_FAULT;
+ case EH_HANDLER_FINALLY:
+ return CORINFO_EH_CLAUSE_FINALLY;
+ default:
+ unreached();
+ }
+}
+
+// ToEHHandlerType: Convert a CORINFO_EH_CLAUSE_FLAGS value obtained from the VM in the EH clause structure
+// to the internal EHHandlerType type.
+inline EHHandlerType ToEHHandlerType(CORINFO_EH_CLAUSE_FLAGS flags)
+{
+ if (flags & CORINFO_EH_CLAUSE_FAULT)
+ {
+ return EH_HANDLER_FAULT;
+ }
+ else if (flags & CORINFO_EH_CLAUSE_FINALLY)
+ {
+ return EH_HANDLER_FINALLY;
+ }
+ else if (flags & CORINFO_EH_CLAUSE_FILTER)
+ {
+ return EH_HANDLER_FILTER;
+ }
+ else
+ {
+ // If it's none of the others, assume it is a try/catch.
+ /* XXX Fri 11/7/2008
+ * The VM (and apparently VC) stick in extra bits in the flags field. We ignore any flags
+ * we don't know about.
+ */
+ return EH_HANDLER_CATCH;
+ }
+}
+
+struct EHblkDsc
+{
+ BasicBlock* ebdTryBeg; // First block of the try
+ BasicBlock* ebdTryLast; // Last block of the try
+ BasicBlock* ebdHndBeg; // First block of the handler
+ BasicBlock* ebdHndLast; // Last block of the handler
+ union {
+ BasicBlock* ebdFilter; // First block of filter, if HasFilter()
+ unsigned ebdTyp; // Exception type (a class token), otherwise
+ };
+
+ EHHandlerType ebdHandlerType;
+
+#if !FEATURE_EH_FUNCLETS
+ // How nested is the try/handler within other *handlers* - 0 for outermost clauses, 1 for nesting with a handler,
+ // etc.
+ unsigned short ebdHandlerNestingLevel;
+#endif // !FEATURE_EH_FUNCLETS
+
+ static const unsigned short NO_ENCLOSING_INDEX = USHRT_MAX;
+
+ // The index of the enclosing outer try region, NO_ENCLOSING_INDEX if none.
+ // Be careful of 'mutually protect' catch and filter clauses (multiple
+ // handlers with the same try region): the try regions 'nest' so we set
+ // ebdEnclosingTryIndex, but the inner catch is *NOT* nested within the outer catch!
+ // That is, if the "inner catch" throws an exception, it won't be caught by
+ // the "outer catch" for mutually protect handlers.
+ unsigned short ebdEnclosingTryIndex;
+
+ // The index of the enclosing outer handler region, NO_ENCLOSING_INDEX if none.
+ unsigned short ebdEnclosingHndIndex;
+
+#if FEATURE_EH_FUNCLETS
+
+ // After funclets are created, this is the index of corresponding FuncInfoDsc
+ // Special case for Filter/Filter-handler:
+ // Like the IL the filter funclet immediately preceeds the filter-handler funclet.
+ // So this index points to the filter-handler funclet. If you want the filter
+ // funclet index, just subtract 1.
+ unsigned short ebdFuncIndex;
+
+#endif // FEATURE_EH_FUNCLETS
+
+ IL_OFFSET ebdTryBegOffset; // IL offsets of EH try/end regions as they are imported
+ IL_OFFSET ebdTryEndOffset;
+ IL_OFFSET ebdFilterBegOffset; // only set if HasFilter()
+ IL_OFFSET ebdHndBegOffset;
+ IL_OFFSET ebdHndEndOffset;
+
+ // Returns the last block of the filter. Assumes the EH clause is a try/filter/filter-handler type.
+ BasicBlock* BBFilterLast();
+
+ bool HasCatchHandler();
+ bool HasFilter();
+ bool HasFinallyHandler();
+ bool HasFaultHandler();
+ bool HasFinallyOrFaultHandler();
+
+ // Returns the block to which control will flow if an (otherwise-uncaught) exception is raised
+ // in the try. This is normally "ebdHndBeg", unless the try region has a filter, in which case that is returned.
+ // (This is, in some sense, the "true handler," at least in the sense of control flow. Note
+ // that we model the transition from a filter to its handler as normal, non-exceptional control flow.)
+ BasicBlock* ExFlowBlock();
+
+ bool InTryRegionILRange(BasicBlock* pBlk);
+ bool InFilterRegionILRange(BasicBlock* pBlk);
+ bool InHndRegionILRange(BasicBlock* pBlk);
+
+ bool InTryRegionBBRange(BasicBlock* pBlk);
+ bool InFilterRegionBBRange(BasicBlock* pBlk);
+ bool InHndRegionBBRange(BasicBlock* pBlk);
+
+ IL_OFFSET ebdTryBegOffs();
+ IL_OFFSET ebdTryEndOffs();
+ IL_OFFSET ebdFilterBegOffs();
+ IL_OFFSET ebdFilterEndOffs();
+ IL_OFFSET ebdHndBegOffs();
+ IL_OFFSET ebdHndEndOffs();
+
+ static bool ebdIsSameILTry(EHblkDsc* h1, EHblkDsc* h2); // Same 'try' region? Compare IL range.
+
+ // Return the region index of the most nested EH region that encloses this region, or NO_ENCLOSING_INDEX
+ // if this region is directly in the main function body. Set '*inTryRegion' to 'true' if this region is
+ // most nested within a 'try' region, or 'false' if this region is most nested within a handler. (Note
+ // that filters cannot contain nested EH regions.)
+ unsigned ebdGetEnclosingRegionIndex(bool* inTryRegion);
+
+ static bool ebdIsSameTry(EHblkDsc* h1, EHblkDsc* h2); // Same 'try' region? Compare begin/last blocks.
+ bool ebdIsSameTry(Compiler* comp, unsigned t2);
+ bool ebdIsSameTry(BasicBlock* ebdTryBeg, BasicBlock* ebdTryLast);
+
+#ifdef DEBUG
+ void DispEntry(unsigned num); // Display this table entry
+#endif // DEBUG
+
+private:
+ static bool InBBRange(BasicBlock* pBlk, BasicBlock* pStart, BasicBlock* pEnd);
+};
+
+/*****************************************************************************/
+#endif // _EH_H_
+/*****************************************************************************/