OSDN Git Service

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