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