public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: MT-safe EH diffs against 1.00
       [not found] <199712080853.JAA18141.cygnus.egcs@lev.labs.trema.com>
@ 1997-12-08  1:52 ` Jason Merrill
  0 siblings, 0 replies; 3+ messages in thread
From: Jason Merrill @ 1997-12-08  1:52 UTC (permalink / raw)
  To: Teemu Torma, egcs, wilson; +Cc: law

Thanks.  Please update this patch to egcs-971207; several things have
changed.  For one, the dwarf2 code no longer uses __eh_pc.  Which is a
binary incompatibility, now that I think about it.

Also, using a libcall to return a pointer will currently break on targets
that return pointers in a different register, because Pmode == some integer
mode.  Jim seemed to think that using libcall for these sorts of functions
was a mistake in any case; why was that, again?  And then how is
memcpy_libfunc supposed to work?

Jason

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: MT-safe EH diffs against 1.00
@ 1997-12-11 13:03 Mike Stump
  0 siblings, 0 replies; 3+ messages in thread
From: Mike Stump @ 1997-12-11 13:03 UTC (permalink / raw)
  To: egcs, tot

I am in favor of appling these patches to the development branch.
Thanks for the hard work guys, it helps a lot.  I glaced through them,
and I would say they look reasonable.

> From: Teemu Torma <tot@trema.com>
> To: egcs@cygnus.com
> Date: Mon, 08 Dec 1997 09:53:05 +0100

> Here are my latest MT-safe exception handling diffs for egcs-1.00.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* MT-safe EH diffs against 1.00
@ 1997-12-08  0:53 Teemu Torma
  0 siblings, 0 replies; 3+ messages in thread
From: Teemu Torma @ 1997-12-08  0:53 UTC (permalink / raw)
  To: egcs

Here are my latest MT-safe exception handling diffs for egcs-1.00.
Some line numbers may not match the release, because I have some
unrelated changes in my version.

Many thanks to Scott Snyder (snyder@d0sgif.fnal.gov) for the initial
patches he posted, and to Andrey Slepuhin (pooh@msu.ru) for testing
sjlj exception part and for supplying patches for AIX.

This version has been tested on the following machines:

     Sparc/Solaris 2.5.1
       - DWARF2 unwinding exceptions / sjlj exceptions
       - Solaris (UI) threads/POSIX threads
     PA/HP-UX 10.20
       - sjlj exceptions
       - DCE threads
     RS6000/AIX 4.1.2
       - sjlj exceptions
       - POSIX threads
     
I have reworked the ChangeLog entries to describe what is different
against 1.00 and what's left of Scott Snyder's patches.

The major changes since I previously posted these are:
    - New file libgcc-thr.h to encapsulate different thread
      implementations.  The interface is similiar to POSIX threads.
    - Calls to __get_eh_context are inside LIBCALL block and
      effectively __attribute__(const).  At least some calls to it
      will get optimized away.
    
Teemu
---------------------------------------------------------------------------
ChangeLog:

1997-12-08  Teemu Torma  <tot@lev.labs.trema.com>

	From Andrey Slepuhin <pooh@msu.ru>:
	* config/rs6000/aix41.h (CPP_SPEC): If -mthreads, set
	-D_PTHREADS. 
	* config/rs6000/t-newas (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
	Added -mthreads with directory name thread.
	
1997-12-02  Teemu Torma  <tot@trema.com>

	Thread support for pthreads, DCE threads and Solaris threads.
	
	* 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.

	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.

	* 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.

cp/ChangeLog:

1997-12-01  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.

Index: except.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/except.c,v
retrieving revision 1.1.1.7
retrieving revision 1.9
diff -c -r1.1.1.7 -r1.9
*** except.c	1997/11/28 08:05:42	1.1.1.7
--- except.c	1997/12/01 12:45:55	1.9
***************
*** 431,447 ****
  
  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.  */
! 
! rtx current_function_dcc;
  
  /* A stack used for keeping track of the currectly active exception
     handling region.  As each exception region is started, an entry
--- 431,440 ----
  
  int throw_used;
  
! /* The EH context.  Nonzero if the function has already
!    fetched a pointer to the EH context  for exception handling.  */
  
! rtx current_function_ehc;
  
  /* A stack used for keeping track of the currectly active exception
     handling region.  As each exception region is started, an entry
***************
*** 496,506 ****
  
  struct label_node *false_label_stack = NULL;
  
- /* The rtx and the tree for the saved PC value.  */
- 
- rtx eh_saved_pc_rtx;
- tree eh_saved_pc;
- 
  rtx expand_builtin_return_addr	PROTO((enum built_in_function, int, rtx));
  \f
  /* Various support routines to manipulate the various data structures
--- 489,494 ----
***************
*** 717,722 ****
--- 705,736 ----
    pop_obstacks ();
  }
  
+ /* 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.  */
+ 
+ rtx
+ get_eh_context ()
+ {
+   rtx ehc;
+   rtx target, insns;
+ 
+   start_sequence ();
+   ehc = emit_library_call_value (get_eh_context_libfunc,
+ 				 NULL_RTX, 1,
+ 				 Pmode, 0);
+   RTX_UNCHANGING_P (ehc) = 1;
+   insns = get_insns ();
+   end_sequence ();
+ 
+   target = gen_reg_rtx (Pmode);
+   emit_libcall_block (insns, target, ehc,
+ 		      gen_rtx (EXPR_LIST, VOIDmode,
+ 			       get_eh_context_libfunc, 0));
+   return target;
+ }
+      
  /* 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
***************
*** 724,766 ****
     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.
! 
!    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.  */
  
  rtx
  get_dynamic_handler_chain ()
  {
! #if 0
!   /* Do this once we figure out how to get this to the front of the
!      function, and we really only want one per real function, not one
!      per inlined function.  */
!   if (current_function_dhc == 0)
!     {
!       rtx dhc, insns;
!       start_sequence ();
! 
!       dhc = emit_library_call_value (get_dynamic_handler_chain_libfunc,
! 				     NULL_RTX, 1,
! 				     Pmode, 0);
!       current_function_dhc = copy_to_reg (dhc);
!       insns = get_insns ();
!       end_sequence ();
!       emit_insns_before (insns, get_first_nonparm_insn ());
!     }
! #else
!   rtx dhc;
!   dhc = emit_library_call_value (get_dynamic_handler_chain_libfunc,
! 				 NULL_RTX, 1,
! 				 Pmode, 0);
!   current_function_dhc = copy_to_reg (dhc);
! #endif
  
!   /* We don't want a copy of the dhc, but rather, the single dhc.  */
!   return gen_rtx (MEM, Pmode, current_function_dhc);
  }
  
  /* Get a reference to the dynamic cleanup chain.  It points to the
--- 738,757 ----
     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 ();
!   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
***************
*** 772,786 ****
  rtx
  get_dynamic_cleanup_chain ()
  {
!   rtx dhc, dcc;
  
    dhc = get_dynamic_handler_chain ();
    dcc = plus_constant (dhc, GET_MODE_SIZE (Pmode));
  
!   current_function_dcc = 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);
  }
  
  /* Generate code to evaluate X and jump to LABEL if the value is nonzero.
--- 763,793 ----
  rtx
  get_dynamic_cleanup_chain ()
  {
!   rtx dhc, dcc, result;
  
    dhc = get_dynamic_handler_chain ();
    dcc = plus_constant (dhc, GET_MODE_SIZE (Pmode));
  
!   result = copy_to_reg (dcc);
  
    /* 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 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.
***************
*** 1160,1167 ****
  expand_internal_throw_indirect (context)
       rtx context;
  {
!   assemble_external (eh_saved_pc);
!   emit_move_insn (eh_saved_pc_rtx, context);
    emit_throw ();
  }
  
--- 1167,1173 ----
  expand_internal_throw_indirect (context)
       rtx context;
  {
!   emit_move_insn (get_saved_pc_ref (), context);
    emit_throw ();
  }
  
***************
*** 1654,1661 ****
    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;
--- 1660,1665 ----
***************
*** 1673,1679 ****
    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);
    
    /* Either set things up so we do a return directly to __throw, or
       we return here instead.  */
--- 1677,1683 ----
    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 (get_saved_pc_ref (), return_val_rtx);
    
    /* Either set things up so we do a return directly to __throw, or
       we return here instead.  */
***************
*** 1933,1944 ****
    /* 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));
- 
-   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);
  }
  
  /* Initialize the per-function EH information.  */
--- 1937,1942 ----
***************
*** 1952,1959 ****
    false_label_stack = 0;
    caught_return_label_stack = 0;
    protect_list = NULL_TREE;
!   current_function_dhc = NULL_RTX;
!   current_function_dcc = NULL_RTX;
  }
  
  /* Save some of the per-function EH info into the save area denoted by
--- 1950,1956 ----
    false_label_stack = 0;
    caught_return_label_stack = 0;
    protect_list = NULL_TREE;
!   current_function_ehc = NULL_RTX;
  }
  
  /* Save some of the per-function EH info into the save area denoted by
***************
*** 1974,1981 ****
    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;
  
    init_eh ();
  }
--- 1971,1977 ----
    p->false_label_stack = false_label_stack;
    p->caught_return_label_stack = caught_return_label_stack;
    p->protect_list = protect_list;
!   p->ehc = current_function_ehc;
  
    init_eh ();
  }
***************
*** 1997,2004 ****
    catch_clauses	= p->catch_clauses;
    ehqueue = p->ehqueue;
    ehstack = p->ehstack;
!   current_function_dhc = p->dhc;
!   current_function_dcc = p->dcc;
  }
  \f
  /* This section is for the exception handling specific optimization
--- 1993,1999 ----
    catch_clauses	= p->catch_clauses;
    ehqueue = p->ehqueue;
    ehstack = p->ehstack;
!   current_function_ehc = p->ehc;
  }
  \f
  /* This section is for the exception handling specific optimization
Index: except.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/except.h,v
retrieving revision 1.1.1.3
retrieving revision 1.5
diff -c -r1.1.1.3 -r1.5
*** except.h	1997/11/24 12:02:19	1.1.1.3
--- except.h	1997/12/01 16:21:51	1.5
***************
*** 251,270 ****
  
  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));
  
  /* 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));
  
  /* Throw an exception.  */
  
--- 251,272 ----
  
  extern rtx exception_handler_labels;
  
  /* Performs optimizations for exception handling, such as removing
     unnecessary exception regions. Invoked from jump_optimize ().  */
  
  extern void exception_optimize			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.  */
  
Index: expr.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/expr.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** expr.h	1997/09/26 09:56:56	1.1.1.1
--- expr.h	1997/09/26 15:43:10	1.2
***************
*** 417,422 ****
--- 417,424 ----
  extern rtx setjmp_libfunc;
  extern rtx longjmp_libfunc;
  extern rtx get_dynamic_handler_chain_libfunc;
+ extern rtx get_saved_pc_libfunc;
+ extern rtx get_eh_context_libfunc;
  
  extern rtx eqhf2_libfunc;
  extern rtx nehf2_libfunc;
Index: frame.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/frame.c,v
retrieving revision 1.1.1.4
retrieving revision 1.10
diff -c -r1.1.1.4 -r1.10
*** frame.c	1997/11/17 08:34:07	1.1.1.4
--- frame.c	1997/12/03 10:00:18	1.10
***************
*** 39,44 ****
--- 39,52 ----
  #include "frame.h"
  #include <stddef.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
  #undef abort
***************
*** 306,311 ****
--- 328,335 ----
    struct object *ob;
    size_t lo, hi;
  
+   __gthread_mutex_lock (&object_mutex);
+ 
    for (ob = objects; ob; ob = ob->next)
      {
        if (ob->pc_begin == 0)
***************
*** 314,319 ****
--- 338,345 ----
  	break;
      }
  
+   __gthread_mutex_unlock (&object_mutex);
+ 
    if (ob == 0)
      return 0;
  
***************
*** 521,528 ****
--- 547,558 ----
    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
***************
*** 540,547 ****
--- 570,581 ----
    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.  */
***************
*** 549,556 ****
  void
  __deregister_frame (void *begin)
  {
!   struct object **p = &objects;
  
    while (*p)
      {
        if ((*p)->fde_begin == begin)
--- 583,593 ----
  void
  __deregister_frame (void *begin)
  {
!   struct object **p;
  
+   __gthread_mutex_lock (&object_mutex);
+ 
+   p = &objects;
    while (*p)
      {
        if ((*p)->fde_begin == begin)
***************
*** 563,572 ****
--- 600,612 ----
  	    free (ob->fde_array);
  	  free (ob);
  
+ 	  __gthread_mutex_unlock (&object_mutex);
  	  return;
  	}
        p = &((*p)->next);
      }
+ 
+   __gthread_mutex_unlock (&object_mutex);
    abort ();
  }
  
Index: function.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/function.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** function.h	1997/09/26 09:56:58	1.1.1.1
--- function.h	1997/12/01 12:45:56	1.2
***************
*** 136,143 ****
    struct label_node *false_label_stack;
    struct label_node *caught_return_label_stack;
    tree protect_list;
!   rtx dhc;
!   rtx dcc;
  
    /* For expr.c.  */
    int pending_stack_adjust;
--- 136,142 ----
    struct label_node *false_label_stack;
    struct label_node *caught_return_label_stack;
    tree protect_list;
!   rtx ehc;
  
    /* For expr.c.  */
    int pending_stack_adjust;
Index: libgcc-thr.h
===================================================================
RCS file: libgcc-thr.h
diff -N libgcc-thr.h
*** /dev/null	Thu Dec  4 11:16:05 1997
--- /tmp/cvsBAAa0057C	Thu Dec  4 11:16:43 1997
***************
*** 0 ****
--- 1,321 ----
+ /* Threads compatibily routines for libgcc2.  */
+ /* Compile this one with gcc.  */
+ /* Copyright (C) 1997 Free Software Foundation, Inc.
+ 
+ This file is part of GNU CC.
+ 
+ GNU CC 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 version.
+ 
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or 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 GNU CC; see the file COPYING.  If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.  */
+ 
+ /* As a special exception, if you link this library with other files,
+    some of which are compiled with GCC, to produce an executable,
+    this library does not by itself cause the resulting executable
+    to be covered by the GNU General Public License.
+    This exception does not however invalidate any other reasons why
+    the executable file might be covered by the GNU General Public License.  */
+ 
+ #ifndef __libgcc_thr_h
+ #define __libgcc_thr_h
+ 
+ /* If this file is compiled with threads support, it must
+        #define __GTHREADS 1
+    to indicate that threads support is present.
+    
+    The threads interface must define the following types:
+      __gthread_key_t
+      __gthread_once_t
+      __gthread_mutex_t
+ 
+    The threads interface must define the following macros:
+ 
+      __GTHREAD_ONCE_INIT
+      		to initialize __gthread_once_t
+      __GTHREAD_MUTEX_INIT
+      		to initialize __gthread_mutex_t to get a fast
+ 		non-recursive mutex.
+ 
+    The threads interface must define the following static functions:
+ 
+      int __gthread_once (__gthread_once_t *once, void (*func) ())
+ 
+      int __gthread_key_create (__gthread_key_t *keyp, void (*dtor) (void *))
+      int __gthread_key_delete (__gthread_key_t key)
+ 
+      void *__gthread_getspecific (__gthread_key_t key)
+      int __gthread_setspecific (__gthread_key_t key, const void *ptr)
+ 
+      int __gthread_mutex_lock (__gthread_mutex_t *mutex);
+      int __gthread_mutex_trylock (__gthread_mutex_t *mutex);
+      int __gthread_mutex_unlock (__gthread_mutex_t *mutex);
+ 
+    All functions returning int should return 0 on success, -1 on error.
+ 
+    Currently supported threads packages are
+      POSIX threads with -D_PTHREADS
+      DCE threads with -D_DCE_THREADS
+      Solaris/UI threads with -D_SOLARIS_THREADS
+ */
+ 
+ #if _PTHREADS
+ /* POSIX threads specific definitions.
+    Easy, since the interface is just one-to-one mapping. */
+ 
+ #define __GTHREADS 1
+ 
+ #include <pthread.h>
+ 
+ typedef pthread_key_t __gthread_key_t;
+ typedef pthread_once_t __gthread_once_t;
+ typedef pthread_mutex_t __gthread_mutex_t;
+ 
+ #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
+ #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
+ 
+ static inline int
+ __gthread_once (__gthread_once_t *once, void (*func) ())
+ {
+   return pthread_once (once, func);
+ }
+ 
+ static inline int
+ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+ {
+   return pthread_key_create (key, dtor);
+ }
+ 
+ static inline int
+ __gthread_key_delete (__gthread_key_t key)
+ {
+   return pthread_key_delete (key);
+ }
+ 
+ static inline void *
+ __gthread_getspecific (__gthread_key_t key)
+ {
+   return pthread_getspecific (key);
+ }
+ 
+ static inline int
+ __gthread_setspecific (__gthread_key_t key, const void *ptr)
+ {
+   return pthread_setspecific (key, ptr);
+ }
+ 
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_lock (mutex);
+ }
+ 
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_trylock (mutex);
+ }
+ 
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_unlock (mutex);
+ }
+ 
+ #elif _DCE_THREADS
+ /* DCE threads interface.
+    DCE threads are based on POSIX threads draft 4, and many things
+    have changed since then. */
+ 
+ #define __GTHREADS 1
+ 
+ #include <pthread.h>
+ 
+ typedef pthread_key_t __gthread_key_t;
+ typedef pthread_once_t __gthread_once_t;
+ typedef pthread_mutex_t __gthread_mutex_t;
+ 
+ #define __GTHREAD_ONCE_INIT pthread_once_init
+ /* Howto define __GTHREAD_MUTEX_INIT? */
+ 
+ static inline int
+ __gthread_once (__gthread_once_t *once, void (*func) ())
+ {
+   return pthread_once (once, func);
+ }
+ 
+ static inline int
+ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+ {
+   return pthread_keycreate (key, dtor);
+ }
+ 
+ static inline int
+ __gthread_key_delete (__gthread_key_t key)
+ {
+   return pthread_key_delete (key);
+ }
+ 
+ static inline void *
+ __gthread_getspecific (__gthread_key_t key)
+ {
+   void *ptr;
+   if (pthread_getspecific (key, &ptr) == 0)
+     return ptr;
+   else
+     return 0;
+ }
+ 
+ static inline int
+ __gthread_setspecific (__gthread_key_t key, const void *ptr)
+ {
+   return pthread_setspecific (key, (void *) ptr);
+ }
+ 
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_lock (mutex);
+ }
+ 
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_trylock (mutex);
+ }
+ 
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   return pthread_mutex_unlock (mutex);
+ }
+ 
+ #elif _SOLARIS_THREADS
+ /* Solaris threads as found in Solaris 2.[456].
+    Actually these are Unix International (UI) threads, but I don't
+    know if anyone else implements these. */
+ 
+ #define __GTHREADS 1
+ 
+ #include <thread.h>
+ #include <errno.h>
+ 
+ typedef thread_key_t __gthread_key_t;
+ typedef struct
+ {
+   mutex_t mutex;
+   int once;
+ } __gthread_once_t;
+ typedef mutex_t __gthread_mutex_t;
+ 
+ #define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
+ #define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
+ 
+ static inline int
+ __gthread_once (__gthread_once_t *once, void (*func) ())
+ {
+   if (once == 0 || func == 0)
+     {
+       errno = EINVAL;
+       return -1;
+     }
+ 
+   if (once->once == 0)
+     {
+       if (mutex_lock (&once->mutex) != 0)
+ 	return -1;
+       if (once->once == 0)
+ 	{
+ 	  (*func) ();
+ 	  once->once ++;
+ 	}
+       mutex_unlock (&once->mutex);
+     }
+   return 0;
+ }
+ 
+ static inline int
+ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+ {
+   return thr_keycreate (key, dtor);
+ }
+ 
+ static inline int
+ __gthread_key_delete (__gthread_key_t key)
+ {
+   /* Not possible. */
+   return -1;
+ }
+ 
+ static inline void *
+ __gthread_getspecific (__gthread_key_t key)
+ {
+   void *ptr;
+   if (thr_getspecific (key, &ptr) == 0)
+     return ptr;
+   else
+     return 0;
+ }
+ 
+ static inline int
+ __gthread_setspecific (__gthread_key_t key, const void *ptr)
+ {
+   return thr_setspecific (key, (void *) ptr);
+ }
+ 
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   return mutex_lock (mutex);
+ }
+ 
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   return mutex_trylock (mutex);
+ }
+ 
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   return mutex_unlock (mutex);
+ }
+ 
+ #else /* no threads */
+ 
+ /* Just provide compatibility for mutex handling. */
+ 
+ typedef int __gthread_mutex_t;
+ 
+ #define __GTHREAD_MUTEX_INIT 0
+ 
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   return 0;
+ }
+ 
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   return 0;
+ }
+ 
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   return 0;
+ }
+ 
+ #endif /* no threads */
+ 
+ #endif /* not __libgcc_thr_h */
Index: libgcc2.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/libgcc2.c,v
retrieving revision 1.1.1.5
retrieving revision 1.13
diff -c -r1.1.1.5 -r1.13
*** libgcc2.c	1997/11/28 08:06:31	1.1.1.5
--- libgcc2.c	1997/12/03 10:00:19	1.13
***************
*** 3107,3117 ****
  \f
  #ifdef L_eh
  
! /* Shared exception handling support routines.  */
  
! /* Language-specific information about the active exception(s).  If there
!    are no active exceptions, it is set to 0.  */
! void *__eh_info;
  
  void
  __default_terminate ()
--- 3107,3115 ----
  \f
  #ifdef L_eh
  
! #include "libgcc-thr.h"
  
! /* Shared exception handling support routines.  */
  
  void
  __default_terminate ()
***************
*** 3144,3184 ****
  {
  }
  \f
  /* 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.  */
  
  extern void longjmp (void *, int);
! 
! static void *top_elt[2];
! void **__dynamic_handler_chain = top_elt;
  
  /* Routine to get the head of the current thread's dynamic handler chain
!    use for exception handling.
! 
!    TODO: make thread safe.  */
  
  void ***
  __get_dynamic_handler_chain ()
  {
!   return &__dynamic_handler_chain;
  }
  
  /* 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.  */
  
  void
  __sjthrow ()
  {
!   void ***dhc = __get_dynamic_handler_chain ();
    void *jmpbuf;
    void (*func)(void *, int);
    void *arg;
--- 3142,3331 ----
  {
  }
  \f
+ /* 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;
+ }
+ \f
+ #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
+ \f
  /* 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);
! #endif
  
  /* Routine to get the head of the current thread's dynamic handler chain
!    use for exception handling. */
  
  void ***
  __get_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.  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 ()
  {
!   struct eh_context *eh = (*get_eh_context) ();
!   void ***dhc = &eh->dynamic_handler_chain;
    void *jmpbuf;
    void (*func)(void *, int);
    void *arg;
***************
*** 3226,3232 ****
    /* 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)
      __terminate ();
      
    /* Find the jmpbuf associated with the top element of the dynamic
--- 3373,3379 ----
    /* 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)
      __terminate ();
      
    /* Find the jmpbuf associated with the top element of the dynamic
***************
*** 3253,3259 ****
  void
  __sjpopnthrow ()
  {
!   void ***dhc = __get_dynamic_handler_chain ();
    void *jmpbuf;
    void (*func)(void *, int);
    void *arg;
--- 3400,3407 ----
  void
  __sjpopnthrow ()
  {
!   struct eh_context *eh = (*get_eh_context) ();
!   void ***dhc = &eh->dynamic_handler_chain;
    void *jmpbuf;
    void (*func)(void *, int);
    void *arg;
***************
*** 3309,3316 ****
  /* This value identifies the place from which an exception is being
     thrown.  */
  
- void *__eh_pc;
- 
  #ifdef EH_TABLE_LOOKUP
  
  EH_TABLE_LOOKUP
--- 3457,3462 ----
***************
*** 3433,3443 ****
  /* See expand_builtin_throw for details.  */
  
  void **__eh_pcnthrow () {
!   static void *buf[2] = {
!     &__eh_pc,
!     &__throw
!   };
!   return buf;
  }
  
  #if #machine(i386)
--- 3579,3586 ----
  /* See expand_builtin_throw for details.  */
  
  void **__eh_pcnthrow () {
!   struct eh_context *eh = (*get_eh_context) ();
!   return &eh->buf[0];
  }
  
  #if #machine(i386)
***************
*** 3644,3649 ****
--- 3787,3793 ----
  void
  __throw ()
  {
+   struct eh_context *eh = (*get_eh_context) ();
    void *pc, *handler, *retaddr;
    frame_state ustruct, ustruct2;
    frame_state *udata = &ustruct;
***************
*** 3654,3660 ****
    /* 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)
      __terminate ();
      
    /* Start at our stack frame.  */
--- 3798,3804 ----
    /* 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)
      __terminate ();
      
    /* Start at our stack frame.  */
***************
*** 3679,3685 ****
    __builtin_unwind_init ();
  
    /* Now reset pc to the right throw point.  */
!   pc = __eh_pc;
  
    handler = 0;
    for (;;)
--- 3823,3829 ----
    __builtin_unwind_init ();
  
    /* Now reset pc to the right throw point.  */
!   pc = eh->saved_pc;
  
    handler = 0;
    for (;;)
***************
*** 3711,3717 ****
    if (! handler)
      __terminate ();
  
!   if (pc == __eh_pc)
      /* We found a handler in the throw context, no need to unwind.  */
      udata = my_udata;
    else
--- 3855,3861 ----
    if (! handler)
      __terminate ();
  
!   if (pc == eh->saved_pc)
      /* We found a handler in the throw context, no need to unwind.  */
      udata = my_udata;
    else
***************
*** 3726,3732 ****
        void *handler_pc = pc;
  
        /* Start from the throw context again.  */
!       pc = __eh_pc;
        memcpy (udata, my_udata, sizeof (*udata));
  
        while (pc != handler_pc)
--- 3870,3876 ----
        void *handler_pc = pc;
  
        /* Start from the throw context again.  */
!       pc = eh->saved_pc;
        memcpy (udata, my_udata, sizeof (*udata));
  
        while (pc != handler_pc)
Index: optabs.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/optabs.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** optabs.c	1997/09/26 09:57:06	1.1.1.1
--- optabs.c	1997/09/26 15:43:12	1.2
***************
*** 125,130 ****
--- 125,132 ----
  rtx setjmp_libfunc;
  rtx longjmp_libfunc;
  rtx get_dynamic_handler_chain_libfunc;
+ rtx get_saved_pc_libfunc;
+ rtx get_eh_context_libfunc;
  
  rtx eqhf2_libfunc;
  rtx nehf2_libfunc;
***************
*** 4290,4295 ****
--- 4292,4299 ----
    longjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "longjmp");
  #endif
    get_dynamic_handler_chain_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_dynamic_handler_chain");
+   get_saved_pc_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_saved_pc");
+   get_eh_context_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_eh_context");
  
    eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
    nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
Index: config/pa/pa-hpux10.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/pa/pa-hpux10.h,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -c -r1.1.1.2 -r1.2
*** pa-hpux10.h	1997/11/24 12:05:48	1.1.1.2
--- pa-hpux10.h	1997/12/02 13:55:16	1.2
***************
*** 30,35 ****
--- 30,46 ----
    "-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
Index: config/pa/pa.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/pa/pa.h,v
retrieving revision 1.1.1.3
retrieving revision 1.2
diff -c -r1.1.1.3 -r1.2
*** pa.h	1997/11/24 12:05:51	1.1.1.3
--- pa.h	1997/12/02 13:55:17	1.2
***************
*** 241,249 ****
  #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}"
  #else
! #define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}} %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
  #endif
  
  /* Defines for a K&R CC */
--- 241,252 ----
  #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}\
!  %{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}\
!  %{threads:-D_REENTRANT -D_DCE_THREADS}"
  #endif
  
  /* Defines for a K&R CC */
Index: config/pa/t-pa
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/pa/t-pa,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -r1.1.1.1 -r1.2
*** t-pa	1997/09/26 09:58:04	1.1.1.1
--- t-pa	1997/12/02 13:55:17	1.2
***************
*** 16,18 ****
--- 16,24 ----
  	cp $(srcdir)/config/pa/ee_fp.asm .
  
  TARGET_LIBGCC2_CFLAGS = -fPIC
+ 
+ MULTILIB_OPTIONS = threads
+ MULTILIB_DIRNAMES = threads
+ 
+ LIBGCC = stmp-multilib
+ INSTALL_LIBGCC = install-multilib
Index: config/rs6000/aix41.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/rs6000/aix41.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.2.1
diff -c -c -r1.1.1.2 -r1.1.1.2.2.1
*** aix41.h	1997/12/02 09:56:53	1.1.1.2
--- aix41.h	1997/12/08 08:33:09	1.1.1.2.2.1
***************
*** 74,80 ****
  #undef CPP_SPEC
  #define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
     %{mpe: -I/usr/lpp/ppe.poe/include}\
!    %{mthreads: -D_THREAD_SAFE}\
     %(cpp_cpu)"
  
  #undef	CPP_DEFAULT_SPEC
--- 74,80 ----
  #undef CPP_SPEC
  #define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
     %{mpe: -I/usr/lpp/ppe.poe/include}\
!    %{mthreads: -D_THREAD_SAFE -D_PTHREADS}\
     %(cpp_cpu)"
  
  #undef	CPP_DEFAULT_SPEC
Index: config/rs6000/t-newas
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/rs6000/t-newas,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -c -c -r1.1.1.1 -r1.1.1.1.2.1
*** t-newas	1997/09/26 09:58:09	1.1.1.1
--- t-newas	1997/12/08 08:33:09	1.1.1.1.2.1
***************
*** 16,25 ****
  # Build the libraries for both hard and soft floating point and all of the 
  # different processor models
  
! MULTILIB_OPTIONS	= msoft-float \
  			  mcpu=common/mcpu=power/mcpu=powerpc
  
! MULTILIB_DIRNAMES	= soft-float \
  			  common power powerpc
  
  MULTILIB_MATCHES	= msoft-float=mcpu?403 \
--- 16,25 ----
  # Build the libraries for both hard and soft floating point and all of the 
  # different processor models
  
! MULTILIB_OPTIONS	= msoft-float mthreads \
  			  mcpu=common/mcpu=power/mcpu=powerpc
  
! MULTILIB_DIRNAMES	= soft-float thread \
  			  common power powerpc
  
  MULTILIB_MATCHES	= msoft-float=mcpu?403 \
Index: config/sparc/sol2.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/sparc/sol2.h,v
retrieving revision 1.1.1.2
retrieving revision 1.6
diff -c -r1.1.1.2 -r1.6
*** sol2.h	1997/10/24 09:12:33	1.1.1.2
--- sol2.h	1997/11/10 12:11:04	1.6
***************
*** 30,35 ****
--- 30,37 ----
  
  #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,137 ****
  
  #undef LIB_SPEC
  #define LIB_SPEC \
!   "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} %{!shared:%{!symbolic:-lc}}"
  
  #undef  ENDFILE_SPEC
  #define ENDFILE_SPEC "crtend.o%s crtn.o%s"
--- 133,144 ----
  
  #undef LIB_SPEC
  #define LIB_SPEC \
!   "%{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"
Index: config/sparc/t-sol2
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/sparc/t-sol2,v
retrieving revision 1.1.1.1
retrieving revision 1.6
diff -c -r1.1.1.1 -r1.6
*** t-sol2	1997/09/26 09:58:14	1.1.1.1
--- t-sol2	1997/11/24 12:35:09	1.6
***************
*** 5,10 ****
--- 5,16 ----
  CROSS_LIBGCC1 =
  LIBGCC1_TEST =
  
+ MULTILIB_OPTIONS = mcpu=v7/mcpu=v8/mcpu=v8plus threads fvtable-thunks
+ MULTILIB_DIRNAMES = sparc-v7 sparc-v8 sparc-v8plus threads vtable-thunks
+ 
+ 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) \
Index: cp/cp-tree.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.1.1.7
retrieving revision 1.2
diff -c -r1.1.1.7 -r1.2
*** cp-tree.h	1997/11/24 12:06:57	1.1.1.7
--- cp-tree.h	1997/12/01 08:47:27	1.2
***************
*** 1516,1522 ****
  /* A node that is a list (length 1) of error_mark_nodes.  */
  extern tree error_mark_list;
  
! extern tree 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;
--- 1516,1522 ----
  /* A node that is a list (length 1) of error_mark_nodes.  */
  extern tree error_mark_list;
  
! 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;
Index: cp/decl.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/cp/decl.c,v
retrieving revision 1.1.1.7
retrieving revision 1.2
diff -c -r1.1.1.7 -r1.2
*** decl.c	1997/11/24 12:06:59	1.1.1.7
--- decl.c	1997/12/01 08:47:29	1.2
***************
*** 241,246 ****
--- 241,250 ----
  tree ptr_type_node;
  static 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;
***************
*** 5064,5069 ****
--- 5068,5074 ----
    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
Index: cp/except.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/cp/except.c,v
retrieving revision 1.1.1.7
retrieving revision 1.7
diff -c -r1.1.1.7 -r1.7
*** except.c	1997/11/28 08:10:47	1.1.1.7
--- except.c	1997/11/28 08:36:25	1.7
***************
*** 189,197 ****
  
     ========================================================================= */
  
- /* Holds the pc for doing "throw" */
- static tree saved_pc;
- 
  extern int throw_used;
  extern rtx catch_clauses;
  
--- 189,194 ----
***************
*** 289,301 ****
  
    pop_lang_context ();
  
-   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;
- 
    /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
       be protected with __terminate.  */
    protect_cleanup_actions_with_terminate = 1;
--- 286,291 ----
***************
*** 885,892 ****
  
    /* search for an exception handler for the saved_pc */
    handler = do_function_call (FirstExceptionMatch,
! 			      expr_tree_cons (NULL_TREE, saved_pc,
! 					 NULL_TREE),
  			      ptr_type_node);
    assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
  
--- 875,884 ----
  
    /* search for an exception handler for the saved_pc */
    handler = do_function_call (FirstExceptionMatch,
! 			      expr_tree_cons (NULL_TREE,
! 					      make_tree (ptr_ptr_type_node,
! 							 get_saved_pc_ref ()),
! 					      NULL_TREE),
  			      ptr_type_node);
    assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
  
***************
*** 966,972 ****
      }
    else
  #endif
!     emit_move_insn (eh_saved_pc_rtx, next_pc);
  
    after_unwind = gen_label_rtx ();
    do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
--- 958,964 ----
      }
    else
  #endif
!     emit_move_insn (get_saved_pc_ref (), next_pc);
  
    after_unwind = gen_label_rtx ();
    do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
Index: cp/exception.cc
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/cp/exception.cc,v
retrieving revision 1.1.1.4
retrieving revision 1.6
diff -c -r1.1.1.4 -r1.6
*** exception.cc	1997/11/28 08:10:47	1.1.1.4
--- exception.cc	1997/11/28 08:36:25	1.6
***************
*** 90,98 ****
    long handlers;
  };
  
! /* Language-specific EH info pointer, defined in libgcc2.  */
  
! extern cp_eh_info *__eh_info;  // actually void*
  
  /* Is P the type_info node for a pointer of some kind?  */
  
--- 90,98 ----
    long handlers;
  };
  
! /* Language-specific EH info pointer, defined in libgcc2. */
  
! extern "C" cp_eh_info **__get_eh_info (); 	// actually void **
  
  /* Is P the type_info node for a pointer of some kind?  */
  
***************
*** 104,110 ****
  extern "C" cp_eh_info *
  __cp_exception_info (void)
  {
!   return __eh_info;
  }
  
  /* Compiler hook to push a new exception onto the stack.
--- 104,110 ----
  extern "C" cp_eh_info *
  __cp_exception_info (void)
  {
!   return *__get_eh_info ();
  }
  
  /* Compiler hook to push a new exception onto the stack.
***************
*** 119,126 ****
    p->cleanup = cleanup;
    p->handlers = 0;
    p->caught = false;
!   p->next = __eh_info;
!   __eh_info = p;
  }
  
  /* Compiler hook to pop an exception that has been finalized.  Used by
--- 119,129 ----
    p->cleanup = cleanup;
    p->handlers = 0;
    p->caught = false;
! 
!   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,137 ****
  extern "C" void
  __cp_pop_exception (cp_eh_info *p, bool handler)
  {
!   cp_eh_info **q = &__eh_info;
  
    --p->handlers;
  
--- 134,140 ----
  extern "C" void
  __cp_pop_exception (cp_eh_info *p, bool handler)
  {
!   cp_eh_info **q = __get_eh_info ();
  
    --p->handlers;
  

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1997-12-11 13:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <199712080853.JAA18141.cygnus.egcs@lev.labs.trema.com>
1997-12-08  1:52 ` MT-safe EH diffs against 1.00 Jason Merrill
1997-12-11 13:03 Mike Stump
  -- strict thread matches above, loose matches on Subject: below --
1997-12-08  0:53 Teemu Torma

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).