X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fexcept.h;h=ef511c9051579f83ea6503e4963b157f6ed11fd3;hb=6c3fbed5ae1cef081ec6bc15edc3f03a94ef2a76;hp=58461483cafdbe2fdc84979e5e47be30fb3541ff;hpb=8ec87476b56e0820cbb5c54007b91ad98859b176;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/except.h b/gcc/except.h index 58461483caf..ef511c90515 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -1,13 +1,13 @@ /* Exception Handling interface routines. - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Mike Stump . This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -16,62 +16,231 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +along with GCC; see the file COPYING3. If not see +. */ +#include "hashtab.h" +#include "vecprim.h" +#include "vecir.h" struct function; +struct eh_region_d; +struct pointer_map_t; + +/* The type of an exception region. */ +enum eh_region_type +{ + /* CLEANUP regions implement e.g. destructors run when exiting a block. + They can be generated from both GIMPLE_TRY_FINALLY and GIMPLE_TRY_CATCH + nodes. It is expected by the runtime that cleanup regions will *not* + resume normal program flow, but will continue propagation of the + exception. */ + ERT_CLEANUP, + + /* TRY regions implement catching an exception. The list of types associated + with the attached catch handlers is examined in order by the runtime and + control is transfered to the appropriate handler. Note that a NULL type + list is a catch-all handler, and that it will catch *all* exceptions + including those originating from a different language. */ + ERT_TRY, + + /* ALLOWED_EXCEPTIONS regions implement exception filtering, e.g. the + throw(type-list) specification that can be added to C++ functions. + The runtime examines the thrown exception vs the type list, and if + the exception does not match, transfers control to the handler. The + normal handler for C++ calls __cxa_call_unexpected. */ + ERT_ALLOWED_EXCEPTIONS, + + /* MUST_NOT_THROW regions prevent all exceptions from propagating. This + region type is used in C++ to surround destructors being run inside a + CLEANUP region. This differs from an ALLOWED_EXCEPTIONS region with + an empty type list in that the runtime is prepared to terminate the + program directly. We only generate code for MUST_NOT_THROW regions + along control paths that are already handling an exception within the + current function. */ + ERT_MUST_NOT_THROW +}; + + +/* A landing pad for a given exception region. Any transfer of control + from the EH runtime to the function happens at a landing pad. */ + +struct GTY(()) eh_landing_pad_d +{ + /* The linked list of all landing pads associated with the region. */ + struct eh_landing_pad_d *next_lp; + + /* The region with which this landing pad is associated. */ + struct eh_region_d *region; + + /* At the gimple level, the location to which control will be transfered + for this landing pad. There can be both EH and normal edges into the + block containing the post-landing-pad label. */ + tree post_landing_pad; + + /* At the rtl level, the location to which the runtime will transfer + control. This differs from the post-landing-pad in that the target's + EXCEPTION_RECEIVER pattern will be expanded here, as well as other + bookkeeping specific to exceptions. There must not be normal edges + into the block containing the landing-pad label. */ + rtx landing_pad; + + /* The index of this landing pad within fun->eh->lp_array. */ + int index; +}; + +/* A catch handler associated with an ERT_TRY region. */ + +struct GTY(()) eh_catch_d +{ + /* The double-linked list of all catch handlers for the region. */ + struct eh_catch_d *next_catch; + struct eh_catch_d *prev_catch; + + /* A TREE_LIST of runtime type objects that this catch handler + will catch, or NULL if all exceptions are caught. */ + tree type_list; + + /* A TREE_LIST of INTEGER_CSTs that correspond to the type_list entries, + having been mapped by assign_filter_values. These integers are to be + compared against the __builtin_eh_filter value. */ + tree filter_list; + + /* The code that should be executed if this catch handler matches the + thrown exception. This label is only maintained until + pass_lower_eh_dispatch, at which point it is cleared. */ + tree label; +}; + +/* Describes one exception region. */ + +struct GTY(()) eh_region_d +{ + /* The immediately surrounding region. */ + struct eh_region_d *outer; + + /* The list of immediately contained regions. */ + struct eh_region_d *inner; + struct eh_region_d *next_peer; + + /* The index of this region within fun->eh->region_array. */ + int index; + + /* Each region does exactly one thing. */ + enum eh_region_type type; + + /* Holds the action to perform based on the preceding type. */ + union eh_region_u { + struct eh_region_u_try { + /* The double-linked list of all catch handlers for this region. */ + struct eh_catch_d *first_catch; + struct eh_catch_d *last_catch; + } GTY ((tag ("ERT_TRY"))) eh_try; + + struct eh_region_u_allowed { + /* A TREE_LIST of runtime type objects allowed to pass. */ + tree type_list; + /* The code that should be executed if the thrown exception does + not match the type list. This label is only maintained until + pass_lower_eh_dispatch, at which point it is cleared. */ + tree label; + /* The integer that will be passed by the runtime to signal that + we should execute the code at LABEL. This integer is assigned + by assign_filter_values and is to be compared against the + __builtin_eh_filter value. */ + int filter; + } GTY ((tag ("ERT_ALLOWED_EXCEPTIONS"))) allowed; + + struct eh_region_u_must_not_throw { + /* A function decl to be invoked if this region is actually reachable + from within the function, rather than implementable from the runtime. + The normal way for this to happen is for there to be a CLEANUP region + contained within this MUST_NOT_THROW region. Note that if the + runtime handles the MUST_NOT_THROW region, we have no control over + what termination function is called; it will be decided by the + personality function in effect for this CIE. */ + tree failure_decl; + /* The location assigned to the call of FAILURE_DECL, if expanded. */ + location_t failure_loc; + } GTY ((tag ("ERT_MUST_NOT_THROW"))) must_not_throw; + } GTY ((desc ("%0.type"))) u; + + /* The list of landing pads associated with this region. */ + struct eh_landing_pad_d *landing_pads; + + /* EXC_PTR and FILTER values copied from the runtime for this region. + Each region gets its own psuedos so that if there are nested exceptions + we do not overwrite the values of the first exception. */ + rtx exc_ptr_reg, filter_reg; + + /* True if this region should use __cxa_end_cleanup instead + of _Unwind_Resume. */ + bool use_cxa_end_cleanup; +}; + +typedef struct eh_landing_pad_d *eh_landing_pad; +typedef struct eh_catch_d *eh_catch; +typedef struct eh_region_d *eh_region; + +DEF_VEC_P(eh_region); +DEF_VEC_ALLOC_P(eh_region, gc); +DEF_VEC_ALLOC_P(eh_region, heap); + +DEF_VEC_P(eh_landing_pad); +DEF_VEC_ALLOC_P(eh_landing_pad, gc); + + +/* The exception status for each function. */ + +struct GTY(()) eh_status +{ + /* The tree of all regions for this function. */ + eh_region region_tree; + + /* The same information as an indexable array. */ + VEC(eh_region,gc) *region_array; + + /* The landing pads as an indexable array. */ + VEC(eh_landing_pad,gc) *lp_array; + + /* At the gimple level, a mapping from gimple statement to landing pad + or must-not-throw region. See record_stmt_eh_region. */ + htab_t GTY((param_is (struct throw_stmt_node))) throw_stmt_table; + + /* All of the runtime type data used by the function. These objects + are emitted to the lang-specific-data-area for the function. */ + VEC(tree,gc) *ttype_data; + + /* The table of all action chains. These encode the eh_region tree in + a compact form for use by the runtime, and is also emitted to the + lang-specific-data-area. Note that the ARM EABI uses a different + format for the encoding than all other ports. */ + union eh_status_u { + VEC(tree,gc) * GTY((tag ("1"))) arm_eabi; + VEC(uchar,gc) * GTY((tag ("0"))) other; + } GTY ((desc ("targetm.arm_eabi_unwinder"))) ehspec_data; +}; -struct inline_remap; - -/* Per-function EH data. Used only in except.c, but GC and others - manipulate pointers to the opaque type. */ -struct eh_status; - -/* Internal structure describing a region. */ -struct eh_region; /* Test: is exception handling turned on? */ extern int doing_eh (int); -/* Note that the current EH region (if any) may contain a throw, or a - call to a function which itself may contain a throw. */ -extern void note_eh_region_may_contain_throw (struct eh_region *); -extern void note_current_region_may_contain_throw (void); - /* Invokes CALLBACK for every exception handler label. Only used by old loop hackery; should not be used by new code. */ extern void for_each_eh_label (void (*) (rtx)); -/* Invokes CALLBACK for every exception region in the current function. */ -extern void for_each_eh_region (void (*) (struct eh_region *)); - -/* Determine if the given INSN can throw an exception. */ -extern bool can_throw_internal_1 (int); -extern bool can_throw_internal (rtx); -extern bool can_throw_external_1 (int); -extern bool can_throw_external (rtx); - -/* Set TREE_NOTHROW and cfun->all_throwers_are_sibcalls. */ -extern void set_nothrow_function_flags (void); - -/* After initial rtl generation, call back to finish generating - exception support code. */ -extern void finish_eh_generation (void); - extern void init_eh (void); extern void init_eh_for_function (void); -extern rtx reachable_handlers (rtx); -extern void maybe_remove_eh_handler (rtx); +extern void remove_eh_landing_pad (eh_landing_pad); +extern void remove_eh_handler (eh_region); -extern void convert_from_eh_region_ranges (void); -extern void convert_to_eh_region_ranges (void); -extern void find_exception_handler_labels (void); extern bool current_function_has_exception_handlers (void); -extern void output_function_exception_table (void); +extern void output_function_exception_table (const char *); +extern rtx expand_builtin_eh_pointer (tree); +extern rtx expand_builtin_eh_filter (tree); +extern rtx expand_builtin_eh_copy_values (tree); extern void expand_builtin_unwind_init (void); extern rtx expand_builtin_eh_return_data_regno (tree); extern rtx expand_builtin_extract_return_addr (tree); @@ -81,62 +250,65 @@ extern rtx expand_builtin_dwarf_sp_column (void); extern void expand_builtin_eh_return (tree, tree); extern void expand_eh_return (void); extern rtx expand_builtin_extend_pointer (tree); -extern rtx get_exception_pointer (struct function *); -extern rtx get_exception_filter (struct function *); -extern int duplicate_eh_regions (struct function *, struct inline_remap *); -extern int check_handled (tree, tree); + +typedef tree (*duplicate_eh_regions_map) (tree, void *); +extern struct pointer_map_t *duplicate_eh_regions + (struct function *, eh_region, int, duplicate_eh_regions_map, void *); extern void sjlj_emit_function_exit_after (rtx); -extern struct eh_region *gen_eh_region_cleanup (struct eh_region *, - struct eh_region *); -extern struct eh_region *gen_eh_region_try (struct eh_region *); -extern struct eh_region *gen_eh_region_catch (struct eh_region *, tree); -extern struct eh_region *gen_eh_region_allowed (struct eh_region *, tree); -extern struct eh_region *gen_eh_region_must_not_throw (struct eh_region *); -extern int get_eh_region_number (struct eh_region *); -extern bool get_eh_region_may_contain_throw (struct eh_region *); -extern tree get_eh_region_tree_label (struct eh_region *); -extern void set_eh_region_tree_label (struct eh_region *, tree); +extern eh_region gen_eh_region_cleanup (eh_region); +extern eh_region gen_eh_region_try (eh_region); +extern eh_region gen_eh_region_allowed (eh_region, tree); +extern eh_region gen_eh_region_must_not_throw (eh_region); + +extern eh_catch gen_eh_region_catch (eh_region, tree); +extern eh_landing_pad gen_eh_landing_pad (eh_region); + +extern eh_region get_eh_region_from_number_fn (struct function *, int); +extern eh_region get_eh_region_from_number (int); +extern eh_landing_pad get_eh_landing_pad_from_number_fn (struct function*,int); +extern eh_landing_pad get_eh_landing_pad_from_number (int); +extern eh_region get_eh_region_from_lp_number_fn (struct function *, int); +extern eh_region get_eh_region_from_lp_number (int); + +extern eh_region eh_region_outermost (struct function *, eh_region, eh_region); -extern void foreach_reachable_handler (int, bool, - void (*) (struct eh_region *, void *), - void *); +extern void make_reg_eh_region_note (rtx insn, int ecf_flags, int lp_nr); +extern void make_reg_eh_region_note_nothrow_nononlocal (rtx); -extern void collect_eh_region_array (void); -extern void expand_resx_expr (tree); +extern void verify_eh_tree (struct function *); +extern void dump_eh_tree (FILE *, struct function *); +void debug_eh_tree (struct function *); +extern void add_type_for_runtime (tree); +extern tree lookup_type_for_runtime (tree); +extern void assign_filter_values (void); -/* tree-eh.c */ -extern int lookup_stmt_eh_region (tree); +extern eh_region get_eh_region_from_rtx (const_rtx); +extern eh_landing_pad get_eh_landing_pad_from_rtx (const_rtx); -/* If non-NULL, this is a function that returns an expression to be +/* If non-NULL, this is a function that returns a function decl to be executed if an unhandled exception is propagated out of a cleanup region. For example, in C++, an exception thrown by a destructor during stack unwinding is required to result in a call to `std::terminate', so the C++ version of this function returns a - CALL_EXPR for `std::terminate'. */ + FUNCTION_DECL for `std::terminate'. */ extern tree (*lang_protect_cleanup_actions) (void); -/* Return true if type A catches type B. */ -extern int (*lang_eh_type_covers) (tree a, tree b); - -/* Map a type to a runtime object to match type. */ -extern tree (*lang_eh_runtime_type) (tree); - /* Just because the user configured --with-sjlj-exceptions=no doesn't mean that we can use call frame exceptions. Detect that the target has appropriate support. */ #ifndef MUST_USE_SJLJ_EXCEPTIONS -# if !(defined (EH_RETURN_DATA_REGNO) \ +# if defined (EH_RETURN_DATA_REGNO) \ && (defined (TARGET_UNWIND_INFO) \ || (DWARF2_UNWIND_INFO \ && (defined (EH_RETURN_HANDLER_RTX) \ - || defined (HAVE_eh_return))))) -# define MUST_USE_SJLJ_EXCEPTIONS 1 -# else + || defined (HAVE_eh_return)))) # define MUST_USE_SJLJ_EXCEPTIONS 0 +# else +# define MUST_USE_SJLJ_EXCEPTIONS 1 # endif #endif @@ -146,16 +318,71 @@ extern tree (*lang_eh_runtime_type) (tree); # endif # if CONFIG_SJLJ_EXCEPTIONS == 0 # define USING_SJLJ_EXCEPTIONS 0 -# ifndef EH_RETURN_DATA_REGNO +# if !defined(EH_RETURN_DATA_REGNO) #error "EH_RETURN_DATA_REGNO required" # endif -# if !defined(EH_RETURN_HANDLER_RTX) && !defined(HAVE_eh_return) +# if ! (defined(TARGET_UNWIND_INFO) || DWARF2_UNWIND_INFO) + #error "{DWARF2,TARGET}_UNWIND_INFO required" +# endif +# if !defined(TARGET_UNWIND_INFO) \ + && !(defined(EH_RETURN_HANDLER_RTX) || defined(HAVE_eh_return)) #error "EH_RETURN_HANDLER_RTX or eh_return required" # endif -# if !defined(DWARF2_UNWIND_INFO) && !defined(TARGET_UNWIND_INFO) - #error "{DWARF2,TARGET}_UNWIND_INFO required" +/* Usually the above error checks will have already triggered an + error, but backends may set MUST_USE_SJLJ_EXCEPTIONS for their own + reasons. */ +# if MUST_USE_SJLJ_EXCEPTIONS + #error "Must use SJLJ exceptions but configured not to" # endif # endif #else # define USING_SJLJ_EXCEPTIONS MUST_USE_SJLJ_EXCEPTIONS #endif + +struct GTY(()) throw_stmt_node { + gimple stmt; + int lp_nr; +}; + +extern struct htab *get_eh_throw_stmt_table (struct function *); +extern void set_eh_throw_stmt_table (struct function *, struct htab *); + +enum eh_personality_kind { + eh_personality_none, + eh_personality_any, + eh_personality_lang +}; + +extern enum eh_personality_kind +function_needs_eh_personality (struct function *); + +/* Pre-order iteration within the eh_region tree. */ + +static inline eh_region +ehr_next (eh_region r, eh_region start) +{ + if (r->inner) + r = r->inner; + else if (r->next_peer && r != start) + r = r->next_peer; + else + { + do + { + r = r->outer; + if (r == start) + return NULL; + } + while (r->next_peer == NULL); + r = r->next_peer; + } + return r; +} + +#define FOR_ALL_EH_REGION_AT(R, START) \ + for ((R) = (START); (R) != NULL; (R) = ehr_next (R, START)) + +#define FOR_ALL_EH_REGION_FN(R, FN) \ + for ((R) = (FN)->eh->region_tree; (R) != NULL; (R) = ehr_next (R, NULL)) + +#define FOR_ALL_EH_REGION(R) FOR_ALL_EH_REGION_FN (R, cfun)