revert: tree.h (phi_arg_d): New field.
[platform/upstream/gcc.git] / gcc / tree-eh.c
1 /* Exception handling semantics and decomposition for trees.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
3    Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "flags.h"
27 #include "function.h"
28 #include "except.h"
29 #include "pointer-set.h"
30 #include "tree-flow.h"
31 #include "tree-dump.h"
32 #include "tree-inline.h"
33 #include "tree-iterator.h"
34 #include "tree-pass.h"
35 #include "timevar.h"
36 #include "langhooks.h"
37 #include "ggc.h"
38 #include "diagnostic-core.h"
39 #include "gimple.h"
40 #include "target.h"
41 #include "cfgloop.h"
42
43 /* In some instances a tree and a gimple need to be stored in a same table,
44    i.e. in hash tables. This is a structure to do this. */
45 typedef union {tree *tp; tree t; gimple g;} treemple;
46
47 /* Nonzero if we are using EH to handle cleanups.  */
48 static int using_eh_for_cleanups_p = 0;
49
50 void
51 using_eh_for_cleanups (void)
52 {
53   using_eh_for_cleanups_p = 1;
54 }
55
56 /* Misc functions used in this file.  */
57
58 /* Remember and lookup EH landing pad data for arbitrary statements.
59    Really this means any statement that could_throw_p.  We could
60    stuff this information into the stmt_ann data structure, but:
61
62    (1) We absolutely rely on this information being kept until
63    we get to rtl.  Once we're done with lowering here, if we lose
64    the information there's no way to recover it!
65
66    (2) There are many more statements that *cannot* throw as
67    compared to those that can.  We should be saving some amount
68    of space by only allocating memory for those that can throw.  */
69
70 /* Add statement T in function IFUN to landing pad NUM.  */
71
72 void
73 add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
74 {
75   struct throw_stmt_node *n;
76   void **slot;
77
78   gcc_assert (num != 0);
79
80   n = ggc_alloc_throw_stmt_node ();
81   n->stmt = t;
82   n->lp_nr = num;
83
84   if (!get_eh_throw_stmt_table (ifun))
85     set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_hash,
86                                                     struct_ptr_eq,
87                                                     ggc_free));
88
89   slot = htab_find_slot (get_eh_throw_stmt_table (ifun), n, INSERT);
90   gcc_assert (!*slot);
91   *slot = n;
92 }
93
94 /* Add statement T in the current function (cfun) to EH landing pad NUM.  */
95
96 void
97 add_stmt_to_eh_lp (gimple t, int num)
98 {
99   add_stmt_to_eh_lp_fn (cfun, t, num);
100 }
101
102 /* Add statement T to the single EH landing pad in REGION.  */
103
104 static void
105 record_stmt_eh_region (eh_region region, gimple t)
106 {
107   if (region == NULL)
108     return;
109   if (region->type == ERT_MUST_NOT_THROW)
110     add_stmt_to_eh_lp_fn (cfun, t, -region->index);
111   else
112     {
113       eh_landing_pad lp = region->landing_pads;
114       if (lp == NULL)
115         lp = gen_eh_landing_pad (region);
116       else
117         gcc_assert (lp->next_lp == NULL);
118       add_stmt_to_eh_lp_fn (cfun, t, lp->index);
119     }
120 }
121
122
123 /* Remove statement T in function IFUN from its EH landing pad.  */
124
125 bool
126 remove_stmt_from_eh_lp_fn (struct function *ifun, gimple t)
127 {
128   struct throw_stmt_node dummy;
129   void **slot;
130
131   if (!get_eh_throw_stmt_table (ifun))
132     return false;
133
134   dummy.stmt = t;
135   slot = htab_find_slot (get_eh_throw_stmt_table (ifun), &dummy,
136                         NO_INSERT);
137   if (slot)
138     {
139       htab_clear_slot (get_eh_throw_stmt_table (ifun), slot);
140       return true;
141     }
142   else
143     return false;
144 }
145
146
147 /* Remove statement T in the current function (cfun) from its
148    EH landing pad.  */
149
150 bool
151 remove_stmt_from_eh_lp (gimple t)
152 {
153   return remove_stmt_from_eh_lp_fn (cfun, t);
154 }
155
156 /* Determine if statement T is inside an EH region in function IFUN.
157    Positive numbers indicate a landing pad index; negative numbers
158    indicate a MUST_NOT_THROW region index; zero indicates that the
159    statement is not recorded in the region table.  */
160
161 int
162 lookup_stmt_eh_lp_fn (struct function *ifun, gimple t)
163 {
164   struct throw_stmt_node *p, n;
165
166   if (ifun->eh->throw_stmt_table == NULL)
167     return 0;
168
169   n.stmt = t;
170   p = (struct throw_stmt_node *) htab_find (ifun->eh->throw_stmt_table, &n);
171   return p ? p->lp_nr : 0;
172 }
173
174 /* Likewise, but always use the current function.  */
175
176 int
177 lookup_stmt_eh_lp (gimple t)
178 {
179   /* We can get called from initialized data when -fnon-call-exceptions
180      is on; prevent crash.  */
181   if (!cfun)
182     return 0;
183   return lookup_stmt_eh_lp_fn (cfun, t);
184 }
185
186 /* First pass of EH node decomposition.  Build up a tree of GIMPLE_TRY_FINALLY
187    nodes and LABEL_DECL nodes.  We will use this during the second phase to
188    determine if a goto leaves the body of a TRY_FINALLY_EXPR node.  */
189
190 struct finally_tree_node
191 {
192   /* When storing a GIMPLE_TRY, we have to record a gimple.  However
193      when deciding whether a GOTO to a certain LABEL_DECL (which is a
194      tree) leaves the TRY block, its necessary to record a tree in
195      this field.  Thus a treemple is used. */
196   treemple child;
197   gimple parent;
198 };
199
200 /* Note that this table is *not* marked GTY.  It is short-lived.  */
201 static htab_t finally_tree;
202
203 static void
204 record_in_finally_tree (treemple child, gimple parent)
205 {
206   struct finally_tree_node *n;
207   void **slot;
208
209   n = XNEW (struct finally_tree_node);
210   n->child = child;
211   n->parent = parent;
212
213   slot = htab_find_slot (finally_tree, n, INSERT);
214   gcc_assert (!*slot);
215   *slot = n;
216 }
217
218 static void
219 collect_finally_tree (gimple stmt, gimple region);
220
221 /* Go through the gimple sequence.  Works with collect_finally_tree to
222    record all GIMPLE_LABEL and GIMPLE_TRY statements. */
223
224 static void
225 collect_finally_tree_1 (gimple_seq seq, gimple region)
226 {
227   gimple_stmt_iterator gsi;
228
229   for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
230     collect_finally_tree (gsi_stmt (gsi), region);
231 }
232
233 static void
234 collect_finally_tree (gimple stmt, gimple region)
235 {
236   treemple temp;
237
238   switch (gimple_code (stmt))
239     {
240     case GIMPLE_LABEL:
241       temp.t = gimple_label_label (stmt);
242       record_in_finally_tree (temp, region);
243       break;
244
245     case GIMPLE_TRY:
246       if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY)
247         {
248           temp.g = stmt;
249           record_in_finally_tree (temp, region);
250           collect_finally_tree_1 (gimple_try_eval (stmt), stmt);
251           collect_finally_tree_1 (gimple_try_cleanup (stmt), region);
252         }
253       else if (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH)
254         {
255           collect_finally_tree_1 (gimple_try_eval (stmt), region);
256           collect_finally_tree_1 (gimple_try_cleanup (stmt), region);
257         }
258       break;
259
260     case GIMPLE_CATCH:
261       collect_finally_tree_1 (gimple_catch_handler (stmt), region);
262       break;
263
264     case GIMPLE_EH_FILTER:
265       collect_finally_tree_1 (gimple_eh_filter_failure (stmt), region);
266       break;
267
268     case GIMPLE_EH_ELSE:
269       collect_finally_tree_1 (gimple_eh_else_n_body (stmt), region);
270       collect_finally_tree_1 (gimple_eh_else_e_body (stmt), region);
271       break;
272
273     default:
274       /* A type, a decl, or some kind of statement that we're not
275          interested in.  Don't walk them.  */
276       break;
277     }
278 }
279
280
281 /* Use the finally tree to determine if a jump from START to TARGET
282    would leave the try_finally node that START lives in.  */
283
284 static bool
285 outside_finally_tree (treemple start, gimple target)
286 {
287   struct finally_tree_node n, *p;
288
289   do
290     {
291       n.child = start;
292       p = (struct finally_tree_node *) htab_find (finally_tree, &n);
293       if (!p)
294         return true;
295       start.g = p->parent;
296     }
297   while (start.g != target);
298
299   return false;
300 }
301
302 /* Second pass of EH node decomposition.  Actually transform the GIMPLE_TRY
303    nodes into a set of gotos, magic labels, and eh regions.
304    The eh region creation is straight-forward, but frobbing all the gotos
305    and such into shape isn't.  */
306
307 /* The sequence into which we record all EH stuff.  This will be
308    placed at the end of the function when we're all done.  */
309 static gimple_seq eh_seq;
310
311 /* Record whether an EH region contains something that can throw,
312    indexed by EH region number.  */
313 static bitmap eh_region_may_contain_throw_map;
314
315 /* The GOTO_QUEUE is is an array of GIMPLE_GOTO and GIMPLE_RETURN
316    statements that are seen to escape this GIMPLE_TRY_FINALLY node.
317    The idea is to record a gimple statement for everything except for
318    the conditionals, which get their labels recorded. Since labels are
319    of type 'tree', we need this node to store both gimple and tree
320    objects.  REPL_STMT is the sequence used to replace the goto/return
321    statement.  CONT_STMT is used to store the statement that allows
322    the return/goto to jump to the original destination. */
323
324 struct goto_queue_node
325 {
326   treemple stmt;
327   gimple_seq repl_stmt;
328   gimple cont_stmt;
329   int index;
330   /* This is used when index >= 0 to indicate that stmt is a label (as
331      opposed to a goto stmt).  */
332   int is_label;
333 };
334
335 /* State of the world while lowering.  */
336
337 struct leh_state
338 {
339   /* What's "current" while constructing the eh region tree.  These
340      correspond to variables of the same name in cfun->eh, which we
341      don't have easy access to.  */
342   eh_region cur_region;
343
344   /* What's "current" for the purposes of __builtin_eh_pointer.  For
345      a CATCH, this is the associated TRY.  For an EH_FILTER, this is
346      the associated ALLOWED_EXCEPTIONS, etc.  */
347   eh_region ehp_region;
348
349   /* Processing of TRY_FINALLY requires a bit more state.  This is
350      split out into a separate structure so that we don't have to
351      copy so much when processing other nodes.  */
352   struct leh_tf_state *tf;
353 };
354
355 struct leh_tf_state
356 {
357   /* Pointer to the GIMPLE_TRY_FINALLY node under discussion.  The
358      try_finally_expr is the original GIMPLE_TRY_FINALLY.  We need to retain
359      this so that outside_finally_tree can reliably reference the tree used
360      in the collect_finally_tree data structures.  */
361   gimple try_finally_expr;
362   gimple top_p;
363
364   /* While lowering a top_p usually it is expanded into multiple statements,
365      thus we need the following field to store them. */
366   gimple_seq top_p_seq;
367
368   /* The state outside this try_finally node.  */
369   struct leh_state *outer;
370
371   /* The exception region created for it.  */
372   eh_region region;
373
374   /* The goto queue.  */
375   struct goto_queue_node *goto_queue;
376   size_t goto_queue_size;
377   size_t goto_queue_active;
378
379   /* Pointer map to help in searching goto_queue when it is large.  */
380   struct pointer_map_t *goto_queue_map;
381
382   /* The set of unique labels seen as entries in the goto queue.  */
383   VEC(tree,heap) *dest_array;
384
385   /* A label to be added at the end of the completed transformed
386      sequence.  It will be set if may_fallthru was true *at one time*,
387      though subsequent transformations may have cleared that flag.  */
388   tree fallthru_label;
389
390   /* True if it is possible to fall out the bottom of the try block.
391      Cleared if the fallthru is converted to a goto.  */
392   bool may_fallthru;
393
394   /* True if any entry in goto_queue is a GIMPLE_RETURN.  */
395   bool may_return;
396
397   /* True if the finally block can receive an exception edge.
398      Cleared if the exception case is handled by code duplication.  */
399   bool may_throw;
400 };
401
402 static gimple_seq lower_eh_must_not_throw (struct leh_state *, gimple);
403
404 /* Search for STMT in the goto queue.  Return the replacement,
405    or null if the statement isn't in the queue.  */
406
407 #define LARGE_GOTO_QUEUE 20
408
409 static void lower_eh_constructs_1 (struct leh_state *state, gimple_seq *seq);
410
411 static gimple_seq
412 find_goto_replacement (struct leh_tf_state *tf, treemple stmt)
413 {
414   unsigned int i;
415   void **slot;
416
417   if (tf->goto_queue_active < LARGE_GOTO_QUEUE)
418     {
419       for (i = 0; i < tf->goto_queue_active; i++)
420         if ( tf->goto_queue[i].stmt.g == stmt.g)
421           return tf->goto_queue[i].repl_stmt;
422       return NULL;
423     }
424
425   /* If we have a large number of entries in the goto_queue, create a
426      pointer map and use that for searching.  */
427
428   if (!tf->goto_queue_map)
429     {
430       tf->goto_queue_map = pointer_map_create ();
431       for (i = 0; i < tf->goto_queue_active; i++)
432         {
433           slot = pointer_map_insert (tf->goto_queue_map,
434                                      tf->goto_queue[i].stmt.g);
435           gcc_assert (*slot == NULL);
436           *slot = &tf->goto_queue[i];
437         }
438     }
439
440   slot = pointer_map_contains (tf->goto_queue_map, stmt.g);
441   if (slot != NULL)
442     return (((struct goto_queue_node *) *slot)->repl_stmt);
443
444   return NULL;
445 }
446
447 /* A subroutine of replace_goto_queue_1.  Handles the sub-clauses of a
448    lowered GIMPLE_COND.  If, by chance, the replacement is a simple goto,
449    then we can just splat it in, otherwise we add the new stmts immediately
450    after the GIMPLE_COND and redirect.  */
451
452 static void
453 replace_goto_queue_cond_clause (tree *tp, struct leh_tf_state *tf,
454                                 gimple_stmt_iterator *gsi)
455 {
456   tree label;
457   gimple_seq new_seq;
458   treemple temp;
459   location_t loc = gimple_location (gsi_stmt (*gsi));
460
461   temp.tp = tp;
462   new_seq = find_goto_replacement (tf, temp);
463   if (!new_seq)
464     return;
465
466   if (gimple_seq_singleton_p (new_seq)
467       && gimple_code (gimple_seq_first_stmt (new_seq)) == GIMPLE_GOTO)
468     {
469       *tp = gimple_goto_dest (gimple_seq_first_stmt (new_seq));
470       return;
471     }
472
473   label = create_artificial_label (loc);
474   /* Set the new label for the GIMPLE_COND */
475   *tp = label;
476
477   gsi_insert_after (gsi, gimple_build_label (label), GSI_CONTINUE_LINKING);
478   gsi_insert_seq_after (gsi, gimple_seq_copy (new_seq), GSI_CONTINUE_LINKING);
479 }
480
481 /* The real work of replace_goto_queue.  Returns with TSI updated to
482    point to the next statement.  */
483
484 static void replace_goto_queue_stmt_list (gimple_seq *, struct leh_tf_state *);
485
486 static void
487 replace_goto_queue_1 (gimple stmt, struct leh_tf_state *tf,
488                       gimple_stmt_iterator *gsi)
489 {
490   gimple_seq seq;
491   treemple temp;
492   temp.g = NULL;
493
494   switch (gimple_code (stmt))
495     {
496     case GIMPLE_GOTO:
497     case GIMPLE_RETURN:
498       temp.g = stmt;
499       seq = find_goto_replacement (tf, temp);
500       if (seq)
501         {
502           gsi_insert_seq_before (gsi, gimple_seq_copy (seq), GSI_SAME_STMT);
503           gsi_remove (gsi, false);
504           return;
505         }
506       break;
507
508     case GIMPLE_COND:
509       replace_goto_queue_cond_clause (gimple_op_ptr (stmt, 2), tf, gsi);
510       replace_goto_queue_cond_clause (gimple_op_ptr (stmt, 3), tf, gsi);
511       break;
512
513     case GIMPLE_TRY:
514       replace_goto_queue_stmt_list (gimple_try_eval_ptr (stmt), tf);
515       replace_goto_queue_stmt_list (gimple_try_cleanup_ptr (stmt), tf);
516       break;
517     case GIMPLE_CATCH:
518       replace_goto_queue_stmt_list (gimple_catch_handler_ptr (stmt), tf);
519       break;
520     case GIMPLE_EH_FILTER:
521       replace_goto_queue_stmt_list (gimple_eh_filter_failure_ptr (stmt), tf);
522       break;
523     case GIMPLE_EH_ELSE:
524       replace_goto_queue_stmt_list (gimple_eh_else_n_body_ptr (stmt), tf);
525       replace_goto_queue_stmt_list (gimple_eh_else_e_body_ptr (stmt), tf);
526       break;
527
528     default:
529       /* These won't have gotos in them.  */
530       break;
531     }
532
533   gsi_next (gsi);
534 }
535
536 /* A subroutine of replace_goto_queue.  Handles GIMPLE_SEQ.  */
537
538 static void
539 replace_goto_queue_stmt_list (gimple_seq *seq, struct leh_tf_state *tf)
540 {
541   gimple_stmt_iterator gsi = gsi_start (*seq);
542
543   while (!gsi_end_p (gsi))
544     replace_goto_queue_1 (gsi_stmt (gsi), tf, &gsi);
545 }
546
547 /* Replace all goto queue members.  */
548
549 static void
550 replace_goto_queue (struct leh_tf_state *tf)
551 {
552   if (tf->goto_queue_active == 0)
553     return;
554   replace_goto_queue_stmt_list (&tf->top_p_seq, tf);
555   replace_goto_queue_stmt_list (&eh_seq, tf);
556 }
557
558 /* Add a new record to the goto queue contained in TF. NEW_STMT is the
559    data to be added, IS_LABEL indicates whether NEW_STMT is a label or
560    a gimple return. */
561
562 static void
563 record_in_goto_queue (struct leh_tf_state *tf,
564                       treemple new_stmt,
565                       int index,
566                       bool is_label)
567 {
568   size_t active, size;
569   struct goto_queue_node *q;
570
571   gcc_assert (!tf->goto_queue_map);
572
573   active = tf->goto_queue_active;
574   size = tf->goto_queue_size;
575   if (active >= size)
576     {
577       size = (size ? size * 2 : 32);
578       tf->goto_queue_size = size;
579       tf->goto_queue
580          = XRESIZEVEC (struct goto_queue_node, tf->goto_queue, size);
581     }
582
583   q = &tf->goto_queue[active];
584   tf->goto_queue_active = active + 1;
585
586   memset (q, 0, sizeof (*q));
587   q->stmt = new_stmt;
588   q->index = index;
589   q->is_label = is_label;
590 }
591
592 /* Record the LABEL label in the goto queue contained in TF.
593    TF is not null.  */
594
595 static void
596 record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label)
597 {
598   int index;
599   treemple temp, new_stmt;
600
601   if (!label)
602     return;
603
604   /* Computed and non-local gotos do not get processed.  Given
605      their nature we can neither tell whether we've escaped the
606      finally block nor redirect them if we knew.  */
607   if (TREE_CODE (label) != LABEL_DECL)
608     return;
609
610   /* No need to record gotos that don't leave the try block.  */
611   temp.t = label;
612   if (!outside_finally_tree (temp, tf->try_finally_expr))
613     return;
614
615   if (! tf->dest_array)
616     {
617       tf->dest_array = VEC_alloc (tree, heap, 10);
618       VEC_quick_push (tree, tf->dest_array, label);
619       index = 0;
620     }
621   else
622     {
623       int n = VEC_length (tree, tf->dest_array);
624       for (index = 0; index < n; ++index)
625         if (VEC_index (tree, tf->dest_array, index) == label)
626           break;
627       if (index == n)
628         VEC_safe_push (tree, heap, tf->dest_array, label);
629     }
630
631   /* In the case of a GOTO we want to record the destination label,
632      since with a GIMPLE_COND we have an easy access to the then/else
633      labels. */
634   new_stmt = stmt;
635   record_in_goto_queue (tf, new_stmt, index, true);
636 }
637
638 /* For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally
639    node, and if so record that fact in the goto queue associated with that
640    try_finally node.  */
641
642 static void
643 maybe_record_in_goto_queue (struct leh_state *state, gimple stmt)
644 {
645   struct leh_tf_state *tf = state->tf;
646   treemple new_stmt;
647
648   if (!tf)
649     return;
650
651   switch (gimple_code (stmt))
652     {
653     case GIMPLE_COND:
654       new_stmt.tp = gimple_op_ptr (stmt, 2);
655       record_in_goto_queue_label (tf, new_stmt, gimple_cond_true_label (stmt));
656       new_stmt.tp = gimple_op_ptr (stmt, 3);
657       record_in_goto_queue_label (tf, new_stmt, gimple_cond_false_label (stmt));
658       break;
659     case GIMPLE_GOTO:
660       new_stmt.g = stmt;
661       record_in_goto_queue_label (tf, new_stmt, gimple_goto_dest (stmt));
662       break;
663
664     case GIMPLE_RETURN:
665       tf->may_return = true;
666       new_stmt.g = stmt;
667       record_in_goto_queue (tf, new_stmt, -1, false);
668       break;
669
670     default:
671       gcc_unreachable ();
672     }
673 }
674
675
676 #ifdef ENABLE_CHECKING
677 /* We do not process GIMPLE_SWITCHes for now.  As long as the original source
678    was in fact structured, and we've not yet done jump threading, then none
679    of the labels will leave outer GIMPLE_TRY_FINALLY nodes. Verify this.  */
680
681 static void
682 verify_norecord_switch_expr (struct leh_state *state, gimple switch_expr)
683 {
684   struct leh_tf_state *tf = state->tf;
685   size_t i, n;
686
687   if (!tf)
688     return;
689
690   n = gimple_switch_num_labels (switch_expr);
691
692   for (i = 0; i < n; ++i)
693     {
694       treemple temp;
695       tree lab = CASE_LABEL (gimple_switch_label (switch_expr, i));
696       temp.t = lab;
697       gcc_assert (!outside_finally_tree (temp, tf->try_finally_expr));
698     }
699 }
700 #else
701 #define verify_norecord_switch_expr(state, switch_expr)
702 #endif
703
704 /* Redirect a RETURN_EXPR pointed to by Q to FINLAB.  If MOD is
705    non-null, insert it before the new branch.  */
706
707 static void
708 do_return_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod)
709 {
710   gimple x;
711
712   /* In the case of a return, the queue node must be a gimple statement.  */
713   gcc_assert (!q->is_label);
714
715   /* Note that the return value may have already been computed, e.g.,
716
717         int x;
718         int foo (void)
719         {
720           x = 0;
721           try {
722             return x;
723           } finally {
724             x++;
725           }
726         }
727
728      should return 0, not 1.  We don't have to do anything to make
729      this happens because the return value has been placed in the
730      RESULT_DECL already.  */
731
732   q->cont_stmt = q->stmt.g;
733
734   if (mod)
735     gimple_seq_add_seq (&q->repl_stmt, mod);
736
737   x = gimple_build_goto (finlab);
738   gimple_seq_add_stmt (&q->repl_stmt, x);
739 }
740
741 /* Similar, but easier, for GIMPLE_GOTO.  */
742
743 static void
744 do_goto_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod,
745                      struct leh_tf_state *tf)
746 {
747   gimple x;
748
749   gcc_assert (q->is_label);
750
751   q->cont_stmt = gimple_build_goto (VEC_index (tree, tf->dest_array, q->index));
752
753   if (mod)
754     gimple_seq_add_seq (&q->repl_stmt, mod);
755
756   x = gimple_build_goto (finlab);
757   gimple_seq_add_stmt (&q->repl_stmt, x);
758 }
759
760 /* Emit a standard landing pad sequence into SEQ for REGION.  */
761
762 static void
763 emit_post_landing_pad (gimple_seq *seq, eh_region region)
764 {
765   eh_landing_pad lp = region->landing_pads;
766   gimple x;
767
768   if (lp == NULL)
769     lp = gen_eh_landing_pad (region);
770
771   lp->post_landing_pad = create_artificial_label (UNKNOWN_LOCATION);
772   EH_LANDING_PAD_NR (lp->post_landing_pad) = lp->index;
773
774   x = gimple_build_label (lp->post_landing_pad);
775   gimple_seq_add_stmt (seq, x);
776 }
777
778 /* Emit a RESX statement into SEQ for REGION.  */
779
780 static void
781 emit_resx (gimple_seq *seq, eh_region region)
782 {
783   gimple x = gimple_build_resx (region->index);
784   gimple_seq_add_stmt (seq, x);
785   if (region->outer)
786     record_stmt_eh_region (region->outer, x);
787 }
788
789 /* Emit an EH_DISPATCH statement into SEQ for REGION.  */
790
791 static void
792 emit_eh_dispatch (gimple_seq *seq, eh_region region)
793 {
794   gimple x = gimple_build_eh_dispatch (region->index);
795   gimple_seq_add_stmt (seq, x);
796 }
797
798 /* Note that the current EH region may contain a throw, or a
799    call to a function which itself may contain a throw.  */
800
801 static void
802 note_eh_region_may_contain_throw (eh_region region)
803 {
804   while (bitmap_set_bit (eh_region_may_contain_throw_map, region->index))
805     {
806       if (region->type == ERT_MUST_NOT_THROW)
807         break;
808       region = region->outer;
809       if (region == NULL)
810         break;
811     }
812 }
813
814 /* Check if REGION has been marked as containing a throw.  If REGION is
815    NULL, this predicate is false.  */
816
817 static inline bool
818 eh_region_may_contain_throw (eh_region r)
819 {
820   return r && bitmap_bit_p (eh_region_may_contain_throw_map, r->index);
821 }
822
823 /* We want to transform
824         try { body; } catch { stuff; }
825    to
826         normal_seqence:
827           body;
828           over:
829         eh_seqence:
830           landing_pad:
831           stuff;
832           goto over;
833
834    TP is a GIMPLE_TRY node.  REGION is the region whose post_landing_pad
835    should be placed before the second operand, or NULL.  OVER is
836    an existing label that should be put at the exit, or NULL.  */
837
838 static gimple_seq
839 frob_into_branch_around (gimple tp, eh_region region, tree over)
840 {
841   gimple x;
842   gimple_seq cleanup, result;
843   location_t loc = gimple_location (tp);
844
845   cleanup = gimple_try_cleanup (tp);
846   result = gimple_try_eval (tp);
847
848   if (region)
849     emit_post_landing_pad (&eh_seq, region);
850
851   if (gimple_seq_may_fallthru (cleanup))
852     {
853       if (!over)
854         over = create_artificial_label (loc);
855       x = gimple_build_goto (over);
856       gimple_seq_add_stmt (&cleanup, x);
857     }
858   gimple_seq_add_seq (&eh_seq, cleanup);
859
860   if (over)
861     {
862       x = gimple_build_label (over);
863       gimple_seq_add_stmt (&result, x);
864     }
865   return result;
866 }
867
868 /* A subroutine of lower_try_finally.  Duplicate the tree rooted at T.
869    Make sure to record all new labels found.  */
870
871 static gimple_seq
872 lower_try_finally_dup_block (gimple_seq seq, struct leh_state *outer_state)
873 {
874   gimple region = NULL;
875   gimple_seq new_seq;
876
877   new_seq = copy_gimple_seq_and_replace_locals (seq);
878
879   if (outer_state->tf)
880     region = outer_state->tf->try_finally_expr;
881   collect_finally_tree_1 (new_seq, region);
882
883   return new_seq;
884 }
885
886 /* A subroutine of lower_try_finally.  Create a fallthru label for
887    the given try_finally state.  The only tricky bit here is that
888    we have to make sure to record the label in our outer context.  */
889
890 static tree
891 lower_try_finally_fallthru_label (struct leh_tf_state *tf)
892 {
893   tree label = tf->fallthru_label;
894   treemple temp;
895
896   if (!label)
897     {
898       label = create_artificial_label (gimple_location (tf->try_finally_expr));
899       tf->fallthru_label = label;
900       if (tf->outer->tf)
901         {
902           temp.t = label;
903           record_in_finally_tree (temp, tf->outer->tf->try_finally_expr);
904         }
905     }
906   return label;
907 }
908
909 /* A subroutine of lower_try_finally.  If FINALLY consits of a
910    GIMPLE_EH_ELSE node, return it.  */
911
912 static inline gimple
913 get_eh_else (gimple_seq finally)
914 {
915   gimple x = gimple_seq_first_stmt (finally);
916   if (gimple_code (x) == GIMPLE_EH_ELSE)
917     {
918       gcc_assert (gimple_seq_singleton_p (finally));
919       return x;
920     }
921   return NULL;
922 }
923
924 /* A subroutine of lower_try_finally.  If the eh_protect_cleanup_actions
925    langhook returns non-null, then the language requires that the exception
926    path out of a try_finally be treated specially.  To wit: the code within
927    the finally block may not itself throw an exception.  We have two choices
928    here. First we can duplicate the finally block and wrap it in a
929    must_not_throw region.  Second, we can generate code like
930
931         try {
932           finally_block;
933         } catch {
934           if (fintmp == eh_edge)
935             protect_cleanup_actions;
936         }
937
938    where "fintmp" is the temporary used in the switch statement generation
939    alternative considered below.  For the nonce, we always choose the first
940    option.
941
942    THIS_STATE may be null if this is a try-cleanup, not a try-finally.  */
943
944 static void
945 honor_protect_cleanup_actions (struct leh_state *outer_state,
946                                struct leh_state *this_state,
947                                struct leh_tf_state *tf)
948 {
949   tree protect_cleanup_actions;
950   gimple_stmt_iterator gsi;
951   bool finally_may_fallthru;
952   gimple_seq finally;
953   gimple x, eh_else;
954
955   /* First check for nothing to do.  */
956   if (lang_hooks.eh_protect_cleanup_actions == NULL)
957     return;
958   protect_cleanup_actions = lang_hooks.eh_protect_cleanup_actions ();
959   if (protect_cleanup_actions == NULL)
960     return;
961
962   finally = gimple_try_cleanup (tf->top_p);
963   eh_else = get_eh_else (finally);
964
965   /* Duplicate the FINALLY block.  Only need to do this for try-finally,
966      and not for cleanups.  If we've got an EH_ELSE, extract it now.  */
967   if (eh_else)
968     {
969       finally = gimple_eh_else_e_body (eh_else);
970       gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else));
971     }
972   else if (this_state)
973     finally = lower_try_finally_dup_block (finally, outer_state);
974   finally_may_fallthru = gimple_seq_may_fallthru (finally);
975
976   /* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP
977      set, the handler of the TRY_CATCH_EXPR is another cleanup which ought
978      to be in an enclosing scope, but needs to be implemented at this level
979      to avoid a nesting violation (see wrap_temporary_cleanups in
980      cp/decl.c).  Since it's logically at an outer level, we should call
981      terminate before we get to it, so strip it away before adding the
982      MUST_NOT_THROW filter.  */
983   gsi = gsi_start (finally);
984   x = gsi_stmt (gsi);
985   if (gimple_code (x) == GIMPLE_TRY
986       && gimple_try_kind (x) == GIMPLE_TRY_CATCH
987       && gimple_try_catch_is_cleanup (x))
988     {
989       gsi_insert_seq_before (&gsi, gimple_try_eval (x), GSI_SAME_STMT);
990       gsi_remove (&gsi, false);
991     }
992
993   /* Wrap the block with protect_cleanup_actions as the action.  */
994   x = gimple_build_eh_must_not_throw (protect_cleanup_actions);
995   x = gimple_build_try (finally, gimple_seq_alloc_with_stmt (x),
996                         GIMPLE_TRY_CATCH);
997   finally = lower_eh_must_not_throw (outer_state, x);
998
999   /* Drop all of this into the exception sequence.  */
1000   emit_post_landing_pad (&eh_seq, tf->region);
1001   gimple_seq_add_seq (&eh_seq, finally);
1002   if (finally_may_fallthru)
1003     emit_resx (&eh_seq, tf->region);
1004
1005   /* Having now been handled, EH isn't to be considered with
1006      the rest of the outgoing edges.  */
1007   tf->may_throw = false;
1008 }
1009
1010 /* A subroutine of lower_try_finally.  We have determined that there is
1011    no fallthru edge out of the finally block.  This means that there is
1012    no outgoing edge corresponding to any incoming edge.  Restructure the
1013    try_finally node for this special case.  */
1014
1015 static void
1016 lower_try_finally_nofallthru (struct leh_state *state,
1017                               struct leh_tf_state *tf)
1018 {
1019   tree lab;
1020   gimple x, eh_else;
1021   gimple_seq finally;
1022   struct goto_queue_node *q, *qe;
1023
1024   lab = create_artificial_label (gimple_location (tf->try_finally_expr));
1025
1026   /* We expect that tf->top_p is a GIMPLE_TRY. */
1027   finally = gimple_try_cleanup (tf->top_p);
1028   tf->top_p_seq = gimple_try_eval (tf->top_p);
1029
1030   x = gimple_build_label (lab);
1031   gimple_seq_add_stmt (&tf->top_p_seq, x);
1032
1033   q = tf->goto_queue;
1034   qe = q + tf->goto_queue_active;
1035   for (; q < qe; ++q)
1036     if (q->index < 0)
1037       do_return_redirection (q, lab, NULL);
1038     else
1039       do_goto_redirection (q, lab, NULL, tf);
1040
1041   replace_goto_queue (tf);
1042
1043   /* Emit the finally block into the stream.  Lower EH_ELSE at this time.  */
1044   eh_else = get_eh_else (finally);
1045   if (eh_else)
1046     {
1047       finally = gimple_eh_else_n_body (eh_else);
1048       lower_eh_constructs_1 (state, &finally);
1049       gimple_seq_add_seq (&tf->top_p_seq, finally);
1050
1051       if (tf->may_throw)
1052         {
1053           finally = gimple_eh_else_e_body (eh_else);
1054           lower_eh_constructs_1 (state, &finally);
1055
1056           emit_post_landing_pad (&eh_seq, tf->region);
1057           gimple_seq_add_seq (&eh_seq, finally);
1058         }
1059     }
1060   else
1061     {
1062       lower_eh_constructs_1 (state, &finally);
1063       gimple_seq_add_seq (&tf->top_p_seq, finally);
1064
1065       if (tf->may_throw)
1066         {
1067           emit_post_landing_pad (&eh_seq, tf->region);
1068
1069           x = gimple_build_goto (lab);
1070           gimple_seq_add_stmt (&eh_seq, x);
1071         }
1072     }
1073 }
1074
1075 /* A subroutine of lower_try_finally.  We have determined that there is
1076    exactly one destination of the finally block.  Restructure the
1077    try_finally node for this special case.  */
1078
1079 static void
1080 lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
1081 {
1082   struct goto_queue_node *q, *qe;
1083   gimple x;
1084   gimple_seq finally;
1085   tree finally_label;
1086   location_t loc = gimple_location (tf->try_finally_expr);
1087
1088   finally = gimple_try_cleanup (tf->top_p);
1089   tf->top_p_seq = gimple_try_eval (tf->top_p);
1090
1091   /* Since there's only one destination, and the destination edge can only
1092      either be EH or non-EH, that implies that all of our incoming edges
1093      are of the same type.  Therefore we can lower EH_ELSE immediately.  */
1094   x = get_eh_else (finally);
1095   if (x)
1096     {
1097       if (tf->may_throw)
1098         finally = gimple_eh_else_e_body (x);
1099       else
1100         finally = gimple_eh_else_n_body (x);
1101     }
1102
1103   lower_eh_constructs_1 (state, &finally);
1104
1105   if (tf->may_throw)
1106     {
1107       /* Only reachable via the exception edge.  Add the given label to
1108          the head of the FINALLY block.  Append a RESX at the end.  */
1109       emit_post_landing_pad (&eh_seq, tf->region);
1110       gimple_seq_add_seq (&eh_seq, finally);
1111       emit_resx (&eh_seq, tf->region);
1112       return;
1113     }
1114
1115   if (tf->may_fallthru)
1116     {
1117       /* Only reachable via the fallthru edge.  Do nothing but let
1118          the two blocks run together; we'll fall out the bottom.  */
1119       gimple_seq_add_seq (&tf->top_p_seq, finally);
1120       return;
1121     }
1122
1123   finally_label = create_artificial_label (loc);
1124   x = gimple_build_label (finally_label);
1125   gimple_seq_add_stmt (&tf->top_p_seq, x);
1126
1127   gimple_seq_add_seq (&tf->top_p_seq, finally);
1128
1129   q = tf->goto_queue;
1130   qe = q + tf->goto_queue_active;
1131
1132   if (tf->may_return)
1133     {
1134       /* Reachable by return expressions only.  Redirect them.  */
1135       for (; q < qe; ++q)
1136         do_return_redirection (q, finally_label, NULL);
1137       replace_goto_queue (tf);
1138     }
1139   else
1140     {
1141       /* Reachable by goto expressions only.  Redirect them.  */
1142       for (; q < qe; ++q)
1143         do_goto_redirection (q, finally_label, NULL, tf);
1144       replace_goto_queue (tf);
1145
1146       if (VEC_index (tree, tf->dest_array, 0) == tf->fallthru_label)
1147         {
1148           /* Reachable by goto to fallthru label only.  Redirect it
1149              to the new label (already created, sadly), and do not
1150              emit the final branch out, or the fallthru label.  */
1151           tf->fallthru_label = NULL;
1152           return;
1153         }
1154     }
1155
1156   /* Place the original return/goto to the original destination
1157      immediately after the finally block. */
1158   x = tf->goto_queue[0].cont_stmt;
1159   gimple_seq_add_stmt (&tf->top_p_seq, x);
1160   maybe_record_in_goto_queue (state, x);
1161 }
1162
1163 /* A subroutine of lower_try_finally.  There are multiple edges incoming
1164    and outgoing from the finally block.  Implement this by duplicating the
1165    finally block for every destination.  */
1166
1167 static void
1168 lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
1169 {
1170   gimple_seq finally;
1171   gimple_seq new_stmt;
1172   gimple_seq seq;
1173   gimple x, eh_else;
1174   tree tmp;
1175   location_t tf_loc = gimple_location (tf->try_finally_expr);
1176
1177   finally = gimple_try_cleanup (tf->top_p);
1178
1179   /* Notice EH_ELSE, and simplify some of the remaining code
1180      by considering FINALLY to be the normal return path only.  */
1181   eh_else = get_eh_else (finally);
1182   if (eh_else)
1183     finally = gimple_eh_else_n_body (eh_else);
1184
1185   tf->top_p_seq = gimple_try_eval (tf->top_p);
1186   new_stmt = NULL;
1187
1188   if (tf->may_fallthru)
1189     {
1190       seq = lower_try_finally_dup_block (finally, state);
1191       lower_eh_constructs_1 (state, &seq);
1192       gimple_seq_add_seq (&new_stmt, seq);
1193
1194       tmp = lower_try_finally_fallthru_label (tf);
1195       x = gimple_build_goto (tmp);
1196       gimple_seq_add_stmt (&new_stmt, x);
1197     }
1198
1199   if (tf->may_throw)
1200     {
1201       /* We don't need to copy the EH path of EH_ELSE,
1202          since it is only emitted once.  */
1203       if (eh_else)
1204         seq = gimple_eh_else_e_body (eh_else);
1205       else
1206         seq = lower_try_finally_dup_block (finally, state);
1207       lower_eh_constructs_1 (state, &seq);
1208
1209       emit_post_landing_pad (&eh_seq, tf->region);
1210       gimple_seq_add_seq (&eh_seq, seq);
1211       emit_resx (&eh_seq, tf->region);
1212     }
1213
1214   if (tf->goto_queue)
1215     {
1216       struct goto_queue_node *q, *qe;
1217       int return_index, index;
1218       struct labels_s
1219       {
1220         struct goto_queue_node *q;
1221         tree label;
1222       } *labels;
1223
1224       return_index = VEC_length (tree, tf->dest_array);
1225       labels = XCNEWVEC (struct labels_s, return_index + 1);
1226
1227       q = tf->goto_queue;
1228       qe = q + tf->goto_queue_active;
1229       for (; q < qe; q++)
1230         {
1231           index = q->index < 0 ? return_index : q->index;
1232
1233           if (!labels[index].q)
1234             labels[index].q = q;
1235         }
1236
1237       for (index = 0; index < return_index + 1; index++)
1238         {
1239           tree lab;
1240
1241           q = labels[index].q;
1242           if (! q)
1243             continue;
1244
1245           lab = labels[index].label
1246             = create_artificial_label (tf_loc);
1247
1248           if (index == return_index)
1249             do_return_redirection (q, lab, NULL);
1250           else
1251             do_goto_redirection (q, lab, NULL, tf);
1252
1253           x = gimple_build_label (lab);
1254           gimple_seq_add_stmt (&new_stmt, x);
1255
1256           seq = lower_try_finally_dup_block (finally, state);
1257           lower_eh_constructs_1 (state, &seq);
1258           gimple_seq_add_seq (&new_stmt, seq);
1259
1260           gimple_seq_add_stmt (&new_stmt, q->cont_stmt);
1261           maybe_record_in_goto_queue (state, q->cont_stmt);
1262         }
1263
1264       for (q = tf->goto_queue; q < qe; q++)
1265         {
1266           tree lab;
1267
1268           index = q->index < 0 ? return_index : q->index;
1269
1270           if (labels[index].q == q)
1271             continue;
1272
1273           lab = labels[index].label;
1274
1275           if (index == return_index)
1276             do_return_redirection (q, lab, NULL);
1277           else
1278             do_goto_redirection (q, lab, NULL, tf);
1279         }
1280
1281       replace_goto_queue (tf);
1282       free (labels);
1283     }
1284
1285   /* Need to link new stmts after running replace_goto_queue due
1286      to not wanting to process the same goto stmts twice.  */
1287   gimple_seq_add_seq (&tf->top_p_seq, new_stmt);
1288 }
1289
1290 /* A subroutine of lower_try_finally.  There are multiple edges incoming
1291    and outgoing from the finally block.  Implement this by instrumenting
1292    each incoming edge and creating a switch statement at the end of the
1293    finally block that branches to the appropriate destination.  */
1294
1295 static void
1296 lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
1297 {
1298   struct goto_queue_node *q, *qe;
1299   tree finally_tmp, finally_label;
1300   int return_index, eh_index, fallthru_index;
1301   int nlabels, ndests, j, last_case_index;
1302   tree last_case;
1303   VEC (tree,heap) *case_label_vec;
1304   gimple_seq switch_body = NULL;
1305   gimple x, eh_else;
1306   tree tmp;
1307   gimple switch_stmt;
1308   gimple_seq finally;
1309   struct pointer_map_t *cont_map = NULL;
1310   /* The location of the TRY_FINALLY stmt.  */
1311   location_t tf_loc = gimple_location (tf->try_finally_expr);
1312   /* The location of the finally block.  */
1313   location_t finally_loc;
1314
1315   finally = gimple_try_cleanup (tf->top_p);
1316   eh_else = get_eh_else (finally);
1317
1318   /* Mash the TRY block to the head of the chain.  */
1319   tf->top_p_seq = gimple_try_eval (tf->top_p);
1320
1321   /* The location of the finally is either the last stmt in the finally
1322      block or the location of the TRY_FINALLY itself.  */
1323   x = gimple_seq_last_stmt (finally);
1324   finally_loc = x ? gimple_location (x) : tf_loc;
1325
1326   /* Lower the finally block itself.  */
1327   lower_eh_constructs_1 (state, &finally);
1328
1329   /* Prepare for switch statement generation.  */
1330   nlabels = VEC_length (tree, tf->dest_array);
1331   return_index = nlabels;
1332   eh_index = return_index + tf->may_return;
1333   fallthru_index = eh_index + (tf->may_throw && !eh_else);
1334   ndests = fallthru_index + tf->may_fallthru;
1335
1336   finally_tmp = create_tmp_var (integer_type_node, "finally_tmp");
1337   finally_label = create_artificial_label (finally_loc);
1338
1339   /* We use VEC_quick_push on case_label_vec throughout this function,
1340      since we know the size in advance and allocate precisely as muce
1341      space as needed.  */
1342   case_label_vec = VEC_alloc (tree, heap, ndests);
1343   last_case = NULL;
1344   last_case_index = 0;
1345
1346   /* Begin inserting code for getting to the finally block.  Things
1347      are done in this order to correspond to the sequence the code is
1348      laid out.  */
1349
1350   if (tf->may_fallthru)
1351     {
1352       x = gimple_build_assign (finally_tmp,
1353                                build_int_cst (integer_type_node,
1354                                               fallthru_index));
1355       gimple_seq_add_stmt (&tf->top_p_seq, x);
1356
1357       tmp = build_int_cst (integer_type_node, fallthru_index);
1358       last_case = build_case_label (tmp, NULL,
1359                                     create_artificial_label (tf_loc));
1360       VEC_quick_push (tree, case_label_vec, last_case);
1361       last_case_index++;
1362
1363       x = gimple_build_label (CASE_LABEL (last_case));
1364       gimple_seq_add_stmt (&switch_body, x);
1365
1366       tmp = lower_try_finally_fallthru_label (tf);
1367       x = gimple_build_goto (tmp);
1368       gimple_seq_add_stmt (&switch_body, x);
1369     }
1370
1371   /* For EH_ELSE, emit the exception path (plus resx) now, then
1372      subsequently we only need consider the normal path.  */
1373   if (eh_else)
1374     {
1375       if (tf->may_throw)
1376         {
1377           finally = gimple_eh_else_e_body (eh_else);
1378           lower_eh_constructs_1 (state, &finally);
1379
1380           emit_post_landing_pad (&eh_seq, tf->region);
1381           gimple_seq_add_seq (&eh_seq, finally);
1382           emit_resx (&eh_seq, tf->region);
1383         }
1384
1385       finally = gimple_eh_else_n_body (eh_else);
1386     }
1387   else if (tf->may_throw)
1388     {
1389       emit_post_landing_pad (&eh_seq, tf->region);
1390
1391       x = gimple_build_assign (finally_tmp,
1392                                build_int_cst (integer_type_node, eh_index));
1393       gimple_seq_add_stmt (&eh_seq, x);
1394
1395       x = gimple_build_goto (finally_label);
1396       gimple_seq_add_stmt (&eh_seq, x);
1397
1398       tmp = build_int_cst (integer_type_node, eh_index);
1399       last_case = build_case_label (tmp, NULL,
1400                                     create_artificial_label (tf_loc));
1401       VEC_quick_push (tree, case_label_vec, last_case);
1402       last_case_index++;
1403
1404       x = gimple_build_label (CASE_LABEL (last_case));
1405       gimple_seq_add_stmt (&eh_seq, x);
1406       emit_resx (&eh_seq, tf->region);
1407     }
1408
1409   x = gimple_build_label (finally_label);
1410   gimple_seq_add_stmt (&tf->top_p_seq, x);
1411
1412   gimple_seq_add_seq (&tf->top_p_seq, finally);
1413
1414   /* Redirect each incoming goto edge.  */
1415   q = tf->goto_queue;
1416   qe = q + tf->goto_queue_active;
1417   j = last_case_index + tf->may_return;
1418   /* Prepare the assignments to finally_tmp that are executed upon the
1419      entrance through a particular edge. */
1420   for (; q < qe; ++q)
1421     {
1422       gimple_seq mod = NULL;
1423       int switch_id;
1424       unsigned int case_index;
1425
1426       if (q->index < 0)
1427         {
1428           x = gimple_build_assign (finally_tmp,
1429                                    build_int_cst (integer_type_node,
1430                                                   return_index));
1431           gimple_seq_add_stmt (&mod, x);
1432           do_return_redirection (q, finally_label, mod);
1433           switch_id = return_index;
1434         }
1435       else
1436         {
1437           x = gimple_build_assign (finally_tmp,
1438                                    build_int_cst (integer_type_node, q->index));
1439           gimple_seq_add_stmt (&mod, x);
1440           do_goto_redirection (q, finally_label, mod, tf);
1441           switch_id = q->index;
1442         }
1443
1444       case_index = j + q->index;
1445       if (VEC_length (tree, case_label_vec) <= case_index
1446           || !VEC_index (tree, case_label_vec, case_index))
1447         {
1448           tree case_lab;
1449           void **slot;
1450           tmp = build_int_cst (integer_type_node, switch_id);
1451           case_lab = build_case_label (tmp, NULL,
1452                                        create_artificial_label (tf_loc));
1453           /* We store the cont_stmt in the pointer map, so that we can recover
1454              it in the loop below.  */
1455           if (!cont_map)
1456             cont_map = pointer_map_create ();
1457           slot = pointer_map_insert (cont_map, case_lab);
1458           *slot = q->cont_stmt;
1459           VEC_quick_push (tree, case_label_vec, case_lab);
1460         }
1461     }
1462   for (j = last_case_index; j < last_case_index + nlabels; j++)
1463     {
1464       gimple cont_stmt;
1465       void **slot;
1466
1467       last_case = VEC_index (tree, case_label_vec, j);
1468
1469       gcc_assert (last_case);
1470       gcc_assert (cont_map);
1471
1472       slot = pointer_map_contains (cont_map, last_case);
1473       gcc_assert (slot);
1474       cont_stmt = *(gimple *) slot;
1475
1476       x = gimple_build_label (CASE_LABEL (last_case));
1477       gimple_seq_add_stmt (&switch_body, x);
1478       gimple_seq_add_stmt (&switch_body, cont_stmt);
1479       maybe_record_in_goto_queue (state, cont_stmt);
1480     }
1481   if (cont_map)
1482     pointer_map_destroy (cont_map);
1483
1484   replace_goto_queue (tf);
1485
1486   /* Make sure that the last case is the default label, as one is required.
1487      Then sort the labels, which is also required in GIMPLE.  */
1488   CASE_LOW (last_case) = NULL;
1489   sort_case_labels (case_label_vec);
1490
1491   /* Build the switch statement, setting last_case to be the default
1492      label.  */
1493   switch_stmt = gimple_build_switch_vec (finally_tmp, last_case,
1494                                          case_label_vec);
1495   gimple_set_location (switch_stmt, finally_loc);
1496
1497   /* Need to link SWITCH_STMT after running replace_goto_queue
1498      due to not wanting to process the same goto stmts twice.  */
1499   gimple_seq_add_stmt (&tf->top_p_seq, switch_stmt);
1500   gimple_seq_add_seq (&tf->top_p_seq, switch_body);
1501 }
1502
1503 /* Decide whether or not we are going to duplicate the finally block.
1504    There are several considerations.
1505
1506    First, if this is Java, then the finally block contains code
1507    written by the user.  It has line numbers associated with it,
1508    so duplicating the block means it's difficult to set a breakpoint.
1509    Since controlling code generation via -g is verboten, we simply
1510    never duplicate code without optimization.
1511
1512    Second, we'd like to prevent egregious code growth.  One way to
1513    do this is to estimate the size of the finally block, multiply
1514    that by the number of copies we'd need to make, and compare against
1515    the estimate of the size of the switch machinery we'd have to add.  */
1516
1517 static bool
1518 decide_copy_try_finally (int ndests, bool may_throw, gimple_seq finally)
1519 {
1520   int f_estimate, sw_estimate;
1521   gimple eh_else;
1522
1523   /* If there's an EH_ELSE involved, the exception path is separate
1524      and really doesn't come into play for this computation.  */
1525   eh_else = get_eh_else (finally);
1526   if (eh_else)
1527     {
1528       ndests -= may_throw;
1529       finally = gimple_eh_else_n_body (eh_else);
1530     }
1531
1532   if (!optimize)
1533     {
1534       gimple_stmt_iterator gsi;
1535
1536       if (ndests == 1)
1537         return true;
1538
1539       for (gsi = gsi_start (finally); !gsi_end_p (gsi); gsi_next (&gsi))
1540         {
1541           gimple stmt = gsi_stmt (gsi);
1542           if (!is_gimple_debug (stmt) && !gimple_clobber_p (stmt))
1543             return false;
1544         }
1545       return true;
1546     }
1547
1548   /* Finally estimate N times, plus N gotos.  */
1549   f_estimate = count_insns_seq (finally, &eni_size_weights);
1550   f_estimate = (f_estimate + 1) * ndests;
1551
1552   /* Switch statement (cost 10), N variable assignments, N gotos.  */
1553   sw_estimate = 10 + 2 * ndests;
1554
1555   /* Optimize for size clearly wants our best guess.  */
1556   if (optimize_function_for_size_p (cfun))
1557     return f_estimate < sw_estimate;
1558
1559   /* ??? These numbers are completely made up so far.  */
1560   if (optimize > 1)
1561     return f_estimate < 100 || f_estimate < sw_estimate * 2;
1562   else
1563     return f_estimate < 40 || f_estimate * 2 < sw_estimate * 3;
1564 }
1565
1566 /* REG is the enclosing region for a possible cleanup region, or the region
1567    itself.  Returns TRUE if such a region would be unreachable.
1568
1569    Cleanup regions within a must-not-throw region aren't actually reachable
1570    even if there are throwing stmts within them, because the personality
1571    routine will call terminate before unwinding.  */
1572
1573 static bool
1574 cleanup_is_dead_in (eh_region reg)
1575 {
1576   while (reg && reg->type == ERT_CLEANUP)
1577     reg = reg->outer;
1578   return (reg && reg->type == ERT_MUST_NOT_THROW);
1579 }
1580
1581 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY_FINALLY nodes
1582    to a sequence of labels and blocks, plus the exception region trees
1583    that record all the magic.  This is complicated by the need to
1584    arrange for the FINALLY block to be executed on all exits.  */
1585
1586 static gimple_seq
1587 lower_try_finally (struct leh_state *state, gimple tp)
1588 {
1589   struct leh_tf_state this_tf;
1590   struct leh_state this_state;
1591   int ndests;
1592   gimple_seq old_eh_seq;
1593
1594   /* Process the try block.  */
1595
1596   memset (&this_tf, 0, sizeof (this_tf));
1597   this_tf.try_finally_expr = tp;
1598   this_tf.top_p = tp;
1599   this_tf.outer = state;
1600   if (using_eh_for_cleanups_p && !cleanup_is_dead_in (state->cur_region))
1601     {
1602       this_tf.region = gen_eh_region_cleanup (state->cur_region);
1603       this_state.cur_region = this_tf.region;
1604     }
1605   else
1606     {
1607       this_tf.region = NULL;
1608       this_state.cur_region = state->cur_region;
1609     }
1610
1611   this_state.ehp_region = state->ehp_region;
1612   this_state.tf = &this_tf;
1613
1614   old_eh_seq = eh_seq;
1615   eh_seq = NULL;
1616
1617   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
1618
1619   /* Determine if the try block is escaped through the bottom.  */
1620   this_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp));
1621
1622   /* Determine if any exceptions are possible within the try block.  */
1623   if (this_tf.region)
1624     this_tf.may_throw = eh_region_may_contain_throw (this_tf.region);
1625   if (this_tf.may_throw)
1626     honor_protect_cleanup_actions (state, &this_state, &this_tf);
1627
1628   /* Determine how many edges (still) reach the finally block.  Or rather,
1629      how many destinations are reached by the finally block.  Use this to
1630      determine how we process the finally block itself.  */
1631
1632   ndests = VEC_length (tree, this_tf.dest_array);
1633   ndests += this_tf.may_fallthru;
1634   ndests += this_tf.may_return;
1635   ndests += this_tf.may_throw;
1636
1637   /* If the FINALLY block is not reachable, dike it out.  */
1638   if (ndests == 0)
1639     {
1640       gimple_seq_add_seq (&this_tf.top_p_seq, gimple_try_eval (tp));
1641       gimple_try_set_cleanup (tp, NULL);
1642     }
1643   /* If the finally block doesn't fall through, then any destination
1644      we might try to impose there isn't reached either.  There may be
1645      some minor amount of cleanup and redirection still needed.  */
1646   else if (!gimple_seq_may_fallthru (gimple_try_cleanup (tp)))
1647     lower_try_finally_nofallthru (state, &this_tf);
1648
1649   /* We can easily special-case redirection to a single destination.  */
1650   else if (ndests == 1)
1651     lower_try_finally_onedest (state, &this_tf);
1652   else if (decide_copy_try_finally (ndests, this_tf.may_throw,
1653                                     gimple_try_cleanup (tp)))
1654     lower_try_finally_copy (state, &this_tf);
1655   else
1656     lower_try_finally_switch (state, &this_tf);
1657
1658   /* If someone requested we add a label at the end of the transformed
1659      block, do so.  */
1660   if (this_tf.fallthru_label)
1661     {
1662       /* This must be reached only if ndests == 0. */
1663       gimple x = gimple_build_label (this_tf.fallthru_label);
1664       gimple_seq_add_stmt (&this_tf.top_p_seq, x);
1665     }
1666
1667   VEC_free (tree, heap, this_tf.dest_array);
1668   free (this_tf.goto_queue);
1669   if (this_tf.goto_queue_map)
1670     pointer_map_destroy (this_tf.goto_queue_map);
1671
1672   /* If there was an old (aka outer) eh_seq, append the current eh_seq.
1673      If there was no old eh_seq, then the append is trivially already done.  */
1674   if (old_eh_seq)
1675     {
1676       if (eh_seq == NULL)
1677         eh_seq = old_eh_seq;
1678       else
1679         {
1680           gimple_seq new_eh_seq = eh_seq;
1681           eh_seq = old_eh_seq;
1682           gimple_seq_add_seq(&eh_seq, new_eh_seq);
1683         }
1684     }
1685
1686   return this_tf.top_p_seq;
1687 }
1688
1689 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY_CATCH with a
1690    list of GIMPLE_CATCH to a sequence of labels and blocks, plus the
1691    exception region trees that records all the magic.  */
1692
1693 static gimple_seq
1694 lower_catch (struct leh_state *state, gimple tp)
1695 {
1696   eh_region try_region = NULL;
1697   struct leh_state this_state = *state;
1698   gimple_stmt_iterator gsi;
1699   tree out_label;
1700   gimple_seq new_seq, cleanup;
1701   gimple x;
1702   location_t try_catch_loc = gimple_location (tp);
1703
1704   if (flag_exceptions)
1705     {
1706       try_region = gen_eh_region_try (state->cur_region);
1707       this_state.cur_region = try_region;
1708     }
1709
1710   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
1711
1712   if (!eh_region_may_contain_throw (try_region))
1713     return gimple_try_eval (tp);
1714
1715   new_seq = NULL;
1716   emit_eh_dispatch (&new_seq, try_region);
1717   emit_resx (&new_seq, try_region);
1718
1719   this_state.cur_region = state->cur_region;
1720   this_state.ehp_region = try_region;
1721
1722   out_label = NULL;
1723   cleanup = gimple_try_cleanup (tp);
1724   for (gsi = gsi_start (cleanup);
1725        !gsi_end_p (gsi);
1726        gsi_next (&gsi))
1727     {
1728       eh_catch c;
1729       gimple gcatch;
1730       gimple_seq handler;
1731
1732       gcatch = gsi_stmt (gsi);
1733       c = gen_eh_region_catch (try_region, gimple_catch_types (gcatch));
1734
1735       handler = gimple_catch_handler (gcatch);
1736       lower_eh_constructs_1 (&this_state, &handler);
1737
1738       c->label = create_artificial_label (UNKNOWN_LOCATION);
1739       x = gimple_build_label (c->label);
1740       gimple_seq_add_stmt (&new_seq, x);
1741
1742       gimple_seq_add_seq (&new_seq, handler);
1743
1744       if (gimple_seq_may_fallthru (new_seq))
1745         {
1746           if (!out_label)
1747             out_label = create_artificial_label (try_catch_loc);
1748
1749           x = gimple_build_goto (out_label);
1750           gimple_seq_add_stmt (&new_seq, x);
1751         }
1752       if (!c->type_list)
1753         break;
1754     }
1755
1756   gimple_try_set_cleanup (tp, new_seq);
1757
1758   return frob_into_branch_around (tp, try_region, out_label);
1759 }
1760
1761 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY with a
1762    GIMPLE_EH_FILTER to a sequence of labels and blocks, plus the exception
1763    region trees that record all the magic.  */
1764
1765 static gimple_seq
1766 lower_eh_filter (struct leh_state *state, gimple tp)
1767 {
1768   struct leh_state this_state = *state;
1769   eh_region this_region = NULL;
1770   gimple inner, x;
1771   gimple_seq new_seq;
1772
1773   inner = gimple_seq_first_stmt (gimple_try_cleanup (tp));
1774
1775   if (flag_exceptions)
1776     {
1777       this_region = gen_eh_region_allowed (state->cur_region,
1778                                            gimple_eh_filter_types (inner));
1779       this_state.cur_region = this_region;
1780     }
1781
1782   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
1783
1784   if (!eh_region_may_contain_throw (this_region))
1785     return gimple_try_eval (tp);
1786
1787   new_seq = NULL;
1788   this_state.cur_region = state->cur_region;
1789   this_state.ehp_region = this_region;
1790
1791   emit_eh_dispatch (&new_seq, this_region);
1792   emit_resx (&new_seq, this_region);
1793
1794   this_region->u.allowed.label = create_artificial_label (UNKNOWN_LOCATION);
1795   x = gimple_build_label (this_region->u.allowed.label);
1796   gimple_seq_add_stmt (&new_seq, x);
1797
1798   lower_eh_constructs_1 (&this_state, gimple_eh_filter_failure_ptr (inner));
1799   gimple_seq_add_seq (&new_seq, gimple_eh_filter_failure (inner));
1800
1801   gimple_try_set_cleanup (tp, new_seq);
1802
1803   return frob_into_branch_around (tp, this_region, NULL);
1804 }
1805
1806 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY with
1807    an GIMPLE_EH_MUST_NOT_THROW to a sequence of labels and blocks,
1808    plus the exception region trees that record all the magic.  */
1809
1810 static gimple_seq
1811 lower_eh_must_not_throw (struct leh_state *state, gimple tp)
1812 {
1813   struct leh_state this_state = *state;
1814
1815   if (flag_exceptions)
1816     {
1817       gimple inner = gimple_seq_first_stmt (gimple_try_cleanup (tp));
1818       eh_region this_region;
1819
1820       this_region = gen_eh_region_must_not_throw (state->cur_region);
1821       this_region->u.must_not_throw.failure_decl
1822         = gimple_eh_must_not_throw_fndecl (inner);
1823       this_region->u.must_not_throw.failure_loc = gimple_location (tp);
1824
1825       /* In order to get mangling applied to this decl, we must mark it
1826          used now.  Otherwise, pass_ipa_free_lang_data won't think it
1827          needs to happen.  */
1828       TREE_USED (this_region->u.must_not_throw.failure_decl) = 1;
1829
1830       this_state.cur_region = this_region;
1831     }
1832
1833   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
1834
1835   return gimple_try_eval (tp);
1836 }
1837
1838 /* Implement a cleanup expression.  This is similar to try-finally,
1839    except that we only execute the cleanup block for exception edges.  */
1840
1841 static gimple_seq
1842 lower_cleanup (struct leh_state *state, gimple tp)
1843 {
1844   struct leh_state this_state = *state;
1845   eh_region this_region = NULL;
1846   struct leh_tf_state fake_tf;
1847   gimple_seq result;
1848   bool cleanup_dead = cleanup_is_dead_in (state->cur_region);
1849
1850   if (flag_exceptions && !cleanup_dead)
1851     {
1852       this_region = gen_eh_region_cleanup (state->cur_region);
1853       this_state.cur_region = this_region;
1854     }
1855
1856   lower_eh_constructs_1 (&this_state, gimple_try_eval_ptr (tp));
1857
1858   if (cleanup_dead || !eh_region_may_contain_throw (this_region))
1859     return gimple_try_eval (tp);
1860
1861   /* Build enough of a try-finally state so that we can reuse
1862      honor_protect_cleanup_actions.  */
1863   memset (&fake_tf, 0, sizeof (fake_tf));
1864   fake_tf.top_p = fake_tf.try_finally_expr = tp;
1865   fake_tf.outer = state;
1866   fake_tf.region = this_region;
1867   fake_tf.may_fallthru = gimple_seq_may_fallthru (gimple_try_eval (tp));
1868   fake_tf.may_throw = true;
1869
1870   honor_protect_cleanup_actions (state, NULL, &fake_tf);
1871
1872   if (fake_tf.may_throw)
1873     {
1874       /* In this case honor_protect_cleanup_actions had nothing to do,
1875          and we should process this normally.  */
1876       lower_eh_constructs_1 (state, gimple_try_cleanup_ptr (tp));
1877       result = frob_into_branch_around (tp, this_region,
1878                                         fake_tf.fallthru_label);
1879     }
1880   else
1881     {
1882       /* In this case honor_protect_cleanup_actions did nearly all of
1883          the work.  All we have left is to append the fallthru_label.  */
1884
1885       result = gimple_try_eval (tp);
1886       if (fake_tf.fallthru_label)
1887         {
1888           gimple x = gimple_build_label (fake_tf.fallthru_label);
1889           gimple_seq_add_stmt (&result, x);
1890         }
1891     }
1892   return result;
1893 }
1894
1895 /* Main loop for lowering eh constructs. Also moves gsi to the next
1896    statement. */
1897
1898 static void
1899 lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
1900 {
1901   gimple_seq replace;
1902   gimple x;
1903   gimple stmt = gsi_stmt (*gsi);
1904
1905   switch (gimple_code (stmt))
1906     {
1907     case GIMPLE_CALL:
1908       {
1909         tree fndecl = gimple_call_fndecl (stmt);
1910         tree rhs, lhs;
1911
1912         if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
1913           switch (DECL_FUNCTION_CODE (fndecl))
1914             {
1915             case BUILT_IN_EH_POINTER:
1916               /* The front end may have generated a call to
1917                  __builtin_eh_pointer (0) within a catch region.  Replace
1918                  this zero argument with the current catch region number.  */
1919               if (state->ehp_region)
1920                 {
1921                   tree nr = build_int_cst (integer_type_node,
1922                                            state->ehp_region->index);
1923                   gimple_call_set_arg (stmt, 0, nr);
1924                 }
1925               else
1926                 {
1927                   /* The user has dome something silly.  Remove it.  */
1928                   rhs = null_pointer_node;
1929                   goto do_replace;
1930                 }
1931               break;
1932
1933             case BUILT_IN_EH_FILTER:
1934               /* ??? This should never appear, but since it's a builtin it
1935                  is accessible to abuse by users.  Just remove it and
1936                  replace the use with the arbitrary value zero.  */
1937               rhs = build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
1938             do_replace:
1939               lhs = gimple_call_lhs (stmt);
1940               x = gimple_build_assign (lhs, rhs);
1941               gsi_insert_before (gsi, x, GSI_SAME_STMT);
1942               /* FALLTHRU */
1943
1944             case BUILT_IN_EH_COPY_VALUES:
1945               /* Likewise this should not appear.  Remove it.  */
1946               gsi_remove (gsi, true);
1947               return;
1948
1949             default:
1950               break;
1951             }
1952       }
1953       /* FALLTHRU */
1954
1955     case GIMPLE_ASSIGN:
1956       /* If the stmt can throw use a new temporary for the assignment
1957          to a LHS.  This makes sure the old value of the LHS is
1958          available on the EH edge.  Only do so for statements that
1959          potentially fall through (no noreturn calls e.g.), otherwise
1960          this new assignment might create fake fallthru regions.  */
1961       if (stmt_could_throw_p (stmt)
1962           && gimple_has_lhs (stmt)
1963           && gimple_stmt_may_fallthru (stmt)
1964           && !tree_could_throw_p (gimple_get_lhs (stmt))
1965           && is_gimple_reg_type (TREE_TYPE (gimple_get_lhs (stmt))))
1966         {
1967           tree lhs = gimple_get_lhs (stmt);
1968           tree tmp = create_tmp_var (TREE_TYPE (lhs), NULL);
1969           gimple s = gimple_build_assign (lhs, tmp);
1970           gimple_set_location (s, gimple_location (stmt));
1971           gimple_set_block (s, gimple_block (stmt));
1972           gimple_set_lhs (stmt, tmp);
1973           if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
1974               || TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
1975             DECL_GIMPLE_REG_P (tmp) = 1;
1976           gsi_insert_after (gsi, s, GSI_SAME_STMT);
1977         }
1978       /* Look for things that can throw exceptions, and record them.  */
1979       if (state->cur_region && stmt_could_throw_p (stmt))
1980         {
1981           record_stmt_eh_region (state->cur_region, stmt);
1982           note_eh_region_may_contain_throw (state->cur_region);
1983         }
1984       break;
1985
1986     case GIMPLE_COND:
1987     case GIMPLE_GOTO:
1988     case GIMPLE_RETURN:
1989       maybe_record_in_goto_queue (state, stmt);
1990       break;
1991
1992     case GIMPLE_SWITCH:
1993       verify_norecord_switch_expr (state, stmt);
1994       break;
1995
1996     case GIMPLE_TRY:
1997       if (gimple_try_kind (stmt) == GIMPLE_TRY_FINALLY)
1998         replace = lower_try_finally (state, stmt);
1999       else
2000         {
2001           x = gimple_seq_first_stmt (gimple_try_cleanup (stmt));
2002           if (!x)
2003             {
2004               replace = gimple_try_eval (stmt);
2005               lower_eh_constructs_1 (state, &replace);
2006             }
2007           else
2008             switch (gimple_code (x))
2009               {
2010                 case GIMPLE_CATCH:
2011                     replace = lower_catch (state, stmt);
2012                     break;
2013                 case GIMPLE_EH_FILTER:
2014                     replace = lower_eh_filter (state, stmt);
2015                     break;
2016                 case GIMPLE_EH_MUST_NOT_THROW:
2017                     replace = lower_eh_must_not_throw (state, stmt);
2018                     break;
2019                 case GIMPLE_EH_ELSE:
2020                     /* This code is only valid with GIMPLE_TRY_FINALLY.  */
2021                     gcc_unreachable ();
2022                 default:
2023                     replace = lower_cleanup (state, stmt);
2024                     break;
2025               }
2026         }
2027
2028       /* Remove the old stmt and insert the transformed sequence
2029          instead. */
2030       gsi_insert_seq_before (gsi, replace, GSI_SAME_STMT);
2031       gsi_remove (gsi, true);
2032
2033       /* Return since we don't want gsi_next () */
2034       return;
2035
2036     case GIMPLE_EH_ELSE:
2037       /* We should be eliminating this in lower_try_finally et al.  */
2038       gcc_unreachable ();
2039
2040     default:
2041       /* A type, a decl, or some kind of statement that we're not
2042          interested in.  Don't walk them.  */
2043       break;
2044     }
2045
2046   gsi_next (gsi);
2047 }
2048
2049 /* A helper to unwrap a gimple_seq and feed stmts to lower_eh_constructs_2. */
2050
2051 static void
2052 lower_eh_constructs_1 (struct leh_state *state, gimple_seq *pseq)
2053 {
2054   gimple_stmt_iterator gsi;
2055   for (gsi = gsi_start (*pseq); !gsi_end_p (gsi);)
2056     lower_eh_constructs_2 (state, &gsi);
2057 }
2058
2059 static unsigned int
2060 lower_eh_constructs (void)
2061 {
2062   struct leh_state null_state;
2063   gimple_seq bodyp;
2064
2065   bodyp = gimple_body (current_function_decl);
2066   if (bodyp == NULL)
2067     return 0;
2068
2069   finally_tree = htab_create (31, struct_ptr_hash, struct_ptr_eq, free);
2070   eh_region_may_contain_throw_map = BITMAP_ALLOC (NULL);
2071   memset (&null_state, 0, sizeof (null_state));
2072
2073   collect_finally_tree_1 (bodyp, NULL);
2074   lower_eh_constructs_1 (&null_state, &bodyp);
2075   gimple_set_body (current_function_decl, bodyp);
2076
2077   /* We assume there's a return statement, or something, at the end of
2078      the function, and thus ploping the EH sequence afterward won't
2079      change anything.  */
2080   gcc_assert (!gimple_seq_may_fallthru (bodyp));
2081   gimple_seq_add_seq (&bodyp, eh_seq);
2082
2083   /* We assume that since BODYP already existed, adding EH_SEQ to it
2084      didn't change its value, and we don't have to re-set the function.  */
2085   gcc_assert (bodyp == gimple_body (current_function_decl));
2086
2087   htab_delete (finally_tree);
2088   BITMAP_FREE (eh_region_may_contain_throw_map);
2089   eh_seq = NULL;
2090
2091   /* If this function needs a language specific EH personality routine
2092      and the frontend didn't already set one do so now.  */
2093   if (function_needs_eh_personality (cfun) == eh_personality_lang
2094       && !DECL_FUNCTION_PERSONALITY (current_function_decl))
2095     DECL_FUNCTION_PERSONALITY (current_function_decl)
2096       = lang_hooks.eh_personality ();
2097
2098   return 0;
2099 }
2100
2101 struct gimple_opt_pass pass_lower_eh =
2102 {
2103  {
2104   GIMPLE_PASS,
2105   "eh",                                 /* name */
2106   NULL,                                 /* gate */
2107   lower_eh_constructs,                  /* execute */
2108   NULL,                                 /* sub */
2109   NULL,                                 /* next */
2110   0,                                    /* static_pass_number */
2111   TV_TREE_EH,                           /* tv_id */
2112   PROP_gimple_lcf,                      /* properties_required */
2113   PROP_gimple_leh,                      /* properties_provided */
2114   0,                                    /* properties_destroyed */
2115   0,                                    /* todo_flags_start */
2116   0                                     /* todo_flags_finish */
2117  }
2118 };
2119 \f
2120 /* Create the multiple edges from an EH_DISPATCH statement to all of
2121    the possible handlers for its EH region.  Return true if there's
2122    no fallthru edge; false if there is.  */
2123
2124 bool
2125 make_eh_dispatch_edges (gimple stmt)
2126 {
2127   eh_region r;
2128   eh_catch c;
2129   basic_block src, dst;
2130
2131   r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt));
2132   src = gimple_bb (stmt);
2133
2134   switch (r->type)
2135     {
2136     case ERT_TRY:
2137       for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
2138         {
2139           dst = label_to_block (c->label);
2140           make_edge (src, dst, 0);
2141
2142           /* A catch-all handler doesn't have a fallthru.  */
2143           if (c->type_list == NULL)
2144             return false;
2145         }
2146       break;
2147
2148     case ERT_ALLOWED_EXCEPTIONS:
2149       dst = label_to_block (r->u.allowed.label);
2150       make_edge (src, dst, 0);
2151       break;
2152
2153     default:
2154       gcc_unreachable ();
2155     }
2156
2157   return true;
2158 }
2159
2160 /* Create the single EH edge from STMT to its nearest landing pad,
2161    if there is such a landing pad within the current function.  */
2162
2163 void
2164 make_eh_edges (gimple stmt)
2165 {
2166   basic_block src, dst;
2167   eh_landing_pad lp;
2168   int lp_nr;
2169
2170   lp_nr = lookup_stmt_eh_lp (stmt);
2171   if (lp_nr <= 0)
2172     return;
2173
2174   lp = get_eh_landing_pad_from_number (lp_nr);
2175   gcc_assert (lp != NULL);
2176
2177   src = gimple_bb (stmt);
2178   dst = label_to_block (lp->post_landing_pad);
2179   make_edge (src, dst, EDGE_EH);
2180 }
2181
2182 /* Do the work in redirecting EDGE_IN to NEW_BB within the EH region tree;
2183    do not actually perform the final edge redirection.
2184
2185    CHANGE_REGION is true when we're being called from cleanup_empty_eh and
2186    we intend to change the destination EH region as well; this means
2187    EH_LANDING_PAD_NR must already be set on the destination block label.
2188    If false, we're being called from generic cfg manipulation code and we
2189    should preserve our place within the region tree.  */
2190
2191 static void
2192 redirect_eh_edge_1 (edge edge_in, basic_block new_bb, bool change_region)
2193 {
2194   eh_landing_pad old_lp, new_lp;
2195   basic_block old_bb;
2196   gimple throw_stmt;
2197   int old_lp_nr, new_lp_nr;
2198   tree old_label, new_label;
2199   edge_iterator ei;
2200   edge e;
2201
2202   old_bb = edge_in->dest;
2203   old_label = gimple_block_label (old_bb);
2204   old_lp_nr = EH_LANDING_PAD_NR (old_label);
2205   gcc_assert (old_lp_nr > 0);
2206   old_lp = get_eh_landing_pad_from_number (old_lp_nr);
2207
2208   throw_stmt = last_stmt (edge_in->src);
2209   gcc_assert (lookup_stmt_eh_lp (throw_stmt) == old_lp_nr);
2210
2211   new_label = gimple_block_label (new_bb);
2212
2213   /* Look for an existing region that might be using NEW_BB already.  */
2214   new_lp_nr = EH_LANDING_PAD_NR (new_label);
2215   if (new_lp_nr)
2216     {
2217       new_lp = get_eh_landing_pad_from_number (new_lp_nr);
2218       gcc_assert (new_lp);
2219
2220       /* Unless CHANGE_REGION is true, the new and old landing pad
2221          had better be associated with the same EH region.  */
2222       gcc_assert (change_region || new_lp->region == old_lp->region);
2223     }
2224   else
2225     {
2226       new_lp = NULL;
2227       gcc_assert (!change_region);
2228     }
2229
2230   /* Notice when we redirect the last EH edge away from OLD_BB.  */
2231   FOR_EACH_EDGE (e, ei, old_bb->preds)
2232     if (e != edge_in && (e->flags & EDGE_EH))
2233       break;
2234
2235   if (new_lp)
2236     {
2237       /* NEW_LP already exists.  If there are still edges into OLD_LP,
2238          there's nothing to do with the EH tree.  If there are no more
2239          edges into OLD_LP, then we want to remove OLD_LP as it is unused.
2240          If CHANGE_REGION is true, then our caller is expecting to remove
2241          the landing pad.  */
2242       if (e == NULL && !change_region)
2243         remove_eh_landing_pad (old_lp);
2244     }
2245   else
2246     {
2247       /* No correct landing pad exists.  If there are no more edges
2248          into OLD_LP, then we can simply re-use the existing landing pad.
2249          Otherwise, we have to create a new landing pad.  */
2250       if (e == NULL)
2251         {
2252           EH_LANDING_PAD_NR (old_lp->post_landing_pad) = 0;
2253           new_lp = old_lp;
2254         }
2255       else
2256         new_lp = gen_eh_landing_pad (old_lp->region);
2257       new_lp->post_landing_pad = new_label;
2258       EH_LANDING_PAD_NR (new_label) = new_lp->index;
2259     }
2260
2261   /* Maybe move the throwing statement to the new region.  */
2262   if (old_lp != new_lp)
2263     {
2264       remove_stmt_from_eh_lp (throw_stmt);
2265       add_stmt_to_eh_lp (throw_stmt, new_lp->index);
2266     }
2267 }
2268
2269 /* Redirect EH edge E to NEW_BB.  */
2270
2271 edge
2272 redirect_eh_edge (edge edge_in, basic_block new_bb)
2273 {
2274   redirect_eh_edge_1 (edge_in, new_bb, false);
2275   return ssa_redirect_edge (edge_in, new_bb);
2276 }
2277
2278 /* This is a subroutine of gimple_redirect_edge_and_branch.  Update the
2279    labels for redirecting a non-fallthru EH_DISPATCH edge E to NEW_BB.
2280    The actual edge update will happen in the caller.  */
2281
2282 void
2283 redirect_eh_dispatch_edge (gimple stmt, edge e, basic_block new_bb)
2284 {
2285   tree new_lab = gimple_block_label (new_bb);
2286   bool any_changed = false;
2287   basic_block old_bb;
2288   eh_region r;
2289   eh_catch c;
2290
2291   r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt));
2292   switch (r->type)
2293     {
2294     case ERT_TRY:
2295       for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
2296         {
2297           old_bb = label_to_block (c->label);
2298           if (old_bb == e->dest)
2299             {
2300               c->label = new_lab;
2301               any_changed = true;
2302             }
2303         }
2304       break;
2305
2306     case ERT_ALLOWED_EXCEPTIONS:
2307       old_bb = label_to_block (r->u.allowed.label);
2308       gcc_assert (old_bb == e->dest);
2309       r->u.allowed.label = new_lab;
2310       any_changed = true;
2311       break;
2312
2313     default:
2314       gcc_unreachable ();
2315     }
2316
2317   gcc_assert (any_changed);
2318 }
2319 \f
2320 /* Helper function for operation_could_trap_p and stmt_could_throw_p.  */
2321
2322 bool
2323 operation_could_trap_helper_p (enum tree_code op,
2324                                bool fp_operation,
2325                                bool honor_trapv,
2326                                bool honor_nans,
2327                                bool honor_snans,
2328                                tree divisor,
2329                                bool *handled)
2330 {
2331   *handled = true;
2332   switch (op)
2333     {
2334     case TRUNC_DIV_EXPR:
2335     case CEIL_DIV_EXPR:
2336     case FLOOR_DIV_EXPR:
2337     case ROUND_DIV_EXPR:
2338     case EXACT_DIV_EXPR:
2339     case CEIL_MOD_EXPR:
2340     case FLOOR_MOD_EXPR:
2341     case ROUND_MOD_EXPR:
2342     case TRUNC_MOD_EXPR:
2343     case RDIV_EXPR:
2344       if (honor_snans || honor_trapv)
2345         return true;
2346       if (fp_operation)
2347         return flag_trapping_math;
2348       if (!TREE_CONSTANT (divisor) || integer_zerop (divisor))
2349         return true;
2350       return false;
2351
2352     case LT_EXPR:
2353     case LE_EXPR:
2354     case GT_EXPR:
2355     case GE_EXPR:
2356     case LTGT_EXPR:
2357       /* Some floating point comparisons may trap.  */
2358       return honor_nans;
2359
2360     case EQ_EXPR:
2361     case NE_EXPR:
2362     case UNORDERED_EXPR:
2363     case ORDERED_EXPR:
2364     case UNLT_EXPR:
2365     case UNLE_EXPR:
2366     case UNGT_EXPR:
2367     case UNGE_EXPR:
2368     case UNEQ_EXPR:
2369       return honor_snans;
2370
2371     case CONVERT_EXPR:
2372     case FIX_TRUNC_EXPR:
2373       /* Conversion of floating point might trap.  */
2374       return honor_nans;
2375
2376     case NEGATE_EXPR:
2377     case ABS_EXPR:
2378     case CONJ_EXPR:
2379       /* These operations don't trap with floating point.  */
2380       if (honor_trapv)
2381         return true;
2382       return false;
2383
2384     case PLUS_EXPR:
2385     case MINUS_EXPR:
2386     case MULT_EXPR:
2387       /* Any floating arithmetic may trap.  */
2388       if (fp_operation && flag_trapping_math)
2389         return true;
2390       if (honor_trapv)
2391         return true;
2392       return false;
2393
2394     case COMPLEX_EXPR:
2395     case CONSTRUCTOR:
2396       /* Constructing an object cannot trap.  */
2397       return false;
2398
2399     default:
2400       /* Any floating arithmetic may trap.  */
2401       if (fp_operation && flag_trapping_math)
2402         return true;
2403
2404       *handled = false;
2405       return false;
2406     }
2407 }
2408
2409 /* Return true if operation OP may trap.  FP_OPERATION is true if OP is applied
2410    on floating-point values.  HONOR_TRAPV is true if OP is applied on integer
2411    type operands that may trap.  If OP is a division operator, DIVISOR contains
2412    the value of the divisor.  */
2413
2414 bool
2415 operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
2416                         tree divisor)
2417 {
2418   bool honor_nans = (fp_operation && flag_trapping_math
2419                      && !flag_finite_math_only);
2420   bool honor_snans = fp_operation && flag_signaling_nans != 0;
2421   bool handled;
2422
2423   if (TREE_CODE_CLASS (op) != tcc_comparison
2424       && TREE_CODE_CLASS (op) != tcc_unary
2425       && TREE_CODE_CLASS (op) != tcc_binary)
2426     return false;
2427
2428   return operation_could_trap_helper_p (op, fp_operation, honor_trapv,
2429                                         honor_nans, honor_snans, divisor,
2430                                         &handled);
2431 }
2432
2433 /* Return true if EXPR can trap, as in dereferencing an invalid pointer
2434    location or floating point arithmetic.  C.f. the rtl version, may_trap_p.
2435    This routine expects only GIMPLE lhs or rhs input.  */
2436
2437 bool
2438 tree_could_trap_p (tree expr)
2439 {
2440   enum tree_code code;
2441   bool fp_operation = false;
2442   bool honor_trapv = false;
2443   tree t, base, div = NULL_TREE;
2444
2445   if (!expr)
2446     return false;
2447
2448   code = TREE_CODE (expr);
2449   t = TREE_TYPE (expr);
2450
2451   if (t)
2452     {
2453       if (COMPARISON_CLASS_P (expr))
2454         fp_operation = FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)));
2455       else
2456         fp_operation = FLOAT_TYPE_P (t);
2457       honor_trapv = INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t);
2458     }
2459
2460   if (TREE_CODE_CLASS (code) == tcc_binary)
2461     div = TREE_OPERAND (expr, 1);
2462   if (operation_could_trap_p (code, fp_operation, honor_trapv, div))
2463     return true;
2464
2465  restart:
2466   switch (code)
2467     {
2468     case TARGET_MEM_REF:
2469       if (TREE_CODE (TMR_BASE (expr)) == ADDR_EXPR
2470           && !TMR_INDEX (expr) && !TMR_INDEX2 (expr))
2471         return false;
2472       return !TREE_THIS_NOTRAP (expr);
2473
2474     case COMPONENT_REF:
2475     case REALPART_EXPR:
2476     case IMAGPART_EXPR:
2477     case BIT_FIELD_REF:
2478     case VIEW_CONVERT_EXPR:
2479     case WITH_SIZE_EXPR:
2480       expr = TREE_OPERAND (expr, 0);
2481       code = TREE_CODE (expr);
2482       goto restart;
2483
2484     case ARRAY_RANGE_REF:
2485       base = TREE_OPERAND (expr, 0);
2486       if (tree_could_trap_p (base))
2487         return true;
2488       if (TREE_THIS_NOTRAP (expr))
2489         return false;
2490       return !range_in_array_bounds_p (expr);
2491
2492     case ARRAY_REF:
2493       base = TREE_OPERAND (expr, 0);
2494       if (tree_could_trap_p (base))
2495         return true;
2496       if (TREE_THIS_NOTRAP (expr))
2497         return false;
2498       return !in_array_bounds_p (expr);
2499
2500     case MEM_REF:
2501       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
2502         return false;
2503       /* Fallthru.  */
2504     case INDIRECT_REF:
2505       return !TREE_THIS_NOTRAP (expr);
2506
2507     case ASM_EXPR:
2508       return TREE_THIS_VOLATILE (expr);
2509
2510     case CALL_EXPR:
2511       t = get_callee_fndecl (expr);
2512       /* Assume that calls to weak functions may trap.  */
2513       if (!t || !DECL_P (t))
2514         return true;
2515       if (DECL_WEAK (t))
2516         return tree_could_trap_p (t);
2517       return false;
2518
2519     case FUNCTION_DECL:
2520       /* Assume that accesses to weak functions may trap, unless we know
2521          they are certainly defined in current TU or in some other
2522          LTO partition.  */
2523       if (DECL_WEAK (expr))
2524         {
2525           struct cgraph_node *node;
2526           if (!DECL_EXTERNAL (expr))
2527             return false;
2528           node = cgraph_function_node (cgraph_get_node (expr), NULL);
2529           if (node && node->symbol.in_other_partition)
2530             return false;
2531           return true;
2532         }
2533       return false;
2534
2535     case VAR_DECL:
2536       /* Assume that accesses to weak vars may trap, unless we know
2537          they are certainly defined in current TU or in some other
2538          LTO partition.  */
2539       if (DECL_WEAK (expr))
2540         {
2541           struct varpool_node *node;
2542           if (!DECL_EXTERNAL (expr))
2543             return false;
2544           node = varpool_variable_node (varpool_get_node (expr), NULL);
2545           if (node && node->symbol.in_other_partition)
2546             return false;
2547           return true;
2548         }
2549       return false;
2550
2551     default:
2552       return false;
2553     }
2554 }
2555
2556
2557 /* Helper for stmt_could_throw_p.  Return true if STMT (assumed to be a
2558    an assignment or a conditional) may throw.  */
2559
2560 static bool
2561 stmt_could_throw_1_p (gimple stmt)
2562 {
2563   enum tree_code code = gimple_expr_code (stmt);
2564   bool honor_nans = false;
2565   bool honor_snans = false;
2566   bool fp_operation = false;
2567   bool honor_trapv = false;
2568   tree t;
2569   size_t i;
2570   bool handled, ret;
2571
2572   if (TREE_CODE_CLASS (code) == tcc_comparison
2573       || TREE_CODE_CLASS (code) == tcc_unary
2574       || TREE_CODE_CLASS (code) == tcc_binary)
2575     {
2576       if (is_gimple_assign (stmt)
2577           && TREE_CODE_CLASS (code) == tcc_comparison)
2578         t = TREE_TYPE (gimple_assign_rhs1 (stmt));
2579       else if (gimple_code (stmt) == GIMPLE_COND)
2580         t = TREE_TYPE (gimple_cond_lhs (stmt));
2581       else
2582         t = gimple_expr_type (stmt);
2583       fp_operation = FLOAT_TYPE_P (t);
2584       if (fp_operation)
2585         {
2586           honor_nans = flag_trapping_math && !flag_finite_math_only;
2587           honor_snans = flag_signaling_nans != 0;
2588         }
2589       else if (INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t))
2590         honor_trapv = true;
2591     }
2592
2593   /* Check if the main expression may trap.  */
2594   t = is_gimple_assign (stmt) ? gimple_assign_rhs2 (stmt) : NULL;
2595   ret = operation_could_trap_helper_p (code, fp_operation, honor_trapv,
2596                                        honor_nans, honor_snans, t,
2597                                        &handled);
2598   if (handled)
2599     return ret;
2600
2601   /* If the expression does not trap, see if any of the individual operands may
2602      trap.  */
2603   for (i = 0; i < gimple_num_ops (stmt); i++)
2604     if (tree_could_trap_p (gimple_op (stmt, i)))
2605       return true;
2606
2607   return false;
2608 }
2609
2610
2611 /* Return true if statement STMT could throw an exception.  */
2612
2613 bool
2614 stmt_could_throw_p (gimple stmt)
2615 {
2616   if (!flag_exceptions)
2617     return false;
2618
2619   /* The only statements that can throw an exception are assignments,
2620      conditionals, calls, resx, and asms.  */
2621   switch (gimple_code (stmt))
2622     {
2623     case GIMPLE_RESX:
2624       return true;
2625
2626     case GIMPLE_CALL:
2627       return !gimple_call_nothrow_p (stmt);
2628
2629     case GIMPLE_ASSIGN:
2630     case GIMPLE_COND:
2631       if (!cfun->can_throw_non_call_exceptions)
2632         return false;
2633       return stmt_could_throw_1_p (stmt);
2634
2635     case GIMPLE_ASM:
2636       if (!cfun->can_throw_non_call_exceptions)
2637         return false;
2638       return gimple_asm_volatile_p (stmt);
2639
2640     default:
2641       return false;
2642     }
2643 }
2644
2645
2646 /* Return true if expression T could throw an exception.  */
2647
2648 bool
2649 tree_could_throw_p (tree t)
2650 {
2651   if (!flag_exceptions)
2652     return false;
2653   if (TREE_CODE (t) == MODIFY_EXPR)
2654     {
2655       if (cfun->can_throw_non_call_exceptions
2656           && tree_could_trap_p (TREE_OPERAND (t, 0)))
2657         return true;
2658       t = TREE_OPERAND (t, 1);
2659     }
2660
2661   if (TREE_CODE (t) == WITH_SIZE_EXPR)
2662     t = TREE_OPERAND (t, 0);
2663   if (TREE_CODE (t) == CALL_EXPR)
2664     return (call_expr_flags (t) & ECF_NOTHROW) == 0;
2665   if (cfun->can_throw_non_call_exceptions)
2666     return tree_could_trap_p (t);
2667   return false;
2668 }
2669
2670 /* Return true if STMT can throw an exception that is not caught within
2671    the current function (CFUN).  */
2672
2673 bool
2674 stmt_can_throw_external (gimple stmt)
2675 {
2676   int lp_nr;
2677
2678   if (!stmt_could_throw_p (stmt))
2679     return false;
2680
2681   lp_nr = lookup_stmt_eh_lp (stmt);
2682   return lp_nr == 0;
2683 }
2684
2685 /* Return true if STMT can throw an exception that is caught within
2686    the current function (CFUN).  */
2687
2688 bool
2689 stmt_can_throw_internal (gimple stmt)
2690 {
2691   int lp_nr;
2692
2693   if (!stmt_could_throw_p (stmt))
2694     return false;
2695
2696   lp_nr = lookup_stmt_eh_lp (stmt);
2697   return lp_nr > 0;
2698 }
2699
2700 /* Given a statement STMT in IFUN, if STMT can no longer throw, then
2701    remove any entry it might have from the EH table.  Return true if
2702    any change was made.  */
2703
2704 bool
2705 maybe_clean_eh_stmt_fn (struct function *ifun, gimple stmt)
2706 {
2707   if (stmt_could_throw_p (stmt))
2708     return false;
2709   return remove_stmt_from_eh_lp_fn (ifun, stmt);
2710 }
2711
2712 /* Likewise, but always use the current function.  */
2713
2714 bool
2715 maybe_clean_eh_stmt (gimple stmt)
2716 {
2717   return maybe_clean_eh_stmt_fn (cfun, stmt);
2718 }
2719
2720 /* Given a statement OLD_STMT and a new statement NEW_STMT that has replaced
2721    OLD_STMT in the function, remove OLD_STMT from the EH table and put NEW_STMT
2722    in the table if it should be in there.  Return TRUE if a replacement was
2723    done that my require an EH edge purge.  */
2724
2725 bool
2726 maybe_clean_or_replace_eh_stmt (gimple old_stmt, gimple new_stmt)
2727 {
2728   int lp_nr = lookup_stmt_eh_lp (old_stmt);
2729
2730   if (lp_nr != 0)
2731     {
2732       bool new_stmt_could_throw = stmt_could_throw_p (new_stmt);
2733
2734       if (new_stmt == old_stmt && new_stmt_could_throw)
2735         return false;
2736
2737       remove_stmt_from_eh_lp (old_stmt);
2738       if (new_stmt_could_throw)
2739         {
2740           add_stmt_to_eh_lp (new_stmt, lp_nr);
2741           return false;
2742         }
2743       else
2744         return true;
2745     }
2746
2747   return false;
2748 }
2749
2750 /* Given a statement OLD_STMT in OLD_FUN and a duplicate statement NEW_STMT
2751    in NEW_FUN, copy the EH table data from OLD_STMT to NEW_STMT.  The MAP
2752    operand is the return value of duplicate_eh_regions.  */
2753
2754 bool
2755 maybe_duplicate_eh_stmt_fn (struct function *new_fun, gimple new_stmt,
2756                             struct function *old_fun, gimple old_stmt,
2757                             struct pointer_map_t *map, int default_lp_nr)
2758 {
2759   int old_lp_nr, new_lp_nr;
2760   void **slot;
2761
2762   if (!stmt_could_throw_p (new_stmt))
2763     return false;
2764
2765   old_lp_nr = lookup_stmt_eh_lp_fn (old_fun, old_stmt);
2766   if (old_lp_nr == 0)
2767     {
2768       if (default_lp_nr == 0)
2769         return false;
2770       new_lp_nr = default_lp_nr;
2771     }
2772   else if (old_lp_nr > 0)
2773     {
2774       eh_landing_pad old_lp, new_lp;
2775
2776       old_lp = VEC_index (eh_landing_pad, old_fun->eh->lp_array, old_lp_nr);
2777       slot = pointer_map_contains (map, old_lp);
2778       new_lp = (eh_landing_pad) *slot;
2779       new_lp_nr = new_lp->index;
2780     }
2781   else
2782     {
2783       eh_region old_r, new_r;
2784
2785       old_r = VEC_index (eh_region, old_fun->eh->region_array, -old_lp_nr);
2786       slot = pointer_map_contains (map, old_r);
2787       new_r = (eh_region) *slot;
2788       new_lp_nr = -new_r->index;
2789     }
2790
2791   add_stmt_to_eh_lp_fn (new_fun, new_stmt, new_lp_nr);
2792   return true;
2793 }
2794
2795 /* Similar, but both OLD_STMT and NEW_STMT are within the current function,
2796    and thus no remapping is required.  */
2797
2798 bool
2799 maybe_duplicate_eh_stmt (gimple new_stmt, gimple old_stmt)
2800 {
2801   int lp_nr;
2802
2803   if (!stmt_could_throw_p (new_stmt))
2804     return false;
2805
2806   lp_nr = lookup_stmt_eh_lp (old_stmt);
2807   if (lp_nr == 0)
2808     return false;
2809
2810   add_stmt_to_eh_lp (new_stmt, lp_nr);
2811   return true;
2812 }
2813 \f
2814 /* Returns TRUE if oneh and twoh are exception handlers (gimple_try_cleanup of
2815    GIMPLE_TRY) that are similar enough to be considered the same.  Currently
2816    this only handles handlers consisting of a single call, as that's the
2817    important case for C++: a destructor call for a particular object showing
2818    up in multiple handlers.  */
2819
2820 static bool
2821 same_handler_p (gimple_seq oneh, gimple_seq twoh)
2822 {
2823   gimple_stmt_iterator gsi;
2824   gimple ones, twos;
2825   unsigned int ai;
2826
2827   gsi = gsi_start (oneh);
2828   if (!gsi_one_before_end_p (gsi))
2829     return false;
2830   ones = gsi_stmt (gsi);
2831
2832   gsi = gsi_start (twoh);
2833   if (!gsi_one_before_end_p (gsi))
2834     return false;
2835   twos = gsi_stmt (gsi);
2836
2837   if (!is_gimple_call (ones)
2838       || !is_gimple_call (twos)
2839       || gimple_call_lhs (ones)
2840       || gimple_call_lhs (twos)
2841       || gimple_call_chain (ones)
2842       || gimple_call_chain (twos)
2843       || !gimple_call_same_target_p (ones, twos)
2844       || gimple_call_num_args (ones) != gimple_call_num_args (twos))
2845     return false;
2846
2847   for (ai = 0; ai < gimple_call_num_args (ones); ++ai)
2848     if (!operand_equal_p (gimple_call_arg (ones, ai),
2849                           gimple_call_arg (twos, ai), 0))
2850       return false;
2851
2852   return true;
2853 }
2854
2855 /* Optimize
2856     try { A() } finally { try { ~B() } catch { ~A() } }
2857     try { ... } finally { ~A() }
2858    into
2859     try { A() } catch { ~B() }
2860     try { ~B() ... } finally { ~A() }
2861
2862    This occurs frequently in C++, where A is a local variable and B is a
2863    temporary used in the initializer for A.  */
2864
2865 static void
2866 optimize_double_finally (gimple one, gimple two)
2867 {
2868   gimple oneh;
2869   gimple_stmt_iterator gsi;
2870   gimple_seq cleanup;
2871
2872   cleanup = gimple_try_cleanup (one);
2873   gsi = gsi_start (cleanup);
2874   if (!gsi_one_before_end_p (gsi))
2875     return;
2876
2877   oneh = gsi_stmt (gsi);
2878   if (gimple_code (oneh) != GIMPLE_TRY
2879       || gimple_try_kind (oneh) != GIMPLE_TRY_CATCH)
2880     return;
2881
2882   if (same_handler_p (gimple_try_cleanup (oneh), gimple_try_cleanup (two)))
2883     {
2884       gimple_seq seq = gimple_try_eval (oneh);
2885
2886       gimple_try_set_cleanup (one, seq);
2887       gimple_try_set_kind (one, GIMPLE_TRY_CATCH);
2888       seq = copy_gimple_seq_and_replace_locals (seq);
2889       gimple_seq_add_seq (&seq, gimple_try_eval (two));
2890       gimple_try_set_eval (two, seq);
2891     }
2892 }
2893
2894 /* Perform EH refactoring optimizations that are simpler to do when code
2895    flow has been lowered but EH structures haven't.  */
2896
2897 static void
2898 refactor_eh_r (gimple_seq seq)
2899 {
2900   gimple_stmt_iterator gsi;
2901   gimple one, two;
2902
2903   one = NULL;
2904   two = NULL;
2905   gsi = gsi_start (seq);
2906   while (1)
2907     {
2908       one = two;
2909       if (gsi_end_p (gsi))
2910         two = NULL;
2911       else
2912         two = gsi_stmt (gsi);
2913       if (one
2914           && two
2915           && gimple_code (one) == GIMPLE_TRY
2916           && gimple_code (two) == GIMPLE_TRY
2917           && gimple_try_kind (one) == GIMPLE_TRY_FINALLY
2918           && gimple_try_kind (two) == GIMPLE_TRY_FINALLY)
2919         optimize_double_finally (one, two);
2920       if (one)
2921         switch (gimple_code (one))
2922           {
2923           case GIMPLE_TRY:
2924             refactor_eh_r (gimple_try_eval (one));
2925             refactor_eh_r (gimple_try_cleanup (one));
2926             break;
2927           case GIMPLE_CATCH:
2928             refactor_eh_r (gimple_catch_handler (one));
2929             break;
2930           case GIMPLE_EH_FILTER:
2931             refactor_eh_r (gimple_eh_filter_failure (one));
2932             break;
2933           case GIMPLE_EH_ELSE:
2934             refactor_eh_r (gimple_eh_else_n_body (one));
2935             refactor_eh_r (gimple_eh_else_e_body (one));
2936             break;
2937           default:
2938             break;
2939           }
2940       if (two)
2941         gsi_next (&gsi);
2942       else
2943         break;
2944     }
2945 }
2946
2947 static unsigned
2948 refactor_eh (void)
2949 {
2950   refactor_eh_r (gimple_body (current_function_decl));
2951   return 0;
2952 }
2953
2954 static bool
2955 gate_refactor_eh (void)
2956 {
2957   return flag_exceptions != 0;
2958 }
2959
2960 struct gimple_opt_pass pass_refactor_eh =
2961 {
2962  {
2963   GIMPLE_PASS,
2964   "ehopt",                              /* name */
2965   gate_refactor_eh,                     /* gate */
2966   refactor_eh,                          /* execute */
2967   NULL,                                 /* sub */
2968   NULL,                                 /* next */
2969   0,                                    /* static_pass_number */
2970   TV_TREE_EH,                           /* tv_id */
2971   PROP_gimple_lcf,                      /* properties_required */
2972   0,                                    /* properties_provided */
2973   0,                                    /* properties_destroyed */
2974   0,                                    /* todo_flags_start */
2975   0                                     /* todo_flags_finish */
2976  }
2977 };
2978 \f
2979 /* At the end of gimple optimization, we can lower RESX.  */
2980
2981 static bool
2982 lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map)
2983 {
2984   int lp_nr;
2985   eh_region src_r, dst_r;
2986   gimple_stmt_iterator gsi;
2987   gimple x;
2988   tree fn, src_nr;
2989   bool ret = false;
2990
2991   lp_nr = lookup_stmt_eh_lp (stmt);
2992   if (lp_nr != 0)
2993     dst_r = get_eh_region_from_lp_number (lp_nr);
2994   else
2995     dst_r = NULL;
2996
2997   src_r = get_eh_region_from_number (gimple_resx_region (stmt));
2998   gsi = gsi_last_bb (bb);
2999
3000   if (src_r == NULL)
3001     {
3002       /* We can wind up with no source region when pass_cleanup_eh shows
3003          that there are no entries into an eh region and deletes it, but
3004          then the block that contains the resx isn't removed.  This can
3005          happen without optimization when the switch statement created by
3006          lower_try_finally_switch isn't simplified to remove the eh case.
3007
3008          Resolve this by expanding the resx node to an abort.  */
3009
3010       fn = builtin_decl_implicit (BUILT_IN_TRAP);
3011       x = gimple_build_call (fn, 0);
3012       gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3013
3014       while (EDGE_COUNT (bb->succs) > 0)
3015         remove_edge (EDGE_SUCC (bb, 0));
3016     }
3017   else if (dst_r)
3018     {
3019       /* When we have a destination region, we resolve this by copying
3020          the excptr and filter values into place, and changing the edge
3021          to immediately after the landing pad.  */
3022       edge e;
3023
3024       if (lp_nr < 0)
3025         {
3026           basic_block new_bb;
3027           void **slot;
3028           tree lab;
3029
3030           /* We are resuming into a MUST_NOT_CALL region.  Expand a call to
3031              the failure decl into a new block, if needed.  */
3032           gcc_assert (dst_r->type == ERT_MUST_NOT_THROW);
3033
3034           slot = pointer_map_contains (mnt_map, dst_r);
3035           if (slot == NULL)
3036             {
3037               gimple_stmt_iterator gsi2;
3038
3039               new_bb = create_empty_bb (bb);
3040               if (current_loops)
3041                 add_bb_to_loop (new_bb, bb->loop_father);
3042               lab = gimple_block_label (new_bb);
3043               gsi2 = gsi_start_bb (new_bb);
3044
3045               fn = dst_r->u.must_not_throw.failure_decl;
3046               x = gimple_build_call (fn, 0);
3047               gimple_set_location (x, dst_r->u.must_not_throw.failure_loc);
3048               gsi_insert_after (&gsi2, x, GSI_CONTINUE_LINKING);
3049
3050               slot = pointer_map_insert (mnt_map, dst_r);
3051               *slot = lab;
3052             }
3053           else
3054             {
3055               lab = (tree) *slot;
3056               new_bb = label_to_block (lab);
3057             }
3058
3059           gcc_assert (EDGE_COUNT (bb->succs) == 0);
3060           e = make_edge (bb, new_bb, EDGE_FALLTHRU);
3061           e->count = bb->count;
3062           e->probability = REG_BR_PROB_BASE;
3063         }
3064       else
3065         {
3066           edge_iterator ei;
3067           tree dst_nr = build_int_cst (integer_type_node, dst_r->index);
3068
3069           fn = builtin_decl_implicit (BUILT_IN_EH_COPY_VALUES);
3070           src_nr = build_int_cst (integer_type_node, src_r->index);
3071           x = gimple_build_call (fn, 2, dst_nr, src_nr);
3072           gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3073
3074           /* Update the flags for the outgoing edge.  */
3075           e = single_succ_edge (bb);
3076           gcc_assert (e->flags & EDGE_EH);
3077           e->flags = (e->flags & ~EDGE_EH) | EDGE_FALLTHRU;
3078
3079           /* If there are no more EH users of the landing pad, delete it.  */
3080           FOR_EACH_EDGE (e, ei, e->dest->preds)
3081             if (e->flags & EDGE_EH)
3082               break;
3083           if (e == NULL)
3084             {
3085               eh_landing_pad lp = get_eh_landing_pad_from_number (lp_nr);
3086               remove_eh_landing_pad (lp);
3087             }
3088         }
3089
3090       ret = true;
3091     }
3092   else
3093     {
3094       tree var;
3095
3096       /* When we don't have a destination region, this exception escapes
3097          up the call chain.  We resolve this by generating a call to the
3098          _Unwind_Resume library function.  */
3099
3100       /* The ARM EABI redefines _Unwind_Resume as __cxa_end_cleanup
3101          with no arguments for C++ and Java.  Check for that.  */
3102       if (src_r->use_cxa_end_cleanup)
3103         {
3104           fn = builtin_decl_implicit (BUILT_IN_CXA_END_CLEANUP);
3105           x = gimple_build_call (fn, 0);
3106           gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3107         }
3108       else
3109         {
3110           fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
3111           src_nr = build_int_cst (integer_type_node, src_r->index);
3112           x = gimple_build_call (fn, 1, src_nr);
3113           var = create_tmp_var (ptr_type_node, NULL);
3114           var = make_ssa_name (var, x);
3115           gimple_call_set_lhs (x, var);
3116           gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3117
3118           fn = builtin_decl_implicit (BUILT_IN_UNWIND_RESUME);
3119           x = gimple_build_call (fn, 1, var);
3120           gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3121         }
3122
3123       gcc_assert (EDGE_COUNT (bb->succs) == 0);
3124     }
3125
3126   gsi_remove (&gsi, true);
3127
3128   return ret;
3129 }
3130
3131 static unsigned
3132 execute_lower_resx (void)
3133 {
3134   basic_block bb;
3135   struct pointer_map_t *mnt_map;
3136   bool dominance_invalidated = false;
3137   bool any_rewritten = false;
3138
3139   mnt_map = pointer_map_create ();
3140
3141   FOR_EACH_BB (bb)
3142     {
3143       gimple last = last_stmt (bb);
3144       if (last && is_gimple_resx (last))
3145         {
3146           dominance_invalidated |= lower_resx (bb, last, mnt_map);
3147           any_rewritten = true;
3148         }
3149     }
3150
3151   pointer_map_destroy (mnt_map);
3152
3153   if (dominance_invalidated)
3154     {
3155       free_dominance_info (CDI_DOMINATORS);
3156       free_dominance_info (CDI_POST_DOMINATORS);
3157     }
3158
3159   return any_rewritten ? TODO_update_ssa_only_virtuals : 0;
3160 }
3161
3162 static bool
3163 gate_lower_resx (void)
3164 {
3165   return flag_exceptions != 0;
3166 }
3167
3168 struct gimple_opt_pass pass_lower_resx =
3169 {
3170  {
3171   GIMPLE_PASS,
3172   "resx",                               /* name */
3173   gate_lower_resx,                      /* gate */
3174   execute_lower_resx,                   /* execute */
3175   NULL,                                 /* sub */
3176   NULL,                                 /* next */
3177   0,                                    /* static_pass_number */
3178   TV_TREE_EH,                           /* tv_id */
3179   PROP_gimple_lcf,                      /* properties_required */
3180   0,                                    /* properties_provided */
3181   0,                                    /* properties_destroyed */
3182   0,                                    /* todo_flags_start */
3183   TODO_verify_flow                      /* todo_flags_finish */
3184  }
3185 };
3186
3187 /* Try to optimize var = {v} {CLOBBER} stmts followed just by
3188    external throw.  */
3189
3190 static void
3191 optimize_clobbers (basic_block bb)
3192 {
3193   gimple_stmt_iterator gsi = gsi_last_bb (bb);
3194   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
3195     {
3196       gimple stmt = gsi_stmt (gsi);
3197       if (is_gimple_debug (stmt))
3198         continue;
3199       if (!gimple_clobber_p (stmt)
3200           || TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME)
3201         return;
3202       unlink_stmt_vdef (stmt);
3203       gsi_remove (&gsi, true);
3204       release_defs (stmt);
3205     }
3206 }
3207
3208 /* Try to sink var = {v} {CLOBBER} stmts followed just by
3209    internal throw to successor BB.  */
3210
3211 static int
3212 sink_clobbers (basic_block bb)
3213 {
3214   edge e;
3215   edge_iterator ei;
3216   gimple_stmt_iterator gsi, dgsi;
3217   basic_block succbb;
3218   bool any_clobbers = false;
3219
3220   /* Only optimize if BB has a single EH successor and
3221      all predecessor edges are EH too.  */
3222   if (!single_succ_p (bb)
3223       || (single_succ_edge (bb)->flags & EDGE_EH) == 0)
3224     return 0;
3225
3226   FOR_EACH_EDGE (e, ei, bb->preds)
3227     {
3228       if ((e->flags & EDGE_EH) == 0)
3229         return 0;
3230     }
3231
3232   /* And BB contains only CLOBBER stmts before the final
3233      RESX.  */
3234   gsi = gsi_last_bb (bb);
3235   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
3236     {
3237       gimple stmt = gsi_stmt (gsi);
3238       if (is_gimple_debug (stmt))
3239         continue;
3240       if (gimple_code (stmt) == GIMPLE_LABEL)
3241         break;
3242       if (!gimple_clobber_p (stmt)
3243           || TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME)
3244         return 0;
3245       any_clobbers = true;
3246     }
3247   if (!any_clobbers)
3248     return 0;
3249
3250   succbb = single_succ (bb);
3251   dgsi = gsi_after_labels (succbb);
3252   gsi = gsi_last_bb (bb);
3253   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
3254     {
3255       gimple stmt = gsi_stmt (gsi);
3256       tree vdef;
3257       if (is_gimple_debug (stmt))
3258         continue;
3259       if (gimple_code (stmt) == GIMPLE_LABEL)
3260         break;
3261       unlink_stmt_vdef (stmt);
3262       gsi_remove (&gsi, false);
3263       vdef = gimple_vdef (stmt);
3264       if (vdef && TREE_CODE (vdef) == SSA_NAME)
3265         {
3266           release_ssa_name (vdef);
3267           vdef = SSA_NAME_VAR (vdef);
3268           mark_sym_for_renaming (vdef);
3269           gimple_set_vdef (stmt, vdef);
3270           gimple_set_vuse (stmt, vdef);
3271         }
3272       gsi_insert_before (&dgsi, stmt, GSI_SAME_STMT);
3273     }
3274
3275   return TODO_update_ssa_only_virtuals;
3276 }
3277
3278 /* At the end of inlining, we can lower EH_DISPATCH.  Return true when 
3279    we have found some duplicate labels and removed some edges.  */
3280
3281 static bool
3282 lower_eh_dispatch (basic_block src, gimple stmt)
3283 {
3284   gimple_stmt_iterator gsi;
3285   int region_nr;
3286   eh_region r;
3287   tree filter, fn;
3288   gimple x;
3289   bool redirected = false;
3290
3291   region_nr = gimple_eh_dispatch_region (stmt);
3292   r = get_eh_region_from_number (region_nr);
3293
3294   gsi = gsi_last_bb (src);
3295
3296   switch (r->type)
3297     {
3298     case ERT_TRY:
3299       {
3300         VEC (tree, heap) *labels = NULL;
3301         tree default_label = NULL;
3302         eh_catch c;
3303         edge_iterator ei;
3304         edge e;
3305         struct pointer_set_t *seen_values = pointer_set_create ();
3306
3307         /* Collect the labels for a switch.  Zero the post_landing_pad
3308            field becase we'll no longer have anything keeping these labels
3309            in existence and the optimizer will be free to merge these
3310            blocks at will.  */
3311         for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
3312           {
3313             tree tp_node, flt_node, lab = c->label;
3314             bool have_label = false;
3315
3316             c->label = NULL;
3317             tp_node = c->type_list;
3318             flt_node = c->filter_list;
3319
3320             if (tp_node == NULL)
3321               {
3322                 default_label = lab;
3323                 break;
3324               }
3325             do
3326               {
3327                 /* Filter out duplicate labels that arise when this handler 
3328                    is shadowed by an earlier one.  When no labels are 
3329                    attached to the handler anymore, we remove 
3330                    the corresponding edge and then we delete unreachable 
3331                    blocks at the end of this pass.  */
3332                 if (! pointer_set_contains (seen_values, TREE_VALUE (flt_node)))
3333                   {
3334                     tree t = build_case_label (TREE_VALUE (flt_node),
3335                                                NULL, lab);
3336                     VEC_safe_push (tree, heap, labels, t);
3337                     pointer_set_insert (seen_values, TREE_VALUE (flt_node));
3338                     have_label = true;
3339                   }
3340
3341                 tp_node = TREE_CHAIN (tp_node);
3342                 flt_node = TREE_CHAIN (flt_node);
3343               }
3344             while (tp_node);
3345             if (! have_label)
3346               {
3347                 remove_edge (find_edge (src, label_to_block (lab)));
3348                 redirected = true;
3349               }
3350           }
3351
3352         /* Clean up the edge flags.  */
3353         FOR_EACH_EDGE (e, ei, src->succs)
3354           {
3355             if (e->flags & EDGE_FALLTHRU)
3356               {
3357                 /* If there was no catch-all, use the fallthru edge.  */
3358                 if (default_label == NULL)
3359                   default_label = gimple_block_label (e->dest);
3360                 e->flags &= ~EDGE_FALLTHRU;
3361               }
3362           }
3363         gcc_assert (default_label != NULL);
3364
3365         /* Don't generate a switch if there's only a default case.
3366            This is common in the form of try { A; } catch (...) { B; }.  */
3367         if (labels == NULL)
3368           {
3369             e = single_succ_edge (src);
3370             e->flags |= EDGE_FALLTHRU;
3371           }
3372         else
3373           {
3374             fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
3375             x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
3376                                                          region_nr));
3377             filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
3378             filter = make_ssa_name (filter, x);
3379             gimple_call_set_lhs (x, filter);
3380             gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3381
3382             /* Turn the default label into a default case.  */
3383             default_label = build_case_label (NULL, NULL, default_label);
3384             sort_case_labels (labels);
3385
3386             x = gimple_build_switch_vec (filter, default_label, labels);
3387             gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3388
3389             VEC_free (tree, heap, labels);
3390           }
3391         pointer_set_destroy (seen_values);
3392       }
3393       break;
3394
3395     case ERT_ALLOWED_EXCEPTIONS:
3396       {
3397         edge b_e = BRANCH_EDGE (src);
3398         edge f_e = FALLTHRU_EDGE (src);
3399
3400         fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
3401         x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
3402                                                      region_nr));
3403         filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
3404         filter = make_ssa_name (filter, x);
3405         gimple_call_set_lhs (x, filter);
3406         gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3407
3408         r->u.allowed.label = NULL;
3409         x = gimple_build_cond (EQ_EXPR, filter,
3410                                build_int_cst (TREE_TYPE (filter),
3411                                               r->u.allowed.filter),
3412                                NULL_TREE, NULL_TREE);
3413         gsi_insert_before (&gsi, x, GSI_SAME_STMT);
3414
3415         b_e->flags = b_e->flags | EDGE_TRUE_VALUE;
3416         f_e->flags = (f_e->flags & ~EDGE_FALLTHRU) | EDGE_FALSE_VALUE;
3417       }
3418       break;
3419
3420     default:
3421       gcc_unreachable ();
3422     }
3423
3424   /* Replace the EH_DISPATCH with the SWITCH or COND generated above.  */
3425   gsi_remove (&gsi, true);
3426   return redirected;
3427 }
3428
3429 static unsigned
3430 execute_lower_eh_dispatch (void)
3431 {
3432   basic_block bb;
3433   int flags = 0;
3434   bool redirected = false;
3435
3436   assign_filter_values ();
3437
3438   FOR_EACH_BB (bb)
3439     {
3440       gimple last = last_stmt (bb);
3441       if (last == NULL)
3442         continue;
3443       if (gimple_code (last) == GIMPLE_EH_DISPATCH)
3444         {
3445           redirected |= lower_eh_dispatch (bb, last);
3446           flags |= TODO_update_ssa_only_virtuals;
3447         }
3448       else if (gimple_code (last) == GIMPLE_RESX)
3449         {
3450           if (stmt_can_throw_external (last))
3451             optimize_clobbers (bb);
3452           else
3453             flags |= sink_clobbers (bb);
3454         }
3455     }
3456
3457   if (redirected)
3458     delete_unreachable_blocks ();
3459   return flags;
3460 }
3461
3462 static bool
3463 gate_lower_eh_dispatch (void)
3464 {
3465   return cfun->eh->region_tree != NULL;
3466 }
3467
3468 struct gimple_opt_pass pass_lower_eh_dispatch =
3469 {
3470  {
3471   GIMPLE_PASS,
3472   "ehdisp",                             /* name */
3473   gate_lower_eh_dispatch,               /* gate */
3474   execute_lower_eh_dispatch,            /* execute */
3475   NULL,                                 /* sub */
3476   NULL,                                 /* next */
3477   0,                                    /* static_pass_number */
3478   TV_TREE_EH,                           /* tv_id */
3479   PROP_gimple_lcf,                      /* properties_required */
3480   0,                                    /* properties_provided */
3481   0,                                    /* properties_destroyed */
3482   0,                                    /* todo_flags_start */
3483   TODO_verify_flow                      /* todo_flags_finish */
3484  }
3485 };
3486 \f
3487 /* Walk statements, see what regions are really referenced and remove
3488    those that are unused.  */
3489
3490 static void
3491 remove_unreachable_handlers (void)
3492 {
3493   sbitmap r_reachable, lp_reachable;
3494   eh_region region;
3495   eh_landing_pad lp;
3496   basic_block bb;
3497   int lp_nr, r_nr;
3498
3499   r_reachable = sbitmap_alloc (VEC_length (eh_region, cfun->eh->region_array));
3500   lp_reachable
3501     = sbitmap_alloc (VEC_length (eh_landing_pad, cfun->eh->lp_array));
3502   sbitmap_zero (r_reachable);
3503   sbitmap_zero (lp_reachable);
3504
3505   FOR_EACH_BB (bb)
3506     {
3507       gimple_stmt_iterator gsi;
3508
3509       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3510         {
3511           gimple stmt = gsi_stmt (gsi);
3512           lp_nr = lookup_stmt_eh_lp (stmt);
3513
3514           /* Negative LP numbers are MUST_NOT_THROW regions which
3515              are not considered BB enders.  */
3516           if (lp_nr < 0)
3517             SET_BIT (r_reachable, -lp_nr);
3518
3519           /* Positive LP numbers are real landing pads, are are BB enders.  */
3520           else if (lp_nr > 0)
3521             {
3522               gcc_assert (gsi_one_before_end_p (gsi));
3523               region = get_eh_region_from_lp_number (lp_nr);
3524               SET_BIT (r_reachable, region->index);
3525               SET_BIT (lp_reachable, lp_nr);
3526             }
3527
3528           /* Avoid removing regions referenced from RESX/EH_DISPATCH.  */
3529           switch (gimple_code (stmt))
3530             {
3531             case GIMPLE_RESX:
3532               SET_BIT (r_reachable, gimple_resx_region (stmt));
3533               break;
3534             case GIMPLE_EH_DISPATCH:
3535               SET_BIT (r_reachable, gimple_eh_dispatch_region (stmt));
3536               break;
3537             default:
3538               break;
3539             }
3540         }
3541     }
3542
3543   if (dump_file)
3544     {
3545       fprintf (dump_file, "Before removal of unreachable regions:\n");
3546       dump_eh_tree (dump_file, cfun);
3547       fprintf (dump_file, "Reachable regions: ");
3548       dump_sbitmap_file (dump_file, r_reachable);
3549       fprintf (dump_file, "Reachable landing pads: ");
3550       dump_sbitmap_file (dump_file, lp_reachable);
3551     }
3552
3553   for (r_nr = 1;
3554        VEC_iterate (eh_region, cfun->eh->region_array, r_nr, region); ++r_nr)
3555     if (region && !TEST_BIT (r_reachable, r_nr))
3556       {
3557         if (dump_file)
3558           fprintf (dump_file, "Removing unreachable region %d\n", r_nr);
3559         remove_eh_handler (region);
3560       }
3561
3562   for (lp_nr = 1;
3563        VEC_iterate (eh_landing_pad, cfun->eh->lp_array, lp_nr, lp); ++lp_nr)
3564     if (lp && !TEST_BIT (lp_reachable, lp_nr))
3565       {
3566         if (dump_file)
3567           fprintf (dump_file, "Removing unreachable landing pad %d\n", lp_nr);
3568         remove_eh_landing_pad (lp);
3569       }
3570
3571   if (dump_file)
3572     {
3573       fprintf (dump_file, "\n\nAfter removal of unreachable regions:\n");
3574       dump_eh_tree (dump_file, cfun);
3575       fprintf (dump_file, "\n\n");
3576     }
3577
3578   sbitmap_free (r_reachable);
3579   sbitmap_free (lp_reachable);
3580
3581 #ifdef ENABLE_CHECKING
3582   verify_eh_tree (cfun);
3583 #endif
3584 }
3585
3586 /* Remove unreachable handlers if any landing pads have been removed after
3587    last ehcleanup pass (due to gimple_purge_dead_eh_edges).  */
3588
3589 void
3590 maybe_remove_unreachable_handlers (void)
3591 {
3592   eh_landing_pad lp;
3593   int i;
3594
3595   if (cfun->eh == NULL)
3596     return;
3597               
3598   for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
3599     if (lp && lp->post_landing_pad)
3600       {
3601         if (label_to_block (lp->post_landing_pad) == NULL)
3602           {
3603             remove_unreachable_handlers ();
3604             return;
3605           }
3606       }
3607 }
3608
3609 /* Remove regions that do not have landing pads.  This assumes
3610    that remove_unreachable_handlers has already been run, and
3611    that we've just manipulated the landing pads since then.  */
3612
3613 static void
3614 remove_unreachable_handlers_no_lp (void)
3615 {
3616   eh_region r;
3617   int i;
3618   sbitmap r_reachable;
3619   basic_block bb;
3620
3621   r_reachable = sbitmap_alloc (VEC_length (eh_region, cfun->eh->region_array));
3622   sbitmap_zero (r_reachable);
3623
3624   FOR_EACH_BB (bb)
3625     {
3626       gimple stmt = last_stmt (bb);
3627       if (stmt)
3628         /* Avoid removing regions referenced from RESX/EH_DISPATCH.  */
3629         switch (gimple_code (stmt))
3630           {
3631           case GIMPLE_RESX:
3632             SET_BIT (r_reachable, gimple_resx_region (stmt));
3633             break;
3634           case GIMPLE_EH_DISPATCH:
3635             SET_BIT (r_reachable, gimple_eh_dispatch_region (stmt));
3636             break;
3637           default:
3638             break;
3639           }
3640     }
3641
3642   for (i = 1; VEC_iterate (eh_region, cfun->eh->region_array, i, r); ++i)
3643     if (r && r->landing_pads == NULL && r->type != ERT_MUST_NOT_THROW
3644         && !TEST_BIT (r_reachable, i))
3645       {
3646         if (dump_file)
3647           fprintf (dump_file, "Removing unreachable region %d\n", i);
3648         remove_eh_handler (r);
3649       }
3650
3651   sbitmap_free (r_reachable);
3652 }
3653
3654 /* Undo critical edge splitting on an EH landing pad.  Earlier, we
3655    optimisticaly split all sorts of edges, including EH edges.  The
3656    optimization passes in between may not have needed them; if not,
3657    we should undo the split.
3658
3659    Recognize this case by having one EH edge incoming to the BB and
3660    one normal edge outgoing; BB should be empty apart from the
3661    post_landing_pad label.
3662
3663    Note that this is slightly different from the empty handler case
3664    handled by cleanup_empty_eh, in that the actual handler may yet
3665    have actual code but the landing pad has been separated from the
3666    handler.  As such, cleanup_empty_eh relies on this transformation
3667    having been done first.  */
3668
3669 static bool
3670 unsplit_eh (eh_landing_pad lp)
3671 {
3672   basic_block bb = label_to_block (lp->post_landing_pad);
3673   gimple_stmt_iterator gsi;
3674   edge e_in, e_out;
3675
3676   /* Quickly check the edge counts on BB for singularity.  */
3677   if (EDGE_COUNT (bb->preds) != 1 || EDGE_COUNT (bb->succs) != 1)
3678     return false;
3679   e_in = EDGE_PRED (bb, 0);
3680   e_out = EDGE_SUCC (bb, 0);
3681
3682   /* Input edge must be EH and output edge must be normal.  */
3683   if ((e_in->flags & EDGE_EH) == 0 || (e_out->flags & EDGE_EH) != 0)
3684     return false;
3685
3686   /* The block must be empty except for the labels and debug insns.  */
3687   gsi = gsi_after_labels (bb);
3688   if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
3689     gsi_next_nondebug (&gsi);
3690   if (!gsi_end_p (gsi))
3691     return false;
3692
3693   /* The destination block must not already have a landing pad
3694      for a different region.  */
3695   for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi))
3696     {
3697       gimple stmt = gsi_stmt (gsi);
3698       tree lab;
3699       int lp_nr;
3700
3701       if (gimple_code (stmt) != GIMPLE_LABEL)
3702         break;
3703       lab = gimple_label_label (stmt);
3704       lp_nr = EH_LANDING_PAD_NR (lab);
3705       if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region)
3706         return false;
3707     }
3708
3709   /* The new destination block must not already be a destination of
3710      the source block, lest we merge fallthru and eh edges and get
3711      all sorts of confused.  */
3712   if (find_edge (e_in->src, e_out->dest))
3713     return false;
3714
3715   /* ??? We can get degenerate phis due to cfg cleanups.  I would have
3716      thought this should have been cleaned up by a phicprop pass, but
3717      that doesn't appear to handle virtuals.  Propagate by hand.  */
3718   if (!gimple_seq_empty_p (phi_nodes (bb)))
3719     {
3720       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
3721         {
3722           gimple use_stmt, phi = gsi_stmt (gsi);
3723           tree lhs = gimple_phi_result (phi);
3724           tree rhs = gimple_phi_arg_def (phi, 0);
3725           use_operand_p use_p;
3726           imm_use_iterator iter;
3727
3728           FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
3729             {
3730               FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
3731                 SET_USE (use_p, rhs);
3732             }
3733
3734           if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
3735             SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs) = 1;
3736
3737           remove_phi_node (&gsi, true);
3738         }
3739     }
3740
3741   if (dump_file && (dump_flags & TDF_DETAILS))
3742     fprintf (dump_file, "Unsplit EH landing pad %d to block %i.\n",
3743              lp->index, e_out->dest->index);
3744
3745   /* Redirect the edge.  Since redirect_eh_edge_1 expects to be moving
3746      a successor edge, humor it.  But do the real CFG change with the
3747      predecessor of E_OUT in order to preserve the ordering of arguments
3748      to the PHI nodes in E_OUT->DEST.  */
3749   redirect_eh_edge_1 (e_in, e_out->dest, false);
3750   redirect_edge_pred (e_out, e_in->src);
3751   e_out->flags = e_in->flags;
3752   e_out->probability = e_in->probability;
3753   e_out->count = e_in->count;
3754   remove_edge (e_in);
3755
3756   return true;
3757 }
3758
3759 /* Examine each landing pad block and see if it matches unsplit_eh.  */
3760
3761 static bool
3762 unsplit_all_eh (void)
3763 {
3764   bool changed = false;
3765   eh_landing_pad lp;
3766   int i;
3767
3768   for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
3769     if (lp)
3770       changed |= unsplit_eh (lp);
3771
3772   return changed;
3773 }
3774
3775 /* A subroutine of cleanup_empty_eh.  Redirect all EH edges incoming
3776    to OLD_BB to NEW_BB; return true on success, false on failure.
3777
3778    OLD_BB_OUT is the edge into NEW_BB from OLD_BB, so if we miss any
3779    PHI variables from OLD_BB we can pick them up from OLD_BB_OUT.
3780    Virtual PHIs may be deleted and marked for renaming.  */
3781
3782 static bool
3783 cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb,
3784                              edge old_bb_out, bool change_region)
3785 {
3786   gimple_stmt_iterator ngsi, ogsi;
3787   edge_iterator ei;
3788   edge e;
3789   bitmap rename_virts;
3790   bitmap ophi_handled;
3791
3792   /* The destination block must not be a regular successor for any
3793      of the preds of the landing pad.  Thus, avoid turning
3794         <..>
3795          |  \ EH
3796          |  <..>
3797          |  /
3798         <..>
3799      into
3800         <..>
3801         |  | EH
3802         <..>
3803      which CFG verification would choke on.  See PR45172 and PR51089.  */
3804   FOR_EACH_EDGE (e, ei, old_bb->preds)
3805     if (find_edge (e->src, new_bb))
3806       return false;
3807
3808   FOR_EACH_EDGE (e, ei, old_bb->preds)
3809     redirect_edge_var_map_clear (e);
3810
3811   ophi_handled = BITMAP_ALLOC (NULL);
3812   rename_virts = BITMAP_ALLOC (NULL);
3813
3814   /* First, iterate through the PHIs on NEW_BB and set up the edge_var_map
3815      for the edges we're going to move.  */
3816   for (ngsi = gsi_start_phis (new_bb); !gsi_end_p (ngsi); gsi_next (&ngsi))
3817     {
3818       gimple ophi, nphi = gsi_stmt (ngsi);
3819       tree nresult, nop;
3820
3821       nresult = gimple_phi_result (nphi);
3822       nop = gimple_phi_arg_def (nphi, old_bb_out->dest_idx);
3823
3824       /* Find the corresponding PHI in OLD_BB so we can forward-propagate
3825          the source ssa_name.  */
3826       ophi = NULL;
3827       for (ogsi = gsi_start_phis (old_bb); !gsi_end_p (ogsi); gsi_next (&ogsi))
3828         {
3829           ophi = gsi_stmt (ogsi);
3830           if (gimple_phi_result (ophi) == nop)
3831             break;
3832           ophi = NULL;
3833         }
3834
3835       /* If we did find the corresponding PHI, copy those inputs.  */
3836       if (ophi)
3837         {
3838           /* If NOP is used somewhere else beyond phis in new_bb, give up.  */
3839           if (!has_single_use (nop))
3840             {
3841               imm_use_iterator imm_iter;
3842               use_operand_p use_p;
3843
3844               FOR_EACH_IMM_USE_FAST (use_p, imm_iter, nop)
3845                 {
3846                   if (!gimple_debug_bind_p (USE_STMT (use_p))
3847                       && (gimple_code (USE_STMT (use_p)) != GIMPLE_PHI
3848                           || gimple_bb (USE_STMT (use_p)) != new_bb))
3849                     goto fail;
3850                 }
3851             }
3852           bitmap_set_bit (ophi_handled, SSA_NAME_VERSION (nop));
3853           FOR_EACH_EDGE (e, ei, old_bb->preds)
3854             {
3855               location_t oloc;
3856               tree oop;
3857
3858               if ((e->flags & EDGE_EH) == 0)
3859                 continue;
3860               oop = gimple_phi_arg_def (ophi, e->dest_idx);
3861               oloc = gimple_phi_arg_location (ophi, e->dest_idx);
3862               redirect_edge_var_map_add (e, nresult, oop, oloc);
3863             }
3864         }
3865       /* If we didn't find the PHI, but it's a VOP, remember to rename
3866          it later, assuming all other tests succeed.  */
3867       else if (!is_gimple_reg (nresult))
3868         bitmap_set_bit (rename_virts, SSA_NAME_VERSION (nresult));
3869       /* If we didn't find the PHI, and it's a real variable, we know
3870          from the fact that OLD_BB is tree_empty_eh_handler_p that the
3871          variable is unchanged from input to the block and we can simply
3872          re-use the input to NEW_BB from the OLD_BB_OUT edge.  */
3873       else
3874         {
3875           location_t nloc
3876             = gimple_phi_arg_location (nphi, old_bb_out->dest_idx);
3877           FOR_EACH_EDGE (e, ei, old_bb->preds)
3878             redirect_edge_var_map_add (e, nresult, nop, nloc);
3879         }
3880     }
3881
3882   /* Second, verify that all PHIs from OLD_BB have been handled.  If not,
3883      we don't know what values from the other edges into NEW_BB to use.  */
3884   for (ogsi = gsi_start_phis (old_bb); !gsi_end_p (ogsi); gsi_next (&ogsi))
3885     {
3886       gimple ophi = gsi_stmt (ogsi);
3887       tree oresult = gimple_phi_result (ophi);
3888       if (!bitmap_bit_p (ophi_handled, SSA_NAME_VERSION (oresult)))
3889         goto fail;
3890     }
3891
3892   /* At this point we know that the merge will succeed.  Remove the PHI
3893      nodes for the virtuals that we want to rename.  */
3894   if (!bitmap_empty_p (rename_virts))
3895     {
3896       for (ngsi = gsi_start_phis (new_bb); !gsi_end_p (ngsi); )
3897         {
3898           gimple nphi = gsi_stmt (ngsi);
3899           tree nresult = gimple_phi_result (nphi);
3900           if (bitmap_bit_p (rename_virts, SSA_NAME_VERSION (nresult)))
3901             {
3902               mark_virtual_phi_result_for_renaming (nphi);
3903               remove_phi_node (&ngsi, true);
3904             }
3905           else
3906             gsi_next (&ngsi);
3907         }
3908     }
3909
3910   /* Finally, move the edges and update the PHIs.  */
3911   for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)); )
3912     if (e->flags & EDGE_EH)
3913       {
3914         /* ???  CFG manipluation routines do not try to update loop
3915            form on edge redirection.  Do so manually here for now.  */
3916         /* If we redirect a loop entry or latch edge that will either create
3917            a multiple entry loop or rotate the loop.  If the loops merge
3918            we may have created a loop with multiple latches.
3919            All of this isn't easily fixed thus cancel the affected loop
3920            and mark the other loop as possibly having multiple latches.  */
3921         if (current_loops
3922             && e->dest == e->dest->loop_father->header)
3923           {
3924             e->dest->loop_father->header = NULL;
3925             e->dest->loop_father->latch = NULL;
3926             new_bb->loop_father->latch = NULL;
3927             loops_state_set (LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
3928           }
3929         redirect_eh_edge_1 (e, new_bb, change_region);
3930         redirect_edge_succ (e, new_bb);
3931         flush_pending_stmts (e);
3932       }
3933     else
3934       ei_next (&ei);
3935
3936   BITMAP_FREE (ophi_handled);
3937   BITMAP_FREE (rename_virts);
3938   return true;
3939
3940  fail:
3941   FOR_EACH_EDGE (e, ei, old_bb->preds)
3942     redirect_edge_var_map_clear (e);
3943   BITMAP_FREE (ophi_handled);
3944   BITMAP_FREE (rename_virts);
3945   return false;
3946 }
3947
3948 /* A subroutine of cleanup_empty_eh.  Move a landing pad LP from its
3949    old region to NEW_REGION at BB.  */
3950
3951 static void
3952 cleanup_empty_eh_move_lp (basic_block bb, edge e_out,
3953                           eh_landing_pad lp, eh_region new_region)
3954 {
3955   gimple_stmt_iterator gsi;
3956   eh_landing_pad *pp;
3957
3958   for (pp = &lp->region->landing_pads; *pp != lp; pp = &(*pp)->next_lp)
3959     continue;
3960   *pp = lp->next_lp;
3961
3962   lp->region = new_region;
3963   lp->next_lp = new_region->landing_pads;
3964   new_region->landing_pads = lp;
3965
3966   /* Delete the RESX that was matched within the empty handler block.  */
3967   gsi = gsi_last_bb (bb);
3968   unlink_stmt_vdef (gsi_stmt (gsi));
3969   gsi_remove (&gsi, true);
3970
3971   /* Clean up E_OUT for the fallthru.  */
3972   e_out->flags = (e_out->flags & ~EDGE_EH) | EDGE_FALLTHRU;
3973   e_out->probability = REG_BR_PROB_BASE;
3974 }
3975
3976 /* A subroutine of cleanup_empty_eh.  Handle more complex cases of
3977    unsplitting than unsplit_eh was prepared to handle, e.g. when
3978    multiple incoming edges and phis are involved.  */
3979
3980 static bool
3981 cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp)
3982 {
3983   gimple_stmt_iterator gsi;
3984   tree lab;
3985
3986   /* We really ought not have totally lost everything following
3987      a landing pad label.  Given that BB is empty, there had better
3988      be a successor.  */
3989   gcc_assert (e_out != NULL);
3990
3991   /* The destination block must not already have a landing pad
3992      for a different region.  */
3993   lab = NULL;
3994   for (gsi = gsi_start_bb (e_out->dest); !gsi_end_p (gsi); gsi_next (&gsi))
3995     {
3996       gimple stmt = gsi_stmt (gsi);
3997       int lp_nr;
3998
3999       if (gimple_code (stmt) != GIMPLE_LABEL)
4000         break;
4001       lab = gimple_label_label (stmt);
4002       lp_nr = EH_LANDING_PAD_NR (lab);
4003       if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region)
4004         return false;
4005     }
4006
4007   /* Attempt to move the PHIs into the successor block.  */
4008   if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, false))
4009     {
4010       if (dump_file && (dump_flags & TDF_DETAILS))
4011         fprintf (dump_file,
4012                  "Unsplit EH landing pad %d to block %i "
4013                  "(via cleanup_empty_eh).\n",
4014                  lp->index, e_out->dest->index);
4015       return true;
4016     }
4017
4018   return false;
4019 }
4020
4021 /* Return true if edge E_FIRST is part of an empty infinite loop
4022    or leads to such a loop through a series of single successor
4023    empty bbs.  */
4024
4025 static bool
4026 infinite_empty_loop_p (edge e_first)
4027 {
4028   bool inf_loop = false;
4029   edge e;
4030
4031   if (e_first->dest == e_first->src)
4032     return true;
4033
4034   e_first->src->aux = (void *) 1;
4035   for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest))
4036     {
4037       gimple_stmt_iterator gsi;
4038       if (e->dest->aux)
4039         {
4040           inf_loop = true;
4041           break;
4042         }
4043       e->dest->aux = (void *) 1;
4044       gsi = gsi_after_labels (e->dest);
4045       if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
4046         gsi_next_nondebug (&gsi);
4047       if (!gsi_end_p (gsi))
4048         break;
4049     }
4050   e_first->src->aux = NULL;
4051   for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest))
4052     e->dest->aux = NULL;
4053
4054   return inf_loop;
4055 }
4056
4057 /* Examine the block associated with LP to determine if it's an empty
4058    handler for its EH region.  If so, attempt to redirect EH edges to
4059    an outer region.  Return true the CFG was updated in any way.  This
4060    is similar to jump forwarding, just across EH edges.  */
4061
4062 static bool
4063 cleanup_empty_eh (eh_landing_pad lp)
4064 {
4065   basic_block bb = label_to_block (lp->post_landing_pad);
4066   gimple_stmt_iterator gsi;
4067   gimple resx;
4068   eh_region new_region;
4069   edge_iterator ei;
4070   edge e, e_out;
4071   bool has_non_eh_pred;
4072   bool ret = false;
4073   int new_lp_nr;
4074
4075   /* There can be zero or one edges out of BB.  This is the quickest test.  */
4076   switch (EDGE_COUNT (bb->succs))
4077     {
4078     case 0:
4079       e_out = NULL;
4080       break;
4081     case 1:
4082       e_out = EDGE_SUCC (bb, 0);
4083       break;
4084     default:
4085       return false;
4086     }
4087
4088   resx = last_stmt (bb);
4089   if (resx && is_gimple_resx (resx))
4090     {
4091       if (stmt_can_throw_external (resx))
4092         optimize_clobbers (bb);
4093       else if (sink_clobbers (bb))
4094         ret = true;
4095     }
4096
4097   gsi = gsi_after_labels (bb);
4098
4099   /* Make sure to skip debug statements.  */
4100   if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
4101     gsi_next_nondebug (&gsi);
4102
4103   /* If the block is totally empty, look for more unsplitting cases.  */
4104   if (gsi_end_p (gsi))
4105     {
4106       /* For the degenerate case of an infinite loop bail out.  */
4107       if (infinite_empty_loop_p (e_out))
4108         return ret;
4109
4110       return ret | cleanup_empty_eh_unsplit (bb, e_out, lp);
4111     }
4112
4113   /* The block should consist only of a single RESX statement, modulo a
4114      preceding call to __builtin_stack_restore if there is no outgoing
4115      edge, since the call can be eliminated in this case.  */
4116   resx = gsi_stmt (gsi);
4117   if (!e_out && gimple_call_builtin_p (resx, BUILT_IN_STACK_RESTORE))
4118     {
4119       gsi_next (&gsi);
4120       resx = gsi_stmt (gsi);
4121     }
4122   if (!is_gimple_resx (resx))
4123     return ret;
4124   gcc_assert (gsi_one_before_end_p (gsi));
4125
4126   /* Determine if there are non-EH edges, or resx edges into the handler.  */
4127   has_non_eh_pred = false;
4128   FOR_EACH_EDGE (e, ei, bb->preds)
4129     if (!(e->flags & EDGE_EH))
4130       has_non_eh_pred = true;
4131
4132   /* Find the handler that's outer of the empty handler by looking at
4133      where the RESX instruction was vectored.  */
4134   new_lp_nr = lookup_stmt_eh_lp (resx);
4135   new_region = get_eh_region_from_lp_number (new_lp_nr);
4136
4137   /* If there's no destination region within the current function,
4138      redirection is trivial via removing the throwing statements from
4139      the EH region, removing the EH edges, and allowing the block
4140      to go unreachable.  */
4141   if (new_region == NULL)
4142     {
4143       gcc_assert (e_out == NULL);
4144       for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
4145         if (e->flags & EDGE_EH)
4146           {
4147             gimple stmt = last_stmt (e->src);
4148             remove_stmt_from_eh_lp (stmt);
4149             remove_edge (e);
4150           }
4151         else
4152           ei_next (&ei);
4153       goto succeed;
4154     }
4155
4156   /* If the destination region is a MUST_NOT_THROW, allow the runtime
4157      to handle the abort and allow the blocks to go unreachable.  */
4158   if (new_region->type == ERT_MUST_NOT_THROW)
4159     {
4160       for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
4161         if (e->flags & EDGE_EH)
4162           {
4163             gimple stmt = last_stmt (e->src);
4164             remove_stmt_from_eh_lp (stmt);
4165             add_stmt_to_eh_lp (stmt, new_lp_nr);
4166             remove_edge (e);
4167           }
4168         else
4169           ei_next (&ei);
4170       goto succeed;
4171     }
4172
4173   /* Try to redirect the EH edges and merge the PHIs into the destination
4174      landing pad block.  If the merge succeeds, we'll already have redirected
4175      all the EH edges.  The handler itself will go unreachable if there were
4176      no normal edges.  */
4177   if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, true))
4178     goto succeed;
4179
4180   /* Finally, if all input edges are EH edges, then we can (potentially)
4181      reduce the number of transfers from the runtime by moving the landing
4182      pad from the original region to the new region.  This is a win when
4183      we remove the last CLEANUP region along a particular exception
4184      propagation path.  Since nothing changes except for the region with
4185      which the landing pad is associated, the PHI nodes do not need to be
4186      adjusted at all.  */
4187   if (!has_non_eh_pred)
4188     {
4189       cleanup_empty_eh_move_lp (bb, e_out, lp, new_region);
4190       if (dump_file && (dump_flags & TDF_DETAILS))
4191         fprintf (dump_file, "Empty EH handler %i moved to EH region %i.\n",
4192                  lp->index, new_region->index);
4193
4194       /* ??? The CFG didn't change, but we may have rendered the
4195          old EH region unreachable.  Trigger a cleanup there.  */
4196       return true;
4197     }
4198
4199   return ret;
4200
4201  succeed:
4202   if (dump_file && (dump_flags & TDF_DETAILS))
4203     fprintf (dump_file, "Empty EH handler %i removed.\n", lp->index);
4204   remove_eh_landing_pad (lp);
4205   return true;
4206 }
4207
4208 /* Do a post-order traversal of the EH region tree.  Examine each
4209    post_landing_pad block and see if we can eliminate it as empty.  */
4210
4211 static bool
4212 cleanup_all_empty_eh (void)
4213 {
4214   bool changed = false;
4215   eh_landing_pad lp;
4216   int i;
4217
4218   for (i = 1; VEC_iterate (eh_landing_pad, cfun->eh->lp_array, i, lp); ++i)
4219     if (lp)
4220       changed |= cleanup_empty_eh (lp);
4221
4222   return changed;
4223 }
4224
4225 /* Perform cleanups and lowering of exception handling
4226     1) cleanups regions with handlers doing nothing are optimized out
4227     2) MUST_NOT_THROW regions that became dead because of 1) are optimized out
4228     3) Info about regions that are containing instructions, and regions
4229        reachable via local EH edges is collected
4230     4) Eh tree is pruned for regions no longer neccesary.
4231
4232    TODO: Push MUST_NOT_THROW regions to the root of the EH tree.
4233          Unify those that have the same failure decl and locus.
4234 */
4235
4236 static unsigned int
4237 execute_cleanup_eh_1 (void)
4238 {
4239   /* Do this first: unsplit_all_eh and cleanup_all_empty_eh can die
4240      looking up unreachable landing pads.  */
4241   remove_unreachable_handlers ();
4242
4243   /* Watch out for the region tree vanishing due to all unreachable.  */
4244   if (cfun->eh->region_tree && optimize)
4245     {
4246       bool changed = false;
4247
4248       changed |= unsplit_all_eh ();
4249       changed |= cleanup_all_empty_eh ();
4250
4251       if (changed)
4252         {
4253           free_dominance_info (CDI_DOMINATORS);
4254           free_dominance_info (CDI_POST_DOMINATORS);
4255
4256           /* We delayed all basic block deletion, as we may have performed
4257              cleanups on EH edges while non-EH edges were still present.  */
4258           delete_unreachable_blocks ();
4259
4260           /* We manipulated the landing pads.  Remove any region that no
4261              longer has a landing pad.  */
4262           remove_unreachable_handlers_no_lp ();
4263
4264           return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
4265         }
4266     }
4267
4268   return 0;
4269 }
4270
4271 static unsigned int
4272 execute_cleanup_eh (void)
4273 {
4274   int ret = execute_cleanup_eh_1 ();
4275
4276   /* If the function no longer needs an EH personality routine
4277      clear it.  This exposes cross-language inlining opportunities
4278      and avoids references to a never defined personality routine.  */
4279   if (DECL_FUNCTION_PERSONALITY (current_function_decl)
4280       && function_needs_eh_personality (cfun) != eh_personality_lang)
4281     DECL_FUNCTION_PERSONALITY (current_function_decl) = NULL_TREE;
4282
4283   return ret;
4284 }
4285
4286 static bool
4287 gate_cleanup_eh (void)
4288 {
4289   return cfun->eh != NULL && cfun->eh->region_tree != NULL;
4290 }
4291
4292 struct gimple_opt_pass pass_cleanup_eh = {
4293   {
4294    GIMPLE_PASS,
4295    "ehcleanup",                 /* name */
4296    gate_cleanup_eh,             /* gate */
4297    execute_cleanup_eh,          /* execute */
4298    NULL,                        /* sub */
4299    NULL,                        /* next */
4300    0,                           /* static_pass_number */
4301    TV_TREE_EH,                  /* tv_id */
4302    PROP_gimple_lcf,             /* properties_required */
4303    0,                           /* properties_provided */
4304    0,                           /* properties_destroyed */
4305    0,                           /* todo_flags_start */
4306    0                            /* todo_flags_finish */
4307    }
4308 };
4309 \f
4310 /* Verify that BB containing STMT as the last statement, has precisely the
4311    edge that make_eh_edges would create.  */
4312
4313 DEBUG_FUNCTION bool
4314 verify_eh_edges (gimple stmt)
4315 {
4316   basic_block bb = gimple_bb (stmt);
4317   eh_landing_pad lp = NULL;
4318   int lp_nr;
4319   edge_iterator ei;
4320   edge e, eh_edge;
4321
4322   lp_nr = lookup_stmt_eh_lp (stmt);
4323   if (lp_nr > 0)
4324     lp = get_eh_landing_pad_from_number (lp_nr);
4325
4326   eh_edge = NULL;
4327   FOR_EACH_EDGE (e, ei, bb->succs)
4328     {
4329       if (e->flags & EDGE_EH)
4330         {
4331           if (eh_edge)
4332             {
4333               error ("BB %i has multiple EH edges", bb->index);
4334               return true;
4335             }
4336           else
4337             eh_edge = e;
4338         }
4339     }
4340
4341   if (lp == NULL)
4342     {
4343       if (eh_edge)
4344         {
4345           error ("BB %i can not throw but has an EH edge", bb->index);
4346           return true;
4347         }
4348       return false;
4349     }
4350
4351   if (!stmt_could_throw_p (stmt))
4352     {
4353       error ("BB %i last statement has incorrectly set lp", bb->index);
4354       return true;
4355     }
4356
4357   if (eh_edge == NULL)
4358     {
4359       error ("BB %i is missing an EH edge", bb->index);
4360       return true;
4361     }
4362
4363   if (eh_edge->dest != label_to_block (lp->post_landing_pad))
4364     {
4365       error ("Incorrect EH edge %i->%i", bb->index, eh_edge->dest->index);
4366       return true;
4367     }
4368
4369   return false;
4370 }
4371
4372 /* Similarly, but handle GIMPLE_EH_DISPATCH specifically.  */
4373
4374 DEBUG_FUNCTION bool
4375 verify_eh_dispatch_edge (gimple stmt)
4376 {
4377   eh_region r;
4378   eh_catch c;
4379   basic_block src, dst;
4380   bool want_fallthru = true;
4381   edge_iterator ei;
4382   edge e, fall_edge;
4383
4384   r = get_eh_region_from_number (gimple_eh_dispatch_region (stmt));
4385   src = gimple_bb (stmt);
4386
4387   FOR_EACH_EDGE (e, ei, src->succs)
4388     gcc_assert (e->aux == NULL);
4389
4390   switch (r->type)
4391     {
4392     case ERT_TRY:
4393       for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
4394         {
4395           dst = label_to_block (c->label);
4396           e = find_edge (src, dst);
4397           if (e == NULL)
4398             {
4399               error ("BB %i is missing an edge", src->index);
4400               return true;
4401             }
4402           e->aux = (void *)e;
4403
4404           /* A catch-all handler doesn't have a fallthru.  */
4405           if (c->type_list == NULL)
4406             {
4407               want_fallthru = false;
4408               break;
4409             }
4410         }
4411       break;
4412
4413     case ERT_ALLOWED_EXCEPTIONS:
4414       dst = label_to_block (r->u.allowed.label);
4415       e = find_edge (src, dst);
4416       if (e == NULL)
4417         {
4418           error ("BB %i is missing an edge", src->index);
4419           return true;
4420         }
4421       e->aux = (void *)e;
4422       break;
4423
4424     default:
4425       gcc_unreachable ();
4426     }
4427
4428   fall_edge = NULL;
4429   FOR_EACH_EDGE (e, ei, src->succs)
4430     {
4431       if (e->flags & EDGE_FALLTHRU)
4432         {
4433           if (fall_edge != NULL)
4434             {
4435               error ("BB %i too many fallthru edges", src->index);
4436               return true;
4437             }
4438           fall_edge = e;
4439         }
4440       else if (e->aux)
4441         e->aux = NULL;
4442       else
4443         {
4444           error ("BB %i has incorrect edge", src->index);
4445           return true;
4446         }
4447     }
4448   if ((fall_edge != NULL) ^ want_fallthru)
4449     {
4450       error ("BB %i has incorrect fallthru edge", src->index);
4451       return true;
4452     }
4453
4454   return false;
4455 }