OSDN Git Service

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