Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-eh.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
1 /* Exception handling semantics and decomposition for trees. | 1 /* Exception handling semantics and decomposition for trees. |
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 | 2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify | 7 GCC is free software; you can redistribute it and/or modify |
33 #include "tree-iterator.h" | 33 #include "tree-iterator.h" |
34 #include "tree-pass.h" | 34 #include "tree-pass.h" |
35 #include "timevar.h" | 35 #include "timevar.h" |
36 #include "langhooks.h" | 36 #include "langhooks.h" |
37 #include "ggc.h" | 37 #include "ggc.h" |
38 #include "toplev.h" | 38 #include "diagnostic-core.h" |
39 #include "gimple.h" | 39 #include "gimple.h" |
40 #include "target.h" | 40 #include "target.h" |
41 | 41 |
42 /* In some instances a tree and a gimple need to be stored in a same table, | 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. */ | 43 i.e. in hash tables. This is a structure to do this. */ |
94 struct throw_stmt_node *n; | 94 struct throw_stmt_node *n; |
95 void **slot; | 95 void **slot; |
96 | 96 |
97 gcc_assert (num != 0); | 97 gcc_assert (num != 0); |
98 | 98 |
99 n = GGC_NEW (struct throw_stmt_node); | 99 n = ggc_alloc_throw_stmt_node (); |
100 n->stmt = t; | 100 n->stmt = t; |
101 n->lp_nr = num; | 101 n->lp_nr = num; |
102 | 102 |
103 if (!get_eh_throw_stmt_table (ifun)) | 103 if (!get_eh_throw_stmt_table (ifun)) |
104 set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_hash, | 104 set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_hash, |
845 call to a function which itself may contain a throw. */ | 845 call to a function which itself may contain a throw. */ |
846 | 846 |
847 static void | 847 static void |
848 note_eh_region_may_contain_throw (eh_region region) | 848 note_eh_region_may_contain_throw (eh_region region) |
849 { | 849 { |
850 while (!bitmap_bit_p (eh_region_may_contain_throw_map, region->index)) | 850 while (bitmap_set_bit (eh_region_may_contain_throw_map, region->index)) |
851 { | 851 { |
852 bitmap_set_bit (eh_region_may_contain_throw_map, region->index); | |
853 region = region->outer; | 852 region = region->outer; |
854 if (region == NULL) | 853 if (region == NULL) |
855 break; | 854 break; |
856 } | 855 } |
857 } | 856 } |
949 } | 948 } |
950 } | 949 } |
951 return label; | 950 return label; |
952 } | 951 } |
953 | 952 |
954 /* A subroutine of lower_try_finally. If lang_protect_cleanup_actions | 953 /* A subroutine of lower_try_finally. If the eh_protect_cleanup_actions |
955 returns non-null, then the language requires that the exception path out | 954 langhook returns non-null, then the language requires that the exception |
956 of a try_finally be treated specially. To wit: the code within the | 955 path out of a try_finally be treated specially. To wit: the code within |
957 finally block may not itself throw an exception. We have two choices here. | 956 the finally block may not itself throw an exception. We have two choices |
958 First we can duplicate the finally block and wrap it in a must_not_throw | 957 here. First we can duplicate the finally block and wrap it in a |
959 region. Second, we can generate code like | 958 must_not_throw region. Second, we can generate code like |
960 | 959 |
961 try { | 960 try { |
962 finally_block; | 961 finally_block; |
963 } catch { | 962 } catch { |
964 if (fintmp == eh_edge) | 963 if (fintmp == eh_edge) |
981 bool finally_may_fallthru; | 980 bool finally_may_fallthru; |
982 gimple_seq finally; | 981 gimple_seq finally; |
983 gimple x; | 982 gimple x; |
984 | 983 |
985 /* First check for nothing to do. */ | 984 /* First check for nothing to do. */ |
986 if (lang_protect_cleanup_actions == NULL) | 985 if (lang_hooks.eh_protect_cleanup_actions == NULL) |
987 return; | 986 return; |
988 protect_cleanup_actions = lang_protect_cleanup_actions (); | 987 protect_cleanup_actions = lang_hooks.eh_protect_cleanup_actions (); |
989 if (protect_cleanup_actions == NULL) | 988 if (protect_cleanup_actions == NULL) |
990 return; | 989 return; |
991 | 990 |
992 finally = gimple_try_cleanup (tf->top_p); | 991 finally = gimple_try_cleanup (tf->top_p); |
993 finally_may_fallthru = gimple_seq_may_fallthru (finally); | 992 finally_may_fallthru = gimple_seq_may_fallthru (finally); |
1875 gimple_call_set_arg (stmt, 0, nr); | 1874 gimple_call_set_arg (stmt, 0, nr); |
1876 } | 1875 } |
1877 else | 1876 else |
1878 { | 1877 { |
1879 /* The user has dome something silly. Remove it. */ | 1878 /* The user has dome something silly. Remove it. */ |
1880 rhs = build_int_cst (ptr_type_node, 0); | 1879 rhs = null_pointer_node; |
1881 goto do_replace; | 1880 goto do_replace; |
1882 } | 1881 } |
1883 break; | 1882 break; |
1884 | 1883 |
1885 case BUILT_IN_EH_FILTER: | 1884 case BUILT_IN_EH_FILTER: |
2333 return true; | 2332 return true; |
2334 if (honor_trapv) | 2333 if (honor_trapv) |
2335 return true; | 2334 return true; |
2336 return false; | 2335 return false; |
2337 | 2336 |
2337 case COMPLEX_EXPR: | |
2338 case CONSTRUCTOR: | |
2339 /* Constructing an object cannot trap. */ | |
2340 return false; | |
2341 | |
2338 default: | 2342 default: |
2339 /* Any floating arithmetic may trap. */ | 2343 /* Any floating arithmetic may trap. */ |
2340 if (fp_operation && flag_trapping_math) | 2344 if (fp_operation && flag_trapping_math) |
2341 return true; | 2345 return true; |
2342 | 2346 |
2403 | 2407 |
2404 restart: | 2408 restart: |
2405 switch (code) | 2409 switch (code) |
2406 { | 2410 { |
2407 case TARGET_MEM_REF: | 2411 case TARGET_MEM_REF: |
2408 /* For TARGET_MEM_REFs use the information based on the original | 2412 if (TREE_CODE (TMR_BASE (expr)) == ADDR_EXPR |
2409 reference. */ | 2413 && !TMR_INDEX (expr) && !TMR_INDEX2 (expr)) |
2410 expr = TMR_ORIGINAL (expr); | 2414 return false; |
2411 code = TREE_CODE (expr); | 2415 return !TREE_THIS_NOTRAP (expr); |
2412 goto restart; | |
2413 | 2416 |
2414 case COMPONENT_REF: | 2417 case COMPONENT_REF: |
2415 case REALPART_EXPR: | 2418 case REALPART_EXPR: |
2416 case IMAGPART_EXPR: | 2419 case IMAGPART_EXPR: |
2417 case BIT_FIELD_REF: | 2420 case BIT_FIELD_REF: |
2435 return true; | 2438 return true; |
2436 if (TREE_THIS_NOTRAP (expr)) | 2439 if (TREE_THIS_NOTRAP (expr)) |
2437 return false; | 2440 return false; |
2438 return !in_array_bounds_p (expr); | 2441 return !in_array_bounds_p (expr); |
2439 | 2442 |
2443 case MEM_REF: | |
2444 if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR) | |
2445 return false; | |
2446 /* Fallthru. */ | |
2440 case INDIRECT_REF: | 2447 case INDIRECT_REF: |
2441 case ALIGN_INDIRECT_REF: | |
2442 case MISALIGNED_INDIRECT_REF: | |
2443 return !TREE_THIS_NOTRAP (expr); | 2448 return !TREE_THIS_NOTRAP (expr); |
2444 | 2449 |
2445 case ASM_EXPR: | 2450 case ASM_EXPR: |
2446 return TREE_THIS_VOLATILE (expr); | 2451 return TREE_THIS_VOLATILE (expr); |
2447 | 2452 |
2524 case GIMPLE_CALL: | 2529 case GIMPLE_CALL: |
2525 return !gimple_call_nothrow_p (stmt); | 2530 return !gimple_call_nothrow_p (stmt); |
2526 | 2531 |
2527 case GIMPLE_ASSIGN: | 2532 case GIMPLE_ASSIGN: |
2528 case GIMPLE_COND: | 2533 case GIMPLE_COND: |
2529 if (!flag_non_call_exceptions) | 2534 if (!cfun->can_throw_non_call_exceptions) |
2530 return false; | 2535 return false; |
2531 return stmt_could_throw_1_p (stmt); | 2536 return stmt_could_throw_1_p (stmt); |
2532 | 2537 |
2533 case GIMPLE_ASM: | 2538 case GIMPLE_ASM: |
2534 if (!flag_non_call_exceptions) | 2539 if (!cfun->can_throw_non_call_exceptions) |
2535 return false; | 2540 return false; |
2536 return gimple_asm_volatile_p (stmt); | 2541 return gimple_asm_volatile_p (stmt); |
2537 | 2542 |
2538 default: | 2543 default: |
2539 return false; | 2544 return false; |
2548 { | 2553 { |
2549 if (!flag_exceptions) | 2554 if (!flag_exceptions) |
2550 return false; | 2555 return false; |
2551 if (TREE_CODE (t) == MODIFY_EXPR) | 2556 if (TREE_CODE (t) == MODIFY_EXPR) |
2552 { | 2557 { |
2553 if (flag_non_call_exceptions | 2558 if (cfun->can_throw_non_call_exceptions |
2554 && tree_could_trap_p (TREE_OPERAND (t, 0))) | 2559 && tree_could_trap_p (TREE_OPERAND (t, 0))) |
2555 return true; | 2560 return true; |
2556 t = TREE_OPERAND (t, 1); | 2561 t = TREE_OPERAND (t, 1); |
2557 } | 2562 } |
2558 | 2563 |
2559 if (TREE_CODE (t) == WITH_SIZE_EXPR) | 2564 if (TREE_CODE (t) == WITH_SIZE_EXPR) |
2560 t = TREE_OPERAND (t, 0); | 2565 t = TREE_OPERAND (t, 0); |
2561 if (TREE_CODE (t) == CALL_EXPR) | 2566 if (TREE_CODE (t) == CALL_EXPR) |
2562 return (call_expr_flags (t) & ECF_NOTHROW) == 0; | 2567 return (call_expr_flags (t) & ECF_NOTHROW) == 0; |
2563 if (flag_non_call_exceptions) | 2568 if (cfun->can_throw_non_call_exceptions) |
2564 return tree_could_trap_p (t); | 2569 return tree_could_trap_p (t); |
2565 return false; | 2570 return false; |
2566 } | 2571 } |
2567 | 2572 |
2568 /* Return true if STMT can throw an exception that is not caught within | 2573 /* Return true if STMT can throw an exception that is not caught within |
3545 } | 3550 } |
3546 | 3551 |
3547 /* If we did find the corresponding PHI, copy those inputs. */ | 3552 /* If we did find the corresponding PHI, copy those inputs. */ |
3548 if (ophi) | 3553 if (ophi) |
3549 { | 3554 { |
3555 /* If NOP is used somewhere else beyond phis in new_bb, give up. */ | |
3556 if (!has_single_use (nop)) | |
3557 { | |
3558 imm_use_iterator imm_iter; | |
3559 use_operand_p use_p; | |
3560 | |
3561 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, nop) | |
3562 { | |
3563 if (!gimple_debug_bind_p (USE_STMT (use_p)) | |
3564 && (gimple_code (USE_STMT (use_p)) != GIMPLE_PHI | |
3565 || gimple_bb (USE_STMT (use_p)) != new_bb)) | |
3566 goto fail; | |
3567 } | |
3568 } | |
3550 bitmap_set_bit (ophi_handled, SSA_NAME_VERSION (nop)); | 3569 bitmap_set_bit (ophi_handled, SSA_NAME_VERSION (nop)); |
3551 FOR_EACH_EDGE (e, ei, old_bb->preds) | 3570 FOR_EACH_EDGE (e, ei, old_bb->preds) |
3552 { | 3571 { |
3553 location_t oloc; | 3572 location_t oloc; |
3554 tree oop; | 3573 tree oop; |
3663 static bool | 3682 static bool |
3664 cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp) | 3683 cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp) |
3665 { | 3684 { |
3666 gimple_stmt_iterator gsi; | 3685 gimple_stmt_iterator gsi; |
3667 tree lab; | 3686 tree lab; |
3687 edge_iterator ei; | |
3688 edge e; | |
3668 | 3689 |
3669 /* We really ought not have totally lost everything following | 3690 /* We really ought not have totally lost everything following |
3670 a landing pad label. Given that BB is empty, there had better | 3691 a landing pad label. Given that BB is empty, there had better |
3671 be a successor. */ | 3692 be a successor. */ |
3672 gcc_assert (e_out != NULL); | 3693 gcc_assert (e_out != NULL); |
3685 lp_nr = EH_LANDING_PAD_NR (lab); | 3706 lp_nr = EH_LANDING_PAD_NR (lab); |
3686 if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region) | 3707 if (lp_nr && get_eh_region_from_lp_number (lp_nr) != lp->region) |
3687 return false; | 3708 return false; |
3688 } | 3709 } |
3689 | 3710 |
3711 /* The destination block must not be a regular successor for any | |
3712 of the preds of the landing pad. Thus, avoid turning | |
3713 <..> | |
3714 | \ EH | |
3715 | <..> | |
3716 | / | |
3717 <..> | |
3718 into | |
3719 <..> | |
3720 | | EH | |
3721 <..> | |
3722 which CFG verification would choke on. See PR45172. */ | |
3723 FOR_EACH_EDGE (e, ei, bb->preds) | |
3724 if (find_edge (e->src, e_out->dest)) | |
3725 return false; | |
3726 | |
3690 /* Attempt to move the PHIs into the successor block. */ | 3727 /* Attempt to move the PHIs into the successor block. */ |
3691 if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, false)) | 3728 if (cleanup_empty_eh_merge_phis (e_out->dest, bb, e_out, false)) |
3692 { | 3729 { |
3693 if (dump_file && (dump_flags & TDF_DETAILS)) | 3730 if (dump_file && (dump_flags & TDF_DETAILS)) |
3694 fprintf (dump_file, | 3731 fprintf (dump_file, |
3697 lp->index, e_out->dest->index); | 3734 lp->index, e_out->dest->index); |
3698 return true; | 3735 return true; |
3699 } | 3736 } |
3700 | 3737 |
3701 return false; | 3738 return false; |
3739 } | |
3740 | |
3741 /* Return true if edge E_FIRST is part of an empty infinite loop | |
3742 or leads to such a loop through a series of single successor | |
3743 empty bbs. */ | |
3744 | |
3745 static bool | |
3746 infinite_empty_loop_p (edge e_first) | |
3747 { | |
3748 bool inf_loop = false; | |
3749 edge e; | |
3750 | |
3751 if (e_first->dest == e_first->src) | |
3752 return true; | |
3753 | |
3754 e_first->src->aux = (void *) 1; | |
3755 for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest)) | |
3756 { | |
3757 gimple_stmt_iterator gsi; | |
3758 if (e->dest->aux) | |
3759 { | |
3760 inf_loop = true; | |
3761 break; | |
3762 } | |
3763 e->dest->aux = (void *) 1; | |
3764 gsi = gsi_after_labels (e->dest); | |
3765 if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) | |
3766 gsi_next_nondebug (&gsi); | |
3767 if (!gsi_end_p (gsi)) | |
3768 break; | |
3769 } | |
3770 e_first->src->aux = NULL; | |
3771 for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest)) | |
3772 e->dest->aux = NULL; | |
3773 | |
3774 return inf_loop; | |
3702 } | 3775 } |
3703 | 3776 |
3704 /* Examine the block associated with LP to determine if it's an empty | 3777 /* Examine the block associated with LP to determine if it's an empty |
3705 handler for its EH region. If so, attempt to redirect EH edges to | 3778 handler for its EH region. If so, attempt to redirect EH edges to |
3706 an outer region. Return true the CFG was updated in any way. This | 3779 an outer region. Return true the CFG was updated in any way. This |
3736 if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) | 3809 if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) |
3737 gsi_next_nondebug (&gsi); | 3810 gsi_next_nondebug (&gsi); |
3738 | 3811 |
3739 /* If the block is totally empty, look for more unsplitting cases. */ | 3812 /* If the block is totally empty, look for more unsplitting cases. */ |
3740 if (gsi_end_p (gsi)) | 3813 if (gsi_end_p (gsi)) |
3741 return cleanup_empty_eh_unsplit (bb, e_out, lp); | 3814 { |
3815 /* For the degenerate case of an infinite loop bail out. */ | |
3816 if (infinite_empty_loop_p (e_out)) | |
3817 return false; | |
3818 | |
3819 return cleanup_empty_eh_unsplit (bb, e_out, lp); | |
3820 } | |
3742 | 3821 |
3743 /* The block should consist only of a single RESX statement. */ | 3822 /* The block should consist only of a single RESX statement. */ |
3744 resx = gsi_stmt (gsi); | 3823 resx = gsi_stmt (gsi); |
3745 if (!is_gimple_resx (resx)) | 3824 if (!is_gimple_resx (resx)) |
3746 return false; | 3825 return false; |
3855 TODO: Push MUST_NOT_THROW regions to the root of the EH tree. | 3934 TODO: Push MUST_NOT_THROW regions to the root of the EH tree. |
3856 Unify those that have the same failure decl and locus. | 3935 Unify those that have the same failure decl and locus. |
3857 */ | 3936 */ |
3858 | 3937 |
3859 static unsigned int | 3938 static unsigned int |
3860 execute_cleanup_eh (void) | 3939 execute_cleanup_eh_1 (void) |
3861 { | 3940 { |
3862 /* Do this first: unsplit_all_eh and cleanup_all_empty_eh can die | 3941 /* Do this first: unsplit_all_eh and cleanup_all_empty_eh can die |
3863 looking up unreachable landing pads. */ | 3942 looking up unreachable landing pads. */ |
3864 remove_unreachable_handlers (); | 3943 remove_unreachable_handlers (); |
3865 | 3944 |
3887 return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals; | 3966 return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals; |
3888 } | 3967 } |
3889 } | 3968 } |
3890 | 3969 |
3891 return 0; | 3970 return 0; |
3971 } | |
3972 | |
3973 static unsigned int | |
3974 execute_cleanup_eh (void) | |
3975 { | |
3976 int ret = execute_cleanup_eh_1 (); | |
3977 | |
3978 /* If the function no longer needs an EH personality routine | |
3979 clear it. This exposes cross-language inlining opportunities | |
3980 and avoids references to a never defined personality routine. */ | |
3981 if (DECL_FUNCTION_PERSONALITY (current_function_decl) | |
3982 && function_needs_eh_personality (cfun) != eh_personality_lang) | |
3983 DECL_FUNCTION_PERSONALITY (current_function_decl) = NULL_TREE; | |
3984 | |
3985 return ret; | |
3892 } | 3986 } |
3893 | 3987 |
3894 static bool | 3988 static bool |
3895 gate_cleanup_eh (void) | 3989 gate_cleanup_eh (void) |
3896 { | 3990 { |
3916 }; | 4010 }; |
3917 | 4011 |
3918 /* Verify that BB containing STMT as the last statement, has precisely the | 4012 /* Verify that BB containing STMT as the last statement, has precisely the |
3919 edge that make_eh_edges would create. */ | 4013 edge that make_eh_edges would create. */ |
3920 | 4014 |
3921 bool | 4015 DEBUG_FUNCTION bool |
3922 verify_eh_edges (gimple stmt) | 4016 verify_eh_edges (gimple stmt) |
3923 { | 4017 { |
3924 basic_block bb = gimple_bb (stmt); | 4018 basic_block bb = gimple_bb (stmt); |
3925 eh_landing_pad lp = NULL; | 4019 eh_landing_pad lp = NULL; |
3926 int lp_nr; | 4020 int lp_nr; |
3977 return false; | 4071 return false; |
3978 } | 4072 } |
3979 | 4073 |
3980 /* Similarly, but handle GIMPLE_EH_DISPATCH specifically. */ | 4074 /* Similarly, but handle GIMPLE_EH_DISPATCH specifically. */ |
3981 | 4075 |
3982 bool | 4076 DEBUG_FUNCTION bool |
3983 verify_eh_dispatch_edge (gimple stmt) | 4077 verify_eh_dispatch_edge (gimple stmt) |
3984 { | 4078 { |
3985 eh_region r; | 4079 eh_region r; |
3986 eh_catch c; | 4080 eh_catch c; |
3987 basic_block src, dst; | 4081 basic_block src, dst; |