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