OSDN Git Service

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