OSDN Git Service

Remove lang_eh_type_covers, which is dead, and the corresponding
[pf3gnuchains/gcc-fork.git] / gcc / except.h
index a75b3d4..59214e0 100644 (file)
@@ -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 <mrs@cygnus.com>.
 
 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,99 +16,230 @@ 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
+<http://www.gnu.org/licenses/>.  */
 
+#include "sbitmap.h"
+#include "vecprim.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);
 
-/* 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 (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 (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 (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 (tree);
-
-/* End a catch clause.  Control will resume after the try/catch block.  */
-extern void expand_end_catch (void);
-
-/* End a sequence of catch handlers for a try block.  */
-extern void expand_end_all_catch (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 (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 (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 (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 (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 (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));
 
-/* Determine if the given INSN can throw an exception.  */
-extern bool can_throw_internal (rtx);
-extern bool can_throw_external (rtx);
-
-/* Set current_function_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);
@@ -118,40 +249,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 int duplicate_eh_regions (struct function *, struct inline_remap *);
+
+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);
 
-/* If non-NULL, this is a function that returns an expression to be
+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);
+
+/* 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)                  \
-       && (defined (IA64_UNWIND_INFO)                  \
+# 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
 
@@ -161,16 +317,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(IA64_UNWIND_INFO)
-    #error "{DWARF2,IA64}_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)