00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "system.h"
00027 #include "coretypes.h"
00028 #include "tm.h"
00029 #include "tree.h"
00030 #include "rtl.h"
00031 #include "tm_p.h"
00032 #include "flags.h"
00033 #include "function.h"
00034 #include "except.h"
00035 #include "tree-flow.h"
00036 #include "tree-dump.h"
00037 #include "tree-inline.h"
00038 #include "tree-iterator.h"
00039 #include "tree-pass.h"
00040 #include "timevar.h"
00041 #include "langhooks.h"
00042 #include "ggc.h"
00043
00044
00045 #ifdef KEY
00046 extern int flag_spin_file;
00047 #endif
00048
00049
00050 static int using_eh_for_cleanups_p = 0;
00051
00052 void
00053 using_eh_for_cleanups (void)
00054 {
00055 using_eh_for_cleanups_p = 1;
00056 }
00057
00058
00059
00060
00061
00062
00063
00064 static int
00065 struct_ptr_eq (const void *a, const void *b)
00066 {
00067 const void * const * x = a;
00068 const void * const * y = b;
00069 return *x == *y;
00070 }
00071
00072 static hashval_t
00073 struct_ptr_hash (const void *a)
00074 {
00075 const void * const * x = a;
00076 return (size_t)*x >> 4;
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 struct throw_stmt_node GTY(())
00093 {
00094 tree stmt;
00095 int region_nr;
00096 };
00097
00098 static GTY((param_is (struct throw_stmt_node))) htab_t throw_stmt_table;
00099
00100 static void
00101 record_stmt_eh_region (struct eh_region *region, tree t)
00102 {
00103 struct throw_stmt_node *n;
00104 void **slot;
00105
00106 if (!region)
00107 return;
00108
00109 n = ggc_alloc (sizeof (*n));
00110 n->stmt = t;
00111 n->region_nr = get_eh_region_number (region);
00112
00113 slot = htab_find_slot (throw_stmt_table, n, INSERT);
00114 gcc_assert (!*slot);
00115 *slot = n;
00116 }
00117
00118 void
00119 add_stmt_to_eh_region (tree t, int num)
00120 {
00121 struct throw_stmt_node *n;
00122 void **slot;
00123
00124 gcc_assert (num >= 0);
00125
00126 n = ggc_alloc (sizeof (*n));
00127 n->stmt = t;
00128 n->region_nr = num;
00129
00130 slot = htab_find_slot (throw_stmt_table, n, INSERT);
00131 gcc_assert (!*slot);
00132 *slot = n;
00133 }
00134
00135 bool
00136 remove_stmt_from_eh_region (tree t)
00137 {
00138 struct throw_stmt_node dummy;
00139 void **slot;
00140
00141 if (!throw_stmt_table)
00142 return false;
00143
00144 dummy.stmt = t;
00145 slot = htab_find_slot (throw_stmt_table, &dummy, NO_INSERT);
00146 if (slot)
00147 {
00148 htab_clear_slot (throw_stmt_table, slot);
00149 return true;
00150 }
00151 else
00152 return false;
00153 }
00154
00155 int
00156 lookup_stmt_eh_region (tree t)
00157 {
00158 struct throw_stmt_node *p, n;
00159
00160 if (!throw_stmt_table)
00161 return -2;
00162
00163 n.stmt = t;
00164 p = htab_find (throw_stmt_table, &n);
00165
00166 return (p ? p->region_nr : -1);
00167 }
00168
00169
00170
00171
00172
00173
00174
00175 struct finally_tree_node
00176 {
00177 tree child, parent;
00178 };
00179
00180
00181 static htab_t finally_tree;
00182
00183 static void
00184 record_in_finally_tree (tree child, tree parent)
00185 {
00186 struct finally_tree_node *n;
00187 void **slot;
00188
00189 n = xmalloc (sizeof (*n));
00190 n->child = child;
00191 n->parent = parent;
00192
00193 slot = htab_find_slot (finally_tree, n, INSERT);
00194 gcc_assert (!*slot);
00195 *slot = n;
00196 }
00197
00198 static void
00199 collect_finally_tree (tree t, tree region)
00200 {
00201 tailrecurse:
00202 switch (TREE_CODE (t))
00203 {
00204 case LABEL_EXPR:
00205 record_in_finally_tree (LABEL_EXPR_LABEL (t), region);
00206 break;
00207
00208 case TRY_FINALLY_EXPR:
00209 record_in_finally_tree (t, region);
00210 collect_finally_tree (TREE_OPERAND (t, 0), t);
00211 t = TREE_OPERAND (t, 1);
00212 goto tailrecurse;
00213
00214 case TRY_CATCH_EXPR:
00215 collect_finally_tree (TREE_OPERAND (t, 0), region);
00216 t = TREE_OPERAND (t, 1);
00217 goto tailrecurse;
00218
00219 case CATCH_EXPR:
00220 t = CATCH_BODY (t);
00221 goto tailrecurse;
00222
00223 case EH_FILTER_EXPR:
00224 t = EH_FILTER_FAILURE (t);
00225 goto tailrecurse;
00226
00227 case STATEMENT_LIST:
00228 {
00229 tree_stmt_iterator i;
00230 for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
00231 collect_finally_tree (tsi_stmt (i), region);
00232 }
00233 break;
00234
00235 default:
00236
00237
00238 break;
00239 }
00240 }
00241
00242
00243
00244
00245 static bool
00246 outside_finally_tree (tree start, tree target)
00247 {
00248 struct finally_tree_node n, *p;
00249
00250 do
00251 {
00252 n.child = start;
00253 p = htab_find (finally_tree, &n);
00254 if (!p)
00255 return true;
00256 start = p->parent;
00257 }
00258 while (start != target);
00259
00260 return false;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270 struct leh_state
00271 {
00272
00273
00274
00275 struct eh_region *cur_region;
00276 struct eh_region *prev_try;
00277
00278
00279
00280
00281 struct leh_tf_state *tf;
00282 };
00283
00284 struct leh_tf_state
00285 {
00286
00287
00288
00289
00290 tree try_finally_expr;
00291 tree *top_p;
00292
00293
00294 struct leh_state *outer;
00295
00296
00297 struct eh_region *region;
00298
00299
00300
00301 struct goto_queue_node {
00302 tree stmt;
00303 tree repl_stmt;
00304 tree cont_stmt;
00305 int index;
00306 } *goto_queue;
00307 size_t goto_queue_size;
00308 size_t goto_queue_active;
00309
00310
00311 varray_type dest_array;
00312
00313
00314
00315
00316 tree fallthru_label;
00317
00318
00319
00320 tree eh_label;
00321
00322
00323
00324 bool may_fallthru;
00325
00326
00327 bool may_return;
00328
00329
00330
00331 bool may_throw;
00332 };
00333
00334 static void lower_eh_filter (struct leh_state *, tree *);
00335 static void lower_eh_constructs_1 (struct leh_state *, tree *);
00336
00337
00338
00339
00340 static int
00341 goto_queue_cmp (const void *x, const void *y)
00342 {
00343 tree a = ((const struct goto_queue_node *)x)->stmt;
00344 tree b = ((const struct goto_queue_node *)y)->stmt;
00345 return (a == b ? 0 : a < b ? -1 : 1);
00346 }
00347
00348
00349
00350
00351 static tree
00352 find_goto_replacement (struct leh_tf_state *tf, tree stmt)
00353 {
00354 struct goto_queue_node tmp, *ret;
00355 tmp.stmt = stmt;
00356 ret = bsearch (&tmp, tf->goto_queue, tf->goto_queue_active,
00357 sizeof (struct goto_queue_node), goto_queue_cmp);
00358 return (ret ? ret->repl_stmt : NULL);
00359 }
00360
00361
00362
00363
00364
00365
00366 static void
00367 replace_goto_queue_cond_clause (tree *tp, struct leh_tf_state *tf,
00368 tree_stmt_iterator *tsi)
00369 {
00370 tree new, one, label;
00371
00372 new = find_goto_replacement (tf, *tp);
00373 if (!new)
00374 return;
00375
00376 one = expr_only (new);
00377 if (one && TREE_CODE (one) == GOTO_EXPR)
00378 {
00379 *tp = one;
00380 return;
00381 }
00382
00383 label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
00384 *tp = build_and_jump (&LABEL_EXPR_LABEL (label));
00385
00386 tsi_link_after (tsi, label, TSI_CONTINUE_LINKING);
00387 tsi_link_after (tsi, new, TSI_CONTINUE_LINKING);
00388 }
00389
00390
00391
00392
00393 static void replace_goto_queue_stmt_list (tree, struct leh_tf_state *);
00394
00395 static void
00396 replace_goto_queue_1 (tree t, struct leh_tf_state *tf, tree_stmt_iterator *tsi)
00397 {
00398 switch (TREE_CODE (t))
00399 {
00400 case GOTO_EXPR:
00401 case RETURN_EXPR:
00402 t = find_goto_replacement (tf, t);
00403 if (t)
00404 {
00405 tsi_link_before (tsi, t, TSI_SAME_STMT);
00406 tsi_delink (tsi);
00407 return;
00408 }
00409 break;
00410
00411 case COND_EXPR:
00412 replace_goto_queue_cond_clause (&COND_EXPR_THEN (t), tf, tsi);
00413 replace_goto_queue_cond_clause (&COND_EXPR_ELSE (t), tf, tsi);
00414 break;
00415
00416 case TRY_FINALLY_EXPR:
00417 case TRY_CATCH_EXPR:
00418 replace_goto_queue_stmt_list (TREE_OPERAND (t, 0), tf);
00419 replace_goto_queue_stmt_list (TREE_OPERAND (t, 1), tf);
00420 break;
00421 case CATCH_EXPR:
00422 replace_goto_queue_stmt_list (CATCH_BODY (t), tf);
00423 break;
00424 case EH_FILTER_EXPR:
00425 replace_goto_queue_stmt_list (EH_FILTER_FAILURE (t), tf);
00426 break;
00427
00428 case STATEMENT_LIST:
00429 gcc_unreachable ();
00430
00431 default:
00432
00433 break;
00434 }
00435
00436 tsi_next (tsi);
00437 }
00438
00439
00440
00441 static void
00442 replace_goto_queue_stmt_list (tree t, struct leh_tf_state *tf)
00443 {
00444 tree_stmt_iterator i = tsi_start (t);
00445 while (!tsi_end_p (i))
00446 replace_goto_queue_1 (tsi_stmt (i), tf, &i);
00447 }
00448
00449
00450
00451 static void
00452 replace_goto_queue (struct leh_tf_state *tf)
00453 {
00454 if (tf->goto_queue_active == 0)
00455 return;
00456 replace_goto_queue_stmt_list (*tf->top_p, tf);
00457 }
00458
00459
00460
00461
00462
00463 static void
00464 maybe_record_in_goto_queue (struct leh_state *state, tree stmt)
00465 {
00466 struct leh_tf_state *tf = state->tf;
00467 struct goto_queue_node *q;
00468 size_t active, size;
00469 int index;
00470
00471 if (!tf)
00472 return;
00473
00474 switch (TREE_CODE (stmt))
00475 {
00476 case GOTO_EXPR:
00477 {
00478 tree lab = GOTO_DESTINATION (stmt);
00479
00480
00481
00482
00483 if (TREE_CODE (lab) != LABEL_DECL)
00484 return;
00485
00486
00487 if (! outside_finally_tree (lab, tf->try_finally_expr))
00488 return;
00489
00490 if (! tf->dest_array)
00491 {
00492 VARRAY_TREE_INIT (tf->dest_array, 10, "dest_array");
00493 VARRAY_PUSH_TREE (tf->dest_array, lab);
00494 index = 0;
00495 }
00496 else
00497 {
00498 int n = VARRAY_ACTIVE_SIZE (tf->dest_array);
00499 for (index = 0; index < n; ++index)
00500 if (VARRAY_TREE (tf->dest_array, index) == lab)
00501 break;
00502 if (index == n)
00503 VARRAY_PUSH_TREE (tf->dest_array, lab);
00504 }
00505 }
00506 break;
00507
00508 case RETURN_EXPR:
00509 tf->may_return = true;
00510 index = -1;
00511 break;
00512
00513 default:
00514 gcc_unreachable ();
00515 }
00516
00517 active = tf->goto_queue_active;
00518 size = tf->goto_queue_size;
00519 if (active >= size)
00520 {
00521 size = (size ? size * 2 : 32);
00522 tf->goto_queue_size = size;
00523 tf->goto_queue
00524 = xrealloc (tf->goto_queue, size * sizeof (struct goto_queue_node));
00525 }
00526
00527 q = &tf->goto_queue[active];
00528 tf->goto_queue_active = active + 1;
00529
00530 memset (q, 0, sizeof (*q));
00531 q->stmt = stmt;
00532 q->index = index;
00533 }
00534
00535 #ifdef ENABLE_CHECKING
00536
00537
00538
00539
00540 static void
00541 verify_norecord_switch_expr (struct leh_state *state, tree switch_expr)
00542 {
00543 struct leh_tf_state *tf = state->tf;
00544 size_t i, n;
00545 tree vec;
00546
00547 if (!tf)
00548 return;
00549
00550 vec = SWITCH_LABELS (switch_expr);
00551 n = TREE_VEC_LENGTH (vec);
00552
00553 for (i = 0; i < n; ++i)
00554 {
00555 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
00556 gcc_assert (!outside_finally_tree (lab, tf->try_finally_expr));
00557 }
00558 }
00559 #else
00560 #define verify_norecord_switch_expr(state, switch_expr)
00561 #endif
00562
00563
00564
00565
00566
00567
00568 static void
00569 do_return_redirection (struct goto_queue_node *q, tree finlab, tree mod,
00570 tree *return_value_p)
00571 {
00572 tree ret_expr = TREE_OPERAND (q->stmt, 0);
00573 tree x;
00574
00575 if (ret_expr)
00576 {
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 switch (TREE_CODE (ret_expr))
00600 {
00601 case RESULT_DECL:
00602 if (!*return_value_p)
00603 *return_value_p = ret_expr;
00604 else
00605 gcc_assert (*return_value_p == ret_expr);
00606 q->cont_stmt = q->stmt;
00607 break;
00608
00609 case MODIFY_EXPR:
00610 {
00611 tree result = TREE_OPERAND (ret_expr, 0);
00612 tree new, old = TREE_OPERAND (ret_expr, 1);
00613
00614 if (!*return_value_p)
00615 {
00616 if (aggregate_value_p (TREE_TYPE (result),
00617 TREE_TYPE (current_function_decl)))
00618
00619
00620
00621
00622
00623 new = result;
00624 else
00625 new = create_tmp_var (TREE_TYPE (old), "rettmp");
00626 *return_value_p = new;
00627 }
00628 else
00629 new = *return_value_p;
00630
00631 x = build (MODIFY_EXPR, TREE_TYPE (new), new, old);
00632 append_to_statement_list (x, &q->repl_stmt);
00633
00634 if (new == result)
00635 x = result;
00636 else
00637 x = build (MODIFY_EXPR, TREE_TYPE (result), result, new);
00638 q->cont_stmt = build1 (RETURN_EXPR, void_type_node, x);
00639 }
00640
00641 default:
00642 gcc_unreachable ();
00643 }
00644 }
00645 else
00646 {
00647
00648 q->cont_stmt = q->stmt;
00649 }
00650
00651 if (mod)
00652 append_to_statement_list (mod, &q->repl_stmt);
00653
00654 x = build1 (GOTO_EXPR, void_type_node, finlab);
00655 append_to_statement_list (x, &q->repl_stmt);
00656 }
00657
00658
00659
00660 static void
00661 do_goto_redirection (struct goto_queue_node *q, tree finlab, tree mod)
00662 {
00663 tree x;
00664
00665 q->cont_stmt = q->stmt;
00666 if (mod)
00667 append_to_statement_list (mod, &q->repl_stmt);
00668
00669 x = build1 (GOTO_EXPR, void_type_node, finlab);
00670 append_to_statement_list (x, &q->repl_stmt);
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682 static void
00683 frob_into_branch_around (tree *tp, tree lab, tree over)
00684 {
00685 tree x, op1;
00686
00687 op1 = TREE_OPERAND (*tp, 1);
00688 *tp = TREE_OPERAND (*tp, 0);
00689
00690 if (block_may_fallthru (*tp))
00691 {
00692 if (!over)
00693 over = create_artificial_label ();
00694 x = build1 (GOTO_EXPR, void_type_node, over);
00695 append_to_statement_list (x, tp);
00696 }
00697
00698 if (lab)
00699 {
00700 x = build1 (LABEL_EXPR, void_type_node, lab);
00701 append_to_statement_list (x, tp);
00702 }
00703
00704 append_to_statement_list (op1, tp);
00705
00706 if (over)
00707 {
00708 x = build1 (LABEL_EXPR, void_type_node, over);
00709 append_to_statement_list (x, tp);
00710 }
00711 }
00712
00713
00714
00715
00716 static tree
00717 lower_try_finally_dup_block (tree t, struct leh_state *outer_state)
00718 {
00719 tree region = NULL;
00720
00721 t = unsave_expr_now (t);
00722
00723 if (outer_state->tf)
00724 region = outer_state->tf->try_finally_expr;
00725 collect_finally_tree (t, region);
00726
00727 return t;
00728 }
00729
00730
00731
00732
00733
00734 static tree
00735 lower_try_finally_fallthru_label (struct leh_tf_state *tf)
00736 {
00737 tree label = tf->fallthru_label;
00738 if (!label)
00739 {
00740 label = create_artificial_label ();
00741 tf->fallthru_label = label;
00742 if (tf->outer->tf)
00743 record_in_finally_tree (label, tf->outer->tf->try_finally_expr);
00744 }
00745 return label;
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768 static void
00769 honor_protect_cleanup_actions (struct leh_state *outer_state,
00770 struct leh_state *this_state,
00771 struct leh_tf_state *tf)
00772 {
00773 tree protect_cleanup_actions, finally, x;
00774 tree_stmt_iterator i;
00775 bool finally_may_fallthru;
00776
00777
00778 if (lang_protect_cleanup_actions)
00779 protect_cleanup_actions = lang_protect_cleanup_actions ();
00780 else
00781 protect_cleanup_actions = NULL;
00782
00783 finally = TREE_OPERAND (*tf->top_p, 1);
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806 finally_may_fallthru = block_may_fallthru (finally);
00807 if (!finally_may_fallthru && !protect_cleanup_actions)
00808 return;
00809
00810
00811
00812 if (this_state)
00813 finally = lower_try_finally_dup_block (finally, outer_state);
00814
00815
00816
00817
00818 if (finally_may_fallthru)
00819 {
00820 tree save_eptr, save_filt;
00821
00822 save_eptr = create_tmp_var (ptr_type_node, "save_eptr");
00823 save_filt = create_tmp_var (integer_type_node, "save_filt");
00824
00825 i = tsi_start (finally);
00826 x = build (EXC_PTR_EXPR, ptr_type_node);
00827 x = build (MODIFY_EXPR, void_type_node, save_eptr, x);
00828 tsi_link_before (&i, x, TSI_CONTINUE_LINKING);
00829
00830 x = build (FILTER_EXPR, integer_type_node);
00831 x = build (MODIFY_EXPR, void_type_node, save_filt, x);
00832 tsi_link_before (&i, x, TSI_CONTINUE_LINKING);
00833
00834 i = tsi_last (finally);
00835 x = build (EXC_PTR_EXPR, ptr_type_node);
00836 x = build (MODIFY_EXPR, void_type_node, x, save_eptr);
00837 tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
00838
00839 x = build (FILTER_EXPR, integer_type_node);
00840 x = build (MODIFY_EXPR, void_type_node, x, save_filt);
00841 tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
00842
00843 x = build1 (RESX_EXPR, void_type_node,
00844 build_int_cst (NULL_TREE,
00845 get_eh_region_number (tf->region)));
00846 tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
00847 }
00848
00849
00850 if (protect_cleanup_actions)
00851 {
00852 x = build (EH_FILTER_EXPR, void_type_node, NULL, NULL);
00853 append_to_statement_list (protect_cleanup_actions, &EH_FILTER_FAILURE (x));
00854 EH_FILTER_MUST_NOT_THROW (x) = 1;
00855 finally = build (TRY_CATCH_EXPR, void_type_node, finally, x);
00856 lower_eh_filter (outer_state, &finally);
00857 }
00858 else
00859 lower_eh_constructs_1 (outer_state, &finally);
00860
00861
00862
00863
00864
00865 i = tsi_last (TREE_OPERAND (*tf->top_p, 0));
00866
00867 if (tf->may_fallthru)
00868 {
00869 x = lower_try_finally_fallthru_label (tf);
00870 x = build1 (GOTO_EXPR, void_type_node, x);
00871 tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
00872
00873 if (this_state)
00874 maybe_record_in_goto_queue (this_state, x);
00875
00876 tf->may_fallthru = false;
00877 }
00878
00879 x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
00880 tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
00881 tsi_link_after (&i, finally, TSI_CONTINUE_LINKING);
00882
00883
00884
00885 tf->may_throw = false;
00886 }
00887
00888
00889
00890
00891
00892
00893 static void
00894 lower_try_finally_nofallthru (struct leh_state *state, struct leh_tf_state *tf)
00895 {
00896 tree x, finally, lab, return_val;
00897 struct goto_queue_node *q, *qe;
00898
00899 if (tf->may_throw)
00900 lab = tf->eh_label;
00901 else
00902 lab = create_artificial_label ();
00903
00904 finally = TREE_OPERAND (*tf->top_p, 1);
00905 *tf->top_p = TREE_OPERAND (*tf->top_p, 0);
00906
00907 x = build1 (LABEL_EXPR, void_type_node, lab);
00908 append_to_statement_list (x, tf->top_p);
00909
00910 return_val = NULL;
00911 q = tf->goto_queue;
00912 qe = q + tf->goto_queue_active;
00913 for (; q < qe; ++q)
00914 if (q->index < 0)
00915 do_return_redirection (q, lab, NULL, &return_val);
00916 else
00917 do_goto_redirection (q, lab, NULL);
00918
00919 replace_goto_queue (tf);
00920
00921 lower_eh_constructs_1 (state, &finally);
00922 append_to_statement_list (finally, tf->top_p);
00923 }
00924
00925
00926
00927
00928
00929 static void
00930 lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
00931 {
00932 struct goto_queue_node *q, *qe;
00933 tree x, finally, finally_label;
00934
00935 finally = TREE_OPERAND (*tf->top_p, 1);
00936 *tf->top_p = TREE_OPERAND (*tf->top_p, 0);
00937
00938 lower_eh_constructs_1 (state, &finally);
00939
00940 if (tf->may_throw)
00941 {
00942
00943
00944
00945 x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
00946 append_to_statement_list (x, tf->top_p);
00947
00948 append_to_statement_list (finally, tf->top_p);
00949
00950 x = build1 (RESX_EXPR, void_type_node,
00951 build_int_cst (NULL_TREE,
00952 get_eh_region_number (tf->region)));
00953 append_to_statement_list (x, tf->top_p);
00954
00955 return;
00956 }
00957
00958 if (tf->may_fallthru)
00959 {
00960
00961
00962 append_to_statement_list (finally, tf->top_p);
00963 return;
00964 }
00965
00966 finally_label = create_artificial_label ();
00967 x = build1 (LABEL_EXPR, void_type_node, finally_label);
00968 append_to_statement_list (x, tf->top_p);
00969
00970 append_to_statement_list (finally, tf->top_p);
00971
00972 q = tf->goto_queue;
00973 qe = q + tf->goto_queue_active;
00974
00975 if (tf->may_return)
00976 {
00977
00978 tree return_val = NULL;
00979 for (; q < qe; ++q)
00980 do_return_redirection (q, finally_label, NULL, &return_val);
00981 replace_goto_queue (tf);
00982 }
00983 else
00984 {
00985
00986 for (; q < qe; ++q)
00987 do_goto_redirection (q, finally_label, NULL);
00988 replace_goto_queue (tf);
00989
00990 if (VARRAY_TREE (tf->dest_array, 0) == tf->fallthru_label)
00991 {
00992
00993
00994
00995 tf->fallthru_label = NULL;
00996 return;
00997 }
00998 }
00999
01000 append_to_statement_list (tf->goto_queue[0].cont_stmt, tf->top_p);
01001 maybe_record_in_goto_queue (state, tf->goto_queue[0].cont_stmt);
01002 }
01003
01004
01005
01006
01007
01008 static void
01009 lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
01010 {
01011 tree finally, new_stmt;
01012 tree x;
01013
01014 finally = TREE_OPERAND (*tf->top_p, 1);
01015 *tf->top_p = TREE_OPERAND (*tf->top_p, 0);
01016
01017 new_stmt = NULL_TREE;
01018
01019 if (tf->may_fallthru)
01020 {
01021 x = lower_try_finally_dup_block (finally, state);
01022 lower_eh_constructs_1 (state, &x);
01023 append_to_statement_list (x, &new_stmt);
01024
01025 x = lower_try_finally_fallthru_label (tf);
01026 x = build1 (GOTO_EXPR, void_type_node, x);
01027 append_to_statement_list (x, &new_stmt);
01028 }
01029
01030 if (tf->may_throw)
01031 {
01032 x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
01033 append_to_statement_list (x, &new_stmt);
01034
01035 x = lower_try_finally_dup_block (finally, state);
01036 lower_eh_constructs_1 (state, &x);
01037 append_to_statement_list (x, &new_stmt);
01038
01039 x = build1 (RESX_EXPR, void_type_node,
01040 build_int_cst (NULL_TREE,
01041 get_eh_region_number (tf->region)));
01042 append_to_statement_list (x, &new_stmt);
01043 }
01044
01045 if (tf->goto_queue)
01046 {
01047 struct goto_queue_node *q, *qe;
01048 tree return_val = NULL;
01049 int return_index, index;
01050 struct
01051 {
01052 struct goto_queue_node *q;
01053 tree label;
01054 } *labels;
01055
01056 if (tf->dest_array)
01057 return_index = VARRAY_ACTIVE_SIZE (tf->dest_array);
01058 else
01059 return_index = 0;
01060 labels = xcalloc (sizeof (*labels), return_index + 1);
01061
01062 q = tf->goto_queue;
01063 qe = q + tf->goto_queue_active;
01064 for (; q < qe; q++)
01065 {
01066 index = q->index < 0 ? return_index : q->index;
01067
01068 if (!labels[index].q)
01069 labels[index].q = q;
01070 }
01071
01072 for (index = 0; index < return_index + 1; index++)
01073 {
01074 tree lab;
01075
01076 q = labels[index].q;
01077 if (! q)
01078 continue;
01079
01080 lab = labels[index].label = create_artificial_label ();
01081
01082 if (index == return_index)
01083 do_return_redirection (q, lab, NULL, &return_val);
01084 else
01085 do_goto_redirection (q, lab, NULL);
01086
01087 x = build1 (LABEL_EXPR, void_type_node, lab);
01088 append_to_statement_list (x, &new_stmt);
01089
01090 x = lower_try_finally_dup_block (finally, state);
01091 lower_eh_constructs_1 (state, &x);
01092 append_to_statement_list (x, &new_stmt);
01093
01094 append_to_statement_list (q->cont_stmt, &new_stmt);
01095 maybe_record_in_goto_queue (state, q->cont_stmt);
01096 }
01097
01098 for (q = tf->goto_queue; q < qe; q++)
01099 {
01100 tree lab;
01101
01102 index = q->index < 0 ? return_index : q->index;
01103
01104 if (labels[index].q == q)
01105 continue;
01106
01107 lab = labels[index].label;
01108
01109 if (index == return_index)
01110 do_return_redirection (q, lab, NULL, &return_val);
01111 else
01112 do_goto_redirection (q, lab, NULL);
01113 }
01114
01115 replace_goto_queue (tf);
01116 free (labels);
01117 }
01118
01119
01120
01121 append_to_statement_list (new_stmt, tf->top_p);
01122 }
01123
01124
01125
01126
01127
01128
01129 static void
01130 lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
01131 {
01132 struct goto_queue_node *q, *qe;
01133 tree return_val = NULL;
01134 tree finally, finally_tmp, finally_label;
01135 int return_index, eh_index, fallthru_index;
01136 int nlabels, ndests, j, last_case_index;
01137 tree case_label_vec, switch_stmt, last_case, switch_body;
01138 tree x;
01139
01140
01141 finally = TREE_OPERAND (*tf->top_p, 1);
01142 *tf->top_p = TREE_OPERAND (*tf->top_p, 0);
01143
01144
01145 lower_eh_constructs_1 (state, &finally);
01146
01147
01148 if (tf->dest_array)
01149 nlabels = VARRAY_ACTIVE_SIZE (tf->dest_array);
01150 else
01151 nlabels = 0;
01152 return_index = nlabels;
01153 eh_index = return_index + tf->may_return;
01154 fallthru_index = eh_index + tf->may_throw;
01155 ndests = fallthru_index + tf->may_fallthru;
01156
01157 finally_tmp = create_tmp_var (integer_type_node, "finally_tmp");
01158 finally_label = create_artificial_label ();
01159
01160 case_label_vec = make_tree_vec (ndests);
01161 switch_stmt = build (SWITCH_EXPR, integer_type_node, finally_tmp,
01162 NULL_TREE, case_label_vec);
01163 switch_body = NULL;
01164 last_case = NULL;
01165 last_case_index = 0;
01166
01167
01168
01169
01170
01171 if (tf->may_fallthru)
01172 {
01173 x = build (MODIFY_EXPR, void_type_node, finally_tmp,
01174 build_int_cst (NULL_TREE, fallthru_index));
01175 append_to_statement_list (x, tf->top_p);
01176
01177 if (tf->may_throw)
01178 {
01179 x = build1 (GOTO_EXPR, void_type_node, finally_label);
01180 append_to_statement_list (x, tf->top_p);
01181 }
01182
01183
01184 last_case = build (CASE_LABEL_EXPR, void_type_node,
01185 build_int_cst (NULL_TREE, fallthru_index), NULL,
01186 create_artificial_label ());
01187 TREE_VEC_ELT (case_label_vec, last_case_index) = last_case;
01188 last_case_index++;
01189
01190 x = build (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
01191 append_to_statement_list (x, &switch_body);
01192
01193 x = lower_try_finally_fallthru_label (tf);
01194 x = build1 (GOTO_EXPR, void_type_node, x);
01195 append_to_statement_list (x, &switch_body);
01196 }
01197
01198 if (tf->may_throw)
01199 {
01200 x = build1 (LABEL_EXPR, void_type_node, tf->eh_label);
01201 append_to_statement_list (x, tf->top_p);
01202
01203 x = build (MODIFY_EXPR, void_type_node, finally_tmp,
01204 build_int_cst (NULL_TREE, eh_index));
01205 append_to_statement_list (x, tf->top_p);
01206
01207 last_case = build (CASE_LABEL_EXPR, void_type_node,
01208 build_int_cst (NULL_TREE, eh_index), NULL,
01209 create_artificial_label ());
01210 TREE_VEC_ELT (case_label_vec, last_case_index) = last_case;
01211 last_case_index++;
01212
01213 x = build (LABEL_EXPR, void_type_node, CASE_LABEL (last_case));
01214 append_to_statement_list (x, &switch_body);
01215 x = build1 (RESX_EXPR, void_type_node,
01216 build_int_cst (NULL_TREE,
01217 get_eh_region_number (tf->region)));
01218 append_to_statement_list (x, &switch_body);
01219 }
01220
01221 x = build1 (LABEL_EXPR, void_type_node, finally_label);
01222 append_to_statement_list (x, tf->top_p);
01223
01224 append_to_statement_list (finally, tf->top_p);
01225
01226
01227 q = tf->goto_queue;
01228 qe = q + tf->goto_queue_active;
01229 j = last_case_index + tf->may_return;
01230 for (; q < qe; ++q)
01231 {
01232 tree mod;
01233 int switch_id, case_index;
01234
01235 if (q->index < 0)
01236 {
01237 mod = build (MODIFY_EXPR, void_type_node, finally_tmp,
01238 build_int_cst (NULL_TREE, return_index));
01239 do_return_redirection (q, finally_label, mod, &return_val);
01240 switch_id = return_index;
01241 }
01242 else
01243 {
01244 mod = build (MODIFY_EXPR, void_type_node, finally_tmp,
01245 build_int_cst (NULL_TREE, q->index));
01246 do_goto_redirection (q, finally_label, mod);
01247 switch_id = q->index;
01248 }
01249
01250 case_index = j + q->index;
01251 if (!TREE_VEC_ELT (case_label_vec, case_index))
01252 TREE_VEC_ELT (case_label_vec, case_index)
01253 = build (CASE_LABEL_EXPR, void_type_node,
01254 build_int_cst (NULL_TREE, switch_id), NULL,
01255
01256
01257
01258
01259
01260
01261 q->cont_stmt);
01262 }
01263 for (j = last_case_index; j < last_case_index + nlabels; j++)
01264 {
01265 tree label;
01266 tree cont_stmt;
01267
01268 last_case = TREE_VEC_ELT (case_label_vec, j);
01269
01270 gcc_assert (last_case);
01271
01272 cont_stmt = CASE_LABEL (last_case);
01273
01274 label = create_artificial_label ();
01275 CASE_LABEL (last_case) = label;
01276
01277 x = build (LABEL_EXPR, void_type_node, label);
01278 append_to_statement_list (x, &switch_body);
01279 append_to_statement_list (cont_stmt, &switch_body);
01280 maybe_record_in_goto_queue (state, cont_stmt);
01281 }
01282 replace_goto_queue (tf);
01283
01284
01285
01286 CASE_LOW (last_case) = NULL;
01287 sort_case_labels (case_label_vec);
01288
01289
01290
01291 append_to_statement_list (switch_stmt, tf->top_p);
01292 append_to_statement_list (switch_body, tf->top_p);
01293 }
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309 static bool
01310 decide_copy_try_finally (int ndests, tree finally)
01311 {
01312 int f_estimate, sw_estimate;
01313
01314 if (!optimize)
01315 return false;
01316
01317
01318 f_estimate = estimate_num_insns (finally);
01319 f_estimate = (f_estimate + 1) * ndests;
01320
01321
01322 sw_estimate = 10 + 2 * ndests;
01323
01324
01325 if (optimize_size)
01326 return f_estimate < sw_estimate;
01327
01328
01329 if (optimize > 1)
01330 return f_estimate < 100 || f_estimate < sw_estimate * 2;
01331 else
01332 return f_estimate < 40 || f_estimate * 2 < sw_estimate * 3;
01333 }
01334
01335
01336
01337
01338
01339
01340 static void
01341 lower_try_finally (struct leh_state *state, tree *tp)
01342 {
01343 struct leh_tf_state this_tf;
01344 struct leh_state this_state;
01345 int ndests;
01346
01347
01348
01349 memset (&this_tf, 0, sizeof (this_tf));
01350 this_tf.try_finally_expr = *tp;
01351 this_tf.top_p = tp;
01352 this_tf.outer = state;
01353 if (using_eh_for_cleanups_p)
01354 this_tf.region
01355 = gen_eh_region_cleanup (state->cur_region, state->prev_try);
01356 else
01357 this_tf.region = NULL;
01358
01359 this_state.cur_region = this_tf.region;
01360 this_state.prev_try = state->prev_try;
01361 this_state.tf = &this_tf;
01362
01363 lower_eh_constructs_1 (&this_state, &TREE_OPERAND (*tp, 0));
01364
01365
01366 this_tf.may_fallthru = block_may_fallthru (TREE_OPERAND (*tp, 0));
01367
01368
01369 if (using_eh_for_cleanups_p)
01370 this_tf.may_throw = get_eh_region_may_contain_throw (this_tf.region);
01371 if (this_tf.may_throw)
01372 {
01373 this_tf.eh_label = create_artificial_label ();
01374 set_eh_region_tree_label (this_tf.region, this_tf.eh_label);
01375 honor_protect_cleanup_actions (state, &this_state, &this_tf);
01376 }
01377
01378
01379 if (this_tf.goto_queue_active > 1)
01380 qsort (this_tf.goto_queue, this_tf.goto_queue_active,
01381 sizeof (struct goto_queue_node), goto_queue_cmp);
01382
01383
01384
01385
01386
01387 if (this_tf.dest_array)
01388 ndests = VARRAY_ACTIVE_SIZE (this_tf.dest_array);
01389 else
01390 ndests = 0;
01391 ndests += this_tf.may_fallthru;
01392 ndests += this_tf.may_return;
01393 ndests += this_tf.may_throw;
01394
01395
01396 if (ndests == 0)
01397 *tp = TREE_OPERAND (*tp, 0);
01398
01399
01400
01401
01402 else if (!block_may_fallthru (TREE_OPERAND (*tp, 1)))
01403 lower_try_finally_nofallthru (state, &this_tf);
01404
01405
01406 else if (ndests == 1)
01407 lower_try_finally_onedest (state, &this_tf);
01408
01409 else if (decide_copy_try_finally (ndests, TREE_OPERAND (*tp, 1)))
01410 lower_try_finally_copy (state, &this_tf);
01411 else
01412 lower_try_finally_switch (state, &this_tf);
01413
01414
01415
01416 if (this_tf.fallthru_label)
01417 {
01418 tree x = build1 (LABEL_EXPR, void_type_node, this_tf.fallthru_label);
01419 append_to_statement_list (x, tp);
01420 }
01421
01422 if (this_tf.goto_queue)
01423 free (this_tf.goto_queue);
01424 }
01425
01426
01427
01428
01429
01430 static void
01431 lower_catch (struct leh_state *state, tree *tp)
01432 {
01433 struct eh_region *try_region;
01434 struct leh_state this_state;
01435 tree_stmt_iterator i;
01436 tree out_label;
01437
01438 try_region = gen_eh_region_try (state->cur_region);
01439 this_state.cur_region = try_region;
01440 this_state.prev_try = try_region;
01441 this_state.tf = state->tf;
01442
01443 lower_eh_constructs_1 (&this_state, &TREE_OPERAND (*tp, 0));
01444
01445 if (!get_eh_region_may_contain_throw (try_region))
01446 {
01447 *tp = TREE_OPERAND (*tp, 0);
01448 return;
01449 }
01450
01451 out_label = NULL;
01452 for (i = tsi_start (TREE_OPERAND (*tp, 1)); !tsi_end_p (i); )
01453 {
01454 struct eh_region *catch_region;
01455 tree catch, x, eh_label;
01456
01457 catch = tsi_stmt (i);
01458 catch_region = gen_eh_region_catch (try_region, CATCH_TYPES (catch));
01459
01460 this_state.cur_region = catch_region;
01461 this_state.prev_try = state->prev_try;
01462 lower_eh_constructs_1 (&this_state, &CATCH_BODY (catch));
01463
01464 eh_label = create_artificial_label ();
01465 set_eh_region_tree_label (catch_region, eh_label);
01466
01467 x = build1 (LABEL_EXPR, void_type_node, eh_label);
01468 tsi_link_before (&i, x, TSI_SAME_STMT);
01469
01470 if (block_may_fallthru (CATCH_BODY (catch)))
01471 {
01472 if (!out_label)
01473 out_label = create_artificial_label ();
01474
01475 x = build1 (GOTO_EXPR, void_type_node, out_label);
01476 append_to_statement_list (x, &CATCH_BODY (catch));
01477 }
01478
01479 tsi_link_before (&i, CATCH_BODY (catch), TSI_SAME_STMT);
01480 tsi_delink (&i);
01481 }
01482
01483 frob_into_branch_around (tp, NULL, out_label);
01484 }
01485
01486
01487
01488
01489
01490 static void
01491 lower_eh_filter (struct leh_state *state, tree *tp)
01492 {
01493 struct leh_state this_state;
01494 struct eh_region *this_region;
01495 tree inner = expr_first (TREE_OPERAND (*tp, 1));
01496 tree eh_label;
01497
01498 if (EH_FILTER_MUST_NOT_THROW (inner))
01499 this_region = gen_eh_region_must_not_throw (state->cur_region);
01500 else
01501 this_region = gen_eh_region_allowed (state->cur_region,
01502 EH_FILTER_TYPES (inner));
01503 this_state = *state;
01504 this_state.cur_region = this_region;
01505
01506 lower_eh_constructs_1 (&this_state, &TREE_OPERAND (*tp, 0));
01507
01508 if (!get_eh_region_may_contain_throw (this_region))
01509 {
01510 *tp = TREE_OPERAND (*tp, 0);
01511 return;
01512 }
01513
01514 lower_eh_constructs_1 (state, &EH_FILTER_FAILURE (inner));
01515 TREE_OPERAND (*tp, 1) = EH_FILTER_FAILURE (inner);
01516
01517 eh_label = create_artificial_label ();
01518 set_eh_region_tree_label (this_region, eh_label);
01519
01520 frob_into_branch_around (tp, eh_label, NULL);
01521 }
01522
01523
01524
01525
01526 static void
01527 lower_cleanup (struct leh_state *state, tree *tp)
01528 {
01529 struct leh_state this_state;
01530 struct eh_region *this_region;
01531 struct leh_tf_state fake_tf;
01532
01533
01534 if (!flag_exceptions)
01535 {
01536 *tp = TREE_OPERAND (*tp, 0);
01537 lower_eh_constructs_1 (state, tp);
01538 return;
01539 }
01540
01541 this_region = gen_eh_region_cleanup (state->cur_region, state->prev_try);
01542 this_state = *state;
01543 this_state.cur_region = this_region;
01544
01545 lower_eh_constructs_1 (&this_state, &TREE_OPERAND (*tp, 0));
01546
01547 if (!get_eh_region_may_contain_throw (this_region))
01548 {
01549 *tp = TREE_OPERAND (*tp, 0);
01550 return;
01551 }
01552
01553
01554
01555 memset (&fake_tf, 0, sizeof (fake_tf));
01556 fake_tf.top_p = tp;
01557 fake_tf.outer = state;
01558 fake_tf.region = this_region;
01559 fake_tf.may_fallthru = block_may_fallthru (TREE_OPERAND (*tp, 0));
01560 fake_tf.may_throw = true;
01561
01562 fake_tf.eh_label = create_artificial_label ();
01563 set_eh_region_tree_label (this_region, fake_tf.eh_label);
01564
01565 honor_protect_cleanup_actions (state, NULL, &fake_tf);
01566
01567 if (fake_tf.may_throw)
01568 {
01569
01570
01571 lower_eh_constructs_1 (state, &TREE_OPERAND (*tp, 1));
01572 frob_into_branch_around (tp, fake_tf.eh_label, fake_tf.fallthru_label);
01573 }
01574 else
01575 {
01576
01577
01578
01579 *tp = TREE_OPERAND (*tp, 0);
01580 if (fake_tf.fallthru_label)
01581 {
01582 tree x = build1 (LABEL_EXPR, void_type_node, fake_tf.fallthru_label);
01583 append_to_statement_list (x, tp);
01584 }
01585 }
01586 }
01587
01588
01589
01590 static void
01591 lower_eh_constructs_1 (struct leh_state *state, tree *tp)
01592 {
01593 tree_stmt_iterator i;
01594 tree t = *tp;
01595
01596 switch (TREE_CODE (t))
01597 {
01598 case COND_EXPR:
01599 lower_eh_constructs_1 (state, &COND_EXPR_THEN (t));
01600 lower_eh_constructs_1 (state, &COND_EXPR_ELSE (t));
01601 break;
01602
01603 case CALL_EXPR:
01604
01605 if (state->cur_region && tree_could_throw_p (t))
01606 {
01607 record_stmt_eh_region (state->cur_region, t);
01608 note_eh_region_may_contain_throw (state->cur_region);
01609 }
01610 break;
01611
01612 case MODIFY_EXPR:
01613
01614 if (state->cur_region && tree_could_throw_p (t))
01615 {
01616 tree op;
01617
01618 record_stmt_eh_region (state->cur_region, t);
01619 note_eh_region_may_contain_throw (state->cur_region);
01620
01621
01622
01623
01624 op = get_call_expr_in (t);
01625 if (op)
01626 record_stmt_eh_region (state->cur_region, op);
01627 }
01628 break;
01629
01630 case GOTO_EXPR:
01631 case RETURN_EXPR:
01632 maybe_record_in_goto_queue (state, t);
01633 break;
01634 case SWITCH_EXPR:
01635 verify_norecord_switch_expr (state, t);
01636 break;
01637
01638 case TRY_FINALLY_EXPR:
01639 lower_try_finally (state, tp);
01640 break;
01641
01642 case TRY_CATCH_EXPR:
01643 i = tsi_start (TREE_OPERAND (t, 1));
01644 switch (TREE_CODE (tsi_stmt (i)))
01645 {
01646 case CATCH_EXPR:
01647 lower_catch (state, tp);
01648 break;
01649 case EH_FILTER_EXPR:
01650 lower_eh_filter (state, tp);
01651 break;
01652 default:
01653 lower_cleanup (state, tp);
01654 break;
01655 }
01656 break;
01657
01658 case STATEMENT_LIST:
01659 for (i = tsi_start (t); !tsi_end_p (i); )
01660 {
01661 lower_eh_constructs_1 (state, tsi_stmt_ptr (i));
01662 t = tsi_stmt (i);
01663 if (TREE_CODE (t) == STATEMENT_LIST)
01664 {
01665 tsi_link_before (&i, t, TSI_SAME_STMT);
01666 tsi_delink (&i);
01667 }
01668 else
01669 tsi_next (&i);
01670 }
01671 break;
01672
01673 default:
01674
01675
01676 break;
01677 }
01678 }
01679
01680 static void
01681 lower_eh_constructs (void)
01682 {
01683 struct leh_state null_state;
01684 tree *tp = &DECL_SAVED_TREE (current_function_decl);
01685
01686 finally_tree = htab_create (31, struct_ptr_hash, struct_ptr_eq, free);
01687 throw_stmt_table = htab_create_ggc (31, struct_ptr_hash, struct_ptr_eq,
01688 ggc_free);
01689
01690 collect_finally_tree (*tp, NULL);
01691
01692 memset (&null_state, 0, sizeof (null_state));
01693 lower_eh_constructs_1 (&null_state, tp);
01694
01695 htab_delete (finally_tree);
01696
01697 collect_eh_region_array ();
01698 }
01699
01700 struct tree_opt_pass pass_lower_eh =
01701 {
01702 "eh",
01703 NULL,
01704 lower_eh_constructs,
01705 NULL,
01706 NULL,
01707 0,
01708 TV_TREE_EH,
01709 PROP_gimple_lcf,
01710 PROP_gimple_leh,
01711 PROP_gimple_lcf,
01712 0,
01713 TODO_dump_func,
01714 0
01715 };
01716
01717
01718
01719
01720 static void
01721 make_eh_edge (struct eh_region *region, void *data)
01722 {
01723 tree stmt, lab;
01724 basic_block src, dst;
01725
01726 stmt = data;
01727 lab = get_eh_region_tree_label (region);
01728
01729 src = bb_for_stmt (stmt);
01730 dst = label_to_block (lab);
01731
01732 make_edge (src, dst, EDGE_ABNORMAL | EDGE_EH);
01733 }
01734
01735 void
01736 make_eh_edges (tree stmt)
01737 {
01738 int region_nr;
01739 bool is_resx;
01740
01741 if (TREE_CODE (stmt) == RESX_EXPR)
01742 {
01743 region_nr = TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0));
01744 is_resx = true;
01745 }
01746 else
01747 {
01748 region_nr = lookup_stmt_eh_region (stmt);
01749 if (region_nr < 0)
01750 return;
01751 is_resx = false;
01752 }
01753
01754 foreach_reachable_handler (region_nr, is_resx, make_eh_edge, stmt);
01755 }
01756
01757
01758
01759
01760
01761
01762
01763 bool
01764 tree_could_trap_p (tree expr)
01765 {
01766 enum tree_code code = TREE_CODE (expr);
01767 bool honor_nans = false;
01768 bool honor_snans = false;
01769 bool fp_operation = false;
01770 bool honor_trapv = false;
01771 tree t, base, idx;
01772
01773 if (TREE_CODE_CLASS (code) == tcc_comparison
01774 || TREE_CODE_CLASS (code) == tcc_unary
01775 || TREE_CODE_CLASS (code) == tcc_binary)
01776 {
01777 t = TREE_TYPE (expr);
01778 fp_operation = FLOAT_TYPE_P (t);
01779 if (fp_operation)
01780 {
01781 honor_nans = flag_trapping_math && !flag_finite_math_only;
01782 honor_snans = flag_signaling_nans != 0;
01783 }
01784 else if (INTEGRAL_TYPE_P (t) && TYPE_TRAP_SIGNED (t))
01785 honor_trapv = true;
01786 }
01787
01788 restart:
01789 switch (code)
01790 {
01791 case COMPONENT_REF:
01792 case REALPART_EXPR:
01793 case IMAGPART_EXPR:
01794 case BIT_FIELD_REF:
01795 case WITH_SIZE_EXPR:
01796 expr = TREE_OPERAND (expr, 0);
01797 code = TREE_CODE (expr);
01798 goto restart;
01799
01800 case ARRAY_RANGE_REF:
01801
01802
01803 if (!TREE_THIS_NOTRAP (expr))
01804 return true;
01805
01806 base = TREE_OPERAND (expr, 0);
01807 return tree_could_trap_p (base);
01808
01809 case ARRAY_REF:
01810 base = TREE_OPERAND (expr, 0);
01811 idx = TREE_OPERAND (expr, 1);
01812 if (tree_could_trap_p (base))
01813 return true;
01814
01815 if (TREE_THIS_NOTRAP (expr))
01816 return false;
01817
01818 return !in_array_bounds_p (expr);
01819
01820 case INDIRECT_REF:
01821 case ALIGN_INDIRECT_REF:
01822 case MISALIGNED_INDIRECT_REF:
01823 return !TREE_THIS_NOTRAP (expr);
01824
01825 case ASM_EXPR:
01826 return TREE_THIS_VOLATILE (expr);
01827
01828 case TRUNC_DIV_EXPR:
01829 case CEIL_DIV_EXPR:
01830 case FLOOR_DIV_EXPR:
01831 case ROUND_DIV_EXPR:
01832 case EXACT_DIV_EXPR:
01833 case CEIL_MOD_EXPR:
01834 case FLOOR_MOD_EXPR:
01835 case ROUND_MOD_EXPR:
01836 case TRUNC_MOD_EXPR:
01837 case RDIV_EXPR:
01838 if (honor_snans || honor_trapv)
01839 return true;
01840 if (fp_operation && flag_trapping_math)
01841 return true;
01842 t = TREE_OPERAND (expr, 1);
01843 if (!TREE_CONSTANT (t) || integer_zerop (t))
01844 return true;
01845 return false;
01846
01847 case LT_EXPR:
01848 case LE_EXPR:
01849 case GT_EXPR:
01850 case GE_EXPR:
01851 case LTGT_EXPR:
01852
01853 return honor_nans;
01854
01855 case EQ_EXPR:
01856 case NE_EXPR:
01857 case UNORDERED_EXPR:
01858 case ORDERED_EXPR:
01859 case UNLT_EXPR:
01860 case UNLE_EXPR:
01861 case UNGT_EXPR:
01862 case UNGE_EXPR:
01863 case UNEQ_EXPR:
01864 return honor_snans;
01865
01866 case CONVERT_EXPR:
01867 case FIX_TRUNC_EXPR:
01868 case FIX_CEIL_EXPR:
01869 case FIX_FLOOR_EXPR:
01870 case FIX_ROUND_EXPR:
01871
01872 return honor_nans;
01873
01874 case NEGATE_EXPR:
01875 case ABS_EXPR:
01876 case CONJ_EXPR:
01877
01878 if (honor_trapv)
01879 return true;
01880 return false;
01881
01882 case PLUS_EXPR:
01883 case MINUS_EXPR:
01884 case MULT_EXPR:
01885
01886 if (fp_operation && flag_trapping_math)
01887 return true;
01888 if (honor_trapv)
01889 return true;
01890 return false;
01891
01892 case CALL_EXPR:
01893 t = get_callee_fndecl (expr);
01894
01895 if (!t || !DECL_P (t) || DECL_WEAK (t))
01896 return true;
01897 return false;
01898
01899 default:
01900
01901 if (fp_operation && flag_trapping_math)
01902 return true;
01903 return false;
01904 }
01905 }
01906
01907 bool
01908 tree_could_throw_p (tree t)
01909 {
01910 if (!flag_exceptions)
01911 return false;
01912 if (TREE_CODE (t) == MODIFY_EXPR)
01913 {
01914 if (flag_non_call_exceptions
01915 && tree_could_trap_p (TREE_OPERAND (t, 0)))
01916 return true;
01917 t = TREE_OPERAND (t, 1);
01918 }
01919
01920 if (TREE_CODE (t) == WITH_SIZE_EXPR)
01921 t = TREE_OPERAND (t, 0);
01922 if (TREE_CODE (t) == CALL_EXPR)
01923 return (call_expr_flags (t) & ECF_NOTHROW) == 0;
01924 if (flag_non_call_exceptions)
01925 return tree_could_trap_p (t);
01926 return false;
01927 }
01928
01929 bool
01930 tree_can_throw_internal (tree stmt)
01931 {
01932 int region_nr = lookup_stmt_eh_region (stmt);
01933 if (region_nr < 0)
01934 return false;
01935 return can_throw_internal_1 (region_nr);
01936 }
01937
01938 bool
01939 tree_can_throw_external (tree stmt)
01940 {
01941 int region_nr = lookup_stmt_eh_region (stmt);
01942 if (region_nr < 0)
01943 return false;
01944 return can_throw_external_1 (region_nr);
01945 }
01946
01947 bool
01948 maybe_clean_eh_stmt (tree stmt)
01949 {
01950 if (!tree_could_throw_p (stmt))
01951 if (remove_stmt_from_eh_region (stmt))
01952 return true;
01953 return false;
01954 }
01955
01956 #include "gt-tree-eh.h"