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