OSDN Git Service

Revert r174848,174849
[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 (size_int (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 = size_int (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 = size_int (FIRST_PSEUDO_REGISTER + 2 - 1);
255 #endif
256 #else
257       /* builtin_setjmp takes a pointer to 5 words.  */
258       tmp = size_int (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 (integer_type_node, 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 (integer_type_node, 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, t;
1289
1290             t_label = create_artificial_label (UNKNOWN_LOCATION);
1291             t = build_int_cst (integer_type_node, disp_index);
1292             case_elt = build_case_label (t, NULL, t_label);
1293             gimple_switch_set_label (switch_stmt, disp_index, case_elt);
1294
1295             label = label_rtx (t_label);
1296           }
1297         else
1298           label = gen_label_rtx ();
1299
1300         if (disp_index == 0)
1301           first_reachable_label = label;
1302         emit_label (label);
1303
1304         r = lp->region;
1305         if (r->exc_ptr_reg)
1306           emit_move_insn (r->exc_ptr_reg, exc_ptr_reg);
1307         if (r->filter_reg)
1308           emit_move_insn (r->filter_reg, filter_reg);
1309
1310         seq2 = get_insns ();
1311         end_sequence ();
1312
1313         before = label_rtx (lp->post_landing_pad);
1314         bb = emit_to_new_bb_before (seq2, before);
1315         e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
1316         e->count = bb->count;
1317         e->probability = REG_BR_PROB_BASE;
1318
1319         disp_index++;
1320       }
1321   gcc_assert (disp_index == num_dispatch);
1322
1323   if (num_dispatch > 1)
1324     {
1325       expand_case (switch_stmt);
1326       expand_builtin_trap ();
1327     }
1328
1329   seq = get_insns ();
1330   end_sequence ();
1331
1332   bb = emit_to_new_bb_before (seq, first_reachable_label);
1333   if (num_dispatch == 1)
1334     {
1335       e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
1336       e->count = bb->count;
1337       e->probability = REG_BR_PROB_BASE;
1338     }
1339 }
1340
1341 static void
1342 sjlj_build_landing_pads (void)
1343 {
1344   int num_dispatch;
1345
1346   num_dispatch = VEC_length (eh_landing_pad, cfun->eh->lp_array);
1347   if (num_dispatch == 0)
1348     return;
1349   VEC_safe_grow (int, heap, sjlj_lp_call_site_index, num_dispatch);
1350
1351   num_dispatch = sjlj_assign_call_site_values ();
1352   if (num_dispatch > 0)
1353     {
1354       rtx dispatch_label = gen_label_rtx ();
1355       int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
1356                                         TYPE_MODE (sjlj_fc_type_node),
1357                                         TYPE_ALIGN (sjlj_fc_type_node));
1358       crtl->eh.sjlj_fc
1359         = assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
1360                               int_size_in_bytes (sjlj_fc_type_node),
1361                               align);
1362
1363       sjlj_mark_call_sites ();
1364       sjlj_emit_function_enter (dispatch_label);
1365       sjlj_emit_dispatch_table (dispatch_label, num_dispatch);
1366       sjlj_emit_function_exit ();
1367     }
1368
1369   /* If we do not have any landing pads, we may still need to register a
1370      personality routine and (empty) LSDA to handle must-not-throw regions.  */
1371   else if (function_needs_eh_personality (cfun) != eh_personality_none)
1372     {
1373       int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
1374                                         TYPE_MODE (sjlj_fc_type_node),
1375                                         TYPE_ALIGN (sjlj_fc_type_node));
1376       crtl->eh.sjlj_fc
1377         = assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
1378                               int_size_in_bytes (sjlj_fc_type_node),
1379                               align);
1380
1381       sjlj_mark_call_sites ();
1382       sjlj_emit_function_enter (NULL_RTX);
1383       sjlj_emit_function_exit ();
1384     }
1385
1386   VEC_free (int, heap, sjlj_lp_call_site_index);
1387 }
1388
1389 /* After initial rtl generation, call back to finish generating
1390    exception support code.  */
1391
1392 static void
1393 finish_eh_generation (void)
1394 {
1395   basic_block bb;
1396
1397   /* Construct the landing pads.  */
1398   if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
1399     sjlj_build_landing_pads ();
1400   else
1401     dw2_build_landing_pads ();
1402   break_superblocks ();
1403
1404   if (targetm.except_unwind_info (&global_options) == UI_SJLJ
1405       /* Kludge for Alpha/Tru64 (see alpha_gp_save_rtx).  */
1406       || single_succ_edge (ENTRY_BLOCK_PTR)->insns.r)
1407     commit_edge_insertions ();
1408
1409   /* Redirect all EH edges from the post_landing_pad to the landing pad.  */
1410   FOR_EACH_BB (bb)
1411     {
1412       eh_landing_pad lp;
1413       edge_iterator ei;
1414       edge e;
1415
1416       lp = get_eh_landing_pad_from_rtx (BB_END (bb));
1417
1418       FOR_EACH_EDGE (e, ei, bb->succs)
1419         if (e->flags & EDGE_EH)
1420           break;
1421
1422       /* We should not have generated any new throwing insns during this
1423          pass, and we should not have lost any EH edges, so we only need
1424          to handle two cases here:
1425          (1) reachable handler and an existing edge to post-landing-pad,
1426          (2) no reachable handler and no edge.  */
1427       gcc_assert ((lp != NULL) == (e != NULL));
1428       if (lp != NULL)
1429         {
1430           gcc_assert (BB_HEAD (e->dest) == label_rtx (lp->post_landing_pad));
1431
1432           redirect_edge_succ (e, BLOCK_FOR_INSN (lp->landing_pad));
1433           e->flags |= (CALL_P (BB_END (bb))
1434                        ? EDGE_ABNORMAL | EDGE_ABNORMAL_CALL
1435                        : EDGE_ABNORMAL);
1436         }
1437     }
1438 }
1439
1440 static bool
1441 gate_handle_eh (void)
1442 {
1443   /* Nothing to do if no regions created.  */
1444   return cfun->eh->region_tree != NULL;
1445 }
1446
1447 /* Complete generation of exception handling code.  */
1448 static unsigned int
1449 rest_of_handle_eh (void)
1450 {
1451   finish_eh_generation ();
1452   cleanup_cfg (CLEANUP_NO_INSN_DEL);
1453   return 0;
1454 }
1455
1456 struct rtl_opt_pass pass_rtl_eh =
1457 {
1458  {
1459   RTL_PASS,
1460   "rtl_eh",                             /* name */
1461   gate_handle_eh,                       /* gate */
1462   rest_of_handle_eh,                    /* execute */
1463   NULL,                                 /* sub */
1464   NULL,                                 /* next */
1465   0,                                    /* static_pass_number */
1466   TV_JUMP,                              /* tv_id */
1467   0,                                    /* properties_required */
1468   0,                                    /* properties_provided */
1469   0,                                    /* properties_destroyed */
1470   0,                                    /* todo_flags_start */
1471   TODO_dump_func                        /* todo_flags_finish */
1472  }
1473 };
1474 \f
1475 /* This section handles removing dead code for flow.  */
1476
1477 void
1478 remove_eh_landing_pad (eh_landing_pad lp)
1479 {
1480   eh_landing_pad *pp;
1481
1482   for (pp = &lp->region->landing_pads; *pp != lp; pp = &(*pp)->next_lp)
1483     continue;
1484   *pp = lp->next_lp;
1485
1486   if (lp->post_landing_pad)
1487     EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
1488   VEC_replace (eh_landing_pad, cfun->eh->lp_array, lp->index, NULL);
1489 }
1490
1491 /* Splice REGION from the region tree.  */
1492
1493 void
1494 remove_eh_handler (eh_region region)
1495 {
1496   eh_region *pp, *pp_start, p, outer;
1497   eh_landing_pad lp;
1498
1499   for (lp = region->landing_pads; lp ; lp = lp->next_lp)
1500     {
1501       if (lp->post_landing_pad)
1502         EH_LANDING_PAD_NR (lp->post_landing_pad) = 0;
1503       VEC_replace (eh_landing_pad, cfun->eh->lp_array, lp->index, NULL);
1504     }
1505
1506   outer = region->outer;
1507   if (outer)
1508     pp_start = &outer->inner;
1509   else
1510     pp_start = &cfun->eh->region_tree;
1511   for (pp = pp_start, p = *pp; p != region; pp = &p->next_peer, p = *pp)
1512     continue;
1513   if (region->inner)
1514     {
1515       *pp = p = region->inner;
1516       do
1517         {
1518           p->outer = outer;
1519           pp = &p->next_peer;
1520           p = *pp;
1521         }
1522       while (p);
1523     }
1524   *pp = region->next_peer;
1525
1526   VEC_replace (eh_region, cfun->eh->region_array, region->index, NULL);
1527 }
1528
1529 /* Invokes CALLBACK for every exception handler landing pad label.
1530    Only used by reload hackery; should not be used by new code.  */
1531
1532 void
1533 for_each_eh_label (void (*callback) (rtx))
1534 {
1535   eh_landing_pad lp;
1536   int i;
1537
1538   for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
1539     {
1540       if (lp)
1541         {
1542           rtx lab = lp->landing_pad;
1543           if (lab && LABEL_P (lab))
1544             (*callback) (lab);
1545         }
1546     }
1547 }
1548 \f
1549 /* Create the REG_EH_REGION note for INSN, given its ECF_FLAGS for a
1550    call insn.
1551
1552    At the gimple level, we use LP_NR
1553        > 0 : The statement transfers to landing pad LP_NR
1554        = 0 : The statement is outside any EH region
1555        < 0 : The statement is within MUST_NOT_THROW region -LP_NR.
1556
1557    At the rtl level, we use LP_NR
1558        > 0 : The insn transfers to landing pad LP_NR
1559        = 0 : The insn cannot throw
1560        < 0 : The insn is within MUST_NOT_THROW region -LP_NR
1561        = INT_MIN : The insn cannot throw or execute a nonlocal-goto.
1562        missing note: The insn is outside any EH region.
1563
1564   ??? This difference probably ought to be avoided.  We could stand
1565   to record nothrow for arbitrary gimple statements, and so avoid
1566   some moderately complex lookups in stmt_could_throw_p.  Perhaps
1567   NOTHROW should be mapped on both sides to INT_MIN.  Perhaps the
1568   no-nonlocal-goto property should be recorded elsewhere as a bit
1569   on the call_insn directly.  Perhaps we should make more use of
1570   attaching the trees to call_insns (reachable via symbol_ref in
1571   direct call cases) and just pull the data out of the trees.  */
1572
1573 void
1574 make_reg_eh_region_note (rtx insn, int ecf_flags, int lp_nr)
1575 {
1576   rtx value;
1577   if (ecf_flags & ECF_NOTHROW)
1578     value = const0_rtx;
1579   else if (lp_nr != 0)
1580     value = GEN_INT (lp_nr);
1581   else
1582     return;
1583   add_reg_note (insn, REG_EH_REGION, value);
1584 }
1585
1586 /* Create a REG_EH_REGION note for a CALL_INSN that cannot throw
1587    nor perform a non-local goto.  Replace the region note if it
1588    already exists.  */
1589
1590 void
1591 make_reg_eh_region_note_nothrow_nononlocal (rtx insn)
1592 {
1593   rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1594   rtx intmin = GEN_INT (INT_MIN);
1595
1596   if (note != 0)
1597     XEXP (note, 0) = intmin;
1598   else
1599     add_reg_note (insn, REG_EH_REGION, intmin);
1600 }
1601
1602 /* Return true if INSN could throw, assuming no REG_EH_REGION note
1603    to the contrary.  */
1604
1605 bool
1606 insn_could_throw_p (const_rtx insn)
1607 {
1608   if (!flag_exceptions)
1609     return false;
1610   if (CALL_P (insn))
1611     return true;
1612   if (INSN_P (insn) && cfun->can_throw_non_call_exceptions)
1613     return may_trap_p (PATTERN (insn));
1614   return false;
1615 }
1616
1617 /* Copy an REG_EH_REGION note to each insn that might throw beginning
1618    at FIRST and ending at LAST.  NOTE_OR_INSN is either the source insn
1619    to look for a note, or the note itself.  */
1620
1621 void
1622 copy_reg_eh_region_note_forward (rtx note_or_insn, rtx first, rtx last)
1623 {
1624   rtx insn, note = note_or_insn;
1625
1626   if (INSN_P (note_or_insn))
1627     {
1628       note = find_reg_note (note_or_insn, REG_EH_REGION, NULL_RTX);
1629       if (note == NULL)
1630         return;
1631     }
1632   note = XEXP (note, 0);
1633
1634   for (insn = first; insn != last ; insn = NEXT_INSN (insn))
1635     if (!find_reg_note (insn, REG_EH_REGION, NULL_RTX)
1636         && insn_could_throw_p (insn))
1637       add_reg_note (insn, REG_EH_REGION, note);
1638 }
1639
1640 /* Likewise, but iterate backward.  */
1641
1642 void
1643 copy_reg_eh_region_note_backward (rtx note_or_insn, rtx last, rtx first)
1644 {
1645   rtx insn, note = note_or_insn;
1646
1647   if (INSN_P (note_or_insn))
1648     {
1649       note = find_reg_note (note_or_insn, REG_EH_REGION, NULL_RTX);
1650       if (note == NULL)
1651         return;
1652     }
1653   note = XEXP (note, 0);
1654
1655   for (insn = last; insn != first; insn = PREV_INSN (insn))
1656     if (insn_could_throw_p (insn))
1657       add_reg_note (insn, REG_EH_REGION, note);
1658 }
1659
1660
1661 /* Extract all EH information from INSN.  Return true if the insn
1662    was marked NOTHROW.  */
1663
1664 static bool
1665 get_eh_region_and_lp_from_rtx (const_rtx insn, eh_region *pr,
1666                                eh_landing_pad *plp)
1667 {
1668   eh_landing_pad lp = NULL;
1669   eh_region r = NULL;
1670   bool ret = false;
1671   rtx note;
1672   int lp_nr;
1673
1674   if (! INSN_P (insn))
1675     goto egress;
1676
1677   if (NONJUMP_INSN_P (insn)
1678       && GET_CODE (PATTERN (insn)) == SEQUENCE)
1679     insn = XVECEXP (PATTERN (insn), 0, 0);
1680
1681   note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1682   if (!note)
1683     {
1684       ret = !insn_could_throw_p (insn);
1685       goto egress;
1686     }
1687
1688   lp_nr = INTVAL (XEXP (note, 0));
1689   if (lp_nr == 0 || lp_nr == INT_MIN)
1690     {
1691       ret = true;
1692       goto egress;
1693     }
1694
1695   if (lp_nr < 0)
1696     r = VEC_index (eh_region, cfun->eh->region_array, -lp_nr);
1697   else
1698     {
1699       lp = VEC_index (eh_landing_pad, cfun->eh->lp_array, lp_nr);
1700       r = lp->region;
1701     }
1702
1703  egress:
1704   *plp = lp;
1705   *pr = r;
1706   return ret;
1707 }
1708
1709 /* Return the landing pad to which INSN may go, or NULL if it does not
1710    have a reachable landing pad within this function.  */
1711
1712 eh_landing_pad
1713 get_eh_landing_pad_from_rtx (const_rtx insn)
1714 {
1715   eh_landing_pad lp;
1716   eh_region r;
1717
1718   get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1719   return lp;
1720 }
1721
1722 /* Return the region to which INSN may go, or NULL if it does not
1723    have a reachable region within this function.  */
1724
1725 eh_region
1726 get_eh_region_from_rtx (const_rtx insn)
1727 {
1728   eh_landing_pad lp;
1729   eh_region r;
1730
1731   get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1732   return r;
1733 }
1734
1735 /* Return true if INSN throws and is caught by something in this function.  */
1736
1737 bool
1738 can_throw_internal (const_rtx insn)
1739 {
1740   return get_eh_landing_pad_from_rtx (insn) != NULL;
1741 }
1742
1743 /* Return true if INSN throws and escapes from the current function.  */
1744
1745 bool
1746 can_throw_external (const_rtx insn)
1747 {
1748   eh_landing_pad lp;
1749   eh_region r;
1750   bool nothrow;
1751
1752   if (! INSN_P (insn))
1753     return false;
1754
1755   if (NONJUMP_INSN_P (insn)
1756       && GET_CODE (PATTERN (insn)) == SEQUENCE)
1757     {
1758       rtx seq = PATTERN (insn);
1759       int i, n = XVECLEN (seq, 0);
1760
1761       for (i = 0; i < n; i++)
1762         if (can_throw_external (XVECEXP (seq, 0, i)))
1763           return true;
1764
1765       return false;
1766     }
1767
1768   nothrow = get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1769
1770   /* If we can't throw, we obviously can't throw external.  */
1771   if (nothrow)
1772     return false;
1773
1774   /* If we have an internal landing pad, then we're not external.  */
1775   if (lp != NULL)
1776     return false;
1777
1778   /* If we're not within an EH region, then we are external.  */
1779   if (r == NULL)
1780     return true;
1781
1782   /* The only thing that ought to be left is MUST_NOT_THROW regions,
1783      which don't always have landing pads.  */
1784   gcc_assert (r->type == ERT_MUST_NOT_THROW);
1785   return false;
1786 }
1787
1788 /* Return true if INSN cannot throw at all.  */
1789
1790 bool
1791 insn_nothrow_p (const_rtx insn)
1792 {
1793   eh_landing_pad lp;
1794   eh_region r;
1795
1796   if (! INSN_P (insn))
1797     return true;
1798
1799   if (NONJUMP_INSN_P (insn)
1800       && GET_CODE (PATTERN (insn)) == SEQUENCE)
1801     {
1802       rtx seq = PATTERN (insn);
1803       int i, n = XVECLEN (seq, 0);
1804
1805       for (i = 0; i < n; i++)
1806         if (!insn_nothrow_p (XVECEXP (seq, 0, i)))
1807           return false;
1808
1809       return true;
1810     }
1811
1812   return get_eh_region_and_lp_from_rtx (insn, &r, &lp);
1813 }
1814
1815 /* Return true if INSN can perform a non-local goto.  */
1816 /* ??? This test is here in this file because it (ab)uses REG_EH_REGION.  */
1817
1818 bool
1819 can_nonlocal_goto (const_rtx insn)
1820 {
1821   if (nonlocal_goto_handler_labels && CALL_P (insn))
1822     {
1823       rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
1824       if (!note || INTVAL (XEXP (note, 0)) != INT_MIN)
1825         return true;
1826     }
1827   return false;
1828 }
1829 \f
1830 /* Set TREE_NOTHROW and crtl->all_throwers_are_sibcalls.  */
1831
1832 static unsigned int
1833 set_nothrow_function_flags (void)
1834 {
1835   rtx insn;
1836
1837   crtl->nothrow = 1;
1838
1839   /* Assume crtl->all_throwers_are_sibcalls until we encounter
1840      something that can throw an exception.  We specifically exempt
1841      CALL_INSNs that are SIBLING_CALL_P, as these are really jumps,
1842      and can't throw.  Most CALL_INSNs are not SIBLING_CALL_P, so this
1843      is optimistic.  */
1844
1845   crtl->all_throwers_are_sibcalls = 1;
1846
1847   /* If we don't know that this implementation of the function will
1848      actually be used, then we must not set TREE_NOTHROW, since
1849      callers must not assume that this function does not throw.  */
1850   if (TREE_NOTHROW (current_function_decl))
1851     return 0;
1852
1853   if (! flag_exceptions)
1854     return 0;
1855
1856   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1857     if (can_throw_external (insn))
1858       {
1859         crtl->nothrow = 0;
1860
1861         if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
1862           {
1863             crtl->all_throwers_are_sibcalls = 0;
1864             return 0;
1865           }
1866       }
1867
1868   for (insn = crtl->epilogue_delay_list; insn;
1869        insn = XEXP (insn, 1))
1870     if (can_throw_external (insn))
1871       {
1872         crtl->nothrow = 0;
1873
1874         if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
1875           {
1876             crtl->all_throwers_are_sibcalls = 0;
1877             return 0;
1878           }
1879       }
1880   if (crtl->nothrow
1881       && (cgraph_function_body_availability (cgraph_get_node
1882                                              (current_function_decl))
1883           >= AVAIL_AVAILABLE))
1884     {
1885       struct cgraph_node *node = cgraph_get_node (current_function_decl);
1886       struct cgraph_edge *e;
1887       for (e = node->callers; e; e = e->next_caller)
1888         e->can_throw_external = false;
1889       cgraph_set_nothrow_flag (node, true);
1890
1891       if (dump_file)
1892         fprintf (dump_file, "Marking function nothrow: %s\n\n",
1893                  current_function_name ());
1894     }
1895   return 0;
1896 }
1897
1898 struct rtl_opt_pass pass_set_nothrow_function_flags =
1899 {
1900  {
1901   RTL_PASS,
1902   "nothrow",                            /* name */
1903   NULL,                                 /* gate */
1904   set_nothrow_function_flags,           /* execute */
1905   NULL,                                 /* sub */
1906   NULL,                                 /* next */
1907   0,                                    /* static_pass_number */
1908   TV_NONE,                              /* tv_id */
1909   0,                                    /* properties_required */
1910   0,                                    /* properties_provided */
1911   0,                                    /* properties_destroyed */
1912   0,                                    /* todo_flags_start */
1913   TODO_dump_func,                       /* todo_flags_finish */
1914  }
1915 };
1916
1917 \f
1918 /* Various hooks for unwind library.  */
1919
1920 /* Expand the EH support builtin functions:
1921    __builtin_eh_pointer and __builtin_eh_filter.  */
1922
1923 static eh_region
1924 expand_builtin_eh_common (tree region_nr_t)
1925 {
1926   HOST_WIDE_INT region_nr;
1927   eh_region region;
1928
1929   gcc_assert (host_integerp (region_nr_t, 0));
1930   region_nr = tree_low_cst (region_nr_t, 0);
1931
1932   region = VEC_index (eh_region, cfun->eh->region_array, region_nr);
1933
1934   /* ??? We shouldn't have been able to delete a eh region without
1935      deleting all the code that depended on it.  */
1936   gcc_assert (region != NULL);
1937
1938   return region;
1939 }
1940
1941 /* Expand to the exc_ptr value from the given eh region.  */
1942
1943 rtx
1944 expand_builtin_eh_pointer (tree exp)
1945 {
1946   eh_region region
1947     = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
1948   if (region->exc_ptr_reg == NULL)
1949     region->exc_ptr_reg = gen_reg_rtx (ptr_mode);
1950   return region->exc_ptr_reg;
1951 }
1952
1953 /* Expand to the filter value from the given eh region.  */
1954
1955 rtx
1956 expand_builtin_eh_filter (tree exp)
1957 {
1958   eh_region region
1959     = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
1960   if (region->filter_reg == NULL)
1961     region->filter_reg = gen_reg_rtx (targetm.eh_return_filter_mode ());
1962   return region->filter_reg;
1963 }
1964
1965 /* Copy the exc_ptr and filter values from one landing pad's registers
1966    to another.  This is used to inline the resx statement.  */
1967
1968 rtx
1969 expand_builtin_eh_copy_values (tree exp)
1970 {
1971   eh_region dst
1972     = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
1973   eh_region src
1974     = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 1));
1975   enum machine_mode fmode = targetm.eh_return_filter_mode ();
1976
1977   if (dst->exc_ptr_reg == NULL)
1978     dst->exc_ptr_reg = gen_reg_rtx (ptr_mode);
1979   if (src->exc_ptr_reg == NULL)
1980     src->exc_ptr_reg = gen_reg_rtx (ptr_mode);
1981
1982   if (dst->filter_reg == NULL)
1983     dst->filter_reg = gen_reg_rtx (fmode);
1984   if (src->filter_reg == NULL)
1985     src->filter_reg = gen_reg_rtx (fmode);
1986
1987   emit_move_insn (dst->exc_ptr_reg, src->exc_ptr_reg);
1988   emit_move_insn (dst->filter_reg, src->filter_reg);
1989
1990   return const0_rtx;
1991 }
1992
1993 /* Do any necessary initialization to access arbitrary stack frames.
1994    On the SPARC, this means flushing the register windows.  */
1995
1996 void
1997 expand_builtin_unwind_init (void)
1998 {
1999   /* Set this so all the registers get saved in our frame; we need to be
2000      able to copy the saved values for any registers from frames we unwind.  */
2001   crtl->saves_all_registers = 1;
2002
2003 #ifdef SETUP_FRAME_ADDRESSES
2004   SETUP_FRAME_ADDRESSES ();
2005 #endif
2006 }
2007
2008 /* Map a non-negative number to an eh return data register number; expands
2009    to -1 if no return data register is associated with the input number.
2010    At least the inputs 0 and 1 must be mapped; the target may provide more.  */
2011
2012 rtx
2013 expand_builtin_eh_return_data_regno (tree exp)
2014 {
2015   tree which = CALL_EXPR_ARG (exp, 0);
2016   unsigned HOST_WIDE_INT iwhich;
2017
2018   if (TREE_CODE (which) != INTEGER_CST)
2019     {
2020       error ("argument of %<__builtin_eh_return_regno%> must be constant");
2021       return constm1_rtx;
2022     }
2023
2024   iwhich = tree_low_cst (which, 1);
2025   iwhich = EH_RETURN_DATA_REGNO (iwhich);
2026   if (iwhich == INVALID_REGNUM)
2027     return constm1_rtx;
2028
2029 #ifdef DWARF_FRAME_REGNUM
2030   iwhich = DWARF_FRAME_REGNUM (iwhich);
2031 #else
2032   iwhich = DBX_REGISTER_NUMBER (iwhich);
2033 #endif
2034
2035   return GEN_INT (iwhich);
2036 }
2037
2038 /* Given a value extracted from the return address register or stack slot,
2039    return the actual address encoded in that value.  */
2040
2041 rtx
2042 expand_builtin_extract_return_addr (tree addr_tree)
2043 {
2044   rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2045
2046   if (GET_MODE (addr) != Pmode
2047       && GET_MODE (addr) != VOIDmode)
2048     {
2049 #ifdef POINTERS_EXTEND_UNSIGNED
2050       addr = convert_memory_address (Pmode, addr);
2051 #else
2052       addr = convert_to_mode (Pmode, addr, 0);
2053 #endif
2054     }
2055
2056   /* First mask out any unwanted bits.  */
2057 #ifdef MASK_RETURN_ADDR
2058   expand_and (Pmode, addr, MASK_RETURN_ADDR, addr);
2059 #endif
2060
2061   /* Then adjust to find the real return address.  */
2062 #if defined (RETURN_ADDR_OFFSET)
2063   addr = plus_constant (addr, RETURN_ADDR_OFFSET);
2064 #endif
2065
2066   return addr;
2067 }
2068
2069 /* Given an actual address in addr_tree, do any necessary encoding
2070    and return the value to be stored in the return address register or
2071    stack slot so the epilogue will return to that address.  */
2072
2073 rtx
2074 expand_builtin_frob_return_addr (tree addr_tree)
2075 {
2076   rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, EXPAND_NORMAL);
2077
2078   addr = convert_memory_address (Pmode, addr);
2079
2080 #ifdef RETURN_ADDR_OFFSET
2081   addr = force_reg (Pmode, addr);
2082   addr = plus_constant (addr, -RETURN_ADDR_OFFSET);
2083 #endif
2084
2085   return addr;
2086 }
2087
2088 /* Set up the epilogue with the magic bits we'll need to return to the
2089    exception handler.  */
2090
2091 void
2092 expand_builtin_eh_return (tree stackadj_tree ATTRIBUTE_UNUSED,
2093                           tree handler_tree)
2094 {
2095   rtx tmp;
2096
2097 #ifdef EH_RETURN_STACKADJ_RTX
2098   tmp = expand_expr (stackadj_tree, crtl->eh.ehr_stackadj,
2099                      VOIDmode, EXPAND_NORMAL);
2100   tmp = convert_memory_address (Pmode, tmp);
2101   if (!crtl->eh.ehr_stackadj)
2102     crtl->eh.ehr_stackadj = copy_to_reg (tmp);
2103   else if (tmp != crtl->eh.ehr_stackadj)
2104     emit_move_insn (crtl->eh.ehr_stackadj, tmp);
2105 #endif
2106
2107   tmp = expand_expr (handler_tree, crtl->eh.ehr_handler,
2108                      VOIDmode, EXPAND_NORMAL);
2109   tmp = convert_memory_address (Pmode, tmp);
2110   if (!crtl->eh.ehr_handler)
2111     crtl->eh.ehr_handler = copy_to_reg (tmp);
2112   else if (tmp != crtl->eh.ehr_handler)
2113     emit_move_insn (crtl->eh.ehr_handler, tmp);
2114
2115   if (!crtl->eh.ehr_label)
2116     crtl->eh.ehr_label = gen_label_rtx ();
2117   emit_jump (crtl->eh.ehr_label);
2118 }
2119
2120 /* Expand __builtin_eh_return.  This exit path from the function loads up
2121    the eh return data registers, adjusts the stack, and branches to a
2122    given PC other than the normal return address.  */
2123
2124 void
2125 expand_eh_return (void)
2126 {
2127   rtx around_label;
2128
2129   if (! crtl->eh.ehr_label)
2130     return;
2131
2132   crtl->calls_eh_return = 1;
2133
2134 #ifdef EH_RETURN_STACKADJ_RTX
2135   emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
2136 #endif
2137
2138   around_label = gen_label_rtx ();
2139   emit_jump (around_label);
2140
2141   emit_label (crtl->eh.ehr_label);
2142   clobber_return_register ();
2143
2144 #ifdef EH_RETURN_STACKADJ_RTX
2145   emit_move_insn (EH_RETURN_STACKADJ_RTX, crtl->eh.ehr_stackadj);
2146 #endif
2147
2148 #ifdef HAVE_eh_return
2149   if (HAVE_eh_return)
2150     emit_insn (gen_eh_return (crtl->eh.ehr_handler));
2151   else
2152 #endif
2153     {
2154 #ifdef EH_RETURN_HANDLER_RTX
2155       emit_move_insn (EH_RETURN_HANDLER_RTX, crtl->eh.ehr_handler);
2156 #else
2157       error ("__builtin_eh_return not supported on this target");
2158 #endif
2159     }
2160
2161   emit_label (around_label);
2162 }
2163
2164 /* Convert a ptr_mode address ADDR_TREE to a Pmode address controlled by
2165    POINTERS_EXTEND_UNSIGNED and return it.  */
2166
2167 rtx
2168 expand_builtin_extend_pointer (tree addr_tree)
2169 {
2170   rtx addr = expand_expr (addr_tree, NULL_RTX, ptr_mode, EXPAND_NORMAL);
2171   int extend;
2172
2173 #ifdef POINTERS_EXTEND_UNSIGNED
2174   extend = POINTERS_EXTEND_UNSIGNED;
2175 #else
2176   /* The previous EH code did an unsigned extend by default, so we do this also
2177      for consistency.  */
2178   extend = 1;
2179 #endif
2180
2181   return convert_modes (targetm.unwind_word_mode (), ptr_mode, addr, extend);
2182 }
2183 \f
2184 /* In the following functions, we represent entries in the action table
2185    as 1-based indices.  Special cases are:
2186
2187          0:     null action record, non-null landing pad; implies cleanups
2188         -1:     null action record, null landing pad; implies no action
2189         -2:     no call-site entry; implies must_not_throw
2190         -3:     we have yet to process outer regions
2191
2192    Further, no special cases apply to the "next" field of the record.
2193    For next, 0 means end of list.  */
2194
2195 struct action_record
2196 {
2197   int offset;
2198   int filter;
2199   int next;
2200 };
2201
2202 static int
2203 action_record_eq (const void *pentry, const void *pdata)
2204 {
2205   const struct action_record *entry = (const struct action_record *) pentry;
2206   const struct action_record *data = (const struct action_record *) pdata;
2207   return entry->filter == data->filter && entry->next == data->next;
2208 }
2209
2210 static hashval_t
2211 action_record_hash (const void *pentry)
2212 {
2213   const struct action_record *entry = (const struct action_record *) pentry;
2214   return entry->next * 1009 + entry->filter;
2215 }
2216
2217 static int
2218 add_action_record (htab_t ar_hash, int filter, int next)
2219 {
2220   struct action_record **slot, *new_ar, tmp;
2221
2222   tmp.filter = filter;
2223   tmp.next = next;
2224   slot = (struct action_record **) htab_find_slot (ar_hash, &tmp, INSERT);
2225
2226   if ((new_ar = *slot) == NULL)
2227     {
2228       new_ar = XNEW (struct action_record);
2229       new_ar->offset = VEC_length (uchar, crtl->eh.action_record_data) + 1;
2230       new_ar->filter = filter;
2231       new_ar->next = next;
2232       *slot = new_ar;
2233
2234       /* The filter value goes in untouched.  The link to the next
2235          record is a "self-relative" byte offset, or zero to indicate
2236          that there is no next record.  So convert the absolute 1 based
2237          indices we've been carrying around into a displacement.  */
2238
2239       push_sleb128 (&crtl->eh.action_record_data, filter);
2240       if (next)
2241         next -= VEC_length (uchar, crtl->eh.action_record_data) + 1;
2242       push_sleb128 (&crtl->eh.action_record_data, next);
2243     }
2244
2245   return new_ar->offset;
2246 }
2247
2248 static int
2249 collect_one_action_chain (htab_t ar_hash, eh_region region)
2250 {
2251   int next;
2252
2253   /* If we've reached the top of the region chain, then we have
2254      no actions, and require no landing pad.  */
2255   if (region == NULL)
2256     return -1;
2257
2258   switch (region->type)
2259     {
2260     case ERT_CLEANUP:
2261       {
2262         eh_region r;
2263         /* A cleanup adds a zero filter to the beginning of the chain, but
2264            there are special cases to look out for.  If there are *only*
2265            cleanups along a path, then it compresses to a zero action.
2266            Further, if there are multiple cleanups along a path, we only
2267            need to represent one of them, as that is enough to trigger
2268            entry to the landing pad at runtime.  */
2269         next = collect_one_action_chain (ar_hash, region->outer);
2270         if (next <= 0)
2271           return 0;
2272         for (r = region->outer; r ; r = r->outer)
2273           if (r->type == ERT_CLEANUP)
2274             return next;
2275         return add_action_record (ar_hash, 0, next);
2276       }
2277
2278     case ERT_TRY:
2279       {
2280         eh_catch c;
2281
2282         /* Process the associated catch regions in reverse order.
2283            If there's a catch-all handler, then we don't need to
2284            search outer regions.  Use a magic -3 value to record
2285            that we haven't done the outer search.  */
2286         next = -3;
2287         for (c = region->u.eh_try.last_catch; c ; c = c->prev_catch)
2288           {
2289             if (c->type_list == NULL)
2290               {
2291                 /* Retrieve the filter from the head of the filter list
2292                    where we have stored it (see assign_filter_values).  */
2293                 int filter = TREE_INT_CST_LOW (TREE_VALUE (c->filter_list));
2294                 next = add_action_record (ar_hash, filter, 0);
2295               }
2296             else
2297               {
2298                 /* Once the outer search is done, trigger an action record for
2299                    each filter we have.  */
2300                 tree flt_node;
2301
2302                 if (next == -3)
2303                   {
2304                     next = collect_one_action_chain (ar_hash, region->outer);
2305
2306                     /* If there is no next action, terminate the chain.  */
2307                     if (next == -1)
2308                       next = 0;
2309                     /* If all outer actions are cleanups or must_not_throw,
2310                        we'll have no action record for it, since we had wanted
2311                        to encode these states in the call-site record directly.
2312                        Add a cleanup action to the chain to catch these.  */
2313                     else if (next <= 0)
2314                       next = add_action_record (ar_hash, 0, 0);
2315                   }
2316
2317                 flt_node = c->filter_list;
2318                 for (; flt_node; flt_node = TREE_CHAIN (flt_node))
2319                   {
2320                     int filter = TREE_INT_CST_LOW (TREE_VALUE (flt_node));
2321                     next = add_action_record (ar_hash, filter, next);
2322                   }
2323               }
2324           }
2325         return next;
2326       }
2327
2328     case ERT_ALLOWED_EXCEPTIONS:
2329       /* An exception specification adds its filter to the
2330          beginning of the chain.  */
2331       next = collect_one_action_chain (ar_hash, region->outer);
2332
2333       /* If there is no next action, terminate the chain.  */
2334       if (next == -1)
2335         next = 0;
2336       /* If all outer actions are cleanups or must_not_throw,
2337          we'll have no action record for it, since we had wanted
2338          to encode these states in the call-site record directly.
2339          Add a cleanup action to the chain to catch these.  */
2340       else if (next <= 0)
2341         next = add_action_record (ar_hash, 0, 0);
2342
2343       return add_action_record (ar_hash, region->u.allowed.filter, next);
2344
2345     case ERT_MUST_NOT_THROW:
2346       /* A must-not-throw region with no inner handlers or cleanups
2347          requires no call-site entry.  Note that this differs from
2348          the no handler or cleanup case in that we do require an lsda
2349          to be generated.  Return a magic -2 value to record this.  */
2350       return -2;
2351     }
2352
2353   gcc_unreachable ();
2354 }
2355
2356 static int
2357 add_call_site (rtx landing_pad, int action, int section)
2358 {
2359   call_site_record record;
2360
2361   record = ggc_alloc_call_site_record_d ();
2362   record->landing_pad = landing_pad;
2363   record->action = action;
2364
2365   VEC_safe_push (call_site_record, gc,
2366                  crtl->eh.call_site_record[section], record);
2367
2368   return call_site_base + VEC_length (call_site_record,
2369                                       crtl->eh.call_site_record[section]) - 1;
2370 }
2371
2372 /* Turn REG_EH_REGION notes back into NOTE_INSN_EH_REGION notes.
2373    The new note numbers will not refer to region numbers, but
2374    instead to call site entries.  */
2375
2376 static unsigned int
2377 convert_to_eh_region_ranges (void)
2378 {
2379   rtx insn, iter, note;
2380   htab_t ar_hash;
2381   int last_action = -3;
2382   rtx last_action_insn = NULL_RTX;
2383   rtx last_landing_pad = NULL_RTX;
2384   rtx first_no_action_insn = NULL_RTX;
2385   int call_site = 0;
2386   int cur_sec = 0;
2387   rtx section_switch_note = NULL_RTX;
2388   rtx first_no_action_insn_before_switch = NULL_RTX;
2389   rtx last_no_action_insn_before_switch = NULL_RTX;
2390   rtx *pad_map = NULL;
2391   sbitmap pad_loc = NULL;
2392   int min_labelno = 0, max_labelno = 0;
2393   int saved_call_site_base = call_site_base;
2394
2395   crtl->eh.action_record_data = VEC_alloc (uchar, gc, 64);
2396
2397   ar_hash = htab_create (31, action_record_hash, action_record_eq, free);
2398
2399   for (iter = get_insns (); iter ; iter = NEXT_INSN (iter))
2400     if (INSN_P (iter))
2401       {
2402         eh_landing_pad lp;
2403         eh_region region;
2404         bool nothrow;
2405         int this_action;
2406         rtx this_landing_pad;
2407
2408         insn = iter;
2409         if (NONJUMP_INSN_P (insn)
2410             && GET_CODE (PATTERN (insn)) == SEQUENCE)
2411           insn = XVECEXP (PATTERN (insn), 0, 0);
2412
2413         nothrow = get_eh_region_and_lp_from_rtx (insn, &region, &lp);
2414         if (nothrow)
2415           continue;
2416         if (region)
2417           this_action = collect_one_action_chain (ar_hash, region);
2418         else
2419           this_action = -1;
2420
2421         /* Existence of catch handlers, or must-not-throw regions
2422            implies that an lsda is needed (even if empty).  */
2423         if (this_action != -1)
2424           crtl->uses_eh_lsda = 1;
2425
2426         /* Delay creation of region notes for no-action regions
2427            until we're sure that an lsda will be required.  */
2428         else if (last_action == -3)
2429           {
2430             first_no_action_insn = iter;
2431             last_action = -1;
2432           }
2433
2434         if (this_action >= 0)
2435           this_landing_pad = lp->landing_pad;
2436         else
2437           this_landing_pad = NULL_RTX;
2438
2439         /* Differing actions or landing pads implies a change in call-site
2440            info, which implies some EH_REGION note should be emitted.  */
2441         if (last_action != this_action
2442             || last_landing_pad != this_landing_pad)
2443           {
2444             /* If there is a queued no-action region in the other section
2445                with hot/cold partitioning, emit it now.  */
2446             if (first_no_action_insn_before_switch)
2447               {
2448                 gcc_assert (this_action != -1
2449                             && last_action == (first_no_action_insn
2450                                                ? -1 : -3));
2451                 call_site = add_call_site (NULL_RTX, 0, 0);
2452                 note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
2453                                          first_no_action_insn_before_switch);
2454                 NOTE_EH_HANDLER (note) = call_site;
2455                 note = emit_note_after (NOTE_INSN_EH_REGION_END,
2456                                         last_no_action_insn_before_switch);
2457                 NOTE_EH_HANDLER (note) = call_site;
2458                 gcc_assert (last_action != -3
2459                             || (last_action_insn
2460                                 == last_no_action_insn_before_switch));
2461                 first_no_action_insn_before_switch = NULL_RTX;
2462                 last_no_action_insn_before_switch = NULL_RTX;
2463                 call_site_base++;
2464               }
2465             /* If we'd not seen a previous action (-3) or the previous
2466                action was must-not-throw (-2), then we do not need an
2467                end note.  */
2468             if (last_action >= -1)
2469               {
2470                 /* If we delayed the creation of the begin, do it now.  */
2471                 if (first_no_action_insn)
2472                   {
2473                     call_site = add_call_site (NULL_RTX, 0, cur_sec);
2474                     note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
2475                                              first_no_action_insn);
2476                     NOTE_EH_HANDLER (note) = call_site;
2477                     first_no_action_insn = NULL_RTX;
2478                   }
2479
2480                 note = emit_note_after (NOTE_INSN_EH_REGION_END,
2481                                         last_action_insn);
2482                 NOTE_EH_HANDLER (note) = call_site;
2483               }
2484
2485             /* If the new action is must-not-throw, then no region notes
2486                are created.  */
2487             if (this_action >= -1)
2488               {
2489                 call_site = add_call_site (this_landing_pad,
2490                                            this_action < 0 ? 0 : this_action,
2491                                            cur_sec);
2492                 note = emit_note_before (NOTE_INSN_EH_REGION_BEG, iter);
2493                 NOTE_EH_HANDLER (note) = call_site;
2494               }
2495
2496             last_action = this_action;
2497             last_landing_pad = this_landing_pad;
2498           }
2499         last_action_insn = iter;
2500       }
2501     else if (NOTE_P (iter)
2502              && NOTE_KIND (iter) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
2503       {
2504         gcc_assert (section_switch_note == NULL_RTX);
2505         gcc_assert (flag_reorder_blocks_and_partition);
2506         section_switch_note = iter;
2507         if (first_no_action_insn)
2508           {
2509             first_no_action_insn_before_switch = first_no_action_insn;
2510             last_no_action_insn_before_switch = last_action_insn;
2511             first_no_action_insn = NULL_RTX;
2512             gcc_assert (last_action == -1);
2513             last_action = -3;
2514           }
2515         /* Force closing of current EH region before section switch and
2516            opening a new one afterwards.  */
2517         else if (last_action != -3)
2518           last_landing_pad = pc_rtx;
2519         call_site_base += VEC_length (call_site_record,
2520                                       crtl->eh.call_site_record[cur_sec]);
2521         cur_sec++;
2522         gcc_assert (crtl->eh.call_site_record[cur_sec] == NULL);
2523         crtl->eh.call_site_record[cur_sec]
2524           = VEC_alloc (call_site_record, gc, 10);
2525         max_labelno = max_label_num ();
2526         min_labelno = get_first_label_num ();
2527         pad_map = XCNEWVEC (rtx, max_labelno - min_labelno + 1);
2528         pad_loc = sbitmap_alloc (max_labelno - min_labelno + 1);
2529       }
2530     else if (LABEL_P (iter) && pad_map)
2531       SET_BIT (pad_loc, CODE_LABEL_NUMBER (iter) - min_labelno);
2532
2533   if (last_action >= -1 && ! first_no_action_insn)
2534     {
2535       note = emit_note_after (NOTE_INSN_EH_REGION_END, last_action_insn);
2536       NOTE_EH_HANDLER (note) = call_site;
2537     }
2538
2539   call_site_base = saved_call_site_base;
2540
2541   if (pad_map)
2542     {
2543       /* When doing hot/cold partitioning, ensure landing pads are
2544          always in the same section as the EH region, .gcc_except_table
2545          can't express it otherwise.  */
2546       for (cur_sec = 0; cur_sec < 2; cur_sec++)
2547         {
2548           int i, idx;
2549           int n = VEC_length (call_site_record,
2550                               crtl->eh.call_site_record[cur_sec]);
2551           basic_block prev_bb = NULL, padbb;
2552
2553           for (i = 0; i < n; ++i)
2554             {
2555               struct call_site_record_d *cs =
2556                 VEC_index (call_site_record,
2557                            crtl->eh.call_site_record[cur_sec], i);
2558               rtx jump, note;
2559
2560               if (cs->landing_pad == NULL_RTX)
2561                 continue;
2562               idx = CODE_LABEL_NUMBER (cs->landing_pad) - min_labelno;
2563               /* If the landing pad is in the correct section, nothing
2564                  is needed.  */
2565               if (TEST_BIT (pad_loc, idx) ^ (cur_sec == 0))
2566                 continue;
2567               /* Otherwise, if we haven't seen this pad yet, we need to
2568                  add a new label and jump to the correct section.  */
2569               if (pad_map[idx] == NULL_RTX)
2570                 {
2571                   pad_map[idx] = gen_label_rtx ();
2572                   if (prev_bb == NULL)
2573                     for (iter = section_switch_note;
2574                          iter; iter = PREV_INSN (iter))
2575                       if (NOTE_INSN_BASIC_BLOCK_P (iter))
2576                         {
2577                           prev_bb = NOTE_BASIC_BLOCK (iter);
2578                           break;
2579                         }
2580                   if (cur_sec == 0)
2581                     {
2582                       note = emit_label_before (pad_map[idx],
2583                                                 section_switch_note);
2584                       jump = emit_jump_insn_before (gen_jump (cs->landing_pad),
2585                                                     section_switch_note);
2586                     }
2587                   else
2588                     {
2589                       jump = emit_jump_insn_after (gen_jump (cs->landing_pad),
2590                                                    section_switch_note);
2591                       note = emit_label_after (pad_map[idx],
2592                                                section_switch_note);
2593                     }
2594                   JUMP_LABEL (jump) = cs->landing_pad;
2595                   add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX);
2596                   iter = NEXT_INSN (cs->landing_pad);
2597                   if (iter && NOTE_INSN_BASIC_BLOCK_P (iter))
2598                     padbb = NOTE_BASIC_BLOCK (iter);
2599                   else
2600                     padbb = NULL;
2601                   if (padbb && prev_bb
2602                       && BB_PARTITION (padbb) != BB_UNPARTITIONED)
2603                     {
2604                       basic_block bb;
2605                       int part
2606                         = BB_PARTITION (padbb) == BB_COLD_PARTITION
2607                           ? BB_HOT_PARTITION : BB_COLD_PARTITION;
2608                       edge_iterator ei;
2609                       edge e;
2610
2611                       bb = create_basic_block (note, jump, prev_bb);
2612                       make_single_succ_edge (bb, padbb, EDGE_CROSSING);
2613                       BB_SET_PARTITION (bb, part);
2614                       for (ei = ei_start (padbb->preds);
2615                            (e = ei_safe_edge (ei)); )
2616                         {
2617                           if ((e->flags & (EDGE_EH|EDGE_CROSSING))
2618                               == (EDGE_EH|EDGE_CROSSING))
2619                             {
2620                               redirect_edge_succ (e, bb);
2621                               e->flags &= ~EDGE_CROSSING;
2622                             }
2623                           else
2624                             ei_next (&ei);
2625                         }
2626                       if (cur_sec == 0)
2627                         prev_bb = bb;
2628                     }
2629                 }
2630               cs->landing_pad = pad_map[idx];
2631             }
2632         }
2633
2634       sbitmap_free (pad_loc);
2635       XDELETEVEC (pad_map);
2636     }
2637
2638   htab_delete (ar_hash);
2639   return 0;
2640 }
2641
2642 static bool
2643 gate_convert_to_eh_region_ranges (void)
2644 {
2645   /* Nothing to do for SJLJ exceptions or if no regions created.  */
2646   if (cfun->eh->region_tree == NULL)
2647     return false;
2648   if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
2649     return false;
2650   return true;
2651 }
2652
2653 struct rtl_opt_pass pass_convert_to_eh_region_ranges =
2654 {
2655  {
2656   RTL_PASS,
2657   "eh_ranges",                          /* name */
2658   gate_convert_to_eh_region_ranges,     /* gate */
2659   convert_to_eh_region_ranges,          /* execute */
2660   NULL,                                 /* sub */
2661   NULL,                                 /* next */
2662   0,                                    /* static_pass_number */
2663   TV_NONE,                              /* tv_id */
2664   0,                                    /* properties_required */
2665   0,                                    /* properties_provided */
2666   0,                                    /* properties_destroyed */
2667   0,                                    /* todo_flags_start */
2668   TODO_dump_func,                       /* todo_flags_finish */
2669  }
2670 };
2671 \f
2672 static void
2673 push_uleb128 (VEC (uchar, gc) **data_area, unsigned int value)
2674 {
2675   do
2676     {
2677       unsigned char byte = value & 0x7f;
2678       value >>= 7;
2679       if (value)
2680         byte |= 0x80;
2681       VEC_safe_push (uchar, gc, *data_area, byte);
2682     }
2683   while (value);
2684 }
2685
2686 static void
2687 push_sleb128 (VEC (uchar, gc) **data_area, int value)
2688 {
2689   unsigned char byte;
2690   int more;
2691
2692   do
2693     {
2694       byte = value & 0x7f;
2695       value >>= 7;
2696       more = ! ((value == 0 && (byte & 0x40) == 0)
2697                 || (value == -1 && (byte & 0x40) != 0));
2698       if (more)
2699         byte |= 0x80;
2700       VEC_safe_push (uchar, gc, *data_area, byte);
2701     }
2702   while (more);
2703 }
2704
2705 \f
2706 #ifndef HAVE_AS_LEB128
2707 static int
2708 dw2_size_of_call_site_table (int section)
2709 {
2710   int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
2711   int size = n * (4 + 4 + 4);
2712   int i;
2713
2714   for (i = 0; i < n; ++i)
2715     {
2716       struct call_site_record_d *cs =
2717         VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
2718       size += size_of_uleb128 (cs->action);
2719     }
2720
2721   return size;
2722 }
2723
2724 static int
2725 sjlj_size_of_call_site_table (void)
2726 {
2727   int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
2728   int size = 0;
2729   int i;
2730
2731   for (i = 0; i < n; ++i)
2732     {
2733       struct call_site_record_d *cs =
2734         VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
2735       size += size_of_uleb128 (INTVAL (cs->landing_pad));
2736       size += size_of_uleb128 (cs->action);
2737     }
2738
2739   return size;
2740 }
2741 #endif
2742
2743 static void
2744 dw2_output_call_site_table (int cs_format, int section)
2745 {
2746   int n = VEC_length (call_site_record, crtl->eh.call_site_record[section]);
2747   int i;
2748   const char *begin;
2749
2750   if (section == 0)
2751     begin = current_function_func_begin_label;
2752   else if (first_function_block_is_cold)
2753     begin = crtl->subsections.hot_section_label;
2754   else
2755     begin = crtl->subsections.cold_section_label;
2756
2757   for (i = 0; i < n; ++i)
2758     {
2759       struct call_site_record_d *cs =
2760         VEC_index (call_site_record, crtl->eh.call_site_record[section], i);
2761       char reg_start_lab[32];
2762       char reg_end_lab[32];
2763       char landing_pad_lab[32];
2764
2765       ASM_GENERATE_INTERNAL_LABEL (reg_start_lab, "LEHB", call_site_base + i);
2766       ASM_GENERATE_INTERNAL_LABEL (reg_end_lab, "LEHE", call_site_base + i);
2767
2768       if (cs->landing_pad)
2769         ASM_GENERATE_INTERNAL_LABEL (landing_pad_lab, "L",
2770                                      CODE_LABEL_NUMBER (cs->landing_pad));
2771
2772       /* ??? Perhaps use insn length scaling if the assembler supports
2773          generic arithmetic.  */
2774       /* ??? Perhaps use attr_length to choose data1 or data2 instead of
2775          data4 if the function is small enough.  */
2776       if (cs_format == DW_EH_PE_uleb128)
2777         {
2778           dw2_asm_output_delta_uleb128 (reg_start_lab, begin,
2779                                         "region %d start", i);
2780           dw2_asm_output_delta_uleb128 (reg_end_lab, reg_start_lab,
2781                                         "length");
2782           if (cs->landing_pad)
2783             dw2_asm_output_delta_uleb128 (landing_pad_lab, begin,
2784                                           "landing pad");
2785           else
2786             dw2_asm_output_data_uleb128 (0, "landing pad");
2787         }
2788       else
2789         {
2790           dw2_asm_output_delta (4, reg_start_lab, begin,
2791                                 "region %d start", i);
2792           dw2_asm_output_delta (4, reg_end_lab, reg_start_lab, "length");
2793           if (cs->landing_pad)
2794             dw2_asm_output_delta (4, landing_pad_lab, begin,
2795                                   "landing pad");
2796           else
2797             dw2_asm_output_data (4, 0, "landing pad");
2798         }
2799       dw2_asm_output_data_uleb128 (cs->action, "action");
2800     }
2801
2802   call_site_base += n;
2803 }
2804
2805 static void
2806 sjlj_output_call_site_table (void)
2807 {
2808   int n = VEC_length (call_site_record, crtl->eh.call_site_record[0]);
2809   int i;
2810
2811   for (i = 0; i < n; ++i)
2812     {
2813       struct call_site_record_d *cs =
2814         VEC_index (call_site_record, crtl->eh.call_site_record[0], i);
2815
2816       dw2_asm_output_data_uleb128 (INTVAL (cs->landing_pad),
2817                                    "region %d landing pad", i);
2818       dw2_asm_output_data_uleb128 (cs->action, "action");
2819     }
2820
2821   call_site_base += n;
2822 }
2823
2824 /* Switch to the section that should be used for exception tables.  */
2825
2826 static void
2827 switch_to_exception_section (const char * ARG_UNUSED (fnname))
2828 {
2829   section *s;
2830
2831   if (exception_section)
2832     s = exception_section;
2833   else
2834     {
2835       /* Compute the section and cache it into exception_section,
2836          unless it depends on the function name.  */
2837       if (targetm.have_named_sections)
2838         {
2839           int flags;
2840
2841           if (EH_TABLES_CAN_BE_READ_ONLY)
2842             {
2843               int tt_format =
2844                 ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
2845               flags = ((! flag_pic
2846                         || ((tt_format & 0x70) != DW_EH_PE_absptr
2847                             && (tt_format & 0x70) != DW_EH_PE_aligned))
2848                        ? 0 : SECTION_WRITE);
2849             }
2850           else
2851             flags = SECTION_WRITE;
2852
2853 #ifdef HAVE_LD_EH_GC_SECTIONS
2854           if (flag_function_sections)
2855             {
2856               char *section_name = XNEWVEC (char, strlen (fnname) + 32);
2857               sprintf (section_name, ".gcc_except_table.%s", fnname);
2858               s = get_section (section_name, flags, NULL);
2859               free (section_name);
2860             }
2861           else
2862 #endif
2863             exception_section
2864               = s = get_section (".gcc_except_table", flags, NULL);
2865         }
2866       else
2867         exception_section
2868           = s = flag_pic ? data_section : readonly_data_section;
2869     }
2870
2871   switch_to_section (s);
2872 }
2873
2874
2875 /* Output a reference from an exception table to the type_info object TYPE.
2876    TT_FORMAT and TT_FORMAT_SIZE describe the DWARF encoding method used for
2877    the value.  */
2878
2879 static void
2880 output_ttype (tree type, int tt_format, int tt_format_size)
2881 {
2882   rtx value;
2883   bool is_public = true;
2884
2885   if (type == NULL_TREE)
2886     value = const0_rtx;
2887   else
2888     {
2889       struct varpool_node *node;
2890
2891       /* FIXME lto.  pass_ipa_free_lang_data changes all types to
2892          runtime types so TYPE should already be a runtime type
2893          reference.  When pass_ipa_free_lang data is made a default
2894          pass, we can then remove the call to lookup_type_for_runtime
2895          below.  */
2896       if (TYPE_P (type))
2897         type = lookup_type_for_runtime (type);
2898
2899       value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
2900
2901       /* Let cgraph know that the rtti decl is used.  Not all of the
2902          paths below go through assemble_integer, which would take
2903          care of this for us.  */
2904       STRIP_NOPS (type);
2905       if (TREE_CODE (type) == ADDR_EXPR)
2906         {
2907           type = TREE_OPERAND (type, 0);
2908           if (TREE_CODE (type) == VAR_DECL)
2909             {
2910               node = varpool_node (type);
2911               if (node)
2912                 varpool_mark_needed_node (node);
2913               is_public = TREE_PUBLIC (type);
2914             }
2915         }
2916       else
2917         gcc_assert (TREE_CODE (type) == INTEGER_CST);
2918     }
2919
2920   /* Allow the target to override the type table entry format.  */
2921   if (targetm.asm_out.ttype (value))
2922     return;
2923
2924   if (tt_format == DW_EH_PE_absptr || tt_format == DW_EH_PE_aligned)
2925     assemble_integer (value, tt_format_size,
2926                       tt_format_size * BITS_PER_UNIT, 1);
2927   else
2928     dw2_asm_output_encoded_addr_rtx (tt_format, value, is_public, NULL);
2929 }
2930
2931 static void
2932 output_one_function_exception_table (int section)
2933 {
2934   int tt_format, cs_format, lp_format, i;
2935 #ifdef HAVE_AS_LEB128
2936   char ttype_label[32];
2937   char cs_after_size_label[32];
2938   char cs_end_label[32];
2939 #else
2940   int call_site_len;
2941 #endif
2942   int have_tt_data;
2943   int tt_format_size = 0;
2944
2945   have_tt_data = (VEC_length (tree, cfun->eh->ttype_data)
2946                   || (targetm.arm_eabi_unwinder
2947                       ? VEC_length (tree, cfun->eh->ehspec_data.arm_eabi)
2948                       : VEC_length (uchar, cfun->eh->ehspec_data.other)));
2949
2950   /* Indicate the format of the @TType entries.  */
2951   if (! have_tt_data)
2952     tt_format = DW_EH_PE_omit;
2953   else
2954     {
2955       tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
2956 #ifdef HAVE_AS_LEB128
2957       ASM_GENERATE_INTERNAL_LABEL (ttype_label,
2958                                    section ? "LLSDATTC" : "LLSDATT",
2959                                    current_function_funcdef_no);
2960 #endif
2961       tt_format_size = size_of_encoded_value (tt_format);
2962
2963       assemble_align (tt_format_size * BITS_PER_UNIT);
2964     }
2965
2966   targetm.asm_out.internal_label (asm_out_file, section ? "LLSDAC" : "LLSDA",
2967                                   current_function_funcdef_no);
2968
2969   /* The LSDA header.  */
2970
2971   /* Indicate the format of the landing pad start pointer.  An omitted
2972      field implies @LPStart == @Start.  */
2973   /* Currently we always put @LPStart == @Start.  This field would
2974      be most useful in moving the landing pads completely out of
2975      line to another section, but it could also be used to minimize
2976      the size of uleb128 landing pad offsets.  */
2977   lp_format = DW_EH_PE_omit;
2978   dw2_asm_output_data (1, lp_format, "@LPStart format (%s)",
2979                        eh_data_format_name (lp_format));
2980
2981   /* @LPStart pointer would go here.  */
2982
2983   dw2_asm_output_data (1, tt_format, "@TType format (%s)",
2984                        eh_data_format_name (tt_format));
2985
2986 #ifndef HAVE_AS_LEB128
2987   if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
2988     call_site_len = sjlj_size_of_call_site_table ();
2989   else
2990     call_site_len = dw2_size_of_call_site_table (section);
2991 #endif
2992
2993   /* A pc-relative 4-byte displacement to the @TType data.  */
2994   if (have_tt_data)
2995     {
2996 #ifdef HAVE_AS_LEB128
2997       char ttype_after_disp_label[32];
2998       ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label,
2999                                    section ? "LLSDATTDC" : "LLSDATTD",
3000                                    current_function_funcdef_no);
3001       dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
3002                                     "@TType base offset");
3003       ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
3004 #else
3005       /* Ug.  Alignment queers things.  */
3006       unsigned int before_disp, after_disp, last_disp, disp;
3007
3008       before_disp = 1 + 1;
3009       after_disp = (1 + size_of_uleb128 (call_site_len)
3010                     + call_site_len
3011                     + VEC_length (uchar, crtl->eh.action_record_data)
3012                     + (VEC_length (tree, cfun->eh->ttype_data)
3013                        * tt_format_size));
3014
3015       disp = after_disp;
3016       do
3017         {
3018           unsigned int disp_size, pad;
3019
3020           last_disp = disp;
3021           disp_size = size_of_uleb128 (disp);
3022           pad = before_disp + disp_size + after_disp;
3023           if (pad % tt_format_size)
3024             pad = tt_format_size - (pad % tt_format_size);
3025           else
3026             pad = 0;
3027           disp = after_disp + pad;
3028         }
3029       while (disp != last_disp);
3030
3031       dw2_asm_output_data_uleb128 (disp, "@TType base offset");
3032 #endif
3033     }
3034
3035   /* Indicate the format of the call-site offsets.  */
3036 #ifdef HAVE_AS_LEB128
3037   cs_format = DW_EH_PE_uleb128;
3038 #else
3039   cs_format = DW_EH_PE_udata4;
3040 #endif
3041   dw2_asm_output_data (1, cs_format, "call-site format (%s)",
3042                        eh_data_format_name (cs_format));
3043
3044 #ifdef HAVE_AS_LEB128
3045   ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label,
3046                                section ? "LLSDACSBC" : "LLSDACSB",
3047                                current_function_funcdef_no);
3048   ASM_GENERATE_INTERNAL_LABEL (cs_end_label,
3049                                section ? "LLSDACSEC" : "LLSDACSE",
3050                                current_function_funcdef_no);
3051   dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
3052                                 "Call-site table length");
3053   ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
3054   if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
3055     sjlj_output_call_site_table ();
3056   else
3057     dw2_output_call_site_table (cs_format, section);
3058   ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
3059 #else
3060   dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length");
3061   if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
3062     sjlj_output_call_site_table ();
3063   else
3064     dw2_output_call_site_table (cs_format, section);
3065 #endif
3066
3067   /* ??? Decode and interpret the data for flag_debug_asm.  */
3068   {
3069     uchar uc;
3070     FOR_EACH_VEC_ELT (uchar, crtl->eh.action_record_data, i, uc)
3071       dw2_asm_output_data (1, uc, i ? NULL : "Action record table");
3072   }
3073
3074   if (have_tt_data)
3075     assemble_align (tt_format_size * BITS_PER_UNIT);
3076
3077   i = VEC_length (tree, cfun->eh->ttype_data);
3078   while (i-- > 0)
3079     {
3080       tree type = VEC_index (tree, cfun->eh->ttype_data, i);
3081       output_ttype (type, tt_format, tt_format_size);
3082     }
3083
3084 #ifdef HAVE_AS_LEB128
3085   if (have_tt_data)
3086       ASM_OUTPUT_LABEL (asm_out_file, ttype_label);
3087 #endif
3088
3089   /* ??? Decode and interpret the data for flag_debug_asm.  */
3090   if (targetm.arm_eabi_unwinder)
3091     {
3092       tree type;
3093       for (i = 0;
3094            VEC_iterate (tree, cfun->eh->ehspec_data.arm_eabi, i, type); ++i)
3095         output_ttype (type, tt_format, tt_format_size);
3096     }
3097   else
3098     {
3099       uchar uc;
3100       for (i = 0;
3101            VEC_iterate (uchar, cfun->eh->ehspec_data.other, i, uc); ++i)
3102         dw2_asm_output_data (1, uc,
3103                              i ? NULL : "Exception specification table");
3104     }
3105 }
3106
3107 void
3108 output_function_exception_table (const char *fnname)
3109 {
3110   rtx personality = get_personality_function (current_function_decl);
3111
3112   /* Not all functions need anything.  */
3113   if (! crtl->uses_eh_lsda)
3114     return;
3115
3116   if (personality)
3117     {
3118       assemble_external_libcall (personality);
3119
3120       if (targetm.asm_out.emit_except_personality)
3121         targetm.asm_out.emit_except_personality (personality);
3122     }
3123
3124   switch_to_exception_section (fnname);
3125
3126   /* If the target wants a label to begin the table, emit it here.  */
3127   targetm.asm_out.emit_except_table_label (asm_out_file);
3128
3129   output_one_function_exception_table (0);
3130   if (crtl->eh.call_site_record[1] != NULL)
3131     output_one_function_exception_table (1);
3132
3133   switch_to_section (current_function_section ());
3134 }
3135
3136 void
3137 set_eh_throw_stmt_table (struct function *fun, struct htab *table)
3138 {
3139   fun->eh->throw_stmt_table = table;
3140 }
3141
3142 htab_t
3143 get_eh_throw_stmt_table (struct function *fun)
3144 {
3145   return fun->eh->throw_stmt_table;
3146 }
3147 \f
3148 /* Determine if the function needs an EH personality function.  */
3149
3150 enum eh_personality_kind
3151 function_needs_eh_personality (struct function *fn)
3152 {
3153   enum eh_personality_kind kind = eh_personality_none;
3154   eh_region i;
3155
3156   FOR_ALL_EH_REGION_FN (i, fn)
3157     {
3158       switch (i->type)
3159         {
3160         case ERT_CLEANUP:
3161           /* Can do with any personality including the generic C one.  */
3162           kind = eh_personality_any;
3163           break;
3164
3165         case ERT_TRY:
3166         case ERT_ALLOWED_EXCEPTIONS:
3167           /* Always needs a EH personality function.  The generic C
3168              personality doesn't handle these even for empty type lists.  */
3169           return eh_personality_lang;
3170
3171         case ERT_MUST_NOT_THROW:
3172           /* Always needs a EH personality function.  The language may specify
3173              what abort routine that must be used, e.g. std::terminate.  */
3174           return eh_personality_lang;
3175         }
3176     }
3177
3178   return kind;
3179 }
3180 \f
3181 /* Dump EH information to OUT.  */
3182
3183 void
3184 dump_eh_tree (FILE * out, struct function *fun)
3185 {
3186   eh_region i;
3187   int depth = 0;
3188   static const char *const type_name[] = {
3189     "cleanup", "try", "allowed_exceptions", "must_not_throw"
3190   };
3191
3192   i = fun->eh->region_tree;
3193   if (!i)
3194     return;
3195
3196   fprintf (out, "Eh tree:\n");
3197   while (1)
3198     {
3199       fprintf (out, "  %*s %i %s", depth * 2, "",
3200                i->index, type_name[(int) i->type]);
3201
3202       if (i->landing_pads)
3203         {
3204           eh_landing_pad lp;
3205
3206           fprintf (out, " land:");
3207           if (current_ir_type () == IR_GIMPLE)
3208             {
3209               for (lp = i->landing_pads; lp ; lp = lp->next_lp)
3210                 {
3211                   fprintf (out, "{%i,", lp->index);
3212                   print_generic_expr (out, lp->post_landing_pad, 0);
3213                   fputc ('}', out);
3214                   if (lp->next_lp)
3215                     fputc (',', out);
3216                 }
3217             }
3218           else
3219             {
3220               for (lp = i->landing_pads; lp ; lp = lp->next_lp)
3221                 {
3222                   fprintf (out, "{%i,", lp->index);
3223                   if (lp->landing_pad)
3224                     fprintf (out, "%i%s,", INSN_UID (lp->landing_pad),
3225                              NOTE_P (lp->landing_pad) ? "(del)" : "");
3226                   else
3227                     fprintf (out, "(nil),");
3228                   if (lp->post_landing_pad)
3229                     {
3230                       rtx lab = label_rtx (lp->post_landing_pad);
3231                       fprintf (out, "%i%s}", INSN_UID (lab),
3232                                NOTE_P (lab) ? "(del)" : "");
3233                     }
3234                   else
3235                     fprintf (out, "(nil)}");
3236                   if (lp->next_lp)
3237                     fputc (',', out);
3238                 }
3239             }
3240         }
3241
3242       switch (i->type)
3243         {
3244         case ERT_CLEANUP:
3245         case ERT_MUST_NOT_THROW:
3246           break;
3247
3248         case ERT_TRY:
3249           {
3250             eh_catch c;
3251             fprintf (out, " catch:");
3252             for (c = i->u.eh_try.first_catch; c; c = c->next_catch)
3253               {
3254                 fputc ('{', out);
3255                 if (c->label)
3256                   {
3257                     fprintf (out, "lab:");
3258                     print_generic_expr (out, c->label, 0);
3259                     fputc (';', out);
3260                   }
3261                 print_generic_expr (out, c->type_list, 0);
3262                 fputc ('}', out);
3263                 if (c->next_catch)
3264                   fputc (',', out);
3265               }
3266           }
3267           break;
3268
3269         case ERT_ALLOWED_EXCEPTIONS:
3270           fprintf (out, " filter :%i types:", i->u.allowed.filter);
3271           print_generic_expr (out, i->u.allowed.type_list, 0);
3272           break;
3273         }
3274       fputc ('\n', out);
3275
3276       /* If there are sub-regions, process them.  */
3277       if (i->inner)
3278         i = i->inner, depth++;
3279       /* If there are peers, process them.  */
3280       else if (i->next_peer)
3281         i = i->next_peer;
3282       /* Otherwise, step back up the tree to the next peer.  */
3283       else
3284         {
3285           do
3286             {
3287               i = i->outer;
3288               depth--;
3289               if (i == NULL)
3290                 return;
3291             }
3292           while (i->next_peer == NULL);
3293           i = i->next_peer;
3294         }
3295     }
3296 }
3297
3298 /* Dump the EH tree for FN on stderr.  */
3299
3300 DEBUG_FUNCTION void
3301 debug_eh_tree (struct function *fn)
3302 {
3303   dump_eh_tree (stderr, fn);
3304 }
3305
3306 /* Verify invariants on EH datastructures.  */
3307
3308 DEBUG_FUNCTION void
3309 verify_eh_tree (struct function *fun)
3310 {
3311   eh_region r, outer;
3312   int nvisited_lp, nvisited_r;
3313   int count_lp, count_r, depth, i;
3314   eh_landing_pad lp;
3315   bool err = false;
3316
3317   if (!fun->eh->region_tree)
3318     return;
3319
3320   count_r = 0;
3321   for (i = 1; VEC_iterate (eh_region, fun->eh->region_array, i, r); ++i)
3322     if (r)
3323       {
3324         if (r->index == i)
3325           count_r++;
3326         else
3327           {
3328             error ("region_array is corrupted for region %i", r->index);
3329             err = true;
3330           }
3331       }
3332
3333   count_lp = 0;
3334   for (i = 1; VEC_iterate (eh_landing_pad, fun->eh->lp_array, i, lp); ++i)
3335     if (lp)
3336       {
3337         if (lp->index == i)
3338           count_lp++;
3339         else
3340           {
3341             error ("lp_array is corrupted for lp %i", lp->index);
3342             err = true;
3343           }
3344       }
3345
3346   depth = nvisited_lp = nvisited_r = 0;
3347   outer = NULL;
3348   r = fun->eh->region_tree;
3349   while (1)
3350     {
3351       if (VEC_index (eh_region, fun->eh->region_array, r->index) != r)
3352         {
3353           error ("region_array is corrupted for region %i", r->index);
3354           err = true;
3355         }
3356       if (r->outer != outer)
3357         {
3358           error ("outer block of region %i is wrong", r->index);
3359           err = true;
3360         }
3361       if (depth < 0)
3362         {
3363           error ("negative nesting depth of region %i", r->index);
3364           err = true;
3365         }
3366       nvisited_r++;
3367
3368       for (lp = r->landing_pads; lp ; lp = lp->next_lp)
3369         {
3370           if (VEC_index (eh_landing_pad, fun->eh->lp_array, lp->index) != lp)
3371             {
3372               error ("lp_array is corrupted for lp %i", lp->index);
3373               err = true;
3374             }
3375           if (lp->region != r)
3376             {
3377               error ("region of lp %i is wrong", lp->index);
3378               err = true;
3379             }
3380           nvisited_lp++;
3381         }
3382
3383       if (r->inner)
3384         outer = r, r = r->inner, depth++;
3385       else if (r->next_peer)
3386         r = r->next_peer;
3387       else
3388         {
3389           do
3390             {
3391               r = r->outer;
3392               if (r == NULL)
3393                 goto region_done;
3394               depth--;
3395               outer = r->outer;
3396             }
3397           while (r->next_peer == NULL);
3398           r = r->next_peer;
3399         }
3400     }
3401  region_done:
3402   if (depth != 0)
3403     {
3404       error ("tree list ends on depth %i", depth);
3405       err = true;
3406     }
3407   if (count_r != nvisited_r)
3408     {
3409       error ("region_array does not match region_tree");
3410       err = true;
3411     }
3412   if (count_lp != nvisited_lp)
3413     {
3414       error ("lp_array does not match region_tree");
3415       err = true;
3416     }
3417
3418   if (err)
3419     {
3420       dump_eh_tree (stderr, fun);
3421       internal_error ("verify_eh_tree failed");
3422     }
3423 }
3424 \f
3425 #include "gt-except.h"