Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / jiteh.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                          Exception Handling                               XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 /*****************************************************************************/
15 #ifndef _EH_H_
16 #define _EH_H_
17
18 struct BasicBlock;
19 class Compiler;
20
21 /*****************************************************************************/
22
23 // The following holds the table of exception handlers.
24
25 enum EHHandlerType
26 {
27     EH_HANDLER_CATCH = 0x1, // Don't use zero (to aid debugging uninitialized memory)
28     EH_HANDLER_FILTER,
29     EH_HANDLER_FAULT,
30     EH_HANDLER_FINALLY,
31     EH_HANDLER_FAULT_WAS_FINALLY
32 };
33
34 // ToCORINFO_EH_CLAUSE_FLAGS: Convert an internal EHHandlerType to a CORINFO_EH_CLAUSE_FLAGS value
35 // to pass back to the VM.
36 inline CORINFO_EH_CLAUSE_FLAGS ToCORINFO_EH_CLAUSE_FLAGS(EHHandlerType type)
37 {
38     switch (type)
39     {
40         case EH_HANDLER_CATCH:
41             return CORINFO_EH_CLAUSE_NONE;
42         case EH_HANDLER_FILTER:
43             return CORINFO_EH_CLAUSE_FILTER;
44         case EH_HANDLER_FAULT:
45         case EH_HANDLER_FAULT_WAS_FINALLY:
46             return CORINFO_EH_CLAUSE_FAULT;
47         case EH_HANDLER_FINALLY:
48             return CORINFO_EH_CLAUSE_FINALLY;
49         default:
50             unreached();
51     }
52 }
53
54 // ToEHHandlerType: Convert a CORINFO_EH_CLAUSE_FLAGS value obtained from the VM in the EH clause structure
55 // to the internal EHHandlerType type.
56 inline EHHandlerType ToEHHandlerType(CORINFO_EH_CLAUSE_FLAGS flags)
57 {
58     if (flags & CORINFO_EH_CLAUSE_FAULT)
59     {
60         return EH_HANDLER_FAULT;
61     }
62     else if (flags & CORINFO_EH_CLAUSE_FINALLY)
63     {
64         return EH_HANDLER_FINALLY;
65     }
66     else if (flags & CORINFO_EH_CLAUSE_FILTER)
67     {
68         return EH_HANDLER_FILTER;
69     }
70     else
71     {
72         // If it's none of the others, assume it is a try/catch.
73         /* XXX Fri 11/7/2008
74          * The VM (and apparently VC) stick in extra bits in the flags field. We ignore any flags
75          * we don't know about.
76          */
77         return EH_HANDLER_CATCH;
78     }
79 }
80
81 struct EHblkDsc
82 {
83     BasicBlock* ebdTryBeg;  // First block of the try
84     BasicBlock* ebdTryLast; // Last block of the try
85     BasicBlock* ebdHndBeg;  // First block of the handler
86     BasicBlock* ebdHndLast; // Last block of the handler
87     union {
88         BasicBlock* ebdFilter; // First block of filter,          if HasFilter()
89         unsigned    ebdTyp;    // Exception type (a class token), otherwise
90     };
91
92     EHHandlerType ebdHandlerType;
93
94 #if !FEATURE_EH_FUNCLETS
95     // How nested is the try/handler within other *handlers* - 0 for outermost clauses, 1 for nesting with a handler,
96     // etc.
97     unsigned short ebdHandlerNestingLevel;
98 #endif // !FEATURE_EH_FUNCLETS
99
100     static const unsigned short NO_ENCLOSING_INDEX = USHRT_MAX;
101
102     // The index of the enclosing outer try region, NO_ENCLOSING_INDEX if none.
103     // Be careful of 'mutually protect' catch and filter clauses (multiple
104     // handlers with the same try region): the try regions 'nest' so we set
105     // ebdEnclosingTryIndex, but the inner catch is *NOT* nested within the outer catch!
106     // That is, if the "inner catch" throws an exception, it won't be caught by
107     // the "outer catch" for mutually protect handlers.
108     unsigned short ebdEnclosingTryIndex;
109
110     // The index of the enclosing outer handler region, NO_ENCLOSING_INDEX if none.
111     unsigned short ebdEnclosingHndIndex;
112
113 #if FEATURE_EH_FUNCLETS
114
115     // After funclets are created, this is the index of corresponding FuncInfoDsc
116     // Special case for Filter/Filter-handler:
117     //   Like the IL the filter funclet immediately preceeds the filter-handler funclet.
118     //   So this index points to the filter-handler funclet. If you want the filter
119     //   funclet index, just subtract 1.
120     unsigned short ebdFuncIndex;
121
122 #endif // FEATURE_EH_FUNCLETS
123
124     IL_OFFSET ebdTryBegOffset; // IL offsets of EH try/end regions as they are imported
125     IL_OFFSET ebdTryEndOffset;
126     IL_OFFSET ebdFilterBegOffset; // only set if HasFilter()
127     IL_OFFSET ebdHndBegOffset;
128     IL_OFFSET ebdHndEndOffset;
129
130     // Returns the last block of the filter. Assumes the EH clause is a try/filter/filter-handler type.
131     BasicBlock* BBFilterLast();
132
133     bool HasCatchHandler();
134     bool HasFilter();
135     bool HasFinallyHandler();
136     bool HasFaultHandler();
137     bool HasFinallyOrFaultHandler();
138
139     // Returns the block to which control will flow if an (otherwise-uncaught) exception is raised
140     // in the try.  This is normally "ebdHndBeg", unless the try region has a filter, in which case that is returned.
141     // (This is, in some sense, the "true handler," at least in the sense of control flow.  Note
142     // that we model the transition from a filter to its handler as normal, non-exceptional control flow.)
143     BasicBlock* ExFlowBlock();
144
145     bool InTryRegionILRange(BasicBlock* pBlk);
146     bool InFilterRegionILRange(BasicBlock* pBlk);
147     bool InHndRegionILRange(BasicBlock* pBlk);
148
149     bool InTryRegionBBRange(BasicBlock* pBlk);
150     bool InFilterRegionBBRange(BasicBlock* pBlk);
151     bool InHndRegionBBRange(BasicBlock* pBlk);
152
153     IL_OFFSET ebdTryBegOffs();
154     IL_OFFSET ebdTryEndOffs();
155     IL_OFFSET ebdFilterBegOffs();
156     IL_OFFSET ebdFilterEndOffs();
157     IL_OFFSET ebdHndBegOffs();
158     IL_OFFSET ebdHndEndOffs();
159
160     static bool ebdIsSameILTry(EHblkDsc* h1, EHblkDsc* h2); // Same 'try' region? Compare IL range.
161
162     // Return the region index of the most nested EH region that encloses this region, or NO_ENCLOSING_INDEX
163     // if this region is directly in the main function body. Set '*inTryRegion' to 'true' if this region is
164     // most nested within a 'try' region, or 'false' if this region is most nested within a handler. (Note
165     // that filters cannot contain nested EH regions.)
166     unsigned ebdGetEnclosingRegionIndex(bool* inTryRegion);
167
168     static bool ebdIsSameTry(EHblkDsc* h1, EHblkDsc* h2); // Same 'try' region? Compare begin/last blocks.
169     bool ebdIsSameTry(Compiler* comp, unsigned t2);
170     bool ebdIsSameTry(BasicBlock* ebdTryBeg, BasicBlock* ebdTryLast);
171
172 #ifdef DEBUG
173     void DispEntry(unsigned num); // Display this table entry
174 #endif                            // DEBUG
175
176 private:
177     static bool InBBRange(BasicBlock* pBlk, BasicBlock* pStart, BasicBlock* pEnd);
178 };
179
180 /*****************************************************************************/
181 #endif // _EH_H_
182 /*****************************************************************************/