OSDN Git Service

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