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