OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [tree-eh.c] - Blame information for rev 779

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.