1 | /* Exception Handling interface routines. |
2 | Copyright (C) 1996-2023 Free Software Foundation, Inc. |
3 | Contributed by Mike Stump <mrs@cygnus.com>. |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free |
9 | Software Foundation; either version 3, or (at your option) any later |
10 | version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ |
20 | |
21 | /* No include guards here, but define an include file marker anyway, so |
22 | that the compiler can keep track of where this file is included. This |
23 | is e.g. used to avoid including this file in front-end specific files. */ |
24 | #ifndef GCC_EXCEPT_H |
25 | #define GCC_EXCEPT_H |
26 | |
27 | |
28 | struct function; |
29 | struct eh_region_d; |
30 | |
31 | /* The type of an exception region. */ |
32 | enum eh_region_type |
33 | { |
34 | /* CLEANUP regions implement e.g. destructors run when exiting a block. |
35 | They can be generated from both GIMPLE_TRY_FINALLY and GIMPLE_TRY_CATCH |
36 | nodes. It is expected by the runtime that cleanup regions will *not* |
37 | resume normal program flow, but will continue propagation of the |
38 | exception. */ |
39 | ERT_CLEANUP, |
40 | |
41 | /* TRY regions implement catching an exception. The list of types associated |
42 | with the attached catch handlers is examined in order by the runtime and |
43 | control is transferred to the appropriate handler. Note that a NULL type |
44 | list is a catch-all handler, and that it will catch *all* exceptions |
45 | including those originating from a different language. */ |
46 | ERT_TRY, |
47 | |
48 | /* ALLOWED_EXCEPTIONS regions implement exception filtering, e.g. the |
49 | throw(type-list) specification that can be added to C++ functions. |
50 | The runtime examines the thrown exception vs the type list, and if |
51 | the exception does not match, transfers control to the handler. The |
52 | normal handler for C++ calls __cxa_call_unexpected. */ |
53 | ERT_ALLOWED_EXCEPTIONS, |
54 | |
55 | /* MUST_NOT_THROW regions prevent all exceptions from propagating. This |
56 | region type is used in C++ to surround destructors being run inside a |
57 | CLEANUP region. This differs from an ALLOWED_EXCEPTIONS region with |
58 | an empty type list in that the runtime is prepared to terminate the |
59 | program directly. We only generate code for MUST_NOT_THROW regions |
60 | along control paths that are already handling an exception within the |
61 | current function. */ |
62 | ERT_MUST_NOT_THROW |
63 | }; |
64 | |
65 | |
66 | /* A landing pad for a given exception region. Any transfer of control |
67 | from the EH runtime to the function happens at a landing pad. */ |
68 | |
69 | struct GTY((chain_next("%h.next_lp" ))) eh_landing_pad_d |
70 | { |
71 | /* The linked list of all landing pads associated with the region. */ |
72 | struct eh_landing_pad_d *next_lp; |
73 | |
74 | /* The region with which this landing pad is associated. */ |
75 | struct eh_region_d *region; |
76 | |
77 | /* At the gimple level, the location to which control will be transferred |
78 | for this landing pad. There can be both EH and normal edges into the |
79 | block containing the post-landing-pad label. */ |
80 | tree post_landing_pad; |
81 | |
82 | /* At the rtl level, the location to which the runtime will transfer |
83 | control. This differs from the post-landing-pad in that the target's |
84 | EXCEPTION_RECEIVER pattern will be expanded here, as well as other |
85 | bookkeeping specific to exceptions. There must not be normal edges |
86 | into the block containing the landing-pad label. */ |
87 | rtx_code_label *landing_pad; |
88 | |
89 | /* The index of this landing pad within fun->eh->lp_array. */ |
90 | int index; |
91 | }; |
92 | |
93 | /* A catch handler associated with an ERT_TRY region. */ |
94 | |
95 | struct GTY(()) eh_catch_d |
96 | { |
97 | /* The double-linked list of all catch handlers for the region. */ |
98 | struct eh_catch_d *next_catch; |
99 | struct eh_catch_d *prev_catch; |
100 | |
101 | /* A TREE_LIST of runtime type objects that this catch handler |
102 | will catch, or NULL if all exceptions are caught. */ |
103 | tree type_list; |
104 | |
105 | /* A TREE_LIST of INTEGER_CSTs that correspond to the type_list entries, |
106 | having been mapped by assign_filter_values. These integers are to be |
107 | compared against the __builtin_eh_filter value. */ |
108 | tree filter_list; |
109 | |
110 | /* The code that should be executed if this catch handler matches the |
111 | thrown exception. This label is only maintained until |
112 | pass_lower_eh_dispatch, at which point it is cleared. */ |
113 | tree label; |
114 | }; |
115 | |
116 | /* Describes one exception region. */ |
117 | |
118 | struct GTY(()) eh_region_d |
119 | { |
120 | /* The immediately surrounding region. */ |
121 | struct eh_region_d *outer; |
122 | |
123 | /* The list of immediately contained regions. */ |
124 | struct eh_region_d *inner; |
125 | struct eh_region_d *next_peer; |
126 | |
127 | /* The index of this region within fun->eh->region_array. */ |
128 | int index; |
129 | |
130 | /* Each region does exactly one thing. */ |
131 | enum eh_region_type type; |
132 | |
133 | /* Holds the action to perform based on the preceding type. */ |
134 | union eh_region_u { |
135 | struct eh_region_u_try { |
136 | /* The double-linked list of all catch handlers for this region. */ |
137 | struct eh_catch_d *first_catch; |
138 | struct eh_catch_d *last_catch; |
139 | } GTY ((tag ("ERT_TRY" ))) eh_try; |
140 | |
141 | struct eh_region_u_allowed { |
142 | /* A TREE_LIST of runtime type objects allowed to pass. */ |
143 | tree type_list; |
144 | /* The code that should be executed if the thrown exception does |
145 | not match the type list. This label is only maintained until |
146 | pass_lower_eh_dispatch, at which point it is cleared. */ |
147 | tree label; |
148 | /* The integer that will be passed by the runtime to signal that |
149 | we should execute the code at LABEL. This integer is assigned |
150 | by assign_filter_values and is to be compared against the |
151 | __builtin_eh_filter value. */ |
152 | int filter; |
153 | } GTY ((tag ("ERT_ALLOWED_EXCEPTIONS" ))) allowed; |
154 | |
155 | struct eh_region_u_must_not_throw { |
156 | /* A function decl to be invoked if this region is actually reachable |
157 | from within the function, rather than implementable from the runtime. |
158 | The normal way for this to happen is for there to be a TRY region |
159 | contained within this MUST_NOT_THROW region. Note that if the |
160 | runtime handles the MUST_NOT_THROW region, we have no control over |
161 | what termination function is called; it will be decided by the |
162 | personality function in effect for this CIE. */ |
163 | tree failure_decl; |
164 | /* The location assigned to the call of FAILURE_DECL, if expanded. */ |
165 | location_t failure_loc; |
166 | } GTY ((tag ("ERT_MUST_NOT_THROW" ))) must_not_throw; |
167 | } GTY ((desc ("%0.type" ))) u; |
168 | |
169 | /* The list of landing pads associated with this region. */ |
170 | struct eh_landing_pad_d *landing_pads; |
171 | |
172 | /* EXC_PTR and FILTER values copied from the runtime for this region. |
173 | Each region gets its own psuedos so that if there are nested exceptions |
174 | we do not overwrite the values of the first exception. */ |
175 | rtx exc_ptr_reg, filter_reg; |
176 | |
177 | /* True if this region should use __cxa_end_cleanup instead |
178 | of _Unwind_Resume. */ |
179 | bool use_cxa_end_cleanup; |
180 | }; |
181 | |
182 | typedef struct eh_landing_pad_d *eh_landing_pad; |
183 | typedef struct eh_catch_d *eh_catch; |
184 | typedef struct eh_region_d *eh_region; |
185 | |
186 | |
187 | |
188 | |
189 | /* The exception status for each function. */ |
190 | |
191 | struct GTY(()) eh_status |
192 | { |
193 | /* The tree of all regions for this function. */ |
194 | eh_region region_tree; |
195 | |
196 | /* The same information as an indexable array. */ |
197 | vec<eh_region, va_gc> *region_array; |
198 | |
199 | /* The landing pads as an indexable array. */ |
200 | vec<eh_landing_pad, va_gc> *lp_array; |
201 | |
202 | /* At the gimple level, a mapping from gimple statement to landing pad |
203 | or must-not-throw region. See record_stmt_eh_region. */ |
204 | hash_map<gimple *, int> *GTY(()) throw_stmt_table; |
205 | |
206 | /* All of the runtime type data used by the function. These objects |
207 | are emitted to the lang-specific-data-area for the function. */ |
208 | vec<tree, va_gc> *ttype_data; |
209 | |
210 | /* The table of all action chains. These encode the eh_region tree in |
211 | a compact form for use by the runtime, and is also emitted to the |
212 | lang-specific-data-area. Note that the ARM EABI uses a different |
213 | format for the encoding than all other ports. */ |
214 | union eh_status_u { |
215 | vec<tree, va_gc> *GTY((tag ("1" ))) arm_eabi; |
216 | vec<uchar, va_gc> *GTY((tag ("0" ))) other; |
217 | } GTY ((desc ("targetm.arm_eabi_unwinder" ))) ehspec_data; |
218 | }; |
219 | |
220 | |
221 | /* Invokes CALLBACK for every exception handler label. Only used by old |
222 | loop hackery; should not be used by new code. */ |
223 | extern void for_each_eh_label (void (*) (rtx)); |
224 | |
225 | extern void init_eh_for_function (void); |
226 | |
227 | extern void remove_eh_landing_pad (eh_landing_pad); |
228 | extern void remove_eh_handler (eh_region); |
229 | extern void remove_unreachable_eh_regions (sbitmap); |
230 | |
231 | extern bool current_function_has_exception_handlers (void); |
232 | extern void output_function_exception_table (int); |
233 | |
234 | extern rtx expand_builtin_eh_pointer (tree); |
235 | extern rtx expand_builtin_eh_filter (tree); |
236 | extern rtx expand_builtin_eh_copy_values (tree); |
237 | extern void expand_builtin_unwind_init (void); |
238 | extern rtx expand_builtin_eh_return_data_regno (tree); |
239 | extern rtx expand_builtin_extract_return_addr (tree); |
240 | extern void expand_builtin_init_dwarf_reg_sizes (tree); |
241 | extern rtx expand_builtin_frob_return_addr (tree); |
242 | extern rtx expand_builtin_dwarf_sp_column (void); |
243 | extern void expand_builtin_eh_return (tree, tree); |
244 | extern void expand_eh_return (void); |
245 | extern rtx expand_builtin_extend_pointer (tree); |
246 | |
247 | typedef tree (*duplicate_eh_regions_map) (tree, void *); |
248 | extern hash_map<void *, void *> *duplicate_eh_regions |
249 | (struct function *, eh_region, int, duplicate_eh_regions_map, void *); |
250 | |
251 | extern void sjlj_emit_function_exit_after (rtx_insn *); |
252 | extern void update_sjlj_context (void); |
253 | |
254 | extern eh_region gen_eh_region_cleanup (eh_region); |
255 | extern eh_region gen_eh_region_try (eh_region); |
256 | extern eh_region gen_eh_region_allowed (eh_region, tree); |
257 | extern eh_region gen_eh_region_must_not_throw (eh_region); |
258 | |
259 | extern eh_catch gen_eh_region_catch (eh_region, tree); |
260 | extern eh_landing_pad gen_eh_landing_pad (eh_region); |
261 | |
262 | extern eh_region get_eh_region_from_number_fn (struct function *, int); |
263 | extern eh_region get_eh_region_from_number (int); |
264 | extern eh_landing_pad get_eh_landing_pad_from_number_fn (struct function*,int); |
265 | extern eh_landing_pad get_eh_landing_pad_from_number (int); |
266 | extern eh_region get_eh_region_from_lp_number_fn (struct function *, int); |
267 | extern eh_region get_eh_region_from_lp_number (int); |
268 | |
269 | extern eh_region eh_region_outermost (struct function *, eh_region, eh_region); |
270 | |
271 | extern void make_reg_eh_region_note (rtx_insn *insn, int ecf_flags, int lp_nr); |
272 | extern void make_reg_eh_region_note_nothrow_nononlocal (rtx_insn *); |
273 | |
274 | extern void verify_eh_tree (struct function *); |
275 | extern void dump_eh_tree (FILE *, struct function *); |
276 | void debug_eh_tree (struct function *); |
277 | extern void add_type_for_runtime (tree); |
278 | extern tree lookup_type_for_runtime (tree); |
279 | extern void assign_filter_values (void); |
280 | |
281 | extern eh_region get_eh_region_from_rtx (const_rtx); |
282 | extern eh_landing_pad get_eh_landing_pad_from_rtx (const_rtx); |
283 | |
284 | extern void finish_eh_generation (void); |
285 | |
286 | struct GTY(()) throw_stmt_node { |
287 | gimple *stmt; |
288 | int lp_nr; |
289 | }; |
290 | |
291 | extern hash_map<gimple *, int> *get_eh_throw_stmt_table (struct function *); |
292 | extern void set_eh_throw_stmt_table (function *, hash_map<gimple *, int> *); |
293 | |
294 | enum eh_personality_kind { |
295 | eh_personality_none, |
296 | eh_personality_any, |
297 | eh_personality_lang |
298 | }; |
299 | |
300 | extern enum eh_personality_kind |
301 | function_needs_eh_personality (struct function *); |
302 | |
303 | /* Pre-order iteration within the eh_region tree. */ |
304 | |
305 | inline eh_region |
306 | ehr_next (eh_region r, eh_region start) |
307 | { |
308 | if (r->inner) |
309 | r = r->inner; |
310 | else if (r->next_peer && r != start) |
311 | r = r->next_peer; |
312 | else |
313 | { |
314 | do |
315 | { |
316 | r = r->outer; |
317 | if (r == start) |
318 | return NULL; |
319 | } |
320 | while (r->next_peer == NULL); |
321 | r = r->next_peer; |
322 | } |
323 | return r; |
324 | } |
325 | |
326 | #define FOR_ALL_EH_REGION_AT(R, START) \ |
327 | for ((R) = (START); (R) != NULL; (R) = ehr_next (R, START)) |
328 | |
329 | #define FOR_ALL_EH_REGION_FN(R, FN) \ |
330 | for ((R) = (FN)->eh->region_tree; (R) != NULL; (R) = ehr_next (R, NULL)) |
331 | |
332 | #define FOR_ALL_EH_REGION(R) FOR_ALL_EH_REGION_FN (R, cfun) |
333 | |
334 | #endif |
335 | |