Branch data Line data Source code
1 : : /* Implements exception handling.
2 : : Copyright (C) 1989-2025 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 : :
22 : : /* An exception is an event that can be "thrown" from within a
23 : : function. This event can then be "caught" by the callers of
24 : : the function.
25 : :
26 : : The representation of exceptions changes several times during
27 : : the compilation process:
28 : :
29 : : In the beginning, in the front end, we have the GENERIC trees
30 : : TRY_CATCH_EXPR, TRY_FINALLY_EXPR, EH_ELSE_EXPR, WITH_CLEANUP_EXPR,
31 : : CLEANUP_POINT_EXPR, CATCH_EXPR, and EH_FILTER_EXPR.
32 : :
33 : : During initial gimplification (gimplify.cc) these are lowered to the
34 : : GIMPLE_TRY, GIMPLE_CATCH, GIMPLE_EH_ELSE, and GIMPLE_EH_FILTER
35 : : nodes. The WITH_CLEANUP_EXPR and CLEANUP_POINT_EXPR nodes are
36 : : converted into GIMPLE_TRY_FINALLY nodes; the others are a more
37 : : direct 1-1 conversion.
38 : :
39 : : During pass_lower_eh (tree-eh.cc) we record the nested structure
40 : : of the TRY nodes in EH_REGION nodes in CFUN->EH->REGION_TREE.
41 : : We expand the eh_protect_cleanup_actions langhook into MUST_NOT_THROW
42 : : regions at this time. We can then flatten the statements within
43 : : the TRY nodes to straight-line code. Statements that had been within
44 : : TRY nodes that can throw are recorded within CFUN->EH->THROW_STMT_TABLE,
45 : : so that we may remember what action is supposed to be taken if
46 : : a given statement does throw. During this lowering process,
47 : : we create an EH_LANDING_PAD node for each EH_REGION that has
48 : : some code within the function that needs to be executed if a
49 : : throw does happen. We also create RESX statements that are
50 : : used to transfer control from an inner EH_REGION to an outer
51 : : EH_REGION. We also create EH_DISPATCH statements as placeholders
52 : : for a runtime type comparison that should be made in order to
53 : : select the action to perform among different CATCH and EH_FILTER
54 : : regions.
55 : :
56 : : During pass_lower_eh_dispatch (tree-eh.cc), which is run after
57 : : all inlining is complete, we are able to run assign_filter_values,
58 : : which allows us to map the set of types manipulated by all of the
59 : : CATCH and EH_FILTER regions to a set of integers. This set of integers
60 : : will be how the exception runtime communicates with the code generated
61 : : within the function. We then expand the GIMPLE_EH_DISPATCH statements
62 : : to a switch or conditional branches that use the argument provided by
63 : : the runtime (__builtin_eh_filter) and the set of integers we computed
64 : : in assign_filter_values.
65 : :
66 : : During pass_lower_resx (tree-eh.cc), which is run near the end
67 : : of optimization, we expand RESX statements. If the eh region
68 : : that is outer to the RESX statement is a MUST_NOT_THROW, then
69 : : the RESX expands to some form of abort statement. If the eh
70 : : region that is outer to the RESX statement is within the current
71 : : function, then the RESX expands to a bookkeeping call
72 : : (__builtin_eh_copy_values) and a goto. Otherwise, the next
73 : : handler for the exception must be within a function somewhere
74 : : up the call chain, so we call back into the exception runtime
75 : : (__builtin_unwind_resume).
76 : :
77 : : During pass_expand (cfgexpand.cc), we generate REG_EH_REGION notes
78 : : that create an rtl to eh_region mapping that corresponds to the
79 : : gimple to eh_region mapping that had been recorded in the
80 : : THROW_STMT_TABLE.
81 : :
82 : : Then, via finish_eh_generation, we generate the real landing pads
83 : : to which the runtime will actually transfer control. These new
84 : : landing pads perform whatever bookkeeping is needed by the target
85 : : backend in order to resume execution within the current function.
86 : : Each of these new landing pads falls through into the post_landing_pad
87 : : label which had been used within the CFG up to this point. All
88 : : exception edges within the CFG are redirected to the new landing pads.
89 : : If the target uses setjmp to implement exceptions, the various extra
90 : : calls into the runtime to register and unregister the current stack
91 : : frame are emitted at this time.
92 : :
93 : : During pass_convert_to_eh_region_ranges (except.cc), we transform
94 : : the REG_EH_REGION notes attached to individual insns into
95 : : non-overlapping ranges of insns bounded by NOTE_INSN_EH_REGION_BEG
96 : : and NOTE_INSN_EH_REGION_END. Each insn within such ranges has the
97 : : same associated action within the exception region tree, meaning
98 : : that (1) the exception is caught by the same landing pad within the
99 : : current function, (2) the exception is blocked by the runtime with
100 : : a MUST_NOT_THROW region, or (3) the exception is not handled at all
101 : : within the current function.
102 : :
103 : : Finally, during assembly generation, we call
104 : : output_function_exception_table (except.cc) to emit the tables with
105 : : which the exception runtime can determine if a given stack frame
106 : : handles a given exception, and if so what filter value to provide
107 : : to the function when the non-local control transfer is effected.
108 : : If the target uses dwarf2 unwinding to implement exceptions, then
109 : : output_call_frame_info (dwarf2out.cc) emits the required unwind data. */
110 : :
111 : :
112 : : #include "config.h"
113 : : #include "system.h"
114 : : #include "coretypes.h"
115 : : #include "backend.h"
116 : : #include "target.h"
117 : : #include "rtl.h"
118 : : #include "tree.h"
119 : : #include "cfghooks.h"
120 : : #include "tree-pass.h"
121 : : #include "memmodel.h"
122 : : #include "tm_p.h"
123 : : #include "stringpool.h"
124 : : #include "expmed.h"
125 : : #include "optabs.h"
126 : : #include "emit-rtl.h"
127 : : #include "cgraph.h"
128 : : #include "diagnostic.h"
129 : : #include "fold-const.h"
130 : : #include "stor-layout.h"
131 : : #include "explow.h"
132 : : #include "stmt.h"
133 : : #include "expr.h"
134 : : #include "calls.h"
135 : : #include "libfuncs.h"
136 : : #include "except.h"
137 : : #include "output.h"
138 : : #include "dwarf2asm.h"
139 : : #include "dwarf2.h"
140 : : #include "common/common-target.h"
141 : : #include "langhooks.h"
142 : : #include "cfgrtl.h"
143 : : #include "tree-pretty-print.h"
144 : : #include "cfgloop.h"
145 : : #include "builtins.h"
146 : : #include "tree-hash-traits.h"
147 : : #include "flags.h"
148 : :
149 : : static GTY(()) int call_site_base;
150 : :
151 : : static GTY(()) hash_map<tree_hash, tree> *type_to_runtime_map;
152 : :
153 : : static GTY(()) tree setjmp_fn;
154 : :
155 : : /* Describe the SjLj_Function_Context structure. */
156 : : static GTY(()) tree sjlj_fc_type_node;
157 : : static int sjlj_fc_call_site_ofs;
158 : : static int sjlj_fc_data_ofs;
159 : : static int sjlj_fc_personality_ofs;
160 : : static int sjlj_fc_lsda_ofs;
161 : : static int sjlj_fc_jbuf_ofs;
162 : :
163 : :
164 : : struct GTY(()) call_site_record_d
165 : : {
166 : : rtx landing_pad;
167 : : int action;
168 : : };
169 : :
170 : : /* In the following structure and associated functions,
171 : : we represent entries in the action table as 1-based indices.
172 : : Special cases are:
173 : :
174 : : 0: null action record, non-null landing pad; implies cleanups
175 : : -1: null action record, null landing pad; implies no action
176 : : -2: no call-site entry; implies must_not_throw
177 : : -3: we have yet to process outer regions
178 : :
179 : : Further, no special cases apply to the "next" field of the record.
180 : : For next, 0 means end of list. */
181 : :
182 : : struct action_record
183 : : {
184 : : int offset;
185 : : int filter;
186 : : int next;
187 : : };
188 : :
189 : : /* Hashtable helpers. */
190 : :
191 : : struct action_record_hasher : free_ptr_hash <action_record>
192 : : {
193 : : static inline hashval_t hash (const action_record *);
194 : : static inline bool equal (const action_record *, const action_record *);
195 : : };
196 : :
197 : : inline hashval_t
198 : 662109 : action_record_hasher::hash (const action_record *entry)
199 : : {
200 : 662109 : return entry->next * 1009 + entry->filter;
201 : : }
202 : :
203 : : inline bool
204 : 331832 : action_record_hasher::equal (const action_record *entry,
205 : : const action_record *data)
206 : : {
207 : 331832 : return entry->filter == data->filter && entry->next == data->next;
208 : : }
209 : :
210 : : typedef hash_table<action_record_hasher> action_hash_type;
211 : :
212 : : static bool get_eh_region_and_lp_from_rtx (const_rtx, eh_region *,
213 : : eh_landing_pad *);
214 : :
215 : : static void dw2_build_landing_pads (void);
216 : :
217 : : static int collect_one_action_chain (action_hash_type *, eh_region);
218 : : static int add_call_site (rtx, int, int);
219 : :
220 : : static void push_uleb128 (vec<uchar, va_gc> **, unsigned int);
221 : : static void push_sleb128 (vec<uchar, va_gc> **, int);
222 : : static int dw2_size_of_call_site_table (int);
223 : : static int sjlj_size_of_call_site_table (void);
224 : : static void dw2_output_call_site_table (int, int);
225 : : static void sjlj_output_call_site_table (void);
226 : :
227 : :
228 : : void
229 : 292728 : init_eh (void)
230 : : {
231 : 292728 : if (! flag_exceptions)
232 : : return;
233 : :
234 : 129281 : type_to_runtime_map = hash_map<tree_hash, tree>::create_ggc (31);
235 : :
236 : : /* Create the SjLj_Function_Context structure. This should match
237 : : the definition in unwind-sjlj.c. */
238 : 129281 : if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ)
239 : : {
240 : 0 : tree f_jbuf, f_per, f_lsda, f_prev, f_cs, f_data, tmp;
241 : :
242 : 0 : sjlj_fc_type_node = lang_hooks.types.make_type (RECORD_TYPE);
243 : :
244 : 0 : f_prev = build_decl (BUILTINS_LOCATION,
245 : : FIELD_DECL, get_identifier ("__prev"),
246 : : build_pointer_type (sjlj_fc_type_node));
247 : 0 : DECL_FIELD_CONTEXT (f_prev) = sjlj_fc_type_node;
248 : :
249 : 0 : f_cs = build_decl (BUILTINS_LOCATION,
250 : : FIELD_DECL, get_identifier ("__call_site"),
251 : : integer_type_node);
252 : 0 : DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
253 : :
254 : 0 : tmp = build_index_type (size_int (4 - 1));
255 : 0 : tmp = build_array_type (lang_hooks.types.type_for_mode
256 : 0 : (targetm.unwind_word_mode (), 1),
257 : : tmp);
258 : 0 : f_data = build_decl (BUILTINS_LOCATION,
259 : : FIELD_DECL, get_identifier ("__data"), tmp);
260 : 0 : DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
261 : :
262 : 0 : f_per = build_decl (BUILTINS_LOCATION,
263 : : FIELD_DECL, get_identifier ("__personality"),
264 : : ptr_type_node);
265 : 0 : DECL_FIELD_CONTEXT (f_per) = sjlj_fc_type_node;
266 : :
267 : 0 : f_lsda = build_decl (BUILTINS_LOCATION,
268 : : FIELD_DECL, get_identifier ("__lsda"),
269 : : ptr_type_node);
270 : 0 : DECL_FIELD_CONTEXT (f_lsda) = sjlj_fc_type_node;
271 : :
272 : : #ifdef DONT_USE_BUILTIN_SETJMP
273 : : #ifdef JMP_BUF_SIZE
274 : : tmp = size_int (JMP_BUF_SIZE - 1);
275 : : #else
276 : : /* Should be large enough for most systems, if it is not,
277 : : JMP_BUF_SIZE should be defined with the proper value. It will
278 : : also tend to be larger than necessary for most systems, a more
279 : : optimal port will define JMP_BUF_SIZE. */
280 : : tmp = size_int (FIRST_PSEUDO_REGISTER + 2 - 1);
281 : : #endif
282 : : #else
283 : : /* Compute a minimally sized jump buffer. We need room to store at
284 : : least 3 pointers - stack pointer, frame pointer and return address.
285 : : Plus for some targets we need room for an extra pointer - in the
286 : : case of MIPS this is the global pointer. This makes a total of four
287 : : pointers, but to be safe we actually allocate room for 5.
288 : :
289 : : If pointers are smaller than words then we allocate enough room for
290 : : 5 words, just in case the backend needs this much room. For more
291 : : discussion on this issue see:
292 : : http://gcc.gnu.org/ml/gcc-patches/2014-05/msg00313.html. */
293 : 0 : if (POINTER_SIZE > BITS_PER_WORD)
294 : 0 : tmp = size_int (5 - 1);
295 : : else
296 : 0 : tmp = size_int ((5 * BITS_PER_WORD / POINTER_SIZE) - 1);
297 : : #endif
298 : :
299 : 0 : tmp = build_index_type (tmp);
300 : 0 : tmp = build_array_type (ptr_type_node, tmp);
301 : 0 : f_jbuf = build_decl (BUILTINS_LOCATION,
302 : : FIELD_DECL, get_identifier ("__jbuf"), tmp);
303 : : #ifdef DONT_USE_BUILTIN_SETJMP
304 : : /* We don't know what the alignment requirements of the
305 : : runtime's jmp_buf has. Overestimate. */
306 : : SET_DECL_ALIGN (f_jbuf, BIGGEST_ALIGNMENT);
307 : : DECL_USER_ALIGN (f_jbuf) = 1;
308 : : #endif
309 : 0 : DECL_FIELD_CONTEXT (f_jbuf) = sjlj_fc_type_node;
310 : :
311 : 0 : TYPE_FIELDS (sjlj_fc_type_node) = f_prev;
312 : 0 : TREE_CHAIN (f_prev) = f_cs;
313 : 0 : TREE_CHAIN (f_cs) = f_data;
314 : 0 : TREE_CHAIN (f_data) = f_per;
315 : 0 : TREE_CHAIN (f_per) = f_lsda;
316 : 0 : TREE_CHAIN (f_lsda) = f_jbuf;
317 : :
318 : 0 : layout_type (sjlj_fc_type_node);
319 : :
320 : : /* Cache the interesting field offsets so that we have
321 : : easy access from rtl. */
322 : 0 : sjlj_fc_call_site_ofs
323 : 0 : = (tree_to_uhwi (DECL_FIELD_OFFSET (f_cs))
324 : 0 : + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_cs)) / BITS_PER_UNIT);
325 : 0 : sjlj_fc_data_ofs
326 : 0 : = (tree_to_uhwi (DECL_FIELD_OFFSET (f_data))
327 : 0 : + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_data)) / BITS_PER_UNIT);
328 : 0 : sjlj_fc_personality_ofs
329 : 0 : = (tree_to_uhwi (DECL_FIELD_OFFSET (f_per))
330 : 0 : + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_per)) / BITS_PER_UNIT);
331 : 0 : sjlj_fc_lsda_ofs
332 : 0 : = (tree_to_uhwi (DECL_FIELD_OFFSET (f_lsda))
333 : 0 : + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_lsda)) / BITS_PER_UNIT);
334 : 0 : sjlj_fc_jbuf_ofs
335 : 0 : = (tree_to_uhwi (DECL_FIELD_OFFSET (f_jbuf))
336 : 0 : + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_jbuf)) / BITS_PER_UNIT);
337 : :
338 : : #ifdef DONT_USE_BUILTIN_SETJMP
339 : : tmp = build_function_type_list (integer_type_node, TREE_TYPE (f_jbuf),
340 : : NULL);
341 : : setjmp_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
342 : : get_identifier ("setjmp"), tmp);
343 : : TREE_PUBLIC (setjmp_fn) = 1;
344 : : DECL_EXTERNAL (setjmp_fn) = 1;
345 : : DECL_ASSEMBLER_NAME (setjmp_fn);
346 : : #endif
347 : : }
348 : : }
349 : :
350 : : void
351 : 171834342 : init_eh_for_function (void)
352 : : {
353 : 171834342 : cfun->eh = ggc_cleared_alloc<eh_status> ();
354 : :
355 : : /* Make sure zero'th entries are used. */
356 : 171834342 : vec_safe_push (cfun->eh->region_array, (eh_region)0);
357 : 171834342 : vec_safe_push (cfun->eh->lp_array, (eh_landing_pad)0);
358 : 171834342 : }
359 : :
360 : : /* Routines to generate the exception tree somewhat directly.
361 : : These are used from tree-eh.cc when processing exception related
362 : : nodes during tree optimization. */
363 : :
364 : : static eh_region
365 : 2494502 : gen_eh_region (enum eh_region_type type, eh_region outer)
366 : : {
367 : 2494502 : eh_region new_eh;
368 : :
369 : : /* Insert a new blank region as a leaf in the tree. */
370 : 2494502 : new_eh = ggc_cleared_alloc<eh_region_d> ();
371 : 2494502 : new_eh->type = type;
372 : 2494502 : new_eh->outer = outer;
373 : 2494502 : if (outer)
374 : : {
375 : 1070159 : new_eh->next_peer = outer->inner;
376 : 1070159 : outer->inner = new_eh;
377 : : }
378 : : else
379 : : {
380 : 1424343 : new_eh->next_peer = cfun->eh->region_tree;
381 : 1424343 : cfun->eh->region_tree = new_eh;
382 : : }
383 : :
384 : 2494502 : new_eh->index = vec_safe_length (cfun->eh->region_array);
385 : 2494502 : vec_safe_push (cfun->eh->region_array, new_eh);
386 : :
387 : : /* Copy the language's notion of whether to use __cxa_end_cleanup. */
388 : 2494502 : if (targetm.arm_eabi_unwinder && lang_hooks.eh_use_cxa_end_cleanup)
389 : 0 : new_eh->use_cxa_end_cleanup = true;
390 : :
391 : 2494502 : return new_eh;
392 : : }
393 : :
394 : : eh_region
395 : 1097373 : gen_eh_region_cleanup (eh_region outer)
396 : : {
397 : 1097373 : return gen_eh_region (ERT_CLEANUP, outer);
398 : : }
399 : :
400 : : eh_region
401 : 44487 : gen_eh_region_try (eh_region outer)
402 : : {
403 : 44487 : return gen_eh_region (ERT_TRY, outer);
404 : : }
405 : :
406 : : eh_catch
407 : 51047 : gen_eh_region_catch (eh_region t, tree type_or_list)
408 : : {
409 : 51047 : eh_catch c, l;
410 : 51047 : tree type_list, type_node;
411 : :
412 : 51047 : gcc_assert (t->type == ERT_TRY);
413 : :
414 : : /* Ensure to always end up with a type list to normalize further
415 : : processing, then register each type against the runtime types map. */
416 : 51047 : type_list = type_or_list;
417 : 51047 : if (type_or_list)
418 : : {
419 : 5821 : if (TREE_CODE (type_or_list) != TREE_LIST)
420 : 5114 : type_list = tree_cons (NULL_TREE, type_or_list, NULL_TREE);
421 : :
422 : 5821 : type_node = type_list;
423 : 11642 : for (; type_node; type_node = TREE_CHAIN (type_node))
424 : 5821 : add_type_for_runtime (TREE_VALUE (type_node));
425 : : }
426 : :
427 : 51047 : c = ggc_cleared_alloc<eh_catch_d> ();
428 : 51047 : c->type_list = type_list;
429 : 51047 : l = t->u.eh_try.last_catch;
430 : 51047 : c->prev_catch = l;
431 : 51047 : if (l)
432 : 2917 : l->next_catch = c;
433 : : else
434 : 48130 : t->u.eh_try.first_catch = c;
435 : 51047 : t->u.eh_try.last_catch = c;
436 : :
437 : 51047 : return c;
438 : : }
439 : :
440 : : eh_region
441 : 4480 : gen_eh_region_allowed (eh_region outer, tree allowed)
442 : : {
443 : 4480 : eh_region region = gen_eh_region (ERT_ALLOWED_EXCEPTIONS, outer);
444 : 4480 : region->u.allowed.type_list = allowed;
445 : :
446 : 4642 : for (; allowed ; allowed = TREE_CHAIN (allowed))
447 : 162 : add_type_for_runtime (TREE_VALUE (allowed));
448 : :
449 : 4480 : return region;
450 : : }
451 : :
452 : : eh_region
453 : 1125759 : gen_eh_region_must_not_throw (eh_region outer)
454 : : {
455 : 1125759 : return gen_eh_region (ERT_MUST_NOT_THROW, outer);
456 : : }
457 : :
458 : : eh_landing_pad
459 : 1790523 : gen_eh_landing_pad (eh_region region)
460 : : {
461 : 1790523 : eh_landing_pad lp = ggc_cleared_alloc<eh_landing_pad_d> ();
462 : :
463 : 1790523 : lp->next_lp = region->landing_pads;
464 : 1790523 : lp->region = region;
465 : 1790523 : lp->index = vec_safe_length (cfun->eh->lp_array);
466 : 1790523 : region->landing_pads = lp;
467 : :
468 : 1790523 : vec_safe_push (cfun->eh->lp_array, lp);
469 : :
470 : 1790523 : return lp;
471 : : }
472 : :
473 : : eh_region
474 : 2188566 : get_eh_region_from_number_fn (struct function *ifun, int i)
475 : : {
476 : 2188566 : return (*ifun->eh->region_array)[i];
477 : : }
478 : :
479 : : eh_region
480 : 2093760 : get_eh_region_from_number (int i)
481 : : {
482 : 2093760 : return get_eh_region_from_number_fn (cfun, i);
483 : : }
484 : :
485 : : eh_landing_pad
486 : 278966942 : get_eh_landing_pad_from_number_fn (struct function *ifun, int i)
487 : : {
488 : 278966942 : return (*ifun->eh->lp_array)[i];
489 : : }
490 : :
491 : : eh_landing_pad
492 : 278966942 : get_eh_landing_pad_from_number (int i)
493 : : {
494 : 278966942 : return get_eh_landing_pad_from_number_fn (cfun, i);
495 : : }
496 : :
497 : : eh_region
498 : 10666441 : get_eh_region_from_lp_number_fn (struct function *ifun, int i)
499 : : {
500 : 10666441 : if (i < 0)
501 : 50206 : return (*ifun->eh->region_array)[-i];
502 : 10616235 : else if (i == 0)
503 : : return NULL;
504 : : else
505 : : {
506 : 4802496 : eh_landing_pad lp;
507 : 4802496 : lp = (*ifun->eh->lp_array)[i];
508 : 4802496 : return lp->region;
509 : : }
510 : : }
511 : :
512 : : eh_region
513 : 4708029 : get_eh_region_from_lp_number (int i)
514 : : {
515 : 4708029 : return get_eh_region_from_lp_number_fn (cfun, i);
516 : : }
517 : :
518 : : /* Returns true if the current function has exception handling regions. */
519 : :
520 : : bool
521 : 178 : current_function_has_exception_handlers (void)
522 : : {
523 : 178 : return cfun->eh->region_tree != NULL;
524 : : }
525 : :
526 : : /* A subroutine of duplicate_eh_regions. Copy the eh_region tree at OLD.
527 : : Root it at OUTER, and apply LP_OFFSET to the lp numbers. */
528 : :
529 : : struct duplicate_eh_regions_data
530 : : {
531 : : duplicate_eh_regions_map label_map;
532 : : void *label_map_data;
533 : : hash_map<void *, void *> *eh_map;
534 : : };
535 : :
536 : : static void
537 : 222403 : duplicate_eh_regions_1 (struct duplicate_eh_regions_data *data,
538 : : eh_region old_r, eh_region outer)
539 : : {
540 : 222403 : eh_landing_pad old_lp, new_lp;
541 : 222403 : eh_region new_r;
542 : :
543 : 222403 : new_r = gen_eh_region (old_r->type, outer);
544 : 222403 : bool existed = data->eh_map->put (old_r, new_r);
545 : 222403 : gcc_assert (!existed);
546 : :
547 : 222403 : switch (old_r->type)
548 : : {
549 : : case ERT_CLEANUP:
550 : : break;
551 : :
552 : 7870 : case ERT_TRY:
553 : 7870 : {
554 : 7870 : eh_catch oc, nc;
555 : 15993 : for (oc = old_r->u.eh_try.first_catch; oc ; oc = oc->next_catch)
556 : : {
557 : : /* We should be doing all our region duplication before and
558 : : during inlining, which is before filter lists are created. */
559 : 8123 : gcc_assert (oc->filter_list == NULL);
560 : 8123 : nc = gen_eh_region_catch (new_r, oc->type_list);
561 : 8123 : nc->label = data->label_map (oc->label, data->label_map_data);
562 : : }
563 : : }
564 : : break;
565 : :
566 : 1077 : case ERT_ALLOWED_EXCEPTIONS:
567 : 1077 : new_r->u.allowed.type_list = old_r->u.allowed.type_list;
568 : 1077 : if (old_r->u.allowed.label)
569 : 163 : new_r->u.allowed.label
570 : 163 : = data->label_map (old_r->u.allowed.label, data->label_map_data);
571 : : else
572 : 914 : new_r->u.allowed.label = NULL_TREE;
573 : : break;
574 : :
575 : 132952 : case ERT_MUST_NOT_THROW:
576 : 265904 : new_r->u.must_not_throw.failure_loc =
577 : 132952 : LOCATION_LOCUS (old_r->u.must_not_throw.failure_loc);
578 : 132952 : new_r->u.must_not_throw.failure_decl =
579 : 132952 : old_r->u.must_not_throw.failure_decl;
580 : 132952 : break;
581 : : }
582 : :
583 : 312218 : for (old_lp = old_r->landing_pads; old_lp ; old_lp = old_lp->next_lp)
584 : : {
585 : : /* Don't bother copying unused landing pads. */
586 : 89815 : if (old_lp->post_landing_pad == NULL)
587 : 1346 : continue;
588 : :
589 : 88469 : new_lp = gen_eh_landing_pad (new_r);
590 : 88469 : bool existed = data->eh_map->put (old_lp, new_lp);
591 : 88469 : gcc_assert (!existed);
592 : :
593 : 88469 : new_lp->post_landing_pad
594 : 88469 : = data->label_map (old_lp->post_landing_pad, data->label_map_data);
595 : 88469 : EH_LANDING_PAD_NR (new_lp->post_landing_pad) = new_lp->index;
596 : : }
597 : :
598 : : /* Make sure to preserve the original use of __cxa_end_cleanup. */
599 : 222403 : new_r->use_cxa_end_cleanup = old_r->use_cxa_end_cleanup;
600 : :
601 : 249254 : for (old_r = old_r->inner; old_r ; old_r = old_r->next_peer)
602 : 26851 : duplicate_eh_regions_1 (data, old_r, new_r);
603 : 222403 : }
604 : :
605 : : /* Duplicate the EH regions from IFUN rooted at COPY_REGION into
606 : : the current function and root the tree below OUTER_REGION.
607 : : The special case of COPY_REGION of NULL means all regions.
608 : : Remap labels using MAP/MAP_DATA callback. Return a pointer map
609 : : that allows the caller to remap uses of both EH regions and
610 : : EH landing pads. */
611 : :
612 : : hash_map<void *, void *> *
613 : 3961974 : duplicate_eh_regions (struct function *ifun,
614 : : eh_region copy_region, int outer_lp,
615 : : duplicate_eh_regions_map map, void *map_data)
616 : : {
617 : 3961974 : struct duplicate_eh_regions_data data;
618 : 3961974 : eh_region outer_region;
619 : :
620 : 3961974 : if (flag_checking)
621 : 3961962 : verify_eh_tree (ifun);
622 : :
623 : 3961974 : data.label_map = map;
624 : 3961974 : data.label_map_data = map_data;
625 : 3961974 : data.eh_map = new hash_map<void *, void *>;
626 : :
627 : 3961974 : outer_region = get_eh_region_from_lp_number_fn (cfun, outer_lp);
628 : :
629 : : /* Copy all the regions in the subtree. */
630 : 3961974 : if (copy_region)
631 : 1857 : duplicate_eh_regions_1 (&data, copy_region, outer_region);
632 : : else
633 : : {
634 : 3960117 : eh_region r;
635 : 4153812 : for (r = ifun->eh->region_tree; r ; r = r->next_peer)
636 : 193695 : duplicate_eh_regions_1 (&data, r, outer_region);
637 : : }
638 : :
639 : 3961974 : if (flag_checking)
640 : 3961962 : verify_eh_tree (cfun);
641 : :
642 : 3961974 : return data.eh_map;
643 : : }
644 : :
645 : : /* Return the region that is outer to both REGION_A and REGION_B in IFUN. */
646 : :
647 : : eh_region
648 : 241 : eh_region_outermost (struct function *ifun, eh_region region_a,
649 : : eh_region region_b)
650 : : {
651 : 241 : gcc_assert (ifun->eh->region_array);
652 : 241 : gcc_assert (ifun->eh->region_tree);
653 : :
654 : 241 : auto_sbitmap b_outer (ifun->eh->region_array->length ());
655 : 241 : bitmap_clear (b_outer);
656 : :
657 : 581 : do
658 : : {
659 : 581 : bitmap_set_bit (b_outer, region_b->index);
660 : 581 : region_b = region_b->outer;
661 : : }
662 : 581 : while (region_b);
663 : :
664 : 481 : do
665 : : {
666 : 481 : if (bitmap_bit_p (b_outer, region_a->index))
667 : : break;
668 : 241 : region_a = region_a->outer;
669 : : }
670 : 241 : while (region_a);
671 : :
672 : 241 : return region_a;
673 : 241 : }
674 : :
675 : : void
676 : 5985 : add_type_for_runtime (tree type)
677 : : {
678 : : /* If TYPE is NOP_EXPR, it means that it already is a runtime type. */
679 : 5985 : if (TREE_CODE (type) == NOP_EXPR)
680 : 10 : return;
681 : :
682 : 5975 : bool existed = false;
683 : 5975 : tree *slot = &type_to_runtime_map->get_or_insert (type, &existed);
684 : 5975 : if (!existed)
685 : 2585 : *slot = lang_hooks.eh_runtime_type (type);
686 : : }
687 : :
688 : : tree
689 : 25636 : lookup_type_for_runtime (tree type)
690 : : {
691 : : /* If TYPE is NOP_EXPR, it means that it already is a runtime type. */
692 : 25636 : if (TREE_CODE (type) == NOP_EXPR)
693 : : return type;
694 : :
695 : : /* We should have always inserted the data earlier. */
696 : 25636 : return *type_to_runtime_map->get (type);
697 : : }
698 : :
699 : :
700 : : /* Represent an entry in @TTypes for either catch actions
701 : : or exception filter actions. */
702 : : struct ttypes_filter {
703 : : tree t;
704 : : int filter;
705 : : };
706 : :
707 : : /* Helper for ttypes_filter hashing. */
708 : :
709 : : struct ttypes_filter_hasher : free_ptr_hash <ttypes_filter>
710 : : {
711 : : typedef tree_node *compare_type;
712 : : static inline hashval_t hash (const ttypes_filter *);
713 : : static inline bool equal (const ttypes_filter *, const tree_node *);
714 : : };
715 : :
716 : : /* Compare ENTRY (a ttypes_filter entry in the hash table) with DATA
717 : : (a tree) for a @TTypes type node we are thinking about adding. */
718 : :
719 : : inline bool
720 : 21680 : ttypes_filter_hasher::equal (const ttypes_filter *entry, const tree_node *data)
721 : : {
722 : 21680 : return entry->t == data;
723 : : }
724 : :
725 : : inline hashval_t
726 : 24701 : ttypes_filter_hasher::hash (const ttypes_filter *entry)
727 : : {
728 : 24701 : return TREE_HASH (entry->t);
729 : : }
730 : :
731 : : typedef hash_table<ttypes_filter_hasher> ttypes_hash_type;
732 : :
733 : :
734 : : /* Helper for ehspec hashing. */
735 : :
736 : : struct ehspec_hasher : free_ptr_hash <ttypes_filter>
737 : : {
738 : : static inline hashval_t hash (const ttypes_filter *);
739 : : static inline bool equal (const ttypes_filter *, const ttypes_filter *);
740 : : };
741 : :
742 : : /* Compare ENTRY with DATA (both struct ttypes_filter) for a @TTypes
743 : : exception specification list we are thinking about adding. */
744 : : /* ??? Currently we use the type lists in the order given. Someone
745 : : should put these in some canonical order. */
746 : :
747 : : inline bool
748 : 514 : ehspec_hasher::equal (const ttypes_filter *entry, const ttypes_filter *data)
749 : : {
750 : 514 : return type_list_equal (entry->t, data->t);
751 : : }
752 : :
753 : : /* Hash function for exception specification lists. */
754 : :
755 : : inline hashval_t
756 : 1760 : ehspec_hasher::hash (const ttypes_filter *entry)
757 : : {
758 : 1760 : hashval_t h = 0;
759 : 1760 : tree list;
760 : :
761 : 1895 : for (list = entry->t; list ; list = TREE_CHAIN (list))
762 : 135 : h = (h << 5) + (h >> 27) + TREE_HASH (TREE_VALUE (list));
763 : 1760 : return h;
764 : : }
765 : :
766 : : typedef hash_table<ehspec_hasher> ehspec_hash_type;
767 : :
768 : :
769 : : /* Add TYPE (which may be NULL) to cfun->eh->ttype_data, using TYPES_HASH
770 : : to speed up the search. Return the filter value to be used. */
771 : :
772 : : static int
773 : 42497 : add_ttypes_entry (ttypes_hash_type *ttypes_hash, tree type)
774 : : {
775 : 42497 : struct ttypes_filter **slot, *n;
776 : :
777 : 42497 : slot = ttypes_hash->find_slot_with_hash (type, (hashval_t) TREE_HASH (type),
778 : : INSERT);
779 : :
780 : 42497 : if ((n = *slot) == NULL)
781 : : {
782 : : /* Filter value is a 1 based table index. */
783 : :
784 : 21134 : n = XNEW (struct ttypes_filter);
785 : 21134 : n->t = type;
786 : 21134 : n->filter = vec_safe_length (cfun->eh->ttype_data) + 1;
787 : 21134 : *slot = n;
788 : :
789 : 21134 : vec_safe_push (cfun->eh->ttype_data, type);
790 : : }
791 : :
792 : 42497 : return n->filter;
793 : : }
794 : :
795 : : /* Add LIST to cfun->eh->ehspec_data, using EHSPEC_HASH and TYPES_HASH
796 : : to speed up the search. Return the filter value to be used. */
797 : :
798 : : static int
799 : 1258 : add_ehspec_entry (ehspec_hash_type *ehspec_hash, ttypes_hash_type *ttypes_hash,
800 : : tree list)
801 : : {
802 : 1258 : struct ttypes_filter **slot, *n;
803 : 1258 : struct ttypes_filter dummy;
804 : :
805 : 1258 : dummy.t = list;
806 : 1258 : slot = ehspec_hash->find_slot (&dummy, INSERT);
807 : :
808 : 1258 : if ((n = *slot) == NULL)
809 : : {
810 : 744 : int len;
811 : :
812 : 744 : if (targetm.arm_eabi_unwinder)
813 : 0 : len = vec_safe_length (cfun->eh->ehspec_data.arm_eabi);
814 : : else
815 : 1488 : len = vec_safe_length (cfun->eh->ehspec_data.other);
816 : :
817 : : /* Filter value is a -1 based byte index into a uleb128 buffer. */
818 : :
819 : 744 : n = XNEW (struct ttypes_filter);
820 : 744 : n->t = list;
821 : 744 : n->filter = -(len + 1);
822 : 744 : *slot = n;
823 : :
824 : : /* Generate a 0 terminated list of filter values. */
825 : 867 : for (; list ; list = TREE_CHAIN (list))
826 : : {
827 : 123 : if (targetm.arm_eabi_unwinder)
828 : 0 : vec_safe_push (cfun->eh->ehspec_data.arm_eabi, TREE_VALUE (list));
829 : : else
830 : : {
831 : : /* Look up each type in the list and encode its filter
832 : : value as a uleb128. */
833 : 246 : push_uleb128 (&cfun->eh->ehspec_data.other,
834 : 123 : add_ttypes_entry (ttypes_hash, TREE_VALUE (list)));
835 : : }
836 : : }
837 : 744 : if (targetm.arm_eabi_unwinder)
838 : 0 : vec_safe_push (cfun->eh->ehspec_data.arm_eabi, NULL_TREE);
839 : : else
840 : 744 : vec_safe_push (cfun->eh->ehspec_data.other, (uchar)0);
841 : : }
842 : :
843 : 1258 : return n->filter;
844 : : }
845 : :
846 : : /* Generate the action filter values to be used for CATCH and
847 : : ALLOWED_EXCEPTIONS regions. When using dwarf2 exception regions,
848 : : we use lots of landing pads, and so every type or list can share
849 : : the same filter value, which saves table space. */
850 : :
851 : : void
852 : 138121 : assign_filter_values (void)
853 : : {
854 : 138121 : int i;
855 : 138121 : eh_region r;
856 : 138121 : eh_catch c;
857 : :
858 : 138121 : vec_alloc (cfun->eh->ttype_data, 16);
859 : 138121 : if (targetm.arm_eabi_unwinder)
860 : 0 : vec_alloc (cfun->eh->ehspec_data.arm_eabi, 64);
861 : : else
862 : 138121 : vec_alloc (cfun->eh->ehspec_data.other, 64);
863 : :
864 : 138121 : ehspec_hash_type ehspec (31);
865 : 138121 : ttypes_hash_type ttypes (31);
866 : :
867 : 1078564 : for (i = 1; vec_safe_iterate (cfun->eh->region_array, i, &r); ++i)
868 : : {
869 : 940443 : if (r == NULL)
870 : 507277 : continue;
871 : :
872 : 433166 : switch (r->type)
873 : : {
874 : 40638 : case ERT_TRY:
875 : 83012 : for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
876 : : {
877 : : /* Whatever type_list is (NULL or true list), we build a list
878 : : of filters for the region. */
879 : 42374 : c->filter_list = NULL_TREE;
880 : :
881 : 42374 : if (c->type_list != NULL)
882 : : {
883 : : /* Get a filter value for each of the types caught and store
884 : : them in the region's dedicated list. */
885 : : tree tp_node = c->type_list;
886 : :
887 : 10096 : for ( ; tp_node; tp_node = TREE_CHAIN (tp_node))
888 : : {
889 : 5048 : int flt
890 : 5048 : = add_ttypes_entry (&ttypes, TREE_VALUE (tp_node));
891 : 5048 : tree flt_node = build_int_cst (integer_type_node, flt);
892 : :
893 : 5048 : c->filter_list
894 : 5048 : = tree_cons (NULL_TREE, flt_node, c->filter_list);
895 : : }
896 : : }
897 : : else
898 : : {
899 : : /* Get a filter value for the NULL list also since it
900 : : will need an action record anyway. */
901 : 37326 : int flt = add_ttypes_entry (&ttypes, NULL);
902 : 37326 : tree flt_node = build_int_cst (integer_type_node, flt);
903 : :
904 : 37326 : c->filter_list
905 : 37326 : = tree_cons (NULL_TREE, flt_node, NULL);
906 : : }
907 : : }
908 : : break;
909 : :
910 : 1258 : case ERT_ALLOWED_EXCEPTIONS:
911 : 1258 : r->u.allowed.filter
912 : 1258 : = add_ehspec_entry (&ehspec, &ttypes, r->u.allowed.type_list);
913 : 1258 : break;
914 : :
915 : : default:
916 : : break;
917 : : }
918 : : }
919 : 138121 : }
920 : :
921 : : /* Emit SEQ into basic block just before INSN (that is assumed to be
922 : : first instruction of some existing BB and return the newly
923 : : produced block. */
924 : : static basic_block
925 : 208024 : emit_to_new_bb_before (rtx_insn *seq, rtx_insn *insn)
926 : : {
927 : 208024 : rtx_insn *next, *last;
928 : 208024 : basic_block bb;
929 : 208024 : edge e;
930 : 208024 : edge_iterator ei;
931 : :
932 : : /* If there happens to be a fallthru edge (possibly created by cleanup_cfg
933 : : call), we don't want it to go into newly created landing pad or other EH
934 : : construct. */
935 : 1056931 : for (ei = ei_start (BLOCK_FOR_INSN (insn)->preds); (e = ei_safe_edge (ei)); )
936 : 848907 : if (e->flags & EDGE_FALLTHRU)
937 : 57950 : force_nonfallthru (e);
938 : : else
939 : 790957 : ei_next (&ei);
940 : :
941 : : /* Make sure to put the location of INSN or a subsequent instruction on SEQ
942 : : to avoid inheriting the location of the previous instruction. */
943 : : next = insn;
944 : 982319 : while (next && !NONDEBUG_INSN_P (next))
945 : 774295 : next = NEXT_INSN (next);
946 : 208024 : if (next)
947 : 208016 : last = emit_insn_before_setloc (seq, insn, INSN_LOCATION (next));
948 : : else
949 : 8 : last = emit_insn_before (seq, insn);
950 : 208024 : if (BARRIER_P (last))
951 : 0 : last = PREV_INSN (last);
952 : 208024 : bb = create_basic_block (seq, last, BLOCK_FOR_INSN (insn)->prev_bb);
953 : 208024 : update_bb_for_insn (bb);
954 : 208024 : bb->flags |= BB_SUPERBLOCK;
955 : 208024 : return bb;
956 : : }
957 : :
958 : : /* A subroutine of dw2_build_landing_pads, also used for edge splitting
959 : : at the rtl level. Emit the code required by the target at a landing
960 : : pad for the given region. */
961 : :
962 : : static void
963 : 208024 : expand_dw2_landing_pad_for_region (eh_region region)
964 : : {
965 : 208024 : if (targetm.have_exception_receiver ())
966 : 0 : emit_insn (targetm.gen_exception_receiver ());
967 : 208024 : else if (targetm.have_nonlocal_goto_receiver ())
968 : 0 : emit_insn (targetm.gen_nonlocal_goto_receiver ());
969 : : else
970 : : { /* Nothing */ }
971 : :
972 : 208024 : if (region->exc_ptr_reg)
973 : 177151 : emit_move_insn (region->exc_ptr_reg,
974 : : gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
975 : 208024 : if (region->filter_reg)
976 : 116377 : emit_move_insn (region->filter_reg,
977 : 232754 : gen_rtx_REG (targetm.eh_return_filter_mode (),
978 : : EH_RETURN_DATA_REGNO (1)));
979 : 208024 : }
980 : :
981 : : /* Expand the extra code needed at landing pads for dwarf2 unwinding. */
982 : :
983 : : static void
984 : 57984 : dw2_build_landing_pads (void)
985 : : {
986 : 57984 : int i;
987 : 57984 : eh_landing_pad lp;
988 : 57984 : int e_flags = EDGE_FALLTHRU;
989 : :
990 : : /* If we're going to partition blocks, we need to be able to add
991 : : new landing pads later, which means that we need to hold on to
992 : : the post-landing-pad block. Prevent it from being merged away.
993 : : We'll remove this bit after partitioning. */
994 : 57984 : if (flag_reorder_blocks_and_partition)
995 : 38047 : e_flags |= EDGE_PRESERVE;
996 : :
997 : 1222652 : for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
998 : : {
999 : 1164668 : basic_block bb;
1000 : 1164668 : rtx_insn *seq;
1001 : :
1002 : 1164668 : if (lp == NULL || lp->post_landing_pad == NULL)
1003 : 956644 : continue;
1004 : :
1005 : 208024 : start_sequence ();
1006 : :
1007 : 208024 : lp->landing_pad = gen_label_rtx ();
1008 : 208024 : emit_label (lp->landing_pad);
1009 : 208024 : LABEL_PRESERVE_P (lp->landing_pad) = 1;
1010 : :
1011 : 208024 : expand_dw2_landing_pad_for_region (lp->region);
1012 : :
1013 : 208024 : seq = get_insns ();
1014 : 208024 : end_sequence ();
1015 : :
1016 : 208024 : bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad));
1017 : 208024 : bb->count = bb->next_bb->count;
1018 : 208024 : make_single_succ_edge (bb, bb->next_bb, e_flags);
1019 : 208024 : if (current_loops)
1020 : : {
1021 : 208024 : class loop *loop = bb->next_bb->loop_father;
1022 : : /* If we created a pre-header block, add the new block to the
1023 : : outer loop, otherwise to the loop itself. */
1024 : 208024 : if (bb->next_bb == loop->header)
1025 : 8402 : add_bb_to_loop (bb, loop_outer (loop));
1026 : : else
1027 : 199622 : add_bb_to_loop (bb, loop);
1028 : : }
1029 : : }
1030 : 57984 : }
1031 : :
1032 : :
1033 : : static vec<int> sjlj_lp_call_site_index;
1034 : :
1035 : : /* Process all active landing pads. Assign each one a compact dispatch
1036 : : index, and a call-site index. */
1037 : :
1038 : : static int
1039 : 0 : sjlj_assign_call_site_values (void)
1040 : : {
1041 : 0 : action_hash_type ar_hash (31);
1042 : 0 : int i, disp_index;
1043 : 0 : eh_landing_pad lp;
1044 : :
1045 : 0 : vec_alloc (crtl->eh.action_record_data, 64);
1046 : :
1047 : 0 : disp_index = 0;
1048 : 0 : call_site_base = 1;
1049 : 0 : for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
1050 : 0 : if (lp && lp->post_landing_pad)
1051 : : {
1052 : 0 : int action, call_site;
1053 : :
1054 : : /* First: build the action table. */
1055 : 0 : action = collect_one_action_chain (&ar_hash, lp->region);
1056 : :
1057 : : /* Next: assign call-site values. If dwarf2 terms, this would be
1058 : : the region number assigned by convert_to_eh_region_ranges, but
1059 : : handles no-action and must-not-throw differently. */
1060 : : /* Map must-not-throw to otherwise unused call-site index 0. */
1061 : 0 : if (action == -2)
1062 : : call_site = 0;
1063 : : /* Map no-action to otherwise unused call-site index -1. */
1064 : 0 : else if (action == -1)
1065 : : call_site = -1;
1066 : : /* Otherwise, look it up in the table. */
1067 : : else
1068 : 0 : call_site = add_call_site (GEN_INT (disp_index), action, 0);
1069 : 0 : sjlj_lp_call_site_index[i] = call_site;
1070 : :
1071 : 0 : disp_index++;
1072 : : }
1073 : :
1074 : 0 : return disp_index;
1075 : 0 : }
1076 : :
1077 : : /* Emit code to record the current call-site index before every
1078 : : insn that can throw. */
1079 : :
1080 : : static void
1081 : 0 : sjlj_mark_call_sites (void)
1082 : : {
1083 : 0 : int last_call_site = -2;
1084 : 0 : rtx_insn *insn;
1085 : 0 : rtx mem;
1086 : :
1087 : 0 : for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
1088 : : {
1089 : 0 : eh_landing_pad lp;
1090 : 0 : eh_region r;
1091 : 0 : bool nothrow;
1092 : 0 : int this_call_site;
1093 : 0 : rtx_insn *before, *p;
1094 : :
1095 : : /* Reset value tracking at extended basic block boundaries. */
1096 : 0 : if (LABEL_P (insn))
1097 : 0 : last_call_site = -2;
1098 : :
1099 : : /* If the function allocates dynamic stack space, the context must
1100 : : be updated after every allocation/deallocation accordingly. */
1101 : 0 : if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_UPDATE_SJLJ_CONTEXT)
1102 : : {
1103 : 0 : rtx buf_addr;
1104 : :
1105 : 0 : start_sequence ();
1106 : 0 : buf_addr = plus_constant (Pmode, XEXP (crtl->eh.sjlj_fc, 0),
1107 : : sjlj_fc_jbuf_ofs);
1108 : 0 : expand_builtin_update_setjmp_buf (buf_addr);
1109 : 0 : p = get_insns ();
1110 : 0 : end_sequence ();
1111 : 0 : emit_insn_before (p, insn);
1112 : : }
1113 : :
1114 : 0 : if (! INSN_P (insn))
1115 : 0 : continue;
1116 : :
1117 : 0 : nothrow = get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1118 : 0 : if (nothrow)
1119 : 0 : continue;
1120 : 0 : if (lp)
1121 : 0 : this_call_site = sjlj_lp_call_site_index[lp->index];
1122 : 0 : else if (r == NULL)
1123 : : {
1124 : : /* Calls (and trapping insns) without notes are outside any
1125 : : exception handling region in this function. Mark them as
1126 : : no action. */
1127 : : this_call_site = -1;
1128 : : }
1129 : : else
1130 : : {
1131 : 0 : gcc_assert (r->type == ERT_MUST_NOT_THROW);
1132 : : this_call_site = 0;
1133 : : }
1134 : :
1135 : 0 : if (this_call_site != -1)
1136 : 0 : crtl->uses_eh_lsda = 1;
1137 : :
1138 : 0 : if (this_call_site == last_call_site)
1139 : 0 : continue;
1140 : :
1141 : : /* Don't separate a call from it's argument loads. */
1142 : 0 : before = insn;
1143 : 0 : if (CALL_P (insn))
1144 : 0 : before = find_first_parameter_load (insn, NULL);
1145 : :
1146 : 0 : start_sequence ();
1147 : 0 : mem = adjust_address (crtl->eh.sjlj_fc, TYPE_MODE (integer_type_node),
1148 : : sjlj_fc_call_site_ofs);
1149 : 0 : emit_move_insn (mem, gen_int_mode (this_call_site, GET_MODE (mem)));
1150 : 0 : p = get_insns ();
1151 : 0 : end_sequence ();
1152 : :
1153 : 0 : emit_insn_before (p, before);
1154 : 0 : last_call_site = this_call_site;
1155 : : }
1156 : 0 : }
1157 : :
1158 : : /* Construct the SjLj_Function_Context. */
1159 : :
1160 : : static void
1161 : 0 : sjlj_emit_function_enter (rtx_code_label *dispatch_label)
1162 : : {
1163 : 0 : rtx_insn *fn_begin, *seq;
1164 : 0 : rtx fc, mem;
1165 : 0 : bool fn_begin_outside_block;
1166 : 0 : rtx personality = get_personality_function (current_function_decl);
1167 : :
1168 : 0 : fc = crtl->eh.sjlj_fc;
1169 : :
1170 : 0 : start_sequence ();
1171 : :
1172 : : /* We're storing this libcall's address into memory instead of
1173 : : calling it directly. Thus, we must call assemble_external_libcall
1174 : : here, as we cannot depend on emit_library_call to do it for us. */
1175 : 0 : assemble_external_libcall (personality);
1176 : 0 : mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
1177 : 0 : emit_move_insn (mem, personality);
1178 : :
1179 : 0 : mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
1180 : 0 : if (crtl->uses_eh_lsda)
1181 : : {
1182 : 0 : char buf[20];
1183 : 0 : rtx sym;
1184 : :
1185 : 0 : ASM_GENERATE_INTERNAL_LABEL (buf, "LLSDA", current_function_funcdef_no);
1186 : 0 : sym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
1187 : 0 : SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_LOCAL;
1188 : 0 : emit_move_insn (mem, sym);
1189 : : }
1190 : : else
1191 : 0 : emit_move_insn (mem, const0_rtx);
1192 : :
1193 : 0 : if (dispatch_label)
1194 : : {
1195 : 0 : rtx addr = plus_constant (Pmode, XEXP (fc, 0), sjlj_fc_jbuf_ofs);
1196 : :
1197 : : #ifdef DONT_USE_BUILTIN_SETJMP
1198 : : addr = copy_addr_to_reg (addr);
1199 : : addr = convert_memory_address (ptr_mode, addr);
1200 : : tree addr_tree = make_tree (ptr_type_node, addr);
1201 : :
1202 : : tree call_expr = build_call_expr (setjmp_fn, 1, addr_tree);
1203 : : rtx x = expand_call (call_expr, NULL_RTX, false);
1204 : :
1205 : : emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
1206 : : TYPE_MODE (integer_type_node), 0,
1207 : : dispatch_label,
1208 : : profile_probability::unlikely ());
1209 : : #else
1210 : 0 : expand_builtin_setjmp_setup (addr, dispatch_label);
1211 : : #endif
1212 : : }
1213 : :
1214 : 0 : emit_library_call (unwind_sjlj_register_libfunc, LCT_NORMAL, VOIDmode,
1215 : 0 : XEXP (fc, 0), Pmode);
1216 : :
1217 : 0 : seq = get_insns ();
1218 : 0 : end_sequence ();
1219 : :
1220 : : /* ??? Instead of doing this at the beginning of the function,
1221 : : do this in a block that is at loop level 0 and dominates all
1222 : : can_throw_internal instructions. */
1223 : :
1224 : 0 : fn_begin_outside_block = true;
1225 : 0 : for (fn_begin = get_insns (); ; fn_begin = NEXT_INSN (fn_begin))
1226 : 0 : if (NOTE_P (fn_begin))
1227 : : {
1228 : 0 : if (NOTE_KIND (fn_begin) == NOTE_INSN_FUNCTION_BEG)
1229 : : break;
1230 : 0 : else if (NOTE_INSN_BASIC_BLOCK_P (fn_begin))
1231 : 0 : fn_begin_outside_block = false;
1232 : : }
1233 : : /* assign_params can indirectly call emit_block_move_via_loop, e.g.
1234 : : for g++.dg/torture/pr85627.C for 16-bit targets. */
1235 : 0 : else if (JUMP_P (fn_begin))
1236 : 0 : fn_begin_outside_block = true;
1237 : :
1238 : : #ifdef DONT_USE_BUILTIN_SETJMP
1239 : : if (dispatch_label)
1240 : : {
1241 : : /* The sequence contains a branch in the middle so we need to force
1242 : : the creation of a new basic block by means of BB_SUPERBLOCK. */
1243 : : if (fn_begin_outside_block)
1244 : : {
1245 : : basic_block bb
1246 : : = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
1247 : : if (JUMP_P (BB_END (bb)))
1248 : : emit_insn_before (seq, BB_END (bb));
1249 : : else
1250 : : emit_insn_after (seq, BB_END (bb));
1251 : : }
1252 : : else
1253 : : emit_insn_after (seq, fn_begin);
1254 : :
1255 : : single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun))->flags |= BB_SUPERBLOCK;
1256 : : return;
1257 : : }
1258 : : #endif
1259 : :
1260 : 0 : if (fn_begin_outside_block)
1261 : 0 : insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
1262 : : else
1263 : 0 : emit_insn_after (seq, fn_begin);
1264 : 0 : }
1265 : :
1266 : : /* Call back from expand_function_end to know where we should put
1267 : : the call to unwind_sjlj_unregister_libfunc if needed. */
1268 : :
1269 : : void
1270 : 0 : sjlj_emit_function_exit_after (rtx_insn *after)
1271 : : {
1272 : 0 : crtl->eh.sjlj_exit_after = after;
1273 : 0 : }
1274 : :
1275 : : static void
1276 : 0 : sjlj_emit_function_exit (void)
1277 : : {
1278 : 0 : rtx_insn *seq, *insn;
1279 : :
1280 : 0 : start_sequence ();
1281 : :
1282 : 0 : emit_library_call (unwind_sjlj_unregister_libfunc, LCT_NORMAL, VOIDmode,
1283 : 0 : XEXP (crtl->eh.sjlj_fc, 0), Pmode);
1284 : :
1285 : 0 : seq = get_insns ();
1286 : 0 : end_sequence ();
1287 : :
1288 : : /* ??? Really this can be done in any block at loop level 0 that
1289 : : post-dominates all can_throw_internal instructions. This is
1290 : : the last possible moment. */
1291 : :
1292 : 0 : insn = crtl->eh.sjlj_exit_after;
1293 : 0 : if (LABEL_P (insn))
1294 : 0 : insn = NEXT_INSN (insn);
1295 : :
1296 : 0 : emit_insn_after (seq, insn);
1297 : 0 : }
1298 : :
1299 : : static void
1300 : 0 : sjlj_emit_dispatch_table (rtx_code_label *dispatch_label, int num_dispatch)
1301 : : {
1302 : 0 : scalar_int_mode unwind_word_mode = targetm.unwind_word_mode ();
1303 : 0 : scalar_int_mode filter_mode = targetm.eh_return_filter_mode ();
1304 : 0 : eh_landing_pad lp;
1305 : 0 : rtx mem, fc, exc_ptr_reg, filter_reg;
1306 : 0 : rtx_insn *seq;
1307 : 0 : basic_block bb;
1308 : 0 : eh_region r;
1309 : 0 : int i, disp_index;
1310 : 0 : vec<tree> dispatch_labels = vNULL;
1311 : :
1312 : 0 : fc = crtl->eh.sjlj_fc;
1313 : :
1314 : 0 : start_sequence ();
1315 : :
1316 : 0 : emit_label (dispatch_label);
1317 : :
1318 : : #ifndef DONT_USE_BUILTIN_SETJMP
1319 : 0 : expand_builtin_setjmp_receiver (dispatch_label);
1320 : :
1321 : : /* The caller of expand_builtin_setjmp_receiver is responsible for
1322 : : making sure that the label doesn't vanish. The only other caller
1323 : : is the expander for __builtin_setjmp_receiver, which places this
1324 : : label on the nonlocal_goto_label list. Since we're modeling these
1325 : : CFG edges more exactly, we can use the forced_labels list instead. */
1326 : 0 : LABEL_PRESERVE_P (dispatch_label) = 1;
1327 : 0 : vec_safe_push<rtx_insn *> (forced_labels, dispatch_label);
1328 : : #endif
1329 : :
1330 : : /* Load up exc_ptr and filter values from the function context. */
1331 : 0 : mem = adjust_address (fc, unwind_word_mode, sjlj_fc_data_ofs);
1332 : 0 : if (unwind_word_mode != ptr_mode)
1333 : : {
1334 : : #ifdef POINTERS_EXTEND_UNSIGNED
1335 : 0 : mem = convert_memory_address (ptr_mode, mem);
1336 : : #else
1337 : : mem = convert_to_mode (ptr_mode, mem, 0);
1338 : : #endif
1339 : : }
1340 : 0 : exc_ptr_reg = force_reg (ptr_mode, mem);
1341 : :
1342 : 0 : mem = adjust_address (fc, unwind_word_mode,
1343 : : sjlj_fc_data_ofs + GET_MODE_SIZE (unwind_word_mode));
1344 : 0 : if (unwind_word_mode != filter_mode)
1345 : 0 : mem = convert_to_mode (filter_mode, mem, 0);
1346 : 0 : filter_reg = force_reg (filter_mode, mem);
1347 : :
1348 : : /* Jump to one of the directly reachable regions. */
1349 : :
1350 : 0 : disp_index = 0;
1351 : 0 : rtx_code_label *first_reachable_label = NULL;
1352 : :
1353 : : /* If there's exactly one call site in the function, don't bother
1354 : : generating a switch statement. */
1355 : 0 : if (num_dispatch > 1)
1356 : 0 : dispatch_labels.create (num_dispatch);
1357 : :
1358 : 0 : for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
1359 : 0 : if (lp && lp->post_landing_pad)
1360 : : {
1361 : 0 : rtx_insn *seq2;
1362 : 0 : rtx_code_label *label;
1363 : :
1364 : 0 : start_sequence ();
1365 : :
1366 : 0 : lp->landing_pad = dispatch_label;
1367 : :
1368 : 0 : if (num_dispatch > 1)
1369 : : {
1370 : 0 : tree t_label, case_elt, t;
1371 : :
1372 : 0 : t_label = create_artificial_label (UNKNOWN_LOCATION);
1373 : 0 : t = build_int_cst (integer_type_node, disp_index);
1374 : 0 : case_elt = build_case_label (t, NULL, t_label);
1375 : 0 : dispatch_labels.quick_push (case_elt);
1376 : 0 : label = jump_target_rtx (t_label);
1377 : : }
1378 : : else
1379 : 0 : label = gen_label_rtx ();
1380 : :
1381 : 0 : if (disp_index == 0)
1382 : 0 : first_reachable_label = label;
1383 : 0 : emit_label (label);
1384 : :
1385 : 0 : r = lp->region;
1386 : 0 : if (r->exc_ptr_reg)
1387 : 0 : emit_move_insn (r->exc_ptr_reg, exc_ptr_reg);
1388 : 0 : if (r->filter_reg)
1389 : 0 : emit_move_insn (r->filter_reg, filter_reg);
1390 : :
1391 : 0 : seq2 = get_insns ();
1392 : 0 : end_sequence ();
1393 : :
1394 : 0 : rtx_insn *before = label_rtx (lp->post_landing_pad);
1395 : 0 : bb = emit_to_new_bb_before (seq2, before);
1396 : 0 : make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU);
1397 : 0 : if (current_loops)
1398 : : {
1399 : 0 : class loop *loop = bb->next_bb->loop_father;
1400 : : /* If we created a pre-header block, add the new block to the
1401 : : outer loop, otherwise to the loop itself. */
1402 : 0 : if (bb->next_bb == loop->header)
1403 : 0 : add_bb_to_loop (bb, loop_outer (loop));
1404 : : else
1405 : 0 : add_bb_to_loop (bb, loop);
1406 : : /* ??? For multiple dispatches we will end up with edges
1407 : : from the loop tree root into this loop, making it a
1408 : : multiple-entry loop. Discard all affected loops. */
1409 : 0 : if (num_dispatch > 1)
1410 : : {
1411 : 0 : for (loop = bb->loop_father;
1412 : 0 : loop_outer (loop); loop = loop_outer (loop))
1413 : 0 : mark_loop_for_removal (loop);
1414 : : }
1415 : : }
1416 : :
1417 : 0 : disp_index++;
1418 : : }
1419 : 0 : gcc_assert (disp_index == num_dispatch);
1420 : :
1421 : 0 : if (num_dispatch > 1)
1422 : : {
1423 : 0 : rtx disp = adjust_address (fc, TYPE_MODE (integer_type_node),
1424 : : sjlj_fc_call_site_ofs);
1425 : 0 : expand_sjlj_dispatch_table (disp, dispatch_labels);
1426 : : }
1427 : :
1428 : 0 : seq = get_insns ();
1429 : 0 : end_sequence ();
1430 : :
1431 : 0 : bb = emit_to_new_bb_before (seq, first_reachable_label);
1432 : 0 : if (num_dispatch == 1)
1433 : : {
1434 : 0 : make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU);
1435 : 0 : if (current_loops)
1436 : : {
1437 : 0 : class loop *loop = bb->next_bb->loop_father;
1438 : : /* If we created a pre-header block, add the new block to the
1439 : : outer loop, otherwise to the loop itself. */
1440 : 0 : if (bb->next_bb == loop->header)
1441 : 0 : add_bb_to_loop (bb, loop_outer (loop));
1442 : : else
1443 : 0 : add_bb_to_loop (bb, loop);
1444 : : }
1445 : : }
1446 : : else
1447 : : {
1448 : : /* We are not wiring up edges here, but as the dispatcher call
1449 : : is at function begin simply associate the block with the
1450 : : outermost (non-)loop. */
1451 : 0 : if (current_loops)
1452 : 0 : add_bb_to_loop (bb, current_loops->tree_root);
1453 : : }
1454 : 0 : }
1455 : :
1456 : : static void
1457 : 0 : sjlj_build_landing_pads (void)
1458 : : {
1459 : 0 : int num_dispatch;
1460 : :
1461 : 0 : num_dispatch = vec_safe_length (cfun->eh->lp_array);
1462 : 0 : if (num_dispatch == 0)
1463 : : return;
1464 : 0 : sjlj_lp_call_site_index.safe_grow_cleared (num_dispatch, true);
1465 : :
1466 : 0 : num_dispatch = sjlj_assign_call_site_values ();
1467 : 0 : if (num_dispatch > 0)
1468 : : {
1469 : 0 : rtx_code_label *dispatch_label = gen_label_rtx ();
1470 : 0 : int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
1471 : : TYPE_MODE (sjlj_fc_type_node),
1472 : : TYPE_ALIGN (sjlj_fc_type_node));
1473 : 0 : crtl->eh.sjlj_fc
1474 : 0 : = assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
1475 : 0 : int_size_in_bytes (sjlj_fc_type_node),
1476 : : align);
1477 : :
1478 : 0 : sjlj_mark_call_sites ();
1479 : 0 : sjlj_emit_function_enter (dispatch_label);
1480 : 0 : sjlj_emit_dispatch_table (dispatch_label, num_dispatch);
1481 : 0 : sjlj_emit_function_exit ();
1482 : : }
1483 : :
1484 : : /* If we do not have any landing pads, we may still need to register a
1485 : : personality routine and (empty) LSDA to handle must-not-throw regions. */
1486 : 0 : else if (function_needs_eh_personality (cfun) != eh_personality_none)
1487 : : {
1488 : 0 : int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
1489 : : TYPE_MODE (sjlj_fc_type_node),
1490 : : TYPE_ALIGN (sjlj_fc_type_node));
1491 : 0 : crtl->eh.sjlj_fc
1492 : 0 : = assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
1493 : 0 : int_size_in_bytes (sjlj_fc_type_node),
1494 : : align);
1495 : :
1496 : 0 : sjlj_mark_call_sites ();
1497 : 0 : sjlj_emit_function_enter (NULL);
1498 : 0 : sjlj_emit_function_exit ();
1499 : : }
1500 : :
1501 : 0 : sjlj_lp_call_site_index.release ();
1502 : : }
1503 : :
1504 : : /* Update the sjlj function context. This function should be called
1505 : : whenever we allocate or deallocate dynamic stack space. */
1506 : :
1507 : : void
1508 : 0 : update_sjlj_context (void)
1509 : : {
1510 : 0 : if (!flag_exceptions)
1511 : : return;
1512 : :
1513 : 0 : emit_note (NOTE_INSN_UPDATE_SJLJ_CONTEXT);
1514 : : }
1515 : :
1516 : : /* After initial rtl generation, call back to finish generating
1517 : : exception support code. */
1518 : :
1519 : : void
1520 : 57984 : finish_eh_generation (void)
1521 : : {
1522 : 57984 : basic_block bb;
1523 : :
1524 : : /* Construct the landing pads. */
1525 : 57984 : if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ)
1526 : 0 : sjlj_build_landing_pads ();
1527 : : else
1528 : 57984 : dw2_build_landing_pads ();
1529 : :
1530 : 57984 : break_superblocks ();
1531 : :
1532 : : /* Redirect all EH edges from the post_landing_pad to the landing pad. */
1533 : 3359559 : FOR_EACH_BB_FN (bb, cfun)
1534 : : {
1535 : 3301575 : eh_landing_pad lp;
1536 : 3301575 : edge_iterator ei;
1537 : 3301575 : edge e;
1538 : :
1539 : 3301575 : lp = get_eh_landing_pad_from_rtx (BB_END (bb));
1540 : :
1541 : 6766903 : FOR_EACH_EDGE (e, ei, bb->succs)
1542 : 4159335 : if (e->flags & EDGE_EH)
1543 : : break;
1544 : :
1545 : : /* We should not have generated any new throwing insns during this
1546 : : pass, and we should not have lost any EH edges, so we only need
1547 : : to handle two cases here:
1548 : : (1) reachable handler and an existing edge to post-landing-pad,
1549 : : (2) no reachable handler and no edge. */
1550 : 3301575 : gcc_assert ((lp != NULL) == (e != NULL));
1551 : 3301575 : if (lp != NULL)
1552 : : {
1553 : 694007 : gcc_assert (BB_HEAD (e->dest) == label_rtx (lp->post_landing_pad));
1554 : :
1555 : 694007 : redirect_edge_succ (e, BLOCK_FOR_INSN (lp->landing_pad));
1556 : 694007 : e->flags |= (CALL_P (BB_END (bb))
1557 : 694007 : ? EDGE_ABNORMAL | EDGE_ABNORMAL_CALL
1558 : : : EDGE_ABNORMAL);
1559 : : }
1560 : : }
1561 : :
1562 : 57984 : if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
1563 : : /* Kludge for Alpha (see alpha_gp_save_rtx). */
1564 : 57984 : || single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->insns.r)
1565 : 0 : commit_edge_insertions ();
1566 : 57984 : }
1567 : :
1568 : : /* This section handles removing dead code for flow. */
1569 : :
1570 : : void
1571 : 1377064 : remove_eh_landing_pad (eh_landing_pad lp)
1572 : : {
1573 : 1377064 : eh_landing_pad *pp;
1574 : :
1575 : 33561785 : for (pp = &lp->region->landing_pads; *pp != lp; pp = &(*pp)->next_lp)
1576 : 32184721 : continue;
1577 : 1377064 : *pp = lp->next_lp;
1578 : :
1579 : 1377064 : if (lp->post_landing_pad)
1580 : 1368189 : EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
1581 : 1377064 : (*cfun->eh->lp_array)[lp->index] = NULL;
1582 : 32184721 : }
1583 : :
1584 : : /* Splice the EH region at PP from the region tree. */
1585 : :
1586 : : static void
1587 : 2122049 : remove_eh_handler_splicer (eh_region *pp)
1588 : : {
1589 : 2122049 : eh_region region = *pp;
1590 : 2122049 : eh_landing_pad lp;
1591 : :
1592 : 2253860 : for (lp = region->landing_pads; lp ; lp = lp->next_lp)
1593 : : {
1594 : 131811 : if (lp->post_landing_pad)
1595 : 131779 : EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
1596 : 131811 : (*cfun->eh->lp_array)[lp->index] = NULL;
1597 : : }
1598 : :
1599 : 2122049 : if (region->inner)
1600 : : {
1601 : 108314 : eh_region p, outer;
1602 : 108314 : outer = region->outer;
1603 : :
1604 : 108314 : *pp = p = region->inner;
1605 : 120304 : do
1606 : : {
1607 : 120304 : p->outer = outer;
1608 : 120304 : pp = &p->next_peer;
1609 : 120304 : p = *pp;
1610 : : }
1611 : 120304 : while (p);
1612 : : }
1613 : 2122049 : *pp = region->next_peer;
1614 : :
1615 : 2122049 : (*cfun->eh->region_array)[region->index] = NULL;
1616 : 2122049 : }
1617 : :
1618 : : /* Splice a single EH region REGION from the region tree.
1619 : :
1620 : : To unlink REGION, we need to find the pointer to it with a relatively
1621 : : expensive search in REGION's outer region. If you are going to
1622 : : remove a number of handlers, using remove_unreachable_eh_regions may
1623 : : be a better option. */
1624 : :
1625 : : void
1626 : 0 : remove_eh_handler (eh_region region)
1627 : : {
1628 : 0 : eh_region *pp, *pp_start, p, outer;
1629 : :
1630 : 0 : outer = region->outer;
1631 : 0 : if (outer)
1632 : 0 : pp_start = &outer->inner;
1633 : : else
1634 : 0 : pp_start = &cfun->eh->region_tree;
1635 : 0 : for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp)
1636 : 0 : continue;
1637 : :
1638 : 0 : remove_eh_handler_splicer (pp);
1639 : 0 : }
1640 : :
1641 : : /* Worker for remove_unreachable_eh_regions.
1642 : : PP is a pointer to the region to start a region tree depth-first
1643 : : search from. R_REACHABLE is the set of regions that have to be
1644 : : preserved. */
1645 : :
1646 : : static void
1647 : 4821482 : remove_unreachable_eh_regions_worker (eh_region *pp, sbitmap r_reachable)
1648 : : {
1649 : 8349430 : while (*pp)
1650 : : {
1651 : 3527948 : eh_region region = *pp;
1652 : 3527948 : remove_unreachable_eh_regions_worker (®ion->inner, r_reachable);
1653 : 3527948 : if (!bitmap_bit_p (r_reachable, region->index))
1654 : 2122049 : remove_eh_handler_splicer (pp);
1655 : : else
1656 : 1405899 : pp = ®ion->next_peer;
1657 : : }
1658 : 4821482 : }
1659 : :
1660 : : /* Splice all EH regions *not* marked in R_REACHABLE from the region tree.
1661 : : Do this by traversing the EH tree top-down and splice out regions that
1662 : : are not marked. By removing regions from the leaves, we avoid costly
1663 : : searches in the region tree. */
1664 : :
1665 : : void
1666 : 1293534 : remove_unreachable_eh_regions (sbitmap r_reachable)
1667 : : {
1668 : 1293534 : remove_unreachable_eh_regions_worker (&cfun->eh->region_tree, r_reachable);
1669 : 1293534 : }
1670 : :
1671 : : /* Invokes CALLBACK for every exception handler landing pad label.
1672 : : Only used by reload hackery; should not be used by new code. */
1673 : :
1674 : : void
1675 : 0 : for_each_eh_label (void (*callback) (rtx))
1676 : : {
1677 : 0 : eh_landing_pad lp;
1678 : 0 : int i;
1679 : :
1680 : 0 : for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
1681 : : {
1682 : 0 : if (lp)
1683 : : {
1684 : 0 : rtx_code_label *lab = lp->landing_pad;
1685 : 0 : if (lab && LABEL_P (lab))
1686 : 0 : (*callback) (lab);
1687 : : }
1688 : : }
1689 : 0 : }
1690 : :
1691 : : /* Create the REG_EH_REGION note for INSN, given its ECF_FLAGS for a
1692 : : call insn.
1693 : :
1694 : : At the gimple level, we use LP_NR
1695 : : > 0 : The statement transfers to landing pad LP_NR
1696 : : = 0 : The statement is outside any EH region
1697 : : < 0 : The statement is within MUST_NOT_THROW region -LP_NR.
1698 : :
1699 : : At the rtl level, we use LP_NR
1700 : : > 0 : The insn transfers to landing pad LP_NR
1701 : : = 0 : The insn cannot throw
1702 : : < 0 : The insn is within MUST_NOT_THROW region -LP_NR
1703 : : = INT_MIN : The insn cannot throw or execute a nonlocal-goto.
1704 : : missing note: The insn is outside any EH region.
1705 : :
1706 : : ??? This difference probably ought to be avoided. We could stand
1707 : : to record nothrow for arbitrary gimple statements, and so avoid
1708 : : some moderately complex lookups in stmt_could_throw_p. Perhaps
1709 : : NOTHROW should be mapped on both sides to INT_MIN. Perhaps the
1710 : : no-nonlocal-goto property should be recorded elsewhere as a bit
1711 : : on the call_insn directly. Perhaps we should make more use of
1712 : : attaching the trees to call_insns (reachable via symbol_ref in
1713 : : direct call cases) and just pull the data out of the trees. */
1714 : :
1715 : : void
1716 : 6469006 : make_reg_eh_region_note (rtx_insn *insn, int ecf_flags, int lp_nr)
1717 : : {
1718 : 6469006 : rtx value;
1719 : 6469006 : if (ecf_flags & ECF_NOTHROW)
1720 : 2244461 : value = const0_rtx;
1721 : 4224545 : else if (lp_nr != 0)
1722 : 760229 : value = GEN_INT (lp_nr);
1723 : : else
1724 : : return;
1725 : 3004690 : add_reg_note (insn, REG_EH_REGION, value);
1726 : : }
1727 : :
1728 : : /* Create a REG_EH_REGION note for a CALL_INSN that cannot throw
1729 : : nor perform a non-local goto. Replace the region note if it
1730 : : already exists. */
1731 : :
1732 : : void
1733 : 496312 : make_reg_eh_region_note_nothrow_nononlocal (rtx_insn *insn)
1734 : : {
1735 : 496312 : rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1736 : 496312 : rtx intmin = GEN_INT (INT_MIN);
1737 : :
1738 : 496312 : if (note != 0)
1739 : 231892 : XEXP (note, 0) = intmin;
1740 : : else
1741 : 264420 : add_reg_note (insn, REG_EH_REGION, intmin);
1742 : 496312 : }
1743 : :
1744 : : /* Return true if INSN could throw, assuming no REG_EH_REGION note
1745 : : to the contrary. */
1746 : :
1747 : : bool
1748 : 3017941406 : insn_could_throw_p (const_rtx insn)
1749 : : {
1750 : 3017941406 : if (!flag_exceptions)
1751 : : return false;
1752 : 2521388104 : if (CALL_P (insn))
1753 : : return true;
1754 : 2158403238 : if (INSN_P (insn) && cfun->can_throw_non_call_exceptions)
1755 : 1875096389 : return may_trap_p (PATTERN (insn));
1756 : : return false;
1757 : : }
1758 : :
1759 : : /* Copy an REG_EH_REGION note to each insn that might throw beginning
1760 : : at FIRST and ending at LAST. NOTE_OR_INSN is either the source insn
1761 : : to look for a note, or the note itself. */
1762 : :
1763 : : void
1764 : 2564941 : copy_reg_eh_region_note_forward (rtx note_or_insn, rtx_insn *first, rtx last)
1765 : : {
1766 : 2564941 : rtx_insn *insn;
1767 : 2564941 : rtx note = note_or_insn;
1768 : :
1769 : 2564941 : if (INSN_P (note_or_insn))
1770 : : {
1771 : 2467010 : note = find_reg_note (note_or_insn, REG_EH_REGION, NULL_RTX);
1772 : 2467010 : if (note == NULL)
1773 : : return;
1774 : : }
1775 : 97931 : else if (is_a <rtx_insn *> (note_or_insn))
1776 : : return;
1777 : 43456 : note = XEXP (note, 0);
1778 : :
1779 : 95211 : for (insn = first; insn != last ; insn = NEXT_INSN (insn))
1780 : 51755 : if (!find_reg_note (insn, REG_EH_REGION, NULL_RTX)
1781 : 51755 : && insn_could_throw_p (insn))
1782 : 13765 : add_reg_note (insn, REG_EH_REGION, note);
1783 : : }
1784 : :
1785 : : /* Likewise, but iterate backward. */
1786 : :
1787 : : void
1788 : 3126 : copy_reg_eh_region_note_backward (rtx note_or_insn, rtx_insn *last, rtx first)
1789 : : {
1790 : 3126 : rtx_insn *insn;
1791 : 3126 : rtx note = note_or_insn;
1792 : :
1793 : 3126 : if (INSN_P (note_or_insn))
1794 : : {
1795 : 0 : note = find_reg_note (note_or_insn, REG_EH_REGION, NULL_RTX);
1796 : 0 : if (note == NULL)
1797 : : return;
1798 : : }
1799 : 3126 : else if (is_a <rtx_insn *> (note_or_insn))
1800 : : return;
1801 : 3126 : note = XEXP (note, 0);
1802 : :
1803 : 8893 : for (insn = last; insn != first; insn = PREV_INSN (insn))
1804 : 5767 : if (insn_could_throw_p (insn))
1805 : 5540 : add_reg_note (insn, REG_EH_REGION, note);
1806 : : }
1807 : :
1808 : :
1809 : : /* Extract all EH information from INSN. Return true if the insn
1810 : : was marked NOTHROW. */
1811 : :
1812 : : static bool
1813 : 3253264452 : get_eh_region_and_lp_from_rtx (const_rtx insn, eh_region *pr,
1814 : : eh_landing_pad *plp)
1815 : : {
1816 : 3253264452 : eh_landing_pad lp = NULL;
1817 : 3253264452 : eh_region r = NULL;
1818 : 3253264452 : bool ret = false;
1819 : 3253264452 : rtx note;
1820 : 3253264452 : int lp_nr;
1821 : :
1822 : 3253264452 : if (! INSN_P (insn))
1823 : 544355 : goto egress;
1824 : :
1825 : 3252720097 : if (NONJUMP_INSN_P (insn)
1826 : 3252720097 : && GET_CODE (PATTERN (insn)) == SEQUENCE)
1827 : 0 : insn = XVECEXP (PATTERN (insn), 0, 0);
1828 : :
1829 : 3252720097 : note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1830 : 3252720097 : if (!note)
1831 : : {
1832 : 3014553066 : ret = !insn_could_throw_p (insn);
1833 : 3014553066 : goto egress;
1834 : : }
1835 : :
1836 : 238167031 : lp_nr = INTVAL (XEXP (note, 0));
1837 : 238167031 : if (lp_nr == 0 || lp_nr == INT_MIN)
1838 : : {
1839 : 189776883 : ret = true;
1840 : 189776883 : goto egress;
1841 : : }
1842 : :
1843 : 48390148 : if (lp_nr < 0)
1844 : 4054051 : r = (*cfun->eh->region_array)[-lp_nr];
1845 : : else
1846 : : {
1847 : 44336097 : lp = (*cfun->eh->lp_array)[lp_nr];
1848 : 44336097 : r = lp->region;
1849 : : }
1850 : :
1851 : 3253264452 : egress:
1852 : 3253264452 : *plp = lp;
1853 : 3253264452 : *pr = r;
1854 : 3253264452 : return ret;
1855 : : }
1856 : :
1857 : : /* Return the landing pad to which INSN may go, or NULL if it does not
1858 : : have a reachable landing pad within this function. */
1859 : :
1860 : : eh_landing_pad
1861 : 2116381857 : get_eh_landing_pad_from_rtx (const_rtx insn)
1862 : : {
1863 : 2116381857 : eh_landing_pad lp;
1864 : 2116381857 : eh_region r;
1865 : :
1866 : 2116381857 : get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1867 : 2116381857 : return lp;
1868 : : }
1869 : :
1870 : : /* Return the region to which INSN may go, or NULL if it does not
1871 : : have a reachable region within this function. */
1872 : :
1873 : : eh_region
1874 : 3785142 : get_eh_region_from_rtx (const_rtx insn)
1875 : : {
1876 : 3785142 : eh_landing_pad lp;
1877 : 3785142 : eh_region r;
1878 : :
1879 : 3785142 : get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1880 : 3785142 : return r;
1881 : : }
1882 : :
1883 : : /* Return true if INSN throws and is caught by something in this function. */
1884 : :
1885 : : bool
1886 : 2078675257 : can_throw_internal (const_rtx insn)
1887 : : {
1888 : 2078675257 : return get_eh_landing_pad_from_rtx (insn) != NULL;
1889 : : }
1890 : :
1891 : : /* Return true if INSN throws and escapes from the current function. */
1892 : :
1893 : : bool
1894 : 33168570 : can_throw_external (const_rtx insn)
1895 : : {
1896 : 33168570 : eh_landing_pad lp;
1897 : 33168570 : eh_region r;
1898 : 33168570 : bool nothrow;
1899 : :
1900 : 33168570 : if (! INSN_P (insn))
1901 : : return false;
1902 : :
1903 : 10897638 : if (NONJUMP_INSN_P (insn)
1904 : 10897638 : && GET_CODE (PATTERN (insn)) == SEQUENCE)
1905 : : {
1906 : 0 : rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
1907 : 0 : int i, n = seq->len ();
1908 : :
1909 : 0 : for (i = 0; i < n; i++)
1910 : 0 : if (can_throw_external (seq->element (i)))
1911 : : return true;
1912 : :
1913 : : return false;
1914 : : }
1915 : :
1916 : 10897638 : nothrow = get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1917 : :
1918 : : /* If we can't throw, we obviously can't throw external. */
1919 : 10897638 : if (nothrow)
1920 : : return false;
1921 : :
1922 : : /* If we have an internal landing pad, then we're not external. */
1923 : 589856 : if (lp != NULL)
1924 : : return false;
1925 : :
1926 : : /* If we're not within an EH region, then we are external. */
1927 : 454459 : if (r == NULL)
1928 : : return true;
1929 : :
1930 : : /* The only thing that ought to be left is MUST_NOT_THROW regions,
1931 : : which don't always have landing pads. */
1932 : 14760 : gcc_assert (r->type == ERT_MUST_NOT_THROW);
1933 : : return false;
1934 : : }
1935 : :
1936 : : /* Return true if INSN cannot throw at all. */
1937 : :
1938 : : bool
1939 : 1110639026 : insn_nothrow_p (const_rtx insn)
1940 : : {
1941 : 1110639026 : eh_landing_pad lp;
1942 : 1110639026 : eh_region r;
1943 : :
1944 : 1110639026 : if (! INSN_P (insn))
1945 : : return true;
1946 : :
1947 : 1110639026 : if (NONJUMP_INSN_P (insn)
1948 : 1110639026 : && GET_CODE (PATTERN (insn)) == SEQUENCE)
1949 : : {
1950 : 0 : rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
1951 : 0 : int i, n = seq->len ();
1952 : :
1953 : 0 : for (i = 0; i < n; i++)
1954 : 0 : if (!insn_nothrow_p (seq->element (i)))
1955 : : return false;
1956 : :
1957 : : return true;
1958 : : }
1959 : :
1960 : 1110639026 : return get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1961 : : }
1962 : :
1963 : : /* Return true if INSN can perform a non-local goto. */
1964 : : /* ??? This test is here in this file because it (ab)uses REG_EH_REGION. */
1965 : :
1966 : : bool
1967 : 385829928 : can_nonlocal_goto (const rtx_insn *insn)
1968 : : {
1969 : 385829928 : if (nonlocal_goto_handler_labels && CALL_P (insn))
1970 : : {
1971 : 89410 : rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1972 : 89410 : if (!note || INTVAL (XEXP (note, 0)) != INT_MIN)
1973 : : return true;
1974 : : }
1975 : : return false;
1976 : : }
1977 : :
1978 : : /* Set TREE_NOTHROW and crtl->all_throwers_are_sibcalls. */
1979 : :
1980 : : static unsigned int
1981 : 1427237 : set_nothrow_function_flags (void)
1982 : : {
1983 : 1427237 : rtx_insn *insn;
1984 : :
1985 : 1427237 : crtl->nothrow = 1;
1986 : :
1987 : : /* Assume crtl->all_throwers_are_sibcalls until we encounter
1988 : : something that can throw an exception. We specifically exempt
1989 : : CALL_INSNs that are SIBLING_CALL_P, as these are really jumps,
1990 : : and can't throw. Most CALL_INSNs are not SIBLING_CALL_P, so this
1991 : : is optimistic. */
1992 : :
1993 : 1427237 : crtl->all_throwers_are_sibcalls = 1;
1994 : :
1995 : : /* If we don't know that this implementation of the function will
1996 : : actually be used, then we must not set TREE_NOTHROW, since
1997 : : callers must not assume that this function does not throw. */
1998 : 1427237 : if (TREE_NOTHROW (current_function_decl))
1999 : : return 0;
2000 : :
2001 : 689939 : if (! flag_exceptions)
2002 : : return 0;
2003 : :
2004 : 32825834 : for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2005 : 32773711 : if (can_throw_external (insn))
2006 : : {
2007 : 438779 : crtl->nothrow = 0;
2008 : :
2009 : 438779 : if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
2010 : : {
2011 : 423661 : crtl->all_throwers_are_sibcalls = 0;
2012 : 423661 : return 0;
2013 : : }
2014 : : }
2015 : :
2016 : 52123 : if (crtl->nothrow
2017 : 52123 : && (cgraph_node::get (current_function_decl)->get_availability ()
2018 : : >= AVAIL_AVAILABLE))
2019 : : {
2020 : 35089 : struct cgraph_node *node = cgraph_node::get (current_function_decl);
2021 : 35089 : struct cgraph_edge *e;
2022 : 44731 : for (e = node->callers; e; e = e->next_caller)
2023 : 9642 : e->can_throw_external = false;
2024 : 35089 : node->set_nothrow_flag (true);
2025 : :
2026 : 35089 : if (dump_file)
2027 : 5 : fprintf (dump_file, "Marking function nothrow: %s\n\n",
2028 : : current_function_name ());
2029 : : }
2030 : : return 0;
2031 : : }
2032 : :
2033 : : namespace {
2034 : :
2035 : : const pass_data pass_data_set_nothrow_function_flags =
2036 : : {
2037 : : RTL_PASS, /* type */
2038 : : "nothrow", /* name */
2039 : : OPTGROUP_NONE, /* optinfo_flags */
2040 : : TV_NONE, /* tv_id */
2041 : : 0, /* properties_required */
2042 : : 0, /* properties_provided */
2043 : : 0, /* properties_destroyed */
2044 : : 0, /* todo_flags_start */
2045 : : 0, /* todo_flags_finish */
2046 : : };
2047 : :
2048 : : class pass_set_nothrow_function_flags : public rtl_opt_pass
2049 : : {
2050 : : public:
2051 : 280831 : pass_set_nothrow_function_flags (gcc::context *ctxt)
2052 : 561662 : : rtl_opt_pass (pass_data_set_nothrow_function_flags, ctxt)
2053 : : {}
2054 : :
2055 : : /* opt_pass methods: */
2056 : 1427237 : unsigned int execute (function *) final override
2057 : : {
2058 : 1427237 : return set_nothrow_function_flags ();
2059 : : }
2060 : :
2061 : : }; // class pass_set_nothrow_function_flags
2062 : :
2063 : : } // anon namespace
2064 : :
2065 : : rtl_opt_pass *
2066 : 280831 : make_pass_set_nothrow_function_flags (gcc::context *ctxt)
2067 : : {
2068 : 280831 : return new pass_set_nothrow_function_flags (ctxt);
2069 : : }
2070 : :
2071 : :
2072 : : /* Various hooks for unwind library. */
2073 : :
2074 : : /* Expand the EH support builtin functions:
2075 : : __builtin_eh_pointer and __builtin_eh_filter. */
2076 : :
2077 : : static eh_region
2078 : 284696 : expand_builtin_eh_common (tree region_nr_t)
2079 : : {
2080 : 284696 : HOST_WIDE_INT region_nr;
2081 : 284696 : eh_region region;
2082 : :
2083 : 284696 : gcc_assert (tree_fits_shwi_p (region_nr_t));
2084 : 284696 : region_nr = tree_to_shwi (region_nr_t);
2085 : :
2086 : 284696 : region = (*cfun->eh->region_array)[region_nr];
2087 : :
2088 : : /* ??? We shouldn't have been able to delete a eh region without
2089 : : deleting all the code that depended on it. */
2090 : 284696 : gcc_assert (region != NULL);
2091 : :
2092 : 284696 : return region;
2093 : : }
2094 : :
2095 : : /* Expand to the exc_ptr value from the given eh region. */
2096 : :
2097 : : rtx
2098 : 86061 : expand_builtin_eh_pointer (tree exp)
2099 : : {
2100 : 86061 : eh_region region
2101 : 86061 : = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
2102 : 86061 : if (region->exc_ptr_reg == NULL)
2103 : 56446 : region->exc_ptr_reg = gen_reg_rtx (ptr_mode);
2104 : 86061 : return region->exc_ptr_reg;
2105 : : }
2106 : :
2107 : : /* Expand to the filter value from the given eh region. */
2108 : :
2109 : : rtx
2110 : 4505 : expand_builtin_eh_filter (tree exp)
2111 : : {
2112 : 4505 : eh_region region
2113 : 4505 : = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
2114 : 4505 : if (region->filter_reg == NULL)
2115 : 3441 : region->filter_reg = gen_reg_rtx (targetm.eh_return_filter_mode ());
2116 : 4505 : return region->filter_reg;
2117 : : }
2118 : :
2119 : : /* Copy the exc_ptr and filter values from one landing pad's registers
2120 : : to another. This is used to inline the resx statement. */
2121 : :
2122 : : rtx
2123 : 97065 : expand_builtin_eh_copy_values (tree exp)
2124 : : {
2125 : 97065 : eh_region dst
2126 : 97065 : = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
2127 : 97065 : eh_region src
2128 : 97065 : = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 1));
2129 : 97065 : scalar_int_mode fmode = targetm.eh_return_filter_mode ();
2130 : :
2131 : 97065 : if (dst->exc_ptr_reg == NULL)
2132 : 72012 : dst->exc_ptr_reg = gen_reg_rtx (ptr_mode);
2133 : 97065 : if (src->exc_ptr_reg == NULL)
2134 : 50103 : src->exc_ptr_reg = gen_reg_rtx (ptr_mode);
2135 : :
2136 : 97065 : if (dst->filter_reg == NULL)
2137 : 72024 : dst->filter_reg = gen_reg_rtx (fmode);
2138 : 97065 : if (src->filter_reg == NULL)
2139 : 49513 : src->filter_reg = gen_reg_rtx (fmode);
2140 : :
2141 : 97065 : emit_move_insn (dst->exc_ptr_reg, src->exc_ptr_reg);
2142 : 97065 : emit_move_insn (dst->filter_reg, src->filter_reg);
2143 : :
2144 : 97065 : return const0_rtx;
2145 : : }
2146 : :
2147 : : /* Do any necessary initialization to access arbitrary stack frames.
2148 : : On the SPARC, this means flushing the register windows. */
2149 : :
2150 : : void
2151 : 34 : expand_builtin_unwind_init (void)
2152 : : {
2153 : : /* Set this so all the registers get saved in our frame; we need to be
2154 : : able to copy the saved values for any registers from frames we unwind. */
2155 : 34 : crtl->saves_all_registers = 1;
2156 : :
2157 : 34 : SETUP_FRAME_ADDRESSES ();
2158 : 34 : }
2159 : :
2160 : : /* Map a non-negative number to an eh return data register number; expands
2161 : : to -1 if no return data register is associated with the input number.
2162 : : At least the inputs 0 and 1 must be mapped; the target may provide more. */
2163 : :
2164 : : rtx
2165 : 21 : expand_builtin_eh_return_data_regno (tree exp)
2166 : : {
2167 : 21 : tree which = CALL_EXPR_ARG (exp, 0);
2168 : 21 : unsigned HOST_WIDE_INT iwhich;
2169 : :
2170 : 21 : if (TREE_CODE (which) != INTEGER_CST)
2171 : : {
2172 : 0 : error ("argument of %<__builtin_eh_return_regno%> must be constant");
2173 : 0 : return constm1_rtx;
2174 : : }
2175 : :
2176 : 21 : if (!tree_fits_uhwi_p (which))
2177 : 1 : return constm1_rtx;
2178 : :
2179 : 20 : iwhich = tree_to_uhwi (which);
2180 : 20 : iwhich = EH_RETURN_DATA_REGNO (iwhich);
2181 : 20 : if (iwhich == INVALID_REGNUM)
2182 : 0 : return constm1_rtx;
2183 : :
2184 : : #ifdef DWARF_FRAME_REGNUM
2185 : 20 : iwhich = DWARF_FRAME_REGNUM (iwhich);
2186 : : #else
2187 : : iwhich = DEBUGGER_REGNO (iwhich);
2188 : : #endif
2189 : :
2190 : 20 : return GEN_INT (iwhich);
2191 : : }
2192 : :
2193 : : /* Given a value extracted from the return address register or stack slot,
2194 : : return the actual address encoded in that value. */
2195 : :
2196 : : rtx
2197 : 2296 : expand_builtin_extract_return_addr (tree addr_tree)
2198 : : {
2199 : 2296 : rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2200 : :
2201 : 2296 : if (GET_MODE (addr) != Pmode
2202 : 2296 : && GET_MODE (addr) != VOIDmode)
2203 : : {
2204 : : #ifdef POINTERS_EXTEND_UNSIGNED
2205 : 0 : addr = convert_memory_address (Pmode, addr);
2206 : : #else
2207 : : addr = convert_to_mode (Pmode, addr, 0);
2208 : : #endif
2209 : : }
2210 : :
2211 : : /* First mask out any unwanted bits. */
2212 : 2296 : rtx mask = MASK_RETURN_ADDR;
2213 : 2296 : if (mask)
2214 : : expand_and (Pmode, addr, mask, addr);
2215 : :
2216 : : /* Then adjust to find the real return address. */
2217 : 2296 : if (RETURN_ADDR_OFFSET)
2218 : : addr = plus_constant (Pmode, addr, RETURN_ADDR_OFFSET);
2219 : :
2220 : 2296 : return addr;
2221 : : }
2222 : :
2223 : : /* Given an actual address in addr_tree, do any necessary encoding
2224 : : and return the value to be stored in the return address register or
2225 : : stack slot so the epilogue will return to that address. */
2226 : :
2227 : : rtx
2228 : 19 : expand_builtin_frob_return_addr (tree addr_tree)
2229 : : {
2230 : 19 : rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, EXPAND_NORMAL);
2231 : :
2232 : 19 : addr = convert_memory_address (Pmode, addr);
2233 : :
2234 : 19 : if (RETURN_ADDR_OFFSET)
2235 : : {
2236 : : addr = force_reg (Pmode, addr);
2237 : : addr = plus_constant (Pmode, addr, -RETURN_ADDR_OFFSET);
2238 : : }
2239 : :
2240 : 19 : return addr;
2241 : : }
2242 : :
2243 : : /* Set up the epilogue with the magic bits we'll need to return to the
2244 : : exception handler. */
2245 : :
2246 : : void
2247 : 29 : expand_builtin_eh_return (tree stackadj_tree ATTRIBUTE_UNUSED,
2248 : : tree handler_tree)
2249 : : {
2250 : 29 : rtx tmp;
2251 : :
2252 : : #ifdef EH_RETURN_STACKADJ_RTX
2253 : 29 : tmp = expand_expr (stackadj_tree, crtl->eh.ehr_stackadj,
2254 : : VOIDmode, EXPAND_NORMAL);
2255 : 29 : tmp = convert_memory_address (Pmode, tmp);
2256 : 29 : if (!crtl->eh.ehr_stackadj)
2257 : 29 : crtl->eh.ehr_stackadj = copy_addr_to_reg (tmp);
2258 : 0 : else if (tmp != crtl->eh.ehr_stackadj)
2259 : 0 : emit_move_insn (crtl->eh.ehr_stackadj, tmp);
2260 : : #endif
2261 : :
2262 : 29 : tmp = expand_expr (handler_tree, crtl->eh.ehr_handler,
2263 : : VOIDmode, EXPAND_NORMAL);
2264 : 29 : tmp = convert_memory_address (Pmode, tmp);
2265 : 29 : if (!crtl->eh.ehr_handler)
2266 : 29 : crtl->eh.ehr_handler = copy_addr_to_reg (tmp);
2267 : 0 : else if (tmp != crtl->eh.ehr_handler)
2268 : 0 : emit_move_insn (crtl->eh.ehr_handler, tmp);
2269 : :
2270 : 29 : if (!crtl->eh.ehr_label)
2271 : 29 : crtl->eh.ehr_label = gen_label_rtx ();
2272 : 29 : emit_jump (crtl->eh.ehr_label);
2273 : 29 : }
2274 : :
2275 : : /* Expand __builtin_eh_return. This exit path from the function loads up
2276 : : the eh return data registers, adjusts the stack, and branches to a
2277 : : given PC other than the normal return address. */
2278 : :
2279 : : void
2280 : 1427972 : expand_eh_return (void)
2281 : : {
2282 : 1427972 : rtx_code_label *around_label;
2283 : :
2284 : 1427972 : if (! crtl->eh.ehr_label)
2285 : : return;
2286 : :
2287 : 29 : crtl->calls_eh_return = 1;
2288 : :
2289 : : #ifdef EH_RETURN_STACKADJ_RTX
2290 : 29 : emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
2291 : : #endif
2292 : :
2293 : : #ifdef EH_RETURN_TAKEN_RTX
2294 : : emit_move_insn (EH_RETURN_TAKEN_RTX, const0_rtx);
2295 : : #endif
2296 : :
2297 : 29 : around_label = gen_label_rtx ();
2298 : 29 : emit_jump (around_label);
2299 : :
2300 : 29 : emit_label (crtl->eh.ehr_label);
2301 : 29 : clobber_return_register ();
2302 : :
2303 : : #ifdef EH_RETURN_STACKADJ_RTX
2304 : 29 : emit_move_insn (EH_RETURN_STACKADJ_RTX, crtl->eh.ehr_stackadj);
2305 : : #endif
2306 : :
2307 : : #ifdef EH_RETURN_TAKEN_RTX
2308 : : emit_move_insn (EH_RETURN_TAKEN_RTX, const1_rtx);
2309 : : #endif
2310 : :
2311 : 29 : if (targetm.have_eh_return ())
2312 : 29 : emit_insn (targetm.gen_eh_return (crtl->eh.ehr_handler));
2313 : : else
2314 : : {
2315 : 0 : if (rtx handler = EH_RETURN_HANDLER_RTX)
2316 : : emit_move_insn (handler, crtl->eh.ehr_handler);
2317 : : else
2318 : 0 : error ("%<__builtin_eh_return%> not supported on this target");
2319 : : }
2320 : :
2321 : : #ifdef EH_RETURN_TAKEN_RTX
2322 : : rtx_code_label *eh_done_label = gen_label_rtx ();
2323 : : emit_jump (eh_done_label);
2324 : : #endif
2325 : :
2326 : 29 : emit_label (around_label);
2327 : :
2328 : : #ifdef EH_RETURN_TAKEN_RTX
2329 : : for (rtx tmp : { EH_RETURN_STACKADJ_RTX, EH_RETURN_HANDLER_RTX })
2330 : : if (tmp && REG_P (tmp))
2331 : : emit_clobber (tmp);
2332 : : emit_label (eh_done_label);
2333 : : #endif
2334 : : }
2335 : :
2336 : : /* Convert a ptr_mode address ADDR_TREE to a Pmode address controlled by
2337 : : POINTERS_EXTEND_UNSIGNED and return it. */
2338 : :
2339 : : rtx
2340 : 2 : expand_builtin_extend_pointer (tree addr_tree)
2341 : : {
2342 : 2 : rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, EXPAND_NORMAL);
2343 : 2 : int extend;
2344 : :
2345 : : #ifdef POINTERS_EXTEND_UNSIGNED
2346 : 2 : extend = POINTERS_EXTEND_UNSIGNED;
2347 : : #else
2348 : : /* The previous EH code did an unsigned extend by default, so we do this also
2349 : : for consistency. */
2350 : : extend = 1;
2351 : : #endif
2352 : :
2353 : 2 : return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend);
2354 : : }
2355 : :
2356 : : static int
2357 : 337535 : add_action_record (action_hash_type *ar_hash, int filter, int next)
2358 : : {
2359 : 337535 : struct action_record **slot, *new_ar, tmp;
2360 : :
2361 : 337535 : tmp.filter = filter;
2362 : 337535 : tmp.next = next;
2363 : 337535 : slot = ar_hash->find_slot (&tmp, INSERT);
2364 : :
2365 : 337535 : if ((new_ar = *slot) == NULL)
2366 : : {
2367 : 23508 : new_ar = XNEW (struct action_record);
2368 : 23508 : new_ar->offset = crtl->eh.action_record_data->length () + 1;
2369 : 23508 : new_ar->filter = filter;
2370 : 23508 : new_ar->next = next;
2371 : 23508 : *slot = new_ar;
2372 : :
2373 : : /* The filter value goes in untouched. The link to the next
2374 : : record is a "self-relative" byte offset, or zero to indicate
2375 : : that there is no next record. So convert the absolute 1 based
2376 : : indices we've been carrying around into a displacement. */
2377 : :
2378 : 23508 : push_sleb128 (&crtl->eh.action_record_data, filter);
2379 : 23508 : if (next)
2380 : 4318 : next -= crtl->eh.action_record_data->length () + 1;
2381 : 23508 : push_sleb128 (&crtl->eh.action_record_data, next);
2382 : : }
2383 : :
2384 : 337535 : return new_ar->offset;
2385 : : }
2386 : :
2387 : : static int
2388 : 25388682 : collect_one_action_chain (action_hash_type *ar_hash, eh_region region)
2389 : : {
2390 : 25388682 : int next;
2391 : :
2392 : : /* If we've reached the top of the region chain, then we have
2393 : : no actions, and require no landing pad. */
2394 : 25388682 : if (region == NULL)
2395 : : return -1;
2396 : :
2397 : 25078579 : switch (region->type)
2398 : : {
2399 : 24703915 : case ERT_CLEANUP:
2400 : 24703915 : {
2401 : 24703915 : eh_region r;
2402 : : /* A cleanup adds a zero filter to the beginning of the chain, but
2403 : : there are special cases to look out for. If there are *only*
2404 : : cleanups along a path, then it compresses to a zero action.
2405 : : Further, if there are multiple cleanups along a path, we only
2406 : : need to represent one of them, as that is enough to trigger
2407 : : entry to the landing pad at runtime. */
2408 : 24703915 : next = collect_one_action_chain (ar_hash, region->outer);
2409 : 24703915 : if (next <= 0)
2410 : : return 0;
2411 : 37723 : for (r = region->outer; r ; r = r->outer)
2412 : 33770 : if (r->type == ERT_CLEANUP)
2413 : : return next;
2414 : 3953 : return add_action_record (ar_hash, 0, next);
2415 : : }
2416 : :
2417 : 325855 : case ERT_TRY:
2418 : 325855 : {
2419 : 325855 : eh_catch c;
2420 : :
2421 : : /* Process the associated catch regions in reverse order.
2422 : : If there's a catch-all handler, then we don't need to
2423 : : search outer regions. Use a magic -3 value to record
2424 : : that we haven't done the outer search. */
2425 : 325855 : next = -3;
2426 : 657181 : for (c = region->u.eh_try.last_catch; c ; c = c->prev_catch)
2427 : : {
2428 : 331326 : if (c->type_list == NULL)
2429 : : {
2430 : : /* Retrieve the filter from the head of the filter list
2431 : : where we have stored it (see assign_filter_values). */
2432 : 320682 : int filter = TREE_INT_CST_LOW (TREE_VALUE (c->filter_list));
2433 : 320682 : next = add_action_record (ar_hash, filter, 0);
2434 : : }
2435 : : else
2436 : : {
2437 : : /* Once the outer search is done, trigger an action record for
2438 : : each filter we have. */
2439 : 10644 : tree flt_node;
2440 : :
2441 : 10644 : if (next == -3)
2442 : : {
2443 : 5173 : next = collect_one_action_chain (ar_hash, region->outer);
2444 : :
2445 : : /* If there is no next action, terminate the chain. */
2446 : 5173 : if (next == -1)
2447 : : next = 0;
2448 : : /* If all outer actions are cleanups or must_not_throw,
2449 : : we'll have no action record for it, since we had wanted
2450 : : to encode these states in the call-site record directly.
2451 : : Add a cleanup action to the chain to catch these. */
2452 : 1975 : else if (next <= 0)
2453 : 1734 : next = add_action_record (ar_hash, 0, 0);
2454 : : }
2455 : :
2456 : 10644 : flt_node = c->filter_list;
2457 : 21288 : for (; flt_node; flt_node = TREE_CHAIN (flt_node))
2458 : : {
2459 : 10644 : int filter = TREE_INT_CST_LOW (TREE_VALUE (flt_node));
2460 : 10644 : next = add_action_record (ar_hash, filter, next);
2461 : : }
2462 : : }
2463 : : }
2464 : : return next;
2465 : : }
2466 : :
2467 : 490 : case ERT_ALLOWED_EXCEPTIONS:
2468 : : /* An exception specification adds its filter to the
2469 : : beginning of the chain. */
2470 : 490 : next = collect_one_action_chain (ar_hash, region->outer);
2471 : :
2472 : : /* If there is no next action, terminate the chain. */
2473 : 490 : if (next == -1)
2474 : : next = 0;
2475 : : /* If all outer actions are cleanups or must_not_throw,
2476 : : we'll have no action record for it, since we had wanted
2477 : : to encode these states in the call-site record directly.
2478 : : Add a cleanup action to the chain to catch these. */
2479 : 41 : else if (next <= 0)
2480 : 32 : next = add_action_record (ar_hash, 0, 0);
2481 : :
2482 : 490 : return add_action_record (ar_hash, region->u.allowed.filter, next);
2483 : :
2484 : : case ERT_MUST_NOT_THROW:
2485 : : /* A must-not-throw region with no inner handlers or cleanups
2486 : : requires no call-site entry. Note that this differs from
2487 : : the no handler or cleanup case in that we do require an lsda
2488 : : to be generated. Return a magic -2 value to record this. */
2489 : : return -2;
2490 : : }
2491 : :
2492 : 0 : gcc_unreachable ();
2493 : : }
2494 : :
2495 : : static int
2496 : 386907 : add_call_site (rtx landing_pad, int action, int section)
2497 : : {
2498 : 386907 : call_site_record record;
2499 : :
2500 : 386907 : record = ggc_alloc<call_site_record_d> ();
2501 : 386907 : record->landing_pad = landing_pad;
2502 : 386907 : record->action = action;
2503 : :
2504 : 386907 : vec_safe_push (crtl->eh.call_site_record_v[section], record);
2505 : :
2506 : 386907 : return call_site_base + crtl->eh.call_site_record_v[section]->length () - 1;
2507 : : }
2508 : :
2509 : : static rtx_note *
2510 : 386907 : emit_note_eh_region_end (rtx_insn *insn)
2511 : : {
2512 : 0 : return emit_note_after (NOTE_INSN_EH_REGION_END, insn);
2513 : : }
2514 : :
2515 : : /* Add NOP after NOTE_INSN_SWITCH_TEXT_SECTIONS when the cold section starts
2516 : : with landing pad.
2517 : : With landing pad being at offset 0 from the start label of the section
2518 : : we would miss EH delivery because 0 is special and means no landing pad. */
2519 : :
2520 : : static bool
2521 : 57971 : maybe_add_nop_after_section_switch (void)
2522 : : {
2523 : 57971 : if (!crtl->uses_eh_lsda
2524 : 57922 : || !crtl->eh.call_site_record_v[1])
2525 : : return false;
2526 : 13676 : int n = vec_safe_length (crtl->eh.call_site_record_v[1]);
2527 : 13676 : hash_set<rtx_insn *> visited;
2528 : :
2529 : 48320 : for (int i = 0; i < n; ++i)
2530 : : {
2531 : 34644 : struct call_site_record_d *cs
2532 : 34644 : = (*crtl->eh.call_site_record_v[1])[i];
2533 : 34644 : if (cs->landing_pad)
2534 : : {
2535 : 17067 : rtx_insn *insn = as_a <rtx_insn *> (cs->landing_pad);
2536 : 251339 : while (true)
2537 : : {
2538 : : /* Landing pads have LABEL_PRESERVE_P flag set. This check make
2539 : : sure that we do not walk past landing pad visited earlier
2540 : : which would result in possible quadratic behaviour. */
2541 : 17067 : if (LABEL_P (insn) && LABEL_PRESERVE_P (insn)
2542 : 151270 : && visited.add (insn))
2543 : : break;
2544 : :
2545 : : /* Conservatively assume that ASM insn may be empty. We have
2546 : : now way to tell what they contain. */
2547 : 132954 : if (active_insn_p (insn)
2548 : 15315 : && GET_CODE (PATTERN (insn)) != ASM_INPUT
2549 : 148269 : && GET_CODE (PATTERN (insn)) != ASM_OPERANDS)
2550 : : break;
2551 : :
2552 : : /* If we reached the start of hot section, then NOP will be
2553 : : needed. */
2554 : 117639 : if (GET_CODE (insn) == NOTE
2555 : 86506 : && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
2556 : : {
2557 : 503 : emit_insn_after (gen_nop (), insn);
2558 : 503 : break;
2559 : : }
2560 : :
2561 : : /* We visit only labels from cold section. We should never hit
2562 : : begining of the insn stream here. */
2563 : 117136 : insn = PREV_INSN (insn);
2564 : 117136 : }
2565 : : }
2566 : : }
2567 : 13676 : return false;
2568 : 13676 : }
2569 : :
2570 : : /* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
2571 : : The new note numbers will not refer to region numbers, but
2572 : : instead to call site entries. */
2573 : :
2574 : : static unsigned int
2575 : 57971 : convert_to_eh_region_ranges (void)
2576 : : {
2577 : 57971 : rtx insn;
2578 : 57971 : rtx_insn *iter;
2579 : 57971 : rtx_note *note;
2580 : 57971 : action_hash_type ar_hash (31);
2581 : 57971 : int last_action = -3;
2582 : 57971 : rtx_insn *last_action_insn = NULL;
2583 : 57971 : rtx last_landing_pad = NULL_RTX;
2584 : 57971 : rtx_insn *first_no_action_insn = NULL;
2585 : 57971 : int call_site = 0;
2586 : 57971 : int cur_sec = 0;
2587 : 57971 : rtx_insn *section_switch_note = NULL;
2588 : 57971 : rtx_insn *first_no_action_insn_before_switch = NULL;
2589 : 57971 : rtx_insn *last_no_action_insn_before_switch = NULL;
2590 : 57971 : int saved_call_site_base = call_site_base;
2591 : :
2592 : 57971 : vec_alloc (crtl->eh.action_record_data, 64);
2593 : :
2594 : 47816054 : for (iter = get_insns (); iter ; iter = NEXT_INSN (iter))
2595 : 47758083 : if (INSN_P (iter))
2596 : : {
2597 : 11560789 : eh_landing_pad lp;
2598 : 11560789 : eh_region region;
2599 : 11560789 : bool nothrow;
2600 : 11560789 : int this_action;
2601 : 11560789 : rtx_code_label *this_landing_pad;
2602 : :
2603 : 11560789 : insn = iter;
2604 : 11560789 : if (NONJUMP_INSN_P (insn)
2605 : 11560789 : && GET_CODE (PATTERN (insn)) == SEQUENCE)
2606 : 0 : insn = XVECEXP (PATTERN (insn), 0, 0);
2607 : :
2608 : 11560789 : nothrow = get_eh_region_and_lp_from_rtx (insn, ®ion, &lp);
2609 : 11560789 : if (nothrow)
2610 : 10651985 : continue;
2611 : 908804 : if (region)
2612 : 679104 : this_action = collect_one_action_chain (&ar_hash, region);
2613 : : else
2614 : : this_action = -1;
2615 : :
2616 : : /* Existence of catch handlers, or must-not-throw regions
2617 : : implies that an lsda is needed (even if empty). */
2618 : 679104 : if (this_action != -1)
2619 : 679104 : crtl->uses_eh_lsda = 1;
2620 : :
2621 : : /* Delay creation of region notes for no-action regions
2622 : : until we're sure that an lsda will be required. */
2623 : 229700 : else if (last_action == -3)
2624 : : {
2625 : 25780 : first_no_action_insn = iter;
2626 : 25780 : last_action = -1;
2627 : : }
2628 : :
2629 : 908804 : if (this_action >= 0)
2630 : 631762 : this_landing_pad = lp->landing_pad;
2631 : : else
2632 : : this_landing_pad = NULL;
2633 : :
2634 : : /* Differing actions or landing pads implies a change in call-site
2635 : : info, which implies some EH_REGION note should be emitted. */
2636 : 908804 : if (last_action != this_action
2637 : 908804 : || last_landing_pad != this_landing_pad)
2638 : : {
2639 : : /* If there is a queued no-action region in the other section
2640 : : with hot/cold partitioning, emit it now. */
2641 : 389133 : if (first_no_action_insn_before_switch)
2642 : : {
2643 : 408 : gcc_assert (this_action != -1
2644 : : && last_action == (first_no_action_insn
2645 : : ? -1 : -3));
2646 : 286 : call_site = add_call_site (NULL_RTX, 0, 0);
2647 : 286 : note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
2648 : : first_no_action_insn_before_switch);
2649 : 286 : NOTE_EH_HANDLER (note) = call_site;
2650 : 286 : note
2651 : 286 : = emit_note_eh_region_end (last_no_action_insn_before_switch);
2652 : 286 : NOTE_EH_HANDLER (note) = call_site;
2653 : 286 : gcc_assert (last_action != -3
2654 : : || (last_action_insn
2655 : : == last_no_action_insn_before_switch));
2656 : 286 : first_no_action_insn_before_switch = NULL;
2657 : 286 : last_no_action_insn_before_switch = NULL;
2658 : 286 : call_site_base++;
2659 : : }
2660 : : /* If we'd not seen a previous action (-3) or the previous
2661 : : action was must-not-throw (-2), then we do not need an
2662 : : end note. */
2663 : 389133 : if (last_action >= -1)
2664 : : {
2665 : : /* If we delayed the creation of the begin, do it now. */
2666 : 338468 : if (first_no_action_insn)
2667 : : {
2668 : 25464 : call_site = add_call_site (NULL_RTX, 0, cur_sec);
2669 : 25464 : note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
2670 : : first_no_action_insn);
2671 : 25464 : NOTE_EH_HANDLER (note) = call_site;
2672 : 25464 : first_no_action_insn = NULL;
2673 : : }
2674 : :
2675 : 338468 : note = emit_note_eh_region_end (last_action_insn);
2676 : 338468 : NOTE_EH_HANDLER (note) = call_site;
2677 : : }
2678 : :
2679 : : /* If the new action is must-not-throw, then no region notes
2680 : : are created. */
2681 : 389133 : if (this_action >= -1)
2682 : : {
2683 : 361157 : call_site = add_call_site (this_landing_pad,
2684 : : this_action < 0 ? 0 : this_action,
2685 : : cur_sec);
2686 : 361157 : note = emit_note_before (NOTE_INSN_EH_REGION_BEG, iter);
2687 : 361157 : NOTE_EH_HANDLER (note) = call_site;
2688 : : }
2689 : :
2690 : : last_action = this_action;
2691 : : last_landing_pad = this_landing_pad;
2692 : : }
2693 : 908804 : last_action_insn = iter;
2694 : : }
2695 : 36197294 : else if (NOTE_P (iter)
2696 : 34076946 : && NOTE_KIND (iter) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
2697 : : {
2698 : 13688 : gcc_assert (section_switch_note == NULL_RTX);
2699 : 13688 : gcc_assert (flag_reorder_blocks_and_partition);
2700 : 13688 : section_switch_note = iter;
2701 : 13688 : if (first_no_action_insn)
2702 : : {
2703 : 286 : first_no_action_insn_before_switch = first_no_action_insn;
2704 : 286 : last_no_action_insn_before_switch = last_action_insn;
2705 : 286 : first_no_action_insn = NULL;
2706 : 286 : gcc_assert (last_action == -1);
2707 : : last_action = -3;
2708 : : }
2709 : : /* Force closing of current EH region before section switch and
2710 : : opening a new one afterwards. */
2711 : 13402 : else if (last_action != -3)
2712 : 12573 : last_landing_pad = pc_rtx;
2713 : 13688 : if (crtl->eh.call_site_record_v[cur_sec])
2714 : 12388 : call_site_base += crtl->eh.call_site_record_v[cur_sec]->length ();
2715 : 13688 : cur_sec++;
2716 : 13688 : gcc_assert (crtl->eh.call_site_record_v[cur_sec] == NULL);
2717 : 13688 : vec_alloc (crtl->eh.call_site_record_v[cur_sec], 10);
2718 : : }
2719 : :
2720 : 57971 : if (last_action >= -1 && ! first_no_action_insn)
2721 : : {
2722 : 48153 : note = emit_note_eh_region_end (last_action_insn);
2723 : 48153 : NOTE_EH_HANDLER (note) = call_site;
2724 : : }
2725 : :
2726 : 57971 : call_site_base = saved_call_site_base;
2727 : :
2728 : 115942 : return 0;
2729 : 57971 : }
2730 : :
2731 : : namespace {
2732 : :
2733 : : const pass_data pass_data_convert_to_eh_region_ranges =
2734 : : {
2735 : : RTL_PASS, /* type */
2736 : : "eh_ranges", /* name */
2737 : : OPTGROUP_NONE, /* optinfo_flags */
2738 : : TV_NONE, /* tv_id */
2739 : : 0, /* properties_required */
2740 : : 0, /* properties_provided */
2741 : : 0, /* properties_destroyed */
2742 : : 0, /* todo_flags_start */
2743 : : 0, /* todo_flags_finish */
2744 : : };
2745 : :
2746 : : class pass_convert_to_eh_region_ranges : public rtl_opt_pass
2747 : : {
2748 : : public:
2749 : 280831 : pass_convert_to_eh_region_ranges (gcc::context *ctxt)
2750 : 561662 : : rtl_opt_pass (pass_data_convert_to_eh_region_ranges, ctxt)
2751 : : {}
2752 : :
2753 : : /* opt_pass methods: */
2754 : : bool gate (function *) final override;
2755 : 57971 : unsigned int execute (function *) final override
2756 : : {
2757 : 57971 : int ret = convert_to_eh_region_ranges ();
2758 : 57971 : maybe_add_nop_after_section_switch ();
2759 : 57971 : return ret;
2760 : : }
2761 : :
2762 : : }; // class pass_convert_to_eh_region_ranges
2763 : :
2764 : : bool
2765 : 1427244 : pass_convert_to_eh_region_ranges::gate (function *)
2766 : : {
2767 : : /* Nothing to do for SJLJ exceptions or if no regions created. */
2768 : 1427244 : if (cfun->eh->region_tree == NULL)
2769 : : return false;
2770 : 57971 : if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ)
2771 : : return false;
2772 : : return true;
2773 : : }
2774 : :
2775 : : } // anon namespace
2776 : :
2777 : : rtl_opt_pass *
2778 : 280831 : make_pass_convert_to_eh_region_ranges (gcc::context *ctxt)
2779 : : {
2780 : 280831 : return new pass_convert_to_eh_region_ranges (ctxt);
2781 : : }
2782 : :
2783 : : static void
2784 : 123 : push_uleb128 (vec<uchar, va_gc> **data_area, unsigned int value)
2785 : : {
2786 : 123 : do
2787 : : {
2788 : 123 : unsigned char byte = value & 0x7f;
2789 : 123 : value >>= 7;
2790 : 123 : if (value)
2791 : 0 : byte |= 0x80;
2792 : 123 : vec_safe_push (*data_area, byte);
2793 : : }
2794 : 123 : while (value);
2795 : 123 : }
2796 : :
2797 : : static void
2798 : 47016 : push_sleb128 (vec<uchar, va_gc> **data_area, int value)
2799 : : {
2800 : 47016 : unsigned char byte;
2801 : 47016 : int more;
2802 : :
2803 : 47016 : do
2804 : : {
2805 : 47016 : byte = value & 0x7f;
2806 : 47016 : value >>= 7;
2807 : 47016 : more = ! ((value == 0 && (byte & 0x40) == 0)
2808 : 4549 : || (value == -1 && (byte & 0x40) != 0));
2809 : : if (more)
2810 : 0 : byte |= 0x80;
2811 : 47016 : vec_safe_push (*data_area, byte);
2812 : : }
2813 : 47016 : while (more);
2814 : 47016 : }
2815 : :
2816 : :
2817 : : static int
2818 : 0 : dw2_size_of_call_site_table (int section)
2819 : : {
2820 : 0 : int n = vec_safe_length (crtl->eh.call_site_record_v[section]);
2821 : 0 : int size = n * (4 + 4 + 4);
2822 : 0 : int i;
2823 : :
2824 : 0 : for (i = 0; i < n; ++i)
2825 : : {
2826 : 0 : struct call_site_record_d *cs =
2827 : 0 : (*crtl->eh.call_site_record_v[section])[i];
2828 : 0 : size += size_of_uleb128 (cs->action);
2829 : : }
2830 : :
2831 : 0 : return size;
2832 : : }
2833 : :
2834 : : static int
2835 : 0 : sjlj_size_of_call_site_table (void)
2836 : : {
2837 : 0 : int n = vec_safe_length (crtl->eh.call_site_record_v[0]);
2838 : 0 : int size = 0;
2839 : 0 : int i;
2840 : :
2841 : 0 : for (i = 0; i < n; ++i)
2842 : : {
2843 : 0 : struct call_site_record_d *cs =
2844 : 0 : (*crtl->eh.call_site_record_v[0])[i];
2845 : 0 : size += size_of_uleb128 (INTVAL (cs->landing_pad));
2846 : 0 : size += size_of_uleb128 (cs->action);
2847 : : }
2848 : :
2849 : 0 : return size;
2850 : : }
2851 : :
2852 : : static void
2853 : 71598 : dw2_output_call_site_table (int cs_format, int section)
2854 : : {
2855 : 71598 : int n = vec_safe_length (crtl->eh.call_site_record_v[section]);
2856 : 71598 : int i;
2857 : 71598 : const char *begin;
2858 : :
2859 : 71598 : if (section == 0)
2860 : 57922 : begin = current_function_func_begin_label;
2861 : 13676 : else if (first_function_block_is_cold)
2862 : 0 : begin = crtl->subsections.hot_section_label;
2863 : : else
2864 : 13676 : begin = crtl->subsections.cold_section_label;
2865 : :
2866 : 458505 : for (i = 0; i < n; ++i)
2867 : : {
2868 : 386907 : struct call_site_record_d *cs = (*crtl->eh.call_site_record_v[section])[i];
2869 : 386907 : char reg_start_lab[32];
2870 : 386907 : char reg_end_lab[32];
2871 : 386907 : char landing_pad_lab[32];
2872 : :
2873 : 386907 : ASM_GENERATE_INTERNAL_LABEL (reg_start_lab, "LEHB", call_site_base + i);
2874 : 386907 : ASM_GENERATE_INTERNAL_LABEL (reg_end_lab, "LEHE", call_site_base + i);
2875 : :
2876 : 386907 : if (cs->landing_pad)
2877 : 264091 : ASM_GENERATE_INTERNAL_LABEL (landing_pad_lab, "L",
2878 : : CODE_LABEL_NUMBER (cs->landing_pad));
2879 : :
2880 : : /* ??? Perhaps use insn length scaling if the assembler supports
2881 : : generic arithmetic. */
2882 : : /* ??? Perhaps use attr_length to choose data1 or data2 instead of
2883 : : data4 if the function is small enough. */
2884 : 386907 : if (cs_format == DW_EH_PE_uleb128)
2885 : : {
2886 : 386907 : dw2_asm_output_delta_uleb128 (reg_start_lab, begin,
2887 : : "region %d start", i);
2888 : 386907 : dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab,
2889 : : "length");
2890 : 386907 : if (cs->landing_pad)
2891 : 264091 : dw2_asm_output_delta_uleb128 (landing_pad_lab, begin,
2892 : : "landing pad");
2893 : : else
2894 : 122816 : dw2_asm_output_data_uleb128 (0, "landing pad");
2895 : : }
2896 : : else
2897 : : {
2898 : 0 : dw2_asm_output_delta (4, reg_start_lab, begin,
2899 : : "region %d start", i);
2900 : 0 : dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length");
2901 : 0 : if (cs->landing_pad)
2902 : 0 : dw2_asm_output_delta (4, landing_pad_lab, begin,
2903 : : "landing pad");
2904 : : else
2905 : 0 : dw2_asm_output_data (4, 0, "landing pad");
2906 : : }
2907 : 386907 : dw2_asm_output_data_uleb128 (cs->action, "action");
2908 : : }
2909 : :
2910 : 71598 : call_site_base += n;
2911 : 71598 : }
2912 : :
2913 : : static void
2914 : 0 : sjlj_output_call_site_table (void)
2915 : : {
2916 : 0 : int n = vec_safe_length (crtl->eh.call_site_record_v[0]);
2917 : 0 : int i;
2918 : :
2919 : 0 : for (i = 0; i < n; ++i)
2920 : : {
2921 : 0 : struct call_site_record_d *cs = (*crtl->eh.call_site_record_v[0])[i];
2922 : :
2923 : 0 : dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad),
2924 : : "region %d landing pad", i);
2925 : 0 : dw2_asm_output_data_uleb128 (cs->action, "action");
2926 : : }
2927 : :
2928 : 0 : call_site_base += n;
2929 : 0 : }
2930 : :
2931 : : /* Switch to the section that should be used for exception tables. */
2932 : :
2933 : : static void
2934 : 71598 : switch_to_exception_section (const char * ARG_UNUSED (fnname))
2935 : : {
2936 : 71598 : section *s;
2937 : :
2938 : 71598 : if (exception_section)
2939 : : s = exception_section;
2940 : : else
2941 : : {
2942 : 56657 : int flags;
2943 : :
2944 : 56657 : if (EH_TABLES_CAN_BE_READ_ONLY)
2945 : : {
2946 : 56657 : int tt_format =
2947 : 56657 : ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
2948 : 113314 : flags = ((! flag_pic
2949 : 4838 : || ((tt_format & 0x70) != DW_EH_PE_absptr
2950 : 4838 : && (tt_format & 0x70) != DW_EH_PE_aligned))
2951 : 56657 : ? 0 : SECTION_WRITE);
2952 : : }
2953 : : else
2954 : : flags = SECTION_WRITE;
2955 : :
2956 : : /* Compute the section and cache it into exception_section,
2957 : : unless it depends on the function name. */
2958 : 56657 : if (targetm_common.have_named_sections)
2959 : : {
2960 : : #ifdef HAVE_LD_EH_GC_SECTIONS
2961 : 56657 : if (flag_function_sections
2962 : 56657 : || (DECL_COMDAT_GROUP (current_function_decl) && HAVE_COMDAT_GROUP))
2963 : : {
2964 : 47773 : char *section_name = XNEWVEC (char, strlen (fnname) + 32);
2965 : : /* The EH table must match the code section, so only mark
2966 : : it linkonce if we have COMDAT groups to tie them together. */
2967 : 47773 : if (DECL_COMDAT_GROUP (current_function_decl) && HAVE_COMDAT_GROUP)
2968 : 24430 : flags |= SECTION_LINKONCE;
2969 : 47773 : sprintf (section_name, ".gcc_except_table.%s", fnname);
2970 : 47773 : s = get_section (section_name, flags, current_function_decl);
2971 : 47773 : free (section_name);
2972 : : }
2973 : : else
2974 : : #endif
2975 : 8884 : exception_section
2976 : 8884 : = s = get_section (".gcc_except_table", flags, NULL);
2977 : : }
2978 : : else
2979 : 0 : exception_section
2980 : 0 : = s = flags == SECTION_WRITE ? data_section : readonly_data_section;
2981 : : }
2982 : :
2983 : 71598 : switch_to_section (s);
2984 : 71598 : }
2985 : :
2986 : : /* Output a reference from an exception table to the type_info object TYPE.
2987 : : TT_FORMAT and TT_FORMAT_SIZE describe the DWARF encoding method used for
2988 : : the value. */
2989 : :
2990 : : static void
2991 : 24547 : output_ttype (tree type, int tt_format, int tt_format_size)
2992 : : {
2993 : 24547 : rtx value;
2994 : 24547 : bool is_public = true;
2995 : :
2996 : 24547 : if (type == NULL_TREE)
2997 : 19551 : value = const0_rtx;
2998 : : else
2999 : : {
3000 : : /* FIXME lto. pass_ipa_free_lang_data changes all types to
3001 : : runtime types so TYPE should already be a runtime type
3002 : : reference. When pass_ipa_free_lang data is made a default
3003 : : pass, we can then remove the call to lookup_type_for_runtime
3004 : : below. */
3005 : 4996 : if (TYPE_P (type))
3006 : 4800 : type = lookup_type_for_runtime (type);
3007 : :
3008 : 4996 : value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
3009 : :
3010 : : /* Let cgraph know that the rtti decl is used. Not all of the
3011 : : paths below go through assemble_integer, which would take
3012 : : care of this for us. */
3013 : 4996 : STRIP_NOPS (type);
3014 : 4996 : if (TREE_CODE (type) == ADDR_EXPR)
3015 : : {
3016 : 4996 : type = TREE_OPERAND (type, 0);
3017 : 4996 : if (VAR_P (type))
3018 : 4996 : is_public = TREE_PUBLIC (type);
3019 : : }
3020 : : else
3021 : 0 : gcc_assert (TREE_CODE (type) == INTEGER_CST);
3022 : : }
3023 : :
3024 : : /* Allow the target to override the type table entry format. */
3025 : 24547 : if (targetm.asm_out.ttype (value))
3026 : : return;
3027 : :
3028 : 24547 : if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned)
3029 : 3061 : assemble_integer (value, tt_format_size,
3030 : 3061 : tt_format_size * BITS_PER_UNIT, 1);
3031 : : else
3032 : 21486 : dw2_asm_output_encoded_addr_rtx (tt_format, value, is_public, NULL);
3033 : : }
3034 : :
3035 : : /* Output an exception table for the current function according to SECTION.
3036 : :
3037 : : If the function has been partitioned into hot and cold parts, value 0 for
3038 : : SECTION refers to the table associated with the hot part while value 1
3039 : : refers to the table associated with the cold part. If the function has
3040 : : not been partitioned, value 0 refers to the single exception table. */
3041 : :
3042 : : static void
3043 : 71598 : output_one_function_exception_table (int section)
3044 : : {
3045 : 71598 : int tt_format, cs_format, lp_format, i;
3046 : 71598 : char ttype_label[32];
3047 : 71598 : char cs_after_size_label[32];
3048 : 71598 : char cs_end_label[32];
3049 : 71598 : int call_site_len;
3050 : 71598 : int have_tt_data;
3051 : 71598 : int tt_format_size = 0;
3052 : :
3053 : 71598 : have_tt_data = (vec_safe_length (cfun->eh->ttype_data)
3054 : 120460 : || (targetm.arm_eabi_unwinder
3055 : 49444 : ? vec_safe_length (cfun->eh->ehspec_data.arm_eabi)
3056 : 49444 : : vec_safe_length (cfun->eh->ehspec_data.other)));
3057 : :
3058 : : /* Indicate the format of the @TType entries. */
3059 : 22394 : if (! have_tt_data)
3060 : : tt_format = DW_EH_PE_omit;
3061 : : else
3062 : : {
3063 : 22394 : tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
3064 : 22394 : if (HAVE_AS_LEB128)
3065 : 41656 : ASM_GENERATE_INTERNAL_LABEL (ttype_label,
3066 : : section ? "LLSDATTC" : "LLSDATT",
3067 : : current_function_funcdef_no);
3068 : :
3069 : 22394 : tt_format_size = size_of_encoded_value (tt_format);
3070 : :
3071 : 22394 : assemble_align (tt_format_size * BITS_PER_UNIT);
3072 : : }
3073 : :
3074 : 71598 : targetm.asm_out.internal_label (asm_out_file, section ? "LLSDAC" : "LLSDA",
3075 : 71598 : current_function_funcdef_no);
3076 : :
3077 : : /* The LSDA header. */
3078 : :
3079 : : /* Indicate the format of the landing pad start pointer. An omitted
3080 : : field implies @LPStart == @Start. */
3081 : : /* Currently we always put @LPStart == @Start. This field would
3082 : : be most useful in moving the landing pads completely out of
3083 : : line to another section, but it could also be used to minimize
3084 : : the size of uleb128 landing pad offsets. */
3085 : 71598 : lp_format = DW_EH_PE_omit;
3086 : 71598 : dw2_asm_output_data (1, lp_format, "@LPStart format (%s)",
3087 : : eh_data_format_name (lp_format));
3088 : :
3089 : : /* @LPStart pointer would go here. */
3090 : :
3091 : 71598 : dw2_asm_output_data (1, tt_format, "@TType format (%s)",
3092 : : eh_data_format_name (tt_format));
3093 : :
3094 : 71598 : if (!HAVE_AS_LEB128)
3095 : : {
3096 : : if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ)
3097 : : call_site_len = sjlj_size_of_call_site_table ();
3098 : : else
3099 : : call_site_len = dw2_size_of_call_site_table (section);
3100 : : }
3101 : :
3102 : : /* A pc-relative 4-byte displacement to the @TType data. */
3103 : 71598 : if (have_tt_data)
3104 : : {
3105 : 22394 : if (HAVE_AS_LEB128)
3106 : : {
3107 : 22394 : char ttype_after_disp_label[32];
3108 : 41656 : ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label,
3109 : : section ? "LLSDATTDC" : "LLSDATTD",
3110 : : current_function_funcdef_no);
3111 : 22394 : dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
3112 : : "@TType base offset");
3113 : 22394 : ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
3114 : : }
3115 : : else
3116 : : {
3117 : : /* Ug. Alignment queers things. */
3118 : : unsigned int before_disp, after_disp, last_disp, disp;
3119 : :
3120 : : before_disp = 1 + 1;
3121 : : after_disp = (1 + size_of_uleb128 (call_site_len)
3122 : : + call_site_len
3123 : : + vec_safe_length (crtl->eh.action_record_data)
3124 : : + (vec_safe_length (cfun->eh->ttype_data)
3125 : : * tt_format_size));
3126 : :
3127 : : disp = after_disp;
3128 : : do
3129 : : {
3130 : : unsigned int disp_size, pad;
3131 : :
3132 : : last_disp = disp;
3133 : : disp_size = size_of_uleb128 (disp);
3134 : : pad = before_disp + disp_size + after_disp;
3135 : : if (pad % tt_format_size)
3136 : : pad = tt_format_size - (pad % tt_format_size);
3137 : : else
3138 : : pad = 0;
3139 : : disp = after_disp + pad;
3140 : : }
3141 : : while (disp != last_disp);
3142 : :
3143 : : dw2_asm_output_data_uleb128 (disp, "@TType base offset");
3144 : : }
3145 : : }
3146 : :
3147 : : /* Indicate the format of the call-site offsets. */
3148 : 71598 : if (HAVE_AS_LEB128)
3149 : 71598 : cs_format = DW_EH_PE_uleb128;
3150 : : else
3151 : : cs_format = DW_EH_PE_udata4;
3152 : :
3153 : 71598 : dw2_asm_output_data (1, cs_format, "call-site format (%s)",
3154 : : eh_data_format_name (cs_format));
3155 : :
3156 : 71598 : if (HAVE_AS_LEB128)
3157 : : {
3158 : 129520 : ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label,
3159 : : section ? "LLSDACSBC" : "LLSDACSB",
3160 : : current_function_funcdef_no);
3161 : 129520 : ASM_GENERATE_INTERNAL_LABEL (cs_end_label,
3162 : : section ? "LLSDACSEC" : "LLSDACSE",
3163 : : current_function_funcdef_no);
3164 : 71598 : dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
3165 : : "Call-site table length");
3166 : 71598 : ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
3167 : 71598 : if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ)
3168 : 0 : sjlj_output_call_site_table ();
3169 : : else
3170 : 71598 : dw2_output_call_site_table (cs_format, section);
3171 : 71598 : ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
3172 : : }
3173 : : else
3174 : : {
3175 : : dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length");
3176 : : if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ)
3177 : : sjlj_output_call_site_table ();
3178 : : else
3179 : : dw2_output_call_site_table (cs_format, section);
3180 : : }
3181 : :
3182 : : /* ??? Decode and interpret the data for flag_debug_asm. */
3183 : 71598 : {
3184 : 71598 : uchar uc;
3185 : 199144 : FOR_EACH_VEC_ELT (*crtl->eh.action_record_data, i, uc)
3186 : 89717 : dw2_asm_output_data (1, uc, i ? NULL : "Action record table");
3187 : : }
3188 : :
3189 : 71598 : if (have_tt_data)
3190 : 22394 : assemble_align (tt_format_size * BITS_PER_UNIT);
3191 : :
3192 : 71598 : i = vec_safe_length (cfun->eh->ttype_data);
3193 : 96145 : while (i-- > 0)
3194 : : {
3195 : 24547 : tree type = (*cfun->eh->ttype_data)[i];
3196 : 24547 : output_ttype (type, tt_format, tt_format_size);
3197 : : }
3198 : :
3199 : 71598 : if (HAVE_AS_LEB128 && have_tt_data)
3200 : 22394 : ASM_OUTPUT_LABEL (asm_out_file, ttype_label);
3201 : :
3202 : : /* ??? Decode and interpret the data for flag_debug_asm. */
3203 : 71598 : if (targetm.arm_eabi_unwinder)
3204 : : {
3205 : : tree type;
3206 : 0 : for (i = 0;
3207 : 0 : vec_safe_iterate (cfun->eh->ehspec_data.arm_eabi, i, &type); ++i)
3208 : 0 : output_ttype (type, tt_format, tt_format_size);
3209 : : }
3210 : : else
3211 : : {
3212 : : uchar uc;
3213 : 505 : for (i = 0;
3214 : 72103 : vec_safe_iterate (cfun->eh->ehspec_data.other, i, &uc); ++i)
3215 : 630 : dw2_asm_output_data (1, uc,
3216 : : i ? NULL : "Exception specification table");
3217 : : }
3218 : 71598 : }
3219 : :
3220 : : /* Output an exception table for the current function according to SECTION,
3221 : : switching back and forth from the function section appropriately.
3222 : :
3223 : : If the function has been partitioned into hot and cold parts, value 0 for
3224 : : SECTION refers to the table associated with the hot part while value 1
3225 : : refers to the table associated with the cold part. If the function has
3226 : : not been partitioned, value 0 refers to the single exception table. */
3227 : :
3228 : : void
3229 : 1487570 : output_function_exception_table (int section)
3230 : : {
3231 : : /* Not all functions need anything. */
3232 : 1487570 : if (!crtl->uses_eh_lsda
3233 : 1487570 : || targetm_common.except_unwind_info (&global_options) == UI_NONE)
3234 : 1415972 : return;
3235 : :
3236 : : /* No need to emit any boilerplate stuff for the cold part. */
3237 : 71598 : if (section == 1 && !crtl->eh.call_site_record_v[1])
3238 : : return;
3239 : :
3240 : 71598 : const char *fnname = get_fnname_from_decl (current_function_decl);
3241 : 71598 : rtx personality = get_personality_function (current_function_decl);
3242 : :
3243 : 71598 : if (personality)
3244 : : {
3245 : 71598 : assemble_external_libcall (personality);
3246 : :
3247 : 71598 : if (targetm.asm_out.emit_except_personality)
3248 : 0 : targetm.asm_out.emit_except_personality (personality);
3249 : : }
3250 : :
3251 : 71598 : switch_to_exception_section (fnname);
3252 : :
3253 : : /* If the target wants a label to begin the table, emit it here. */
3254 : 71598 : targetm.asm_out.emit_except_table_label (asm_out_file);
3255 : :
3256 : : /* Do the real work. */
3257 : 71598 : output_one_function_exception_table (section);
3258 : :
3259 : 71598 : switch_to_section (current_function_section ());
3260 : : }
3261 : :
3262 : : void
3263 : 1784552 : set_eh_throw_stmt_table (function *fun, hash_map<gimple *, int> *table)
3264 : : {
3265 : 1784552 : fun->eh->throw_stmt_table = table;
3266 : 1784552 : }
3267 : :
3268 : : hash_map<gimple *, int> *
3269 : 625719636 : get_eh_throw_stmt_table (struct function *fun)
3270 : : {
3271 : 625719636 : return fun->eh->throw_stmt_table;
3272 : : }
3273 : :
3274 : : /* Determine if the function needs an EH personality function. */
3275 : :
3276 : : enum eh_personality_kind
3277 : 5049482 : function_needs_eh_personality (struct function *fn)
3278 : : {
3279 : 5049482 : enum eh_personality_kind kind = eh_personality_none;
3280 : 5049482 : eh_region i;
3281 : :
3282 : 5917683 : FOR_ALL_EH_REGION_FN (i, fn)
3283 : : {
3284 : 1737372 : switch (i->type)
3285 : : {
3286 : 868201 : case ERT_CLEANUP:
3287 : : /* Can do with any personality including the generic C one. */
3288 : 868201 : kind = eh_personality_any;
3289 : 868201 : break;
3290 : :
3291 : : case ERT_TRY:
3292 : : case ERT_ALLOWED_EXCEPTIONS:
3293 : : /* Always needs a EH personality function. The generic C
3294 : : personality doesn't handle these even for empty type lists. */
3295 : : return eh_personality_lang;
3296 : :
3297 : : case ERT_MUST_NOT_THROW:
3298 : : /* Always needs a EH personality function. The language may specify
3299 : : what abort routine that must be used, e.g. std::terminate. */
3300 : : return eh_personality_lang;
3301 : : }
3302 : : }
3303 : :
3304 : : return kind;
3305 : : }
3306 : :
3307 : : /* Dump EH information to OUT. */
3308 : :
3309 : : void
3310 : 627 : dump_eh_tree (FILE * out, struct function *fun)
3311 : : {
3312 : 627 : eh_region i;
3313 : 627 : int depth = 0;
3314 : 627 : static const char *const type_name[] = {
3315 : : "cleanup", "try", "allowed_exceptions", "must_not_throw"
3316 : : };
3317 : :
3318 : 627 : i = fun->eh->region_tree;
3319 : 627 : if (!i)
3320 : : return;
3321 : :
3322 : 41 : fprintf (out, "Eh tree:\n");
3323 : 94 : while (1)
3324 : : {
3325 : 94 : fprintf (out, " %*s %i %s", depth * 2, "",
3326 : 94 : i->index, type_name[(int) i->type]);
3327 : :
3328 : 94 : if (i->landing_pads)
3329 : : {
3330 : 29 : eh_landing_pad lp;
3331 : :
3332 : 29 : fprintf (out, " land:");
3333 : 29 : if (current_ir_type () == IR_GIMPLE)
3334 : : {
3335 : 58 : for (lp = i->landing_pads; lp ; lp = lp->next_lp)
3336 : : {
3337 : 29 : fprintf (out, "{%i,", lp->index);
3338 : 29 : print_generic_expr (out, lp->post_landing_pad);
3339 : 29 : fputc ('}', out);
3340 : 29 : if (lp->next_lp)
3341 : 0 : fputc (',', out);
3342 : : }
3343 : : }
3344 : : else
3345 : : {
3346 : 0 : for (lp = i->landing_pads; lp ; lp = lp->next_lp)
3347 : : {
3348 : 0 : fprintf (out, "{%i,", lp->index);
3349 : 0 : if (lp->landing_pad)
3350 : 0 : fprintf (out, "%i%s,", INSN_UID (lp->landing_pad),
3351 : 0 : NOTE_P (lp->landing_pad) ? "(del)" : "");
3352 : : else
3353 : 0 : fprintf (out, "(nil),");
3354 : 0 : if (lp->post_landing_pad)
3355 : : {
3356 : 0 : rtx_insn *lab = label_rtx (lp->post_landing_pad);
3357 : 0 : fprintf (out, "%i%s}", INSN_UID (lab),
3358 : 0 : NOTE_P (lab) ? "(del)" : "");
3359 : : }
3360 : : else
3361 : 0 : fprintf (out, "(nil)}");
3362 : 0 : if (lp->next_lp)
3363 : 0 : fputc (',', out);
3364 : : }
3365 : : }
3366 : : }
3367 : :
3368 : 94 : switch (i->type)
3369 : : {
3370 : : case ERT_CLEANUP:
3371 : : case ERT_MUST_NOT_THROW:
3372 : : break;
3373 : :
3374 : 0 : case ERT_TRY:
3375 : 0 : {
3376 : 0 : eh_catch c;
3377 : 0 : fprintf (out, " catch:");
3378 : 0 : for (c = i->u.eh_try.first_catch; c; c = c->next_catch)
3379 : : {
3380 : 0 : fputc ('{', out);
3381 : 0 : if (c->label)
3382 : : {
3383 : 0 : fprintf (out, "lab:");
3384 : 0 : print_generic_expr (out, c->label);
3385 : 0 : fputc (';', out);
3386 : : }
3387 : 0 : print_generic_expr (out, c->type_list);
3388 : 0 : fputc ('}', out);
3389 : 0 : if (c->next_catch)
3390 : 0 : fputc (',', out);
3391 : : }
3392 : : }
3393 : : break;
3394 : :
3395 : 0 : case ERT_ALLOWED_EXCEPTIONS:
3396 : 0 : fprintf (out, " filter :%i types:", i->u.allowed.filter);
3397 : 0 : print_generic_expr (out, i->u.allowed.type_list);
3398 : 0 : break;
3399 : : }
3400 : 94 : fputc ('\n', out);
3401 : :
3402 : : /* If there are sub-regions, process them. */
3403 : 94 : if (i->inner)
3404 : 30 : i = i->inner, depth++;
3405 : : /* If there are peers, process them. */
3406 : 64 : else if (i->next_peer)
3407 : : i = i->next_peer;
3408 : : /* Otherwise, step back up the tree to the next peer. */
3409 : : else
3410 : : {
3411 : 71 : do
3412 : : {
3413 : 71 : i = i->outer;
3414 : 71 : depth--;
3415 : 71 : if (i == NULL)
3416 : : return;
3417 : : }
3418 : 30 : while (i->next_peer == NULL);
3419 : : i = i->next_peer;
3420 : : }
3421 : : }
3422 : : }
3423 : :
3424 : : /* Dump the EH tree for FN on stderr. */
3425 : :
3426 : : DEBUG_FUNCTION void
3427 : 0 : debug_eh_tree (struct function *fn)
3428 : : {
3429 : 0 : dump_eh_tree (stderr, fn);
3430 : 0 : }
3431 : :
3432 : : /* Verify invariants on EH datastructures. */
3433 : :
3434 : : DEBUG_FUNCTION void
3435 : 8960491 : verify_eh_tree (struct function *fun)
3436 : : {
3437 : 8960491 : eh_region r, outer;
3438 : 8960491 : int nvisited_lp, nvisited_r;
3439 : 8960491 : int count_lp, count_r, depth, i;
3440 : 8960491 : eh_landing_pad lp;
3441 : 8960491 : bool err = false;
3442 : :
3443 : 8960491 : if (!fun->eh->region_tree)
3444 : 8960491 : return;
3445 : :
3446 : : count_r = 0;
3447 : 94133499 : for (i = 1; vec_safe_iterate (fun->eh->region_array, i, &r); ++i)
3448 : 91157433 : if (r)
3449 : : {
3450 : 57642278 : if (r->index == i)
3451 : 57642278 : count_r++;
3452 : : else
3453 : : {
3454 : 0 : error ("%<region_array%> is corrupted for region %i", r->index);
3455 : 0 : err = true;
3456 : : }
3457 : : }
3458 : :
3459 : : count_lp = 0;
3460 : 44212314 : for (i = 1; vec_safe_iterate (fun->eh->lp_array, i, &lp); ++i)
3461 : 41236248 : if (lp)
3462 : : {
3463 : 32077958 : if (lp->index == i)
3464 : 32077958 : count_lp++;
3465 : : else
3466 : : {
3467 : 0 : error ("%<lp_array%> is corrupted for lp %i", lp->index);
3468 : 0 : err = true;
3469 : : }
3470 : : }
3471 : :
3472 : 2976066 : depth = nvisited_lp = nvisited_r = 0;
3473 : 2976066 : outer = NULL;
3474 : 2976066 : r = fun->eh->region_tree;
3475 : 57642278 : while (1)
3476 : : {
3477 : 57642278 : if ((*fun->eh->region_array)[r->index] != r)
3478 : : {
3479 : 0 : error ("%<region_array%> is corrupted for region %i", r->index);
3480 : 0 : err = true;
3481 : : }
3482 : 57642278 : if (r->outer != outer)
3483 : : {
3484 : 0 : error ("outer block of region %i is wrong", r->index);
3485 : 0 : err = true;
3486 : : }
3487 : 57642278 : if (depth < 0)
3488 : : {
3489 : 0 : error ("negative nesting depth of region %i", r->index);
3490 : 0 : err = true;
3491 : : }
3492 : 57642278 : nvisited_r++;
3493 : :
3494 : 89720236 : for (lp = r->landing_pads; lp ; lp = lp->next_lp)
3495 : : {
3496 : 32077958 : if ((*fun->eh->lp_array)[lp->index] != lp)
3497 : : {
3498 : 0 : error ("%<lp_array%> is corrupted for lp %i", lp->index);
3499 : 0 : err = true;
3500 : : }
3501 : 32077958 : if (lp->region != r)
3502 : : {
3503 : 0 : error ("region of lp %i is wrong", lp->index);
3504 : 0 : err = true;
3505 : : }
3506 : 32077958 : nvisited_lp++;
3507 : : }
3508 : :
3509 : 57642278 : if (r->inner)
3510 : 20194188 : outer = r, r = r->inner, depth++;
3511 : 37448090 : else if (r->next_peer)
3512 : : r = r->next_peer;
3513 : : else
3514 : : {
3515 : 23170254 : do
3516 : : {
3517 : 23170254 : r = r->outer;
3518 : 23170254 : if (r == NULL)
3519 : 2976066 : goto region_done;
3520 : 20194188 : depth--;
3521 : 20194188 : outer = r->outer;
3522 : : }
3523 : 20194188 : while (r->next_peer == NULL);
3524 : : r = r->next_peer;
3525 : : }
3526 : : }
3527 : 2976066 : region_done:
3528 : 2976066 : if (depth != 0)
3529 : : {
3530 : 0 : error ("tree list ends on depth %i", depth);
3531 : 0 : err = true;
3532 : : }
3533 : 2976066 : if (count_r != nvisited_r)
3534 : : {
3535 : 0 : error ("%<region_array%> does not match %<region_tree%>");
3536 : 0 : err = true;
3537 : : }
3538 : 2976066 : if (count_lp != nvisited_lp)
3539 : : {
3540 : 0 : error ("%<lp_array%> does not match %<region_tree%>");
3541 : 0 : err = true;
3542 : : }
3543 : :
3544 : 2976066 : if (err)
3545 : : {
3546 : 0 : dump_eh_tree (stderr, fun);
3547 : 0 : internal_error ("%qs failed", __func__);
3548 : : }
3549 : : }
3550 : :
3551 : : #include "gt-except.h"
|