X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fexcept.h;h=72fd76ef646a66867b5845795e5fa55e5fec1003;hb=c3a945cde92094f4713cefdafe5c1bd3f07fbbcc;hp=40d1676794396cc16818d3457cb709c2327b26ba;hpb=95cedffb7229d00b1fe6f7943139ff8c6d2bf0b4;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/except.h b/gcc/except.h index 40d16767943..72fd76ef646 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 - 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,163 +16,324 @@ 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 +. */ + +/* No include guards here, but define an include file marker anyway, so + that the compiler can keep track of where this file is included. This + is e.g. used to avoid including this file in front-end specific files. */ +#ifndef GCC_EXCEPT_H +# define GCC_EXCEPT_H +#endif +#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 PARAMS ((int)); - -/* Start an exception handling region. All instructions emitted after - this point are considered to be part of the region until an - expand_eh_region_end variant is invoked. */ -extern void expand_eh_region_start PARAMS ((void)); - -/* End an exception handling region for a cleanup. HANDLER is an - expression to expand for the cleanup. */ -extern void expand_eh_region_end_cleanup PARAMS ((tree)); - -/* End an exception handling region for a try block, and prepares - for subsequent calls to expand_start_catch. */ -extern void expand_start_all_catch PARAMS ((void)); - -/* Begin a catch clause. TYPE is an object to be matched by the - runtime, or a list of such objects, or null if this is a catch-all - clause. */ -extern void expand_start_catch PARAMS ((tree)); - -/* End a catch clause. Control will resume after the try/catch block. */ -extern void expand_end_catch PARAMS ((void)); - -/* End a sequence of catch handlers for a try block. */ -extern void expand_end_all_catch PARAMS ((void)); - -/* End an exception region for an exception type filter. ALLOWED is a - TREE_LIST of TREE_VALUE objects to be matched by the runtime. - FAILURE is a function to invoke if a mismatch occurs. */ -extern void expand_eh_region_end_allowed PARAMS ((tree, tree)); - -/* End an exception region for a must-not-throw filter. FAILURE is a - function to invoke if an uncaught exception propagates this far. */ -extern void expand_eh_region_end_must_not_throw PARAMS ((tree)); - -/* End an exception region for a throw. No handling goes on here, - but it's the easiest way for the front-end to indicate what type - is being thrown. */ -extern void expand_eh_region_end_throw PARAMS ((tree)); - -/* End a fixup region. Within this region the cleanups for the immediately - enclosing region are _not_ run. This is used for goto cleanup to avoid - destroying an object twice. */ -extern void expand_eh_region_end_fixup PARAMS ((tree)); - -/* 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 PARAMS ((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 PARAMS ((void (*) (rtx))); - -/* Determine if the given INSN can throw an exception. */ -extern bool can_throw_internal PARAMS ((rtx)); -extern bool can_throw_external PARAMS ((rtx)); - -/* Set current_function_nothrow and cfun->all_throwers_are_sibcalls. */ -extern void set_nothrow_function_flags PARAMS ((void)); - -/* After initial rtl generation, call back to finish generating - exception support code. */ -extern void finish_eh_generation PARAMS ((void)); - -extern void init_eh PARAMS ((void)); -extern void init_eh_for_function PARAMS ((void)); - -extern rtx reachable_handlers PARAMS ((rtx)); -extern void maybe_remove_eh_handler PARAMS ((rtx)); - -extern void convert_from_eh_region_ranges PARAMS ((void)); -extern void convert_to_eh_region_ranges PARAMS ((void)); -extern void find_exception_handler_labels PARAMS ((void)); -extern bool current_function_has_exception_handlers PARAMS ((void)); -extern void output_function_exception_table PARAMS ((void)); - -extern void expand_builtin_unwind_init PARAMS ((void)); -extern rtx expand_builtin_eh_return_data_regno PARAMS ((tree)); -extern rtx expand_builtin_extract_return_addr PARAMS ((tree)); -extern void expand_builtin_init_dwarf_reg_sizes PARAMS ((tree)); -extern rtx expand_builtin_frob_return_addr PARAMS ((tree)); -extern rtx expand_builtin_dwarf_fp_regnum PARAMS ((void)); -extern void expand_builtin_eh_return PARAMS ((tree, tree)); -extern void expand_eh_return PARAMS ((void)); -extern rtx get_exception_pointer PARAMS ((struct function *)); -extern int duplicate_eh_regions PARAMS ((struct function *, - struct inline_remap *)); - -extern void sjlj_emit_function_exit_after PARAMS ((rtx)); - - -/* If non-NULL, this is a function that returns an expression 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'. */ -extern tree (*lang_protect_cleanup_actions) PARAMS ((void)); - -/* Return true if type A catches type B. */ -extern int (*lang_eh_type_covers) PARAMS ((tree a, tree b)); - -/* Map a type to a runtime object to match type. */ -extern tree (*lang_eh_runtime_type) PARAMS ((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. */ - -#if ! (defined (EH_RETURN_DATA_REGNO) \ - && (defined (IA64_UNWIND_INFO) \ - || (DWARF2_UNWIND_INFO \ - && defined (EH_RETURN_STACKADJ_RTX) \ - && (defined (EH_RETURN_HANDLER_RTX) \ - || defined (HAVE_eh_return))))) -#define MUST_USE_SJLJ_EXCEPTIONS 1 -#else -#define MUST_USE_SJLJ_EXCEPTIONS 0 -#endif - -#ifdef CONFIG_SJLJ_EXCEPTIONS -# if CONFIG_SJLJ_EXCEPTIONS == 1 -# define USING_SJLJ_EXCEPTIONS 1 -# endif -# if CONFIG_SJLJ_EXCEPTIONS == 0 -# define USING_SJLJ_EXCEPTIONS 0 -# ifndef EH_RETURN_DATA_REGNO - #error "EH_RETURN_DATA_REGNO required" -# endif -# ifndef EH_RETURN_STACKADJ_RTX - #error "EH_RETURN_STACKADJ_RTX required" -# endif -# if !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(IA64_UNWIND_INFO) - #error "{DWARF2,IA64}_UNWIND_INFO required" -# endif -# endif -#else -# define USING_SJLJ_EXCEPTIONS MUST_USE_SJLJ_EXCEPTIONS -#endif +extern void for_each_eh_label (void (*) (rtx)); + +extern void init_eh_for_function (void); + +extern void remove_eh_landing_pad (eh_landing_pad); +extern void remove_eh_handler (eh_region); + +extern bool current_function_has_exception_handlers (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); +extern void expand_builtin_init_dwarf_reg_sizes (tree); +extern rtx expand_builtin_frob_return_addr (tree); +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); + +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 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 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 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); + +extern eh_region get_eh_region_from_rtx (const_rtx); +extern eh_landing_pad get_eh_landing_pad_from_rtx (const_rtx); + +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)