Line data Source code
1 : /* Exception Handling interface routines.
2 : Copyright (C) 1996-2026 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 6148844 : ehr_next (eh_region r, eh_region start)
307 : {
308 6148844 : if (r->inner)
309 : r = r->inner;
310 4654324 : else if (r->next_peer && r != start)
311 : r = r->next_peer;
312 : else
313 : {
314 4098456 : do
315 : {
316 4098456 : r = r->outer;
317 4098456 : if (r == start)
318 : return NULL;
319 : }
320 1475975 : 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
|