summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>1997-12-12 04:53:20 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>1997-12-12 04:53:20 +0000
commit732992fad81a5d42283b07fd9442441acf685b5a (patch)
treeb1e33498c494a6a7e60f2adbf6b766688bf20d7a
parentb35797d55be1fdfacd475669c1c78ce9c74513db (diff)
downloadgcc-732992fad81a5d42283b07fd9442441acf685b5a.tar.gz
Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
Thread-safe EH support for pthreads, DCE threads and Solaris threads. * integrate.c (expand_inline_function): If the inline fn uses eh context, make sure that the current fn has one. * toplev.c (rest_of_compilation): Call emit_eh_context. * except.c (use_eh_context): New fn. (get_eh_context_once): New fn. (call_get_eh_context): New fn. (emit_eh_context): New fn. (get_eh_context): Call either get_eh_context_once or call_get_eh_context, depending on what we have. (get_dynamic_handler_chain): Call get_eh_context_once. * except.h: Prototypes for fns above. * optabs.c (get_eh_context_libfunc): Removed. (init_optabs): Don't initialize it. * expr.h (get_eh_context_libfunc): Removed. * rtl.h, rtl.c: New reg_note REG_EH_CONTEXT. * config/pa/pa.h (CPP_SPEC): Support for -threads. * config/pa/pa-hpux10.h (LIB_SPEC): Ditto. * config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): New multilib for -threads. * config/sparc/t-sol2: Added multilibs for -threads and made -pthreads alias to it. * config/sparc/sol2.h (CPP_SPEC, LIB_SPEC): Added -threads and -pthreads options. * libgcc-thr.h: New file. * libgcc2.c: (__get_cpp_eh_context): Removed. (struct cpp_eh_context): Removed. (struct eh_context): Replaced cpp_eh_context with generic language specific pointer. (__get_eh_info): New function. (__throw): Check eh_context::info. (__sjthrow): Ditto. * libgcc2.c: Include libgcc-thr.h. (new_eh_context, __get_eh_context, eh_pthread_initialize, eh_context_initialize, eh_context_static, eh_context_specific, eh_context_free): New functions. (get_eh_context, eh_context_key): New variables. (__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use get_eh_context to get the context. (longjmp): Move the declaration inside #ifdef DONT_USE_BUILTIN_SETJMP. * frame.c: Include libgcc-thr.h. (object_mutex): Mutex to protect the object list. (find_fde, __register_frame, __register_frame_table, __deregister_frame): Hold the lock while accessing objects. * except.h (get_eh_context): Declare. * except.c (current_function_ehc): Define. (current_function_dhc, current_function_dcc): Removed. (get_eh_context): New function. (get_dynamic_handler_chain): Use get_eh_context. (get_saved_pc_ref): Ditto. (get_dynamic_cleanup_chain): Removed references to current_function_dcc. (save_eh_status, restore_eh_status): Save and restore current_function_ehc instead. * optabs.c (get_eh_context_libfunc): New variable. (init_optabs): Initialize it. * expr.h: Declare get_eh_context_libfunc. * function.h (struct function): Replaced dhc and dcc with ehc. * except.c (get_saved_pc_ref): New functions. (eh_saved_pc_rtx, eh_saved_pc): Deleted. (expand_internal_throw_indirect): Use get_saved_pc_ref() instead of eh_saved_pc. (end_eh_unwinder): Likewise. (init_eh): Remove initialization of eh_saved_pc. * optabs.c (get_saved_pc_libfunc): New variable. (init_optabs): Initialize it. * expr.h: Declare get_saved_pc_libfunc. * except.h (eh_saved_pc_rtx): Deleted. (get_saved_pc_ref): Declared. From Scott Snyder <snyder@d0sgif.fnal.gov>: * libgcc2.c (__get_saved_pc): New. (__eh_type, __eh_pc): Deleted. (__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc. (__get_dynamic_handler_chain): Move __dynamic_handler_chain inside this fcn. cp/: Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com> * decl.c (ptr_ptr_type_node): Define. (init_decl_processing): Initialize it. * cp-tree.h: Declare it. * exception.cc (__cp_exception_info): Use __get_eh_info. (__cp_push_exception): Ditto. (__cp_pop_exception): Ditto. From Scott Snyder <snyder@d0sgif.fnal.gov>: * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of saved_pc. (init_exception_processing): Removed saved_pc initialization. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@17052 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog81
-rw-r--r--gcc/config/pa/pa-hpux10.h11
-rw-r--r--gcc/config/pa/pa.h7
-rw-r--r--gcc/config/pa/t-pa6
-rw-r--r--gcc/config/sparc/sol2.h9
-rw-r--r--gcc/config/sparc/t-sol27
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c5
-rw-r--r--gcc/cp/except.c20
-rw-r--r--gcc/cp/exception.cc15
-rw-r--r--gcc/except.c233
-rw-r--r--gcc/except.h21
-rw-r--r--gcc/frame.c27
-rw-r--r--gcc/function.h24
-rw-r--r--gcc/integrate.c6
-rw-r--r--gcc/libgcc2.c206
-rw-r--r--gcc/rtl.c2
-rw-r--r--gcc/rtl.h2
-rw-r--r--gcc/toplev.c3
20 files changed, 567 insertions, 134 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0bb0666e46a..8d36284cf57 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,84 @@
+Thu Dec 11 20:42:18 1997 Teemu Torma <tot@trema.com>
+
+ Thread-safe EH support for pthreads, DCE threads and Solaris threads.
+
+ * integrate.c (expand_inline_function): If the inline fn uses eh
+ context, make sure that the current fn has one.
+ * toplev.c (rest_of_compilation): Call emit_eh_context.
+ * except.c (use_eh_context): New fn.
+ (get_eh_context_once): New fn.
+ (call_get_eh_context): New fn.
+ (emit_eh_context): New fn.
+ (get_eh_context): Call either get_eh_context_once or
+ call_get_eh_context, depending on what we have.
+ (get_dynamic_handler_chain): Call get_eh_context_once.
+ * except.h: Prototypes for fns above.
+ * optabs.c (get_eh_context_libfunc): Removed.
+ (init_optabs): Don't initialize it.
+ * expr.h (get_eh_context_libfunc): Removed.
+ * rtl.h, rtl.c: New reg_note REG_EH_CONTEXT.
+ * config/pa/pa.h (CPP_SPEC): Support for -threads.
+ * config/pa/pa-hpux10.h (LIB_SPEC): Ditto.
+ * config/pa/t-pa (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
+ New multilib for -threads.
+ * config/sparc/t-sol2: Added multilibs for -threads and
+ made -pthreads alias to it.
+ * config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
+ Added -threads and -pthreads options.
+ * libgcc-thr.h: New file.
+ * libgcc2.c: (__get_cpp_eh_context): Removed.
+ (struct cpp_eh_context): Removed.
+ (struct eh_context): Replaced cpp_eh_context with generic language
+ specific pointer.
+ (__get_eh_info): New function.
+ (__throw): Check eh_context::info.
+ (__sjthrow): Ditto.
+ * libgcc2.c: Include libgcc-thr.h.
+ (new_eh_context, __get_eh_context,
+ eh_pthread_initialize, eh_context_initialize, eh_context_static,
+ eh_context_specific, eh_context_free): New functions.
+ (get_eh_context, eh_context_key): New variables.
+ (__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
+ get_eh_context to get the context.
+ (longjmp): Move the declaration inside
+ #ifdef DONT_USE_BUILTIN_SETJMP.
+ * frame.c: Include libgcc-thr.h.
+ (object_mutex): Mutex to protect the object list.
+ (find_fde, __register_frame, __register_frame_table,
+ __deregister_frame): Hold the lock while accessing objects.
+ * except.h (get_eh_context): Declare.
+ * except.c (current_function_ehc): Define.
+ (current_function_dhc, current_function_dcc): Removed.
+ (get_eh_context): New function.
+ (get_dynamic_handler_chain): Use get_eh_context.
+ (get_saved_pc_ref): Ditto.
+ (get_dynamic_cleanup_chain): Removed references to
+ current_function_dcc.
+ (save_eh_status, restore_eh_status): Save and restore
+ current_function_ehc instead.
+ * optabs.c (get_eh_context_libfunc): New variable.
+ (init_optabs): Initialize it.
+ * expr.h: Declare get_eh_context_libfunc.
+ * function.h (struct function): Replaced dhc and dcc with ehc.
+ * except.c (get_saved_pc_ref): New functions.
+ (eh_saved_pc_rtx, eh_saved_pc): Deleted.
+ (expand_internal_throw_indirect): Use get_saved_pc_ref() instead
+ of eh_saved_pc.
+ (end_eh_unwinder): Likewise.
+ (init_eh): Remove initialization of eh_saved_pc.
+ * optabs.c (get_saved_pc_libfunc): New variable.
+ (init_optabs): Initialize it.
+ * expr.h: Declare get_saved_pc_libfunc.
+ * except.h (eh_saved_pc_rtx): Deleted.
+ (get_saved_pc_ref): Declared.
+
+ From Scott Snyder <snyder@d0sgif.fnal.gov>:
+ * libgcc2.c (__get_saved_pc): New.
+ (__eh_type, __eh_pc): Deleted.
+ (__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
+ (__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
+ this fcn.
+
Thu Dec 11 17:23:48 1997 John F. Carr <jfc@mit.edu>
* sparc/sol2.h: Use 64 bit multiply and divide functions in
diff --git a/gcc/config/pa/pa-hpux10.h b/gcc/config/pa/pa-hpux10.h
index 9a2af5d578c..0cd59127f68 100644
--- a/gcc/config/pa/pa-hpux10.h
+++ b/gcc/config/pa/pa-hpux10.h
@@ -30,6 +30,17 @@ Boston, MA 02111-1307, USA. */
"-z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}"
#endif
+/* Like the default, except no -lg. */
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{!shared:\
+ %{!p:\
+ %{!pg:\
+ %{!threads:-lc}\
+ %{threads:-lcma -lc_r}}\
+ %{p: -L/lib/libp/ -lc}\
+ %{pg: -L/lib/libp/ -lc}}}"
+
/* The hpux10 assembler requires a .LEVEL pseudo-op at the start of
the assembly file. */
#undef ASM_FILE_START
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index c286fb9fa04..a127c84673d 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -241,9 +241,12 @@ extern int target_flags;
#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) == 0
#define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\
%{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}\
- %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
+ %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}\
+ %{threads:-D_REENTRANT -D_DCE_THREADS}"
#else
-#define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}} %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
+#define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}} \
+ %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}\
+ %{threads:-D_REENTRANT -D_DCE_THREADS}"
#endif
/* Defines for a K&R CC */
diff --git a/gcc/config/pa/t-pa b/gcc/config/pa/t-pa
index a359918a125..b6dcec1212e 100644
--- a/gcc/config/pa/t-pa
+++ b/gcc/config/pa/t-pa
@@ -16,3 +16,9 @@ ee_fp.asm: $(srcdir)/config/pa/ee_fp.asm
cp $(srcdir)/config/pa/ee_fp.asm .
TARGET_LIBGCC2_CFLAGS = -fPIC
+
+MULTILIB_OPTIONS = threads
+MULTILIB_DIRNAMES = threads
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index 5891222a0ce..76cade44d9e 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -30,6 +30,8 @@ Boston, MA 02111-1307, USA. */
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
+%{pthreads:-D_REENTRANT -D_PTHREADS} \
+%{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
"
@@ -131,7 +133,12 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
#define LIB_SPEC \
- "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} %{!shared:%{!symbolic:-lc}}"
+ "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
+ %{!shared:\
+ %{!symbolic:\
+ %{pthreads:-lpthread} \
+ %{!pthreads:%{threads:-lthread}} \
+ -lc}}"
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
diff --git a/gcc/config/sparc/t-sol2 b/gcc/config/sparc/t-sol2
index d41254adb44..309aedfd9f9 100644
--- a/gcc/config/sparc/t-sol2
+++ b/gcc/config/sparc/t-sol2
@@ -5,6 +5,13 @@ LIBGCC1 =
CROSS_LIBGCC1 =
LIBGCC1_TEST =
+MULTILIB_OPTIONS = threads
+MULTILIB_DIRNAMES = threads
+MULTILIB_MATCHES = threads=pthreads
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
# gmon build rule:
gmon.o: $(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) stmp-int-hdrs
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 88732201b20..d2070090997 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+Thu Dec 11 20:43:33 1997 Teemu Torma <tot@trema.com>
+
+ * decl.c (ptr_ptr_type_node): Define.
+ (init_decl_processing): Initialize it.
+ * cp-tree.h: Declare it.
+ * exception.cc (__cp_exception_info): Use __get_eh_info.
+ (__cp_push_exception): Ditto.
+ (__cp_pop_exception): Ditto.
+
+ From Scott Snyder <snyder@d0sgif.fnal.gov>:
+ * except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
+ saved_pc.
+ (init_exception_processing): Removed saved_pc initialization.
+
Wed Dec 10 11:04:45 1997 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (instantiate_decl): Defer all templates but inline functions.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e1653020194..48740a5e3cb 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1511,7 +1511,7 @@ extern tree vt_off_identifier;
/* A node that is a list (length 1) of error_mark_nodes. */
extern tree error_mark_list;
-extern tree ptr_type_node;
+extern tree ptr_type_node, ptr_ptr_type_node;
extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
extern tree unknown_type_node;
extern tree opaque_type_node, signature_type_node;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7ece1d33d38..fd753d8ad79 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -241,6 +241,10 @@ tree void_zero_node;
tree ptr_type_node;
tree const_ptr_type_node;
+/* Node for type `void **'. */
+
+tree ptr_ptr_type_node;
+
/* Nodes for types `char *' and `const char *'. */
tree string_type_node, const_string_type_node;
@@ -5065,6 +5069,7 @@ init_decl_processing ()
ptr_type_node = build_pointer_type (void_type_node);
const_ptr_type_node
= build_pointer_type (build_type_variant (void_type_node, 1, 0));
+ ptr_ptr_type_node = build_pointer_type (ptr_type_node);
#if 0
record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
#endif
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 3d62c771845..0fa5c2425a8 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -186,9 +186,6 @@ static tree Unwind;
========================================================================= */
#ifndef DWARF2_UNWIND_INFO
-/* Holds the pc for doing "throw" */
-static tree saved_pc;
-
extern int throw_used;
#endif
@@ -258,15 +255,6 @@ init_exception_processing ()
pop_lang_context ();
-#ifndef DWARF2_UNWIND_INFO
- d = build_decl (VAR_DECL, get_identifier ("__eh_pc"), ptr_type_node);
- TREE_PUBLIC (d) = 1;
- DECL_EXTERNAL (d) = 1;
- DECL_ARTIFICIAL (d) = 1;
- cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
- saved_pc = d;
-#endif
-
/* If we use setjmp/longjmp EH, arrange for all cleanup actions to
be protected with __terminate. */
protect_cleanup_actions_with_terminate = 1;
@@ -812,8 +800,10 @@ expand_builtin_throw ()
/* search for an exception handler for the saved_pc */
handler = do_function_call (FirstExceptionMatch,
- expr_tree_cons (NULL_TREE, saved_pc,
- NULL_TREE),
+ expr_tree_cons (NULL_TREE,
+ make_tree (ptr_ptr_type_node,
+ get_saved_pc_ref ()),
+ NULL_TREE),
ptr_type_node);
/* did we find one? */
@@ -892,7 +882,7 @@ expand_builtin_throw ()
}
else
#endif
- emit_move_insn (eh_saved_pc_rtx, next_pc);
+ emit_move_insn (get_saved_pc_ref (), next_pc);
after_unwind = gen_label_rtx ();
do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc
index aa5a46e2b26..399d2c60dbc 100644
--- a/gcc/cp/exception.cc
+++ b/gcc/cp/exception.cc
@@ -91,9 +91,9 @@ struct cp_eh_info
long handlers;
};
-/* Language-specific EH info pointer, defined in libgcc2. */
+/* Language-specific EH info pointer, defined in libgcc2. */
-extern cp_eh_info *__eh_info; // actually void*
+extern "C" cp_eh_info **__get_eh_info (); // actually void **
/* Is P the type_info node for a pointer of some kind? */
@@ -105,7 +105,7 @@ extern bool __is_pointer (void *);
extern "C" cp_eh_info *
__cp_exception_info (void)
{
- return __eh_info;
+ return *__get_eh_info ();
}
/* Compiler hook to push a new exception onto the stack.
@@ -120,8 +120,11 @@ __cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
p->cleanup = cleanup;
p->handlers = 0;
p->caught = false;
- p->next = __eh_info;
- __eh_info = p;
+
+ cp_eh_info **q = __get_eh_info ();
+
+ p->next = *q;
+ *q = p;
}
/* Compiler hook to pop an exception that has been finalized. Used by
@@ -131,7 +134,7 @@ __cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
extern "C" void
__cp_pop_exception (cp_eh_info *p)
{
- cp_eh_info **q = &__eh_info;
+ cp_eh_info **q = __get_eh_info ();
--p->handlers;
diff --git a/gcc/except.c b/gcc/except.c
index a39d8e5544c..11c3be87fc5 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -431,17 +431,10 @@ rtx exception_handler_labels;
int throw_used;
-/* The dynamic handler chain. Nonzero if the function has already
- fetched a pointer to the dynamic handler chain for exception
- handling. */
-
-rtx current_function_dhc;
-
-/* The dynamic cleanup chain. Nonzero if the function has already
- fetched a pointer to the dynamic cleanup chain for exception
- handling. */
+/* The EH context. Nonzero if the function has already
+ fetched a pointer to the EH context for exception handling. */
-rtx current_function_dcc;
+rtx current_function_ehc;
/* A stack used for keeping track of the currently active exception
handling region. As each exception region is started, an entry
@@ -496,13 +489,6 @@ struct label_node *outer_context_label_stack = NULL;
struct label_node *false_label_stack = NULL;
-#ifndef DWARF2_UNWIND_INFO
-/* The rtx and the tree for the saved PC value. */
-
-rtx eh_saved_pc_rtx;
-tree eh_saved_pc;
-#endif
-
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
static void expand_rethrow PROTO((rtx));
@@ -721,37 +707,20 @@ add_partial_entry (handler)
pop_obstacks ();
}
-/* Get a reference to the dynamic handler chain. It points to the
- pointer to the next element in the dynamic handler chain. It ends
- when there are no more elements in the dynamic handler chain, when
- the value is &top_elt from libgcc2.c. Immediately after the
- pointer, is an area suitable for setjmp/longjmp when
- DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for
- __builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP
- isn't defined.
+/* Emit code to get EH context to current function. */
- This routine is here to facilitate the porting of this code to
- systems with threads. One can either replace the routine we emit a
- call for here in libgcc2.c, or one can modify this routine to work
- with their thread system.
-
- Ideally, we really only want one per real function, not one
- per inlined function. */
-
-rtx
-get_dynamic_handler_chain ()
+static rtx
+call_get_eh_context (before)
+ rtx before;
{
static tree fn;
tree expr;
- rtx insns;
-
- if (current_function_dhc)
- return current_function_dhc;
+ rtx ehc, reg, insns;
if (fn == NULL_TREE)
{
tree fntype;
- fn = get_identifier ("__get_dynamic_handler_chain");
+ fn = get_identifier ("__get_eh_context");
push_obstacks_nochange ();
end_temporary_allocation ();
fntype = build_pointer_type (build_pointer_type
@@ -771,15 +740,105 @@ get_dynamic_handler_chain ()
expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
expr, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (expr) = 1;
- expr = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
start_sequence ();
- current_function_dhc = expand_expr (expr, NULL_RTX, VOIDmode, 0);
+ ehc = expand_expr (expr, NULL_RTX, VOIDmode, 0);
+ reg = copy_to_reg (ehc);
+
insns = get_insns ();
end_sequence ();
- emit_insns_before (insns, get_first_nonparm_insn ());
- return current_function_dhc;
+ if (before != 0)
+ emit_insns_before (insns, before);
+ else
+ emit_insns (insns);
+
+ return reg;
+}
+
+/* Get a reference to the EH context.
+ We will only generate a register for the current function EH context here,
+ and emit a USE insn to mark that this is a EH context register.
+
+ Later, emit_eh_context will emit needed call to __get_eh_context
+ in libgcc2, and copy the value to the register we have generated. */
+
+rtx
+use_eh_context ()
+{
+ if (current_function_ehc == 0)
+ {
+ rtx insn;
+
+ current_function_ehc = gen_reg_rtx (Pmode);
+
+ insn = gen_rtx (USE,
+ GET_MODE (current_function_ehc),
+ copy_rtx (current_function_ehc));
+ insn = emit_insn_before (insn, get_first_nonparm_insn ());
+
+ REG_NOTES (insn)
+ = gen_rtx (EXPR_LIST,
+ REG_EH_CONTEXT, copy_rtx (current_function_ehc),
+ REG_NOTES (insn));
+ }
+ return current_function_ehc;
+}
+
+/* Get reference to EH context only once per fn. */
+
+rtx
+get_eh_context_once ()
+{
+ rtx ehc;
+
+ if (current_function_ehc == 0)
+ use_eh_context ();
+
+ ehc = gen_reg_rtx (Pmode);
+ emit_move_insn (ehc, current_function_ehc);
+
+ return ehc;
+}
+
+/* Get reference to EH context by calling __get_eh_context. */
+
+rtx
+get_eh_context ()
+{
+ rtx ehc;
+
+ /* If we already have an EH context in the current function,
+ use it. */
+ if (current_function_ehc)
+ ehc = get_eh_context_once ();
+ else
+ ehc = call_get_eh_context (0);
+
+ return ehc;
+}
+
+/* Get a reference to the dynamic handler chain. It points to the
+ pointer to the next element in the dynamic handler chain. It ends
+ when there are no more elements in the dynamic handler chain, when
+ the value is &top_elt from libgcc2.c. Immediately after the
+ pointer, is an area suitable for setjmp/longjmp when
+ DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for
+ __builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP
+ isn't defined. */
+
+rtx
+get_dynamic_handler_chain ()
+{
+ rtx ehc, dhc, result;
+
+ ehc = get_eh_context_once ();
+ dhc = ehc;
+
+ result = copy_to_reg (dhc);
+
+ /* We don't want a copy of the dcc, but rather, the single dcc. */
+ return gen_rtx (MEM, Pmode, result);
}
/* Get a reference to the dynamic cleanup chain. It points to the
@@ -791,15 +850,31 @@ get_dynamic_handler_chain ()
rtx
get_dynamic_cleanup_chain ()
{
- rtx dhc, dcc;
+ rtx dhc, dcc, result;
dhc = get_dynamic_handler_chain ();
dcc = plus_constant (dhc, GET_MODE_SIZE (Pmode));
- current_function_dcc = copy_to_reg (dcc);
+ result = copy_to_reg (dcc);
/* We don't want a copy of the dcc, but rather, the single dcc. */
- return gen_rtx (MEM, Pmode, current_function_dcc);
+ return gen_rtx (MEM, Pmode, result);
+}
+
+/* Get a reference to the saved_pc variable. */
+
+rtx
+get_saved_pc_ref ()
+{
+ rtx ehc, ehpc, result;
+
+ /* Saved PC is the second word into the returned structure. */
+ ehc = get_eh_context ();
+ ehpc = plus_constant (ehc, GET_MODE_SIZE (Pmode));
+ result = copy_to_reg (ehpc);
+
+ /* We don't want a copy of the ehpc, but rather, the single ehpc. */
+ return gen_rtx (MEM, Pmode, result);
}
/* Generate code to evaluate X and jump to LABEL if the value is nonzero.
@@ -1220,8 +1295,7 @@ expand_internal_throw ()
rtx label = gen_label_rtx ();
emit_label (label);
label = gen_rtx (LABEL_REF, Pmode, label);
- assemble_external (eh_saved_pc);
- emit_move_insn (eh_saved_pc_rtx, label);
+ emit_move_insn (get_saved_pc_ref (), label);
}
#endif
emit_throw ();
@@ -1698,8 +1772,6 @@ end_eh_unwinder ()
return;
#else /* DWARF2_UNWIND_INFO */
- assemble_external (eh_saved_pc);
-
expr = make_node (RTL_EXPR);
TREE_TYPE (expr) = void_type_node;
RTL_EXPR_RTL (expr) = const0_rtx;
@@ -1717,7 +1789,7 @@ end_eh_unwinder ()
return_val_rtx = eh_outer_context (return_val_rtx);
return_val_rtx = expand_binop (Pmode, sub_optab, return_val_rtx, GEN_INT (1),
NULL_RTX, 0, OPTAB_LIB_WIDEN);
- emit_move_insn (eh_saved_pc_rtx, return_val_rtx);
+ emit_move_insn (get_saved_pc_ref (), return_val_rtx);
/* Either set things up so we do a return directly to __throw, or
we return here instead. */
@@ -1828,6 +1900,46 @@ emit_unwinder ()
emit_insns_after (insns, insn);
}
+/* Emit code to get EH context.
+
+ We have to scan thru the code to find possible EH context registers.
+ Inlined functions may use it too, and thus we'll have to be able
+ to change them too.
+
+ This is done only if using exceptions_via_longjmp. */
+
+void
+emit_eh_context ()
+{
+ rtx insn;
+ rtx ehc = 0;
+
+ if (! doing_eh (0))
+ return;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == USE)
+ {
+ rtx reg = find_reg_note (insn, REG_EH_CONTEXT, 0);
+ if (reg)
+ {
+ rtx insns;
+
+ /* If this is the first use insn, emit the call here. */
+ if (ehc == 0)
+ ehc = call_get_eh_context (insn);
+
+ start_sequence ();
+ emit_move_insn (XEXP (reg, 0), ehc);
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_insns_before (insns, insn);
+ }
+ }
+}
+
/* Scan the current insns and build a list of handler labels. The
resulting list is placed in the global variable exception_handler_labels.
@@ -1977,14 +2089,6 @@ init_eh ()
/* Generate rtl to reference the variable in which the PC of the
current context is saved. */
tree type = build_pointer_type (make_node (VOID_TYPE));
-
-#ifndef DWARF2_UNWIND_INFO
- eh_saved_pc = build_decl (VAR_DECL, get_identifier ("__eh_pc"), type);
- DECL_EXTERNAL (eh_saved_pc) = 1;
- TREE_PUBLIC (eh_saved_pc) = 1;
- make_decl_rtl (eh_saved_pc, NULL_PTR, 1);
- eh_saved_pc_rtx = DECL_RTL (eh_saved_pc);
-#endif
}
/* Initialize the per-function EH information. */
@@ -1998,8 +2102,7 @@ init_eh_for_function ()
false_label_stack = 0;
caught_return_label_stack = 0;
protect_list = NULL_TREE;
- current_function_dhc = NULL_RTX;
- current_function_dcc = NULL_RTX;
+ current_function_ehc = NULL_RTX;
}
/* Save some of the per-function EH info into the save area denoted by
@@ -2020,8 +2123,7 @@ save_eh_status (p)
p->false_label_stack = false_label_stack;
p->caught_return_label_stack = caught_return_label_stack;
p->protect_list = protect_list;
- p->dhc = current_function_dhc;
- p->dcc = current_function_dcc;
+ p->ehc = current_function_ehc;
init_eh ();
}
@@ -2043,8 +2145,7 @@ restore_eh_status (p)
catch_clauses = p->catch_clauses;
ehqueue = p->ehqueue;
ehstack = p->ehstack;
- current_function_dhc = p->dhc;
- current_function_dcc = p->dcc;
+ current_function_ehc = p->ehc;
}
/* This section is for the exception handling specific optimization
diff --git a/gcc/except.h b/gcc/except.h
index 46b1f47879e..abfeb478ea6 100644
--- a/gcc/except.h
+++ b/gcc/except.h
@@ -201,6 +201,11 @@ extern void expand_internal_throw PROTO((void));
extern void expand_leftover_cleanups PROTO((void));
+/* If necessary, emit insns to get EH context for the current
+ function. */
+
+extern void emit_eh_context PROTO((void));
+
/* If necessary, emit insns for the start of per-function unwinder for
the current function. */
@@ -240,21 +245,29 @@ extern struct label_node *false_label_stack;
extern rtx exception_handler_labels;
-/* The rtx for the saved PC value. */
-
-extern rtx eh_saved_pc_rtx;
-
/* Performs optimizations for exception handling, such as removing
unnecessary exception regions. Invoked from jump_optimize (). */
extern void exception_optimize PROTO((void));
+/* Use EH context once per fn. */
+extern rtx use_eh_context PROTO((void));
+
+/* Get the EH contex only once per fn. */
+extern rtx get_eh_context_once PROTO((void));
+
+/* Get the EH contex. */
+extern rtx get_eh_context PROTO((void));
+
/* Get the dynamic handler chain. */
extern rtx get_dynamic_handler_chain PROTO((void));
/* Get the dynamic cleanup chain. */
extern rtx get_dynamic_cleanup_chain PROTO((void));
+/* Get the saved PC variable. */
+extern rtx get_saved_pc_ref PROTO((void));
+
/* Throw an exception. */
extern void emit_throw PROTO((void));
diff --git a/gcc/frame.c b/gcc/frame.c
index 747fb9f1c40..296e6a9456d 100644
--- a/gcc/frame.c
+++ b/gcc/frame.c
@@ -39,6 +39,13 @@ Boston, MA 02111-1307, USA. */
#include "dwarf2.h"
#include <stddef.h>
#include "frame.h"
+#include "libgcc-thr.h"
+
+#ifdef __GTHREAD_MUTEX_INIT
+static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
+#else
+static __gthread_mutex_t object_mutex;
+#endif
/* Don't use `fancy_abort' here even if config.h says to use it. */
#ifdef abort
@@ -296,6 +303,8 @@ find_fde (void *pc)
struct object *ob;
size_t lo, hi;
+ __gthread_mutex_lock (&object_mutex);
+
for (ob = objects; ob; ob = ob->next)
{
if (ob->pc_begin == 0)
@@ -304,6 +313,8 @@ find_fde (void *pc)
break;
}
+ __gthread_mutex_unlock (&object_mutex);
+
if (ob == 0)
return 0;
@@ -509,8 +520,12 @@ __register_frame (void *begin, struct object *ob)
ob->fde_array = 0;
ob->count = 0;
+ __gthread_mutex_lock (&object_mutex);
+
ob->next = objects;
objects = ob;
+
+ __gthread_mutex_unlock (&object_mutex);
}
/* Similar, but BEGIN is actually a pointer to a table of unwind entries
@@ -526,8 +541,12 @@ __register_frame_table (void *begin, struct object *ob)
ob->pc_begin = ob->pc_end = 0;
ob->count = 0;
+ __gthread_mutex_lock (&object_mutex);
+
ob->next = objects;
objects = ob;
+
+ __gthread_mutex_unlock (&object_mutex);
}
/* Called from crtend.o to deregister the unwind info for an object. */
@@ -535,8 +554,11 @@ __register_frame_table (void *begin, struct object *ob)
void
__deregister_frame (void *begin)
{
- struct object **p = &objects;
+ struct object **p;
+ __gthread_mutex_lock (&object_mutex);
+
+ p = &objects;
while (*p)
{
if ((*p)->fde_begin == begin)
@@ -548,10 +570,13 @@ __deregister_frame (void *begin)
if (ob->pc_begin)
free (ob->fde_array);
+ __gthread_mutex_unlock (&object_mutex);
return;
}
p = &((*p)->next);
}
+
+ __gthread_mutex_unlock (&object_mutex);
abort ();
}
diff --git a/gcc/function.h b/gcc/function.h
index f54622fa71d..a0a37467ab5 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -136,8 +136,7 @@ struct function
struct label_node *false_label_stack;
struct label_node *caught_return_label_stack;
tree protect_list;
- rtx dhc;
- rtx dcc;
+ rtx ehc;
/* For expr.c. */
int pending_stack_adjust;
@@ -200,6 +199,7 @@ struct function
struct pool_sym **const_rtx_sym_hash_table;
struct pool_constant *first_pool, *last_pool;
int pool_offset;
+ rtx const_double_chain;
};
/* The FUNCTION_DECL for an inline function currently being expanded. */
@@ -234,12 +234,24 @@ extern HOST_WIDE_INT get_frame_size PROTO((void));
/* These variables hold pointers to functions to
save and restore machine-specific data,
in push_function_context and pop_function_context. */
-extern void (*save_machine_status) ();
-extern void (*restore_machine_status) ();
+extern void (*save_machine_status) PROTO((struct function *));
+extern void (*restore_machine_status) PROTO((struct function *));
-/* Save and restore varasm.c status for a nested function. */
-extern void save_varasm_status PROTO((struct function *));
+/* Save and restore status information for a nested function. */
+extern void save_tree_status PROTO((struct function *, tree));
+extern void restore_tree_status PROTO((struct function *, tree));
+extern void save_varasm_status PROTO((struct function *, tree));
extern void restore_varasm_status PROTO((struct function *));
+extern void save_eh_status PROTO((struct function *));
+extern void restore_eh_status PROTO((struct function *));
+extern void save_stmt_status PROTO((struct function *));
+extern void restore_stmt_status PROTO((struct function *));
+extern void save_expr_status PROTO((struct function *));
+extern void restore_expr_status PROTO((struct function *));
+extern void save_emit_status PROTO((struct function *));
+extern void restore_emit_status PROTO((struct function *));
+extern void save_storage_status PROTO((struct function *));
+extern void restore_storage_status PROTO((struct function *));
#ifdef rtx
#undef rtx
diff --git a/gcc/integrate.c b/gcc/integrate.c
index 2b2c8560918..f69adb11485 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -1805,6 +1805,12 @@ expand_inline_function (fndecl, parms, target, ignore, type,
inline_target. */
break;
+ /* If the inline fn needs eh context, make sure that
+ the current fn has one. */
+ if (GET_CODE (pattern) == USE
+ && find_reg_note (insn, REG_EH_CONTEXT, 0) != 0)
+ use_eh_context ();
+
/* Ignore setting a function value that we don't want to use. */
if (map->inline_target == 0
&& set != 0
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
index ad51863e912..1ad63013a15 100644
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -2962,11 +2962,9 @@ int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
#ifdef L_eh
-/* Shared exception handling support routines. */
+#include "libgcc-thr.h"
-/* Language-specific information about the active exception(s). If there
- are no active exceptions, it is set to 0. */
-void *__eh_info;
+/* Shared exception handling support routines. */
void
__default_terminate ()
@@ -2999,41 +2997,190 @@ __empty ()
{
}
+/* EH context structure. */
+
+struct eh_context
+{
+ void **dynamic_handler_chain;
+ void *saved_pc;
+#ifndef DWARF2_UNWIND_INFO
+ void *buf[2];
+#endif
+ /* This is language dependent part of the eh context. */
+ void *info;
+};
+
+/* This is a safeguard for dynamic handler chain. */
+
+static void *top_elt[2];
+
+/* Allocate and return a new EH context structure. */
+
+extern void __throw ();
+
+static void *
+new_eh_context ()
+{
+ struct eh_context *eh = (struct eh_context *) malloc (sizeof *eh);
+ if (! eh)
+ __terminate ();
+
+ memset (eh, 0, sizeof *eh);
+
+ eh->dynamic_handler_chain = top_elt;
+#ifndef DWARF2_UNWIND_INFO
+ eh->buf[0] = &eh->saved_pc;
+ eh->buf[1] = &__throw;
+#endif
+
+ return eh;
+}
+
+#if __GTHREADS
+static __gthread_key_t eh_context_key;
+
+/* Destructor for struct eh_context. */
+static void
+eh_context_free (void *ptr)
+{
+ if (ptr)
+ free (ptr);
+}
+#endif
+
+/* Pointer to function to return EH context. */
+
+static struct eh_context *eh_context_initialize ();
+static struct eh_context *eh_context_static ();
+#if __GTHREADS
+static struct eh_context *eh_context_specific ();
+#endif
+
+static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
+
+/* Routine to get EH context.
+ This one will simply call the function pointer. */
+
+void *
+__get_eh_context ()
+{
+ return (void *) (*get_eh_context) ();
+}
+
+/* Get and set the language specific info pointer. */
+
+void **
+__get_eh_info ()
+{
+ struct eh_context *eh = (*get_eh_context) ();
+ return (void **) &eh->info;
+}
+
+#if __GTHREADS
+static void
+eh_threads_initialize ()
+{
+ /* Try to create the key. If it fails, revert to static method,
+ otherwise start using thread specific EH contexts. */
+ if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
+ get_eh_context = &eh_context_specific;
+ else
+ get_eh_context = &eh_context_static;
+}
+#endif /* no __GTHREADS */
+
+/* Initialize EH context.
+ This will be called only once, since we change GET_EH_CONTEXT
+ pointer to another routine. */
+
+static struct eh_context *
+eh_context_initialize ()
+{
+#if __GTHREADS
+
+ static __gthread_once_t once = __GTHREAD_ONCE_INIT;
+ __gthread_once (&once, eh_threads_initialize);
+
+#else /* no __GTHREADS */
+
+ /* Use static version of EH context. */
+ get_eh_context = &eh_context_static;
+
+#endif /* no __GTHREADS */
+
+ return (*get_eh_context) ();
+}
+
+/* Return a static EH context. */
+
+static struct eh_context *
+eh_context_static ()
+{
+ static struct eh_context *eh;
+ if (! eh)
+ eh = new_eh_context ();
+ return eh;
+}
+
+#if __GTHREADS
+/* Return a thread specific EH context. */
+
+static struct eh_context *
+eh_context_specific ()
+{
+ struct eh_context *eh;
+ eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
+ if (! eh)
+ {
+ eh = new_eh_context ();
+ if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
+ __terminate ();
+ }
+
+ return eh;
+}
+#endif __GTHREADS
+
/* Support routines for setjmp/longjmp exception handling. */
/* Calls to __sjthrow are generated by the compiler when an exception
is raised when using the setjmp/longjmp exception handling codegen
method. */
+#ifdef DONT_USE_BUILTIN_SETJMP
extern void longjmp (void *, int);
-
-static void *top_elt[2];
-void **__dynamic_handler_chain = top_elt;
+#endif
/* Routine to get the head of the current thread's dynamic handler chain
- use for exception handling.
-
- TODO: make thread safe. */
+ use for exception handling. */
void ***
__get_dynamic_handler_chain ()
{
- return &__dynamic_handler_chain;
+ struct eh_context *eh = (*get_eh_context) ();
+ return (void ***) &eh->dynamic_handler_chain;
+}
+
+void **
+__get_saved_pc ()
+{
+ struct eh_context *eh = (*get_eh_context) ();
+ return (void **) &eh->saved_pc;
}
/* This is used to throw an exception when the setjmp/longjmp codegen
method is used for exception handling.
- We call __terminate if there are no handlers left (we know this
- when the dynamic handler chain is top_elt). Otherwise we run the
- cleanup actions off the dynamic cleanup stack, and pop the top of
- the dynamic handler chain, and use longjmp to transfer back to the
- associated handler. */
+ We call __terminate if there are no handlers left. Otherwise we run the
+ cleanup actions off the dynamic cleanup stack, and pop the top of the
+ dynamic handler chain, and use longjmp to transfer back to the associated
+ handler. */
void
__sjthrow ()
{
- void ***dhc = __get_dynamic_handler_chain ();
+ struct eh_context *eh = (*get_eh_context) ();
+ void ***dhc = &eh->dynamic_handler_chain;
void *jmpbuf;
void (*func)(void *, int);
void *arg;
@@ -3081,7 +3228,7 @@ __sjthrow ()
/* We must call terminate if we try and rethrow an exception, when
there is no exception currently active and when there are no
handlers left. */
- if (! __eh_info || (*dhc) == top_elt)
+ if (! eh->info || (*dhc) == top_elt)
__terminate ();
/* Find the jmpbuf associated with the top element of the dynamic
@@ -3108,7 +3255,8 @@ __sjthrow ()
void
__sjpopnthrow ()
{
- void ***dhc = __get_dynamic_handler_chain ();
+ struct eh_context *eh = (*get_eh_context) ();
+ void ***dhc = &eh->dynamic_handler_chain;
void *jmpbuf;
void (*func)(void *, int);
void *arg;
@@ -3288,11 +3436,8 @@ __throw ()
/* See expand_builtin_throw for details. */
void **__eh_pcnthrow () {
- static void *buf[2] = {
- &__eh_pc,
- &__throw
- };
- return buf;
+ struct eh_context *eh = (*get_eh_context) ();
+ return &eh->buf[0];
}
#if #machine(i386)
@@ -3499,7 +3644,8 @@ in_reg_window (int reg, frame_state *udata)
void
__throw ()
{
- void *pc, *handler, *retaddr, *__eh_pc;
+ struct eh_context *eh = (*get_eh_context) ();
+ void *saved_pc, *pc, *handler, *retaddr;
frame_state ustruct, ustruct2;
frame_state *udata = &ustruct;
frame_state *sub_udata = &ustruct2;
@@ -3509,7 +3655,7 @@ __throw ()
/* This is required for C++ semantics. We must call terminate if we
try and rethrow an exception, when there is no exception currently
active. */
- if (! __eh_info)
+ if (! eh->info)
__terminate ();
/* Start at our stack frame. */
@@ -3534,8 +3680,8 @@ label:
__builtin_unwind_init ();
/* Now reset pc to the right throw point. */
- __eh_pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
- pc = __eh_pc;
+ pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
+ saved_pc = pc;
handler = 0;
for (;;)
@@ -3567,7 +3713,7 @@ label:
if (! handler)
__terminate ();
- if (pc == __eh_pc)
+ if (pc == saved_pc)
/* We found a handler in the throw context, no need to unwind. */
udata = my_udata;
else
@@ -3582,7 +3728,7 @@ label:
void *handler_pc = pc;
/* Start from the throw context again. */
- pc = __eh_pc;
+ pc = saved_pc;
memcpy (udata, my_udata, sizeof (*udata));
while (pc != handler_pc)
diff --git a/gcc/rtl.c b/gcc/rtl.c
index dde2a8396a5..69e517143db 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -182,7 +182,7 @@ char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
"REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
"REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
"REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA",
- "REG_BR_PRED" };
+ "REG_BR_PRED", "REG_EH_CONTEXT" };
static void dump_and_abort PROTO((int, int, FILE *));
static void read_name PROTO((char *, FILE *));
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 667cab72c5b..62b13427687 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -325,7 +325,7 @@ enum reg_note { REG_DEAD = 1, REG_INC = 2, REG_EQUIV = 3, REG_WAS_0 = 4,
REG_CC_SETTER = 11, REG_CC_USER = 12, REG_LABEL = 13,
REG_DEP_ANTI = 14, REG_DEP_OUTPUT = 15, REG_BR_PROB = 16,
REG_EXEC_COUNT = 17, REG_NOALIAS = 18, REG_SAVE_AREA = 19,
- REG_BR_PRED = 20 };
+ REG_BR_PRED = 20, REG_EH_CONTEXT = 21 };
/* The base value for branch probability notes. */
#define REG_BR_PROB_BASE 10000
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 17318e25c44..9cbd513fca2 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3201,6 +3201,9 @@ rest_of_compilation (decl)
goto exit_rest_of_compilation;
}
+ /* Emit code to get eh context, if needed. */
+ emit_eh_context ();
+
/* Add an unwinder for exception handling, if needed.
This must be done before we finalize PIC code. */
emit_unwinder ();