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