OSDN Git Service

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