public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Merge from LTO: eh_personality changes
@ 2009-09-04 13:34 Richard Guenther
  2009-09-04 13:37 ` Diego Novillo
                   ` (2 more replies)
  0 siblings, 3 replies; 39+ messages in thread
From: Richard Guenther @ 2009-09-04 13:34 UTC (permalink / raw)
  To: gcc-patches; +Cc: Diego Novillo


This merges the eh_personality changes from the branch.  It moves us
to store the eh personality decl per function.  The entanglement
between the C and ObjC frontends makes a new langhook necessary to
initialize the personality decl - other frontends don't really need it.

Bootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk?

This is the last non-LTO specific bits after fld merge on the branch.

Thanks,
Richard.

2009-09-04  Richard Guenther  <rguenther@suse.de>
	Rafael Avila de Espindola  <espindola@google.com>

	* c-decl.c (c_maybe_initialize_eh): Init eh_personality_decl
        instead of eh_personality_libfunc.
        (finish_decl): Don't call c_maybe_initialize_eh.
        * c-parser.c (c_parse_file): Call lang_hooks.init_eh.
        * dwarf2out.c (output_call_frame_info, dwarf2out_do_cfi_startproc,
	dwarf2out_begin_prologue): Use personality from current_function_decl.
        * except.c (sjlj_emit_function_enter, output_function_exception_table):
        Use personality from current_function_decl.
        * expr.h (build_personality_function, get_personality_function): New.
        * libfuncs.h (libfunc_index): Remove LTI_eh_personality.
        (eh_personality_libfunc): Remove.
        * lto-function-in.c (lto_init_eh): Don't set eh_personality_libfunc.
        (input_function_decl): Read decl->function_decl.personality.
        * lto-function-out.c (output_function_decl): Write
        decl->function_decl.personality.
        * optabs.c (build_libfunc_function): New function split out from ...
	(init_one_libfunc): ... here.
        * toplev.c (eh_personality_decl): New.
        * tree.c (make_node_stat):  Set DECL_FUNCTION_PERSONALITY.
        * tree.h (DECL_FUNCTION_PERSONALITY): New.
        (tree_function_decl): Add personality.
        (eh_personality_decl): New.

	* langhooks-def.h (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_INITIALIZER): Adjust.
	* langhooks.h (struct lang_hooks): Add init_eh.
	* c-lang.c (LANG_HOOKS_INIT_EH): Define.

	objc/
	* objc-act.c (objc_init_exceptions): Export.  Move warning code ...
	(objc_begin_try_stmt): ... here
	(objc_build_throw_stmt): ... and here.
	* objc-act.h (objc_init_exceptions): Declare.
	* objc-lang.c (LANG_HOOKS_INIT_EH): Define.

	cp/
	* except.c (init_exception_processing, choose_personality_routine):
	Init eh_personality_decl instead of eh_personality_libfunc.

	java/
	* decl.c (java_init_decl_processing): Init eh_personality_decl
	instead of eh_personality_libfunc.

	ada/
	* gcc-interface/misc.c (gnat_init_gcc_eh): Init eh_personality_decl
	instead of eh_personality_libfunc.

	fortran/
	* f95-lang.c (gfc_maybe_initialize_eh): Init eh_personality_decl
	instead of eh_personality_libfunc.

Index: gcc/java/decl.c
===================================================================
*** gcc/java/decl.c.orig	2009-09-03 16:53:25.000000000 +0200
--- gcc/java/decl.c	2009-09-03 17:04:07.000000000 +0200
*************** java_init_decl_processing (void)
*** 1195,1203 ****
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                                              ? "__gcj_personality_sj0"
!                                              : "__gcj_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
--- 1195,1206 ----
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
! 
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcj_personality_sj0"
! 				  : "__gcj_personality_v0");
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
Index: gcc/libfuncs.h
===================================================================
*** gcc/libfuncs.h.orig	2009-09-03 16:53:25.000000000 +0200
--- gcc/libfuncs.h	2009-09-03 17:04:07.000000000 +0200
*************** enum libfunc_index
*** 31,37 ****
    LTI_setbits,
  
    LTI_unwind_resume,
-   LTI_eh_personality,
    LTI_setjmp,
    LTI_longjmp,
    LTI_unwind_sjlj_register,
--- 31,36 ----
*************** extern GTY(()) rtx libfunc_table[LTI_MAX
*** 61,67 ****
  #define setbits_libfunc	(libfunc_table[LTI_setbits])
  
  #define unwind_resume_libfunc	(libfunc_table[LTI_unwind_resume])
- #define eh_personality_libfunc	(libfunc_table[LTI_eh_personality])
  #define setjmp_libfunc	(libfunc_table[LTI_setjmp])
  #define longjmp_libfunc	(libfunc_table[LTI_longjmp])
  #define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
--- 60,65 ----
Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c.orig	2009-09-03 16:53:25.000000000 +0200
--- gcc/optabs.c	2009-09-03 17:04:07.000000000 +0200
*************** libfunc_decl_eq (const void *entry1, con
*** 6023,6028 ****
--- 6023,6050 ----
    return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
  }
  
+ /* Build a decl for a libfunc named NAME. */
+ 
+ tree
+ build_libfunc_function (const char *name)
+ {
+   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+ 			  get_identifier (name),
+                           build_function_type (integer_type_node, NULL_TREE));
+   /* ??? We don't have any type information except for this is
+      a function.  Pretend this is "int foo()".  */
+   DECL_ARTIFICIAL (decl) = 1;
+   DECL_EXTERNAL (decl) = 1;
+   TREE_PUBLIC (decl) = 1;
+   gcc_assert (DECL_ASSEMBLER_NAME (decl));
+ 
+   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
+      are the flags assigned by targetm.encode_section_info.  */
+   SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
+ 
+   return decl;
+ }
+ 
  rtx
  init_one_libfunc (const char *name)
  {
*************** init_one_libfunc (const char *name)
*** 6043,6061 ****
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       /* ??? We don't have any type information except for this is
! 	 a function.  Pretend this is "int foo()".  */
!       decl = build_decl (UNKNOWN_LOCATION,
! 			 FUNCTION_DECL, get_identifier (name),
! 			 build_function_type (integer_type_node, NULL_TREE));
!       DECL_ARTIFICIAL (decl) = 1;
!       DECL_EXTERNAL (decl) = 1;
!       TREE_PUBLIC (decl) = 1;
! 
!       /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
! 	 are the flags assigned by targetm.encode_section_info.  */
!       SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
! 
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
--- 6065,6071 ----
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       decl = build_libfunc_function (name);
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/tree.h	2009-09-03 17:04:07.000000000 +0200
*************** struct GTY(()) tree_decl_minimal {
*** 2533,2538 ****
--- 2533,2541 ----
  #define DECL_DEBUG_EXPR_IS_FROM(NODE) \
    (DECL_COMMON_CHECK (NODE)->decl_common.debug_expr_is_from)
  
+ #define DECL_FUNCTION_PERSONALITY(NODE) \
+   (FUNCTION_DECL_CHECK (NODE)->function_decl.personality)
+ 
  /* Nonzero for a given ..._DECL node means that the name of this node should
     be ignored for symbolic debug purposes.  */
  #define DECL_IGNORED_P(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.ignored_flag)
*************** struct GTY(()) tree_function_decl {
*** 3183,3188 ****
--- 3186,3194 ----
  
    struct function *f;
  
+   /* The personality function. Used for stack unwinding. */
+   tree personality;
+ 
    /* Function specific options that are used by this function.  */
    tree function_specific_target;	/* target options */
    tree function_specific_optimization;	/* optimization options */
*************** extern int pedantic_lvalues;
*** 4556,4561 ****
--- 4562,4570 ----
  
  extern GTY(()) tree current_function_decl;
  
+ /* The eh personally function that this FE wants to use. */
+ extern GTY(()) tree eh_personality_decl;
+ 
  /* Nonzero means a FUNC_BEGIN label was emitted.  */
  extern GTY(()) const char * current_function_func_begin_label;
  \f
Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/objc/objc-act.c	2009-09-03 18:57:23.000000000 +0200
*************** objc_eh_runtime_type (tree type)
*** 3497,3503 ****
  
  /* Initialize exception handling.  */
  
! static void
  objc_init_exceptions (void)
  {
    static bool done = false;
--- 3497,3503 ----
  
  /* Initialize exception handling.  */
  
! void
  objc_init_exceptions (void)
  {
    static bool done = false;
*************** objc_init_exceptions (void)
*** 3505,3526 ****
      return;
    done = true;
  
-   if (flag_objc_sjlj_exceptions)
-     {
-       /* On Darwin, ObjC exceptions require a sufficiently recent
- 	 version of the runtime, so the user must ask for them explicitly.  */
-       if (!flag_objc_exceptions)
- 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
- 		 "exception syntax");
-     }
  #ifndef OBJCPLUS
!   else
      {
        c_eh_initialized_p = true;
!       eh_personality_libfunc
! 	= init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 			    ? "__gnu_objc_personality_sj0"
! 			    : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
        lang_eh_runtime_type = objc_eh_runtime_type;
--- 3505,3519 ----
      return;
    done = true;
  
  #ifndef OBJCPLUS
!   if (!flag_objc_sjlj_exceptions)
      {
        c_eh_initialized_p = true;
!       eh_personality_decl
! 	= build_personality_function (USING_SJLJ_EXCEPTIONS
! 				      ? "__gnu_objc_personality_sj0"
! 				      : "__gnu_objc_personality_v0");
! 
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
        lang_eh_runtime_type = objc_eh_runtime_type;
*************** objc_begin_try_stmt (location_t try_locu
*** 3824,3830 ****
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   objc_init_exceptions ();
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
--- 3817,3830 ----
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
*************** objc_build_throw_stmt (location_t loc, t
*** 3973,3979 ****
  {
    tree args;
  
!   objc_init_exceptions ();
  
    if (throw_expr == NULL)
      {
--- 3973,3986 ----
  {
    tree args;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (throw_expr == NULL)
      {
Index: gcc/toplev.c
===================================================================
*** gcc/toplev.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/toplev.c	2009-09-03 17:04:07.000000000 +0200
*************** int optimize_size = 0;
*** 202,207 ****
--- 202,210 ----
     or 0 if between functions.  */
  tree current_function_decl;
  
+ /* The EH personality function that this FE wants to use. */
+ tree eh_personality_decl;
+ 
  /* Set to the FUNC_BEGIN label of the current function, or NULL
     if none.  */
  const char * current_function_func_begin_label;
Index: gcc/cp/except.c
===================================================================
*** gcc/cp/except.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/cp/except.c	2009-09-03 17:04:07.000000000 +0200
*************** init_exception_processing (void)
*** 78,86 ****
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 					     ? "__gxx_personality_sj0"
! 					     : "__gxx_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
--- 78,88 ----
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gxx_personality_sj0"
! 				  : "__gxx_personality_v0");
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
*************** decl_is_java_type (tree decl, int err)
*** 313,319 ****
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_libfunc is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
--- 315,321 ----
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_decl is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
*************** choose_personality_routine (enum languag
*** 354,362 ****
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 						 ? "__gcj_personality_sj0"
! 						 : "__gcj_personality_v0");
        break;
  
      default:
--- 356,365 ----
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_decl
! 	= build_personality_function (USING_SJLJ_EXCEPTIONS
! 				      ? "__gcj_personality_sj0"
! 				      : "__gcj_personality_v0");
        break;
  
      default:
Index: gcc/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/dwarf2out.c	2009-09-03 17:04:07.000000000 +0200
*************** static GTY(()) section *debug_str_sectio
*** 216,221 ****
--- 216,225 ----
  static GTY(()) section *debug_ranges_section;
  static GTY(()) section *debug_frame_section;
  
+ /* Personality decl of current unit.  Used only when assembler does not support
+    personality CFI.  */
+ static GTY(()) rtx current_unit_personality;
+ 
  /* How to start an assembler comment.  */
  #ifndef ASM_COMMENT_START
  #define ASM_COMMENT_START ";#"
*************** output_call_frame_info (int for_eh)
*** 3599,3604 ****
--- 3603,3609 ----
    int per_encoding = DW_EH_PE_absptr;
    int lsda_encoding = DW_EH_PE_absptr;
    int return_reg;
+   rtx personality = NULL;
    int dw_cie_version;
  
    /* Don't emit a CIE if there won't be any FDEs.  */
*************** output_call_frame_info (int for_eh)
*** 3684,3689 ****
--- 3689,3696 ----
  
    augmentation[0] = 0;
    augmentation_size = 0;
+ 
+   personality = current_unit_personality;
    if (for_eh)
      {
        char *p;
*************** output_call_frame_info (int for_eh)
*** 3703,3713 ****
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (eh_personality_libfunc)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (eh_personality_libfunc);
  	}
        if (any_lsda_needed)
  	{
--- 3710,3720 ----
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (personality)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (personality);
  	}
        if (any_lsda_needed)
  	{
*************** output_call_frame_info (int for_eh)
*** 3726,3732 ****
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
--- 3733,3739 ----
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (personality && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
*************** output_call_frame_info (int for_eh)
*** 3760,3771 ****
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (eh_personality_libfunc)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   eh_personality_libfunc,
  					   true, NULL);
  	}
  
--- 3767,3778 ----
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (personality)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   personality,
  					   true, NULL);
  	}
  
*************** dwarf2out_do_cfi_startproc (bool second)
*** 3824,3836 ****
  {
    int enc;
    rtx ref;
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (eh_personality_libfunc)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = eh_personality_libfunc;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
--- 3831,3844 ----
  {
    int enc;
    rtx ref;
+   rtx personality = get_personality_function (current_function_decl);
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (personality)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = personality;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
*************** dwarf2out_begin_prologue (unsigned int l
*** 3873,3878 ****
--- 3881,3887 ----
    char label[MAX_ARTIFICIAL_LABEL_BYTES];
    char * dup_label;
    dw_fde_ref fde;
+   rtx personality;
    section *fnsec;
  
    current_function_func_begin_label = NULL;
*************** dwarf2out_begin_prologue (unsigned int l
*** 3967,3974 ****
--- 3976,3992 ----
      dwarf2out_source_line (line, file, 0, true);
  #endif
  
+   personality = get_personality_function (current_function_decl);
    if (dwarf2out_do_cfi_asm ())
      dwarf2out_do_cfi_startproc (false);
+   else
+     {
+       if (!current_unit_personality || current_unit_personality == personality)
+         current_unit_personality = personality;
+       else
+ 	sorry ("Multiple EH personalities are supported only with assemblers "
+ 	       "supporting .cfi.personality directive.");
+     }
  }
  
  /* Output a marker (i.e. a label) for the absolute end of the generated code
Index: gcc/expr.h
===================================================================
*** gcc/expr.h.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/expr.h	2009-09-03 17:04:07.000000000 +0200
*************** extern void init_all_optabs (void);
*** 814,819 ****
--- 814,845 ----
  extern rtx init_one_libfunc (const char *);
  extern rtx set_user_assembler_libfunc (const char *, const char *);
  
+ /* Build a decl for a libfunc named NAME. */
+ extern tree build_libfunc_function (const char *);
+ 
+ /* Build a decl for a personality function named NAME. */
+ static inline tree
+ build_personality_function (const char *name)
+ {
+   return build_libfunc_function (name);
+ }
+ 
+ /* Extracts the personality function of DECL and returns the corresponding
+    libfunc. */
+ 
+ static inline rtx
+ get_personality_function (tree decl)
+ {
+   tree personality = DECL_FUNCTION_PERSONALITY (decl);
+   tree name;
+   if (!personality)
+     return NULL;
+ 
+   name = DECL_ASSEMBLER_NAME (personality);
+ 
+   return init_one_libfunc (IDENTIFIER_POINTER (name));
+ }
+ 
  extern int vector_mode_valid_p (enum machine_mode);
  
  #endif /* GCC_EXPR_H */
Index: gcc/ada/gcc-interface/misc.c
===================================================================
*** gcc/ada/gcc-interface/misc.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/ada/gcc-interface/misc.c	2009-09-03 17:04:07.000000000 +0200
*************** gnat_init_gcc_eh (void)
*** 431,439 ****
       right exception regions.  */
    using_eh_for_cleanups ();
  
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 					     ? "__gnat_eh_personality_sj"
! 					     : "__gnat_eh_personality");
    lang_eh_type_covers = gnat_eh_type_covers;
    lang_eh_runtime_type = gnat_return_tree;
    default_init_unwind_resume_libfunc ();
--- 431,441 ----
       right exception regions.  */
    using_eh_for_cleanups ();
  
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gnat_eh_personality_sj"
! 				  : "__gnat_eh_personality");
! 
    lang_eh_type_covers = gnat_eh_type_covers;
    lang_eh_runtime_type = gnat_return_tree;
    default_init_unwind_resume_libfunc ();
Index: gcc/c-decl.c
===================================================================
*** gcc/c-decl.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/c-decl.c	2009-09-03 17:04:07.000000000 +0200
*************** merge_decls (tree newdecl, tree olddecl,
*** 2365,2371 ****
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID and DECL_CONTEXT.  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
--- 2365,2372 ----
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
!      DECL_ARGUMENTS (if appropriate).  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
*************** c_maybe_initialize_eh (void)
*** 4052,4061 ****
      return;
  
    c_eh_initialized_p = true;
!   eh_personality_libfunc
!     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 			? "__gcc_personality_sj0"
! 			: "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 4053,4063 ----
      return;
  
    c_eh_initialized_p = true;
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcc_personality_sj0"
! 				  : "__gcc_personality_v0");
! 
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
*************** finish_decl (tree decl, location_t init_
*** 4360,4368 ****
  	  TREE_USED (decl) = 1;
  	  TREE_USED (cleanup_decl) = 1;
  
- 	  /* Initialize EH, if we've been told to do so.  */
- 	  c_maybe_initialize_eh ();
- 
  	  push_cleanup (decl, cleanup, false);
  	}
      }
--- 4362,4367 ----
Index: gcc/fortran/f95-lang.c
===================================================================
*** gcc/fortran/f95-lang.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/fortran/f95-lang.c	2009-09-03 17:04:07.000000000 +0200
*************** gfc_maybe_initialize_eh (void)
*** 1155,1164 ****
      return;
  
    gfc_eh_initialized_p = true;
!   eh_personality_libfunc
!     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                        ? "__gcc_personality_sj0"
!                        : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 1155,1164 ----
      return;
  
    gfc_eh_initialized_p = true;
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcc_personality_sj0"
! 				  : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/except.c	2009-09-03 17:04:07.000000000 +0200
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2424,2429 ****
--- 2424,2430 ----
  {
    rtx fn_begin, fc, mem, seq;
    bool fn_begin_outside_block;
+   rtx personality = get_personality_function (current_function_decl);
  
    fc = crtl->eh.sjlj_fc;
  
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2432,2440 ****
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (eh_personality_libfunc);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, eh_personality_libfunc);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
--- 2433,2441 ----
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (personality);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, personality);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
*************** output_ttype (tree type, int tt_format, 
*** 4394,4400 ****
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section)
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
--- 4395,4401 ----
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section, rtx ARG_UNUSED (personality))
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
*************** output_one_function_exception_table (con
*** 4410,4416 ****
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, eh_personality_libfunc);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
--- 4411,4417 ----
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, personality);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
*************** output_one_function_exception_table (con
*** 4580,4595 ****
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (eh_personality_libfunc)
!     assemble_external_libcall (eh_personality_libfunc);
  
!   output_one_function_exception_table (fnname, 0);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1);
  
    switch_to_section (current_function_section ());
  }
--- 4581,4598 ----
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
+   rtx personality = get_personality_function (current_function_decl);
+ 
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (personality)
!     assemble_external_libcall (personality);
  
!   output_one_function_exception_table (fnname, 0, personality);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1, personality);
  
    switch_to_section (current_function_section ());
  }
Index: gcc/c-parser.c
===================================================================
*** gcc/c-parser.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/c-parser.c	2009-09-03 17:25:23.000000000 +0200
*************** c_parse_file (void)
*** 8607,8612 ****
--- 8607,8615 ----
    the_parser = GGC_NEW (c_parser);
    *the_parser = tparser;
  
+   /* Initialize EH, if we've been told to do so.  */
+   lang_hooks.init_eh ();
+ 
    c_parser_translation_unit (the_parser);
    the_parser = NULL;
  }
Index: gcc/tree.c
===================================================================
*** gcc/tree.c.orig	2009-09-03 16:53:26.000000000 +0200
--- gcc/tree.c	2009-09-03 17:04:07.000000000 +0200
*************** make_node_stat (enum tree_code code MEM_
*** 867,872 ****
--- 867,873 ----
  	    {
  	      DECL_ALIGN (t) = FUNCTION_BOUNDARY;
  	      DECL_MODE (t) = FUNCTION_MODE;
+ 	      DECL_FUNCTION_PERSONALITY (t) = eh_personality_decl;
  	    }
  	  else
  	    DECL_ALIGN (t) = 1;
Index: gcc/c-lang.c
===================================================================
*** gcc/c-lang.c.orig	2009-09-03 17:25:31.000000000 +0200
--- gcc/c-lang.c	2009-09-03 17:26:29.000000000 +0200
*************** enum c_language_kind c_language = clk_c;
*** 44,49 ****
--- 44,51 ----
  #define LANG_HOOKS_NAME "GNU C"
  #undef LANG_HOOKS_INIT
  #define LANG_HOOKS_INIT c_objc_common_init
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH c_maybe_initialize_eh
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/langhooks-def.h
===================================================================
*** gcc/langhooks-def.h.orig	2009-09-03 17:20:17.000000000 +0200
--- gcc/langhooks-def.h	2009-09-03 17:29:30.000000000 +0200
*************** extern void lhd_omp_firstprivatize_type_
*** 107,112 ****
--- 107,113 ----
  #define LANG_HOOKS_EXPR_TO_DECL		lhd_expr_to_decl
  #define LANG_HOOKS_TO_TARGET_CHARSET	lhd_to_target_charset
  #define LANG_HOOKS_INIT_TS		lhd_do_nothing
+ #define LANG_HOOKS_INIT_EH		NULL
  
  /* Attribute hooks.  */
  #define LANG_HOOKS_ATTRIBUTE_TABLE		NULL
*************** extern tree lhd_make_node (enum tree_cod
*** 271,276 ****
--- 272,278 ----
    LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
    LANG_HOOKS_INIT_TS,          \
    LANG_HOOKS_EXPR_TO_DECL, \
+   LANG_HOOKS_INIT_EH, \
  }
  
  #endif /* GCC_LANG_HOOKS_DEF_H */
Index: gcc/langhooks.h
===================================================================
*** gcc/langhooks.h.orig	2009-09-03 17:20:17.000000000 +0200
--- gcc/langhooks.h	2009-09-03 17:22:05.000000000 +0200
*************** struct lang_hooks
*** 414,419 ****
--- 414,422 ----
       if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating.  */
    tree (*expr_to_decl) (tree expr, bool *tc, bool *se);
  
+   /* Called to initialize the exception handing personality.  */
+   void (*init_eh) (void);
+ 
    /* Whenever you add entries here, make sure you adjust langhooks-def.h
       and langhooks.c accordingly.  */
  };
Index: gcc/objc/objc-act.h
===================================================================
*** gcc/objc/objc-act.h.orig	2009-09-03 17:24:39.000000000 +0200
--- gcc/objc/objc-act.h	2009-09-03 17:28:37.000000000 +0200
*************** const char *objc_printable_name (tree, i
*** 32,37 ****
--- 32,38 ----
  void objc_finish_file (void);
  tree objc_fold_obj_type_ref (tree, tree);
  int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+ void objc_init_exceptions (void);
  
  /* NB: The remaining public functions are prototyped in c-common.h, for the
     benefit of stub-objc.c and objc-act.c.  */
Index: gcc/objc/objc-lang.c
===================================================================
*** gcc/objc/objc-lang.c.orig	2009-09-03 17:23:12.000000000 +0200
--- gcc/objc/objc-lang.c	2009-09-03 17:24:19.000000000 +0200
*************** static void objc_init_ts (void);
*** 50,55 ****
--- 50,57 ----
  #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS objc_init_ts
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH objc_init_exceptions
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-04 13:34 [PATCH] Merge from LTO: eh_personality changes Richard Guenther
@ 2009-09-04 13:37 ` Diego Novillo
  2009-09-04 13:41   ` Richard Guenther
  2009-09-05 16:37 ` Richard Henderson
  2009-09-05 16:38 ` Richard Henderson
  2 siblings, 1 reply; 39+ messages in thread
From: Diego Novillo @ 2009-09-04 13:37 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On Fri, Sep 4, 2009 at 09:34, Richard Guenther<rguenther@suse.de> wrote:

>        * lto-function-in.c (lto_init_eh): Don't set eh_personality_libfunc.
>        (input_function_decl): Read decl->function_decl.personality.
>        * lto-function-out.c (output_function_decl): Write
>        decl->function_decl.personality.

These two entries should not be needed yet.


Diego.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-04 13:37 ` Diego Novillo
@ 2009-09-04 13:41   ` Richard Guenther
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Guenther @ 2009-09-04 13:41 UTC (permalink / raw)
  To: Diego Novillo; +Cc: gcc-patches

[-- Attachment #1: Type: TEXT/PLAIN, Size: 588 bytes --]

On Fri, 4 Sep 2009, Diego Novillo wrote:

> On Fri, Sep 4, 2009 at 09:34, Richard Guenther<rguenther@suse.de> wrote:
> 
> >        * lto-function-in.c (lto_init_eh): Don't set eh_personality_libfunc.
> >        (input_function_decl): Read decl->function_decl.personality.
> >        * lto-function-out.c (output_function_decl): Write
> >        decl->function_decl.personality.
> 
> These two entries should not be needed yet.

Eh - right.  I cut'n'pasted the changelog entry.

And obviously - ok after the freeze is over?

Thanks,
Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-04 13:34 [PATCH] Merge from LTO: eh_personality changes Richard Guenther
  2009-09-04 13:37 ` Diego Novillo
@ 2009-09-05 16:37 ` Richard Henderson
  2009-09-05 16:38 ` Richard Henderson
  2 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2009-09-05 16:37 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/04/2009 06:34 AM, Richard Guenther wrote:
> + 	sorry ("Multiple EH personalities are supported only with assemblers "
> + 	       "supporting .cfi.personality directive.");

There's no reason this can't be fixed.  You simply need to rearrange
the .eh_frame generation to emit multiple CFI's.

Also, I think you need to add something to prevent inlining of functions
that use different personality functions.

Do you have a strategy for handling

   if (targetm.arm_eabi_unwinder)
     unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");

since this function is only used for c++/java?


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-04 13:34 [PATCH] Merge from LTO: eh_personality changes Richard Guenther
  2009-09-04 13:37 ` Diego Novillo
  2009-09-05 16:37 ` Richard Henderson
@ 2009-09-05 16:38 ` Richard Henderson
  2009-09-05 17:24   ` Richard Guenther
  2 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2009-09-05 16:38 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/04/2009 06:34 AM, Richard Guenther wrote:
> + 	sorry ("Multiple EH personalities are supported only with assemblers "
> + 	       "supporting .cfi.personality directive.");

There's no reason this can't be fixed.  You simply need to rearrange
the .eh_frame generation to emit multiple CFI's.

Also, I think you need to add something to prevent inlining of functions
that use different personality functions.

Do you have a strategy for handling

   if (targetm.arm_eabi_unwinder)
     unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");

since this function is only used for c++/java?


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-05 16:38 ` Richard Henderson
@ 2009-09-05 17:24   ` Richard Guenther
  2009-09-05 18:11     ` Richard Henderson
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-05 17:24 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Sat, 5 Sep 2009, Richard Henderson wrote:

> On 09/04/2009 06:34 AM, Richard Guenther wrote:
> > + 	sorry ("Multiple EH personalities are supported only with assemblers "
> > + 	       "supporting .cfi.personality directive.");
> 
> There's no reason this can't be fixed.  You simply need to rearrange
> the .eh_frame generation to emit multiple CFI's.

Ok.  The sorry () merely affects LTO for now (there's no other way you
can have different personalities in a TU), so I guess a FIXME is enough
here?  I understand that without this patch LTOing C and C++ together
wouldn't work, but maybe Diego can clarify.

> Also, I think you need to add something to prevent inlining of functions
> that use different personality functions.

I don't think so.  The IL should be still in a state where the inlined
pieces would simply inherit the callers personality.  But maybe I'm
missing something?

> Do you have a strategy for handling
> 
>   if (targetm.arm_eabi_unwinder)
>     unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
> 
> since this function is only used for c++/java?

No.  Do you have something in mind?

I see the patch is somewhat incomplete (there's also
lang_eh_runtime_type, but maybe we never call add_type_for_runtime
after a frontend finishes - in which case this should have been
a langhook?) - and in general the integration of EH aware and
non-EH aware code with LTO still needs work and thought.

At least it seems to work - and as I'm not too deep into EH
related code I don't have plans to extend it much.

Thanks,
Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-05 17:24   ` Richard Guenther
@ 2009-09-05 18:11     ` Richard Henderson
  2009-09-08 12:37       ` Richard Guenther
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2009-09-05 18:11 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/05/2009 10:24 AM, Richard Guenther wrote:
>> Also, I think you need to add something to prevent inlining of functions
>> that use different personality functions.
>
> I don't think so.  The IL should be still in a state where the inlined
> pieces would simply inherit the callers personality.  But maybe I'm
> missing something?

You're missing that the personality functions have to deal with
the language's runtime types, as recorded in the catch type_list
and the allowed-exceptions type_list.

You can't expect the Ada personality to deal with C++ runtime types.

>> Do you have a strategy for handling
>>
>>    if (targetm.arm_eabi_unwinder)
>>      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
>>
>> since this function is only used for c++/java?
>
> No.  Do you have something in mind?

The only thing I can think of is to record the fact that the
GIMPLE_TRY came from c++/java in the eh_region tree, which would
allow the RESX expander to emit the proper function for this
particular region.  It's not elegant, but it should work.

> I see the patch is somewhat incomplete (there's also
> lang_eh_runtime_type, but maybe we never call add_type_for_runtime
> after a frontend finishes - in which case this should have been
> a langhook?) - and in general the integration of EH aware and
> non-EH aware code with LTO still needs work and thought.

We do all the calls to add_type_for_runtime during
pass_lower_eh, right toward the beginning of compilation.
I'm pretty sure we don't need to do anything else with
that lang hook for LTO.


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-05 18:11     ` Richard Henderson
@ 2009-09-08 12:37       ` Richard Guenther
  2009-09-08 15:20         ` Richard Guenther
  2009-09-08 15:48         ` Richard Henderson
  0 siblings, 2 replies; 39+ messages in thread
From: Richard Guenther @ 2009-09-08 12:37 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Sat, 5 Sep 2009, Richard Henderson wrote:

> On 09/05/2009 10:24 AM, Richard Guenther wrote:
> > > Also, I think you need to add something to prevent inlining of functions
> > > that use different personality functions.
> > 
> > I don't think so.  The IL should be still in a state where the inlined
> > pieces would simply inherit the callers personality.  But maybe I'm
> > missing something?
> 
> You're missing that the personality functions have to deal with
> the language's runtime types, as recorded in the catch type_list
> and the allowed-exceptions type_list.
> 
> You can't expect the Ada personality to deal with C++ runtime types.

Hmm, ok.  So how about setting DECL_EH_PERSONALITY during eh-lowering
and only for functions with a non-empty EH tree.  We then would
disallow inlining functions with different non-NULL personality.

> > > Do you have a strategy for handling
> > > 
> > >    if (targetm.arm_eabi_unwinder)
> > >      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
> > > 
> > > since this function is only used for c++/java?
> > 
> > No.  Do you have something in mind?
> 
> The only thing I can think of is to record the fact that the
> GIMPLE_TRY came from c++/java in the eh_region tree, which would
> allow the RESX expander to emit the proper function for this
> particular region.  It's not elegant, but it should work.

With your EH rewrite we could make this function explicit in the IL,
can we?

> > I see the patch is somewhat incomplete (there's also
> > lang_eh_runtime_type, but maybe we never call add_type_for_runtime
> > after a frontend finishes - in which case this should have been
> > a langhook?) - and in general the integration of EH aware and
> > non-EH aware code with LTO still needs work and thought.
> 
> We do all the calls to add_type_for_runtime during
> pass_lower_eh, right toward the beginning of compilation.
> I'm pretty sure we don't need to do anything else with
> that lang hook for LTO.

Ok.  I'll modify the patch to make this a true langhook and maybe move
the eh-personality also to a langhook called from eh lowering.

How does that sound?

Thanks,
Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-08 12:37       ` Richard Guenther
@ 2009-09-08 15:20         ` Richard Guenther
  2009-09-08 15:49           ` Richard Henderson
  2009-09-08 17:38           ` Eric Botcazou
  2009-09-08 15:48         ` Richard Henderson
  1 sibling, 2 replies; 39+ messages in thread
From: Richard Guenther @ 2009-09-08 15:20 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Tue, 8 Sep 2009, Richard Guenther wrote:

> On Sat, 5 Sep 2009, Richard Henderson wrote:
> 
> > On 09/05/2009 10:24 AM, Richard Guenther wrote:
> > > > Also, I think you need to add something to prevent inlining of functions
> > > > that use different personality functions.
> > > 
> > > I don't think so.  The IL should be still in a state where the inlined
> > > pieces would simply inherit the callers personality.  But maybe I'm
> > > missing something?
> > 
> > You're missing that the personality functions have to deal with
> > the language's runtime types, as recorded in the catch type_list
> > and the allowed-exceptions type_list.
> > 
> > You can't expect the Ada personality to deal with C++ runtime types.
> 
> Hmm, ok.  So how about setting DECL_EH_PERSONALITY during eh-lowering
> and only for functions with a non-empty EH tree.  We then would
> disallow inlining functions with different non-NULL personality.
> 
> > > > Do you have a strategy for handling
> > > > 
> > > >    if (targetm.arm_eabi_unwinder)
> > > >      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
> > > > 
> > > > since this function is only used for c++/java?
> > > 
> > > No.  Do you have something in mind?
> > 
> > The only thing I can think of is to record the fact that the
> > GIMPLE_TRY came from c++/java in the eh_region tree, which would
> > allow the RESX expander to emit the proper function for this
> > particular region.  It's not elegant, but it should work.
> 
> With your EH rewrite we could make this function explicit in the IL,
> can we?
> 
> > > I see the patch is somewhat incomplete (there's also
> > > lang_eh_runtime_type, but maybe we never call add_type_for_runtime
> > > after a frontend finishes - in which case this should have been
> > > a langhook?) - and in general the integration of EH aware and
> > > non-EH aware code with LTO still needs work and thought.
> > 
> > We do all the calls to add_type_for_runtime during
> > pass_lower_eh, right toward the beginning of compilation.
> > I'm pretty sure we don't need to do anything else with
> > that lang hook for LTO.
> 
> Ok.  I'll modify the patch to make this a true langhook and maybe move
> the eh-personality also to a langhook called from eh lowering.

The latter is difficult as C++ is playing some tricks with Java vs.
non-Java personality, so I leave that alone for now.

> How does that sound?

FYI the following two patches would implement the above (untested).

Richard.

2009-09-08  Richard Guenther  <rguenther@suse.de>

	* c-decl.c (finish_decl): Don't call c_maybe_initialize_eh.
        * c-parser.c (c_parser_omp_construct): Likewise.
	(c_parse_file): Call lang_hooks.init_eh.
	* except.h (lang_eh_runtime_type): Remove.
        * except.c (lang_eh_runtime_type): Remove.
	(add_type_for_runtime): Call lang_hooks.type_for_runtime instead.

	* langhooks-def.h (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.
	(LANG_HOOKS_INITIALIZER): Adjust.
	(lhd_pass_through_t): Declare.
	* langhooks.h (struct lang_hooks): Add init_eh and eh_runtime_type.
	* langhooks.c (lhd_pass_through_t): New function.

	* c-lang.c (LANG_HOOKS_INIT_EH): Define.

	objc/
	* objc-act.c (objc_eh_runtime_type): Export.
	(objc_init_exceptions): Export.  Do not set objc_init_exceptions.
	Move warning code ...
	(objc_begin_try_stmt): ... here
	(objc_build_throw_stmt): ... and here.
	* objc-act.h (objc_init_exceptions): Declare.
	(objc_eh_runtime_type): Likewise.
	* objc-lang.c (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.

	cp/
	* except.c (init_exception_processing): Do not set
	lang_eh_runtime_type.
	* cp-lang.c (LANG_HOOKS_EH_RUNTIME_TYPE): Define.

	java/
	* decl.c (do_nothing): Remove.
	(java_init_decl_processing): Do not set lang_eh_runtime_type.

	ada/
	* gcc-interface/misc.c (gnat_init_gcc_eh): Do not set
	lang_eh_runtime_type.

Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c.orig	2009-08-31 15:50:38.000000000 +0200
--- gcc/objc/objc-act.c	2009-09-08 12:29:56.000000000 +0200
*************** static struct objc_try_context *cur_try_
*** 3488,3494 ****
  /* ??? Isn't there a class object or some such?  Is it easy to get?  */
  
  #ifndef OBJCPLUS
! static tree
  objc_eh_runtime_type (tree type)
  {
    return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
--- 3488,3494 ----
  /* ??? Isn't there a class object or some such?  Is it easy to get?  */
  
  #ifndef OBJCPLUS
! tree
  objc_eh_runtime_type (tree type)
  {
    return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
*************** objc_eh_runtime_type (tree type)
*** 3497,3503 ****
  
  /* Initialize exception handling.  */
  
! static void
  objc_init_exceptions (void)
  {
    static bool done = false;
--- 3497,3503 ----
  
  /* Initialize exception handling.  */
  
! void
  objc_init_exceptions (void)
  {
    static bool done = false;
*************** objc_init_exceptions (void)
*** 3505,3520 ****
      return;
    done = true;
  
-   if (flag_objc_sjlj_exceptions)
-     {
-       /* On Darwin, ObjC exceptions require a sufficiently recent
- 	 version of the runtime, so the user must ask for them explicitly.  */
-       if (!flag_objc_exceptions)
- 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
- 		 "exception syntax");
-     }
  #ifndef OBJCPLUS
!   else
      {
        c_eh_initialized_p = true;
        eh_personality_libfunc
--- 3505,3512 ----
      return;
    done = true;
  
  #ifndef OBJCPLUS
!   if (!flag_objc_sjlj_exceptions)
      {
        c_eh_initialized_p = true;
        eh_personality_libfunc
*************** objc_init_exceptions (void)
*** 3523,3529 ****
  			    : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
-       lang_eh_runtime_type = objc_eh_runtime_type;
      }
  #endif
  }
--- 3515,3520 ----
*************** objc_begin_try_stmt (location_t try_locu
*** 3824,3830 ****
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   objc_init_exceptions ();
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
--- 3815,3828 ----
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
*************** objc_build_throw_stmt (location_t loc, t
*** 3973,3979 ****
  {
    tree args;
  
!   objc_init_exceptions ();
  
    if (throw_expr == NULL)
      {
--- 3971,3984 ----
  {
    tree args;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (throw_expr == NULL)
      {
Index: gcc/c-decl.c
===================================================================
*** gcc/c-decl.c.orig	2009-08-31 15:50:38.000000000 +0200
--- gcc/c-decl.c	2009-09-08 12:18:56.000000000 +0200
*************** finish_decl (tree decl, location_t init_
*** 4360,4368 ****
  	  TREE_USED (decl) = 1;
  	  TREE_USED (cleanup_decl) = 1;
  
- 	  /* Initialize EH, if we've been told to do so.  */
- 	  c_maybe_initialize_eh ();
- 
  	  push_cleanup (decl, cleanup, false);
  	}
      }
--- 4360,4365 ----
Index: gcc/c-parser.c
===================================================================
*** gcc/c-parser.c.orig	2009-08-31 15:50:38.000000000 +0200
--- gcc/c-parser.c	2009-09-08 12:34:32.000000000 +0200
*************** c_parser_omp_construct (c_parser *parser
*** 8489,8500 ****
    p_kind = c_parser_peek_token (parser)->pragma_kind;
    c_parser_consume_pragma (parser);
  
-   /* For all constructs below except #pragma omp atomic
-      MUST_NOT_THROW catch handlers are needed when exceptions
-      are enabled.  */
-   if (p_kind != PRAGMA_OMP_ATOMIC)
-     c_maybe_initialize_eh ();
- 
    switch (p_kind)
      {
      case PRAGMA_OMP_ATOMIC:
--- 8489,8494 ----
*************** c_parse_file (void)
*** 8607,8612 ****
--- 8601,8609 ----
    the_parser = GGC_NEW (c_parser);
    *the_parser = tparser;
  
+   /* Initialize EH, if we've been told to do so.  */
+   lang_hooks.init_eh ();
+ 
    c_parser_translation_unit (the_parser);
    the_parser = NULL;
  }
Index: gcc/c-lang.c
===================================================================
*** gcc/c-lang.c.orig	2009-09-04 15:05:57.000000000 +0200
--- gcc/c-lang.c	2009-09-08 12:18:56.000000000 +0200
*************** enum c_language_kind c_language = clk_c;
*** 44,49 ****
--- 44,51 ----
  #define LANG_HOOKS_NAME "GNU C"
  #undef LANG_HOOKS_INIT
  #define LANG_HOOKS_INIT c_objc_common_init
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH c_maybe_initialize_eh
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/langhooks-def.h
===================================================================
*** gcc/langhooks-def.h.orig	2009-09-04 15:05:57.000000000 +0200
--- gcc/langhooks-def.h	2009-09-08 12:29:01.000000000 +0200
*************** extern void lhd_do_nothing (void);
*** 40,45 ****
--- 40,46 ----
  extern void lhd_do_nothing_t (tree);
  extern void lhd_do_nothing_i (int);
  extern void lhd_do_nothing_f (struct function *);
+ extern tree lhd_pass_through_t (tree);
  extern bool lhd_post_options (const char **);
  extern alias_set_type lhd_get_alias_set (tree);
  extern tree lhd_return_null_tree_v (void);
*************** extern void lhd_omp_firstprivatize_type_
*** 107,112 ****
--- 108,115 ----
  #define LANG_HOOKS_EXPR_TO_DECL		lhd_expr_to_decl
  #define LANG_HOOKS_TO_TARGET_CHARSET	lhd_to_target_charset
  #define LANG_HOOKS_INIT_TS		lhd_do_nothing
+ #define LANG_HOOKS_INIT_EH		NULL
+ #define LANG_HOOKS_EH_RUNTIME_TYPE	lhd_pass_through_t
  
  /* Attribute hooks.  */
  #define LANG_HOOKS_ATTRIBUTE_TABLE		NULL
*************** extern tree lhd_make_node (enum tree_cod
*** 271,276 ****
--- 274,281 ----
    LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
    LANG_HOOKS_INIT_TS,          \
    LANG_HOOKS_EXPR_TO_DECL, \
+   LANG_HOOKS_INIT_EH, \
+   LANG_HOOKS_EH_RUNTIME_TYPE, \
  }
  
  #endif /* GCC_LANG_HOOKS_DEF_H */
Index: gcc/langhooks.h
===================================================================
*** gcc/langhooks.h.orig	2009-09-04 15:05:56.000000000 +0200
--- gcc/langhooks.h	2009-09-08 12:23:32.000000000 +0200
*************** struct lang_hooks
*** 414,419 ****
--- 414,425 ----
       if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating.  */
    tree (*expr_to_decl) (tree expr, bool *tc, bool *se);
  
+   /* Called to initialize the exception handing personality.  */
+   void (*init_eh) (void);
+ 
+   /* Map a type to a runtime object to match type.  */
+   tree (*eh_runtime_type) (tree);
+ 
    /* Whenever you add entries here, make sure you adjust langhooks-def.h
       and langhooks.c accordingly.  */
  };
Index: gcc/objc/objc-act.h
===================================================================
*** gcc/objc/objc-act.h.orig	2009-06-15 11:55:46.000000000 +0200
--- gcc/objc/objc-act.h	2009-09-08 12:31:39.000000000 +0200
*************** const char *objc_printable_name (tree, i
*** 32,37 ****
--- 32,39 ----
  void objc_finish_file (void);
  tree objc_fold_obj_type_ref (tree, tree);
  int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+ void objc_init_exceptions (void);
+ tree objc_eh_runtime_type (tree);
  
  /* NB: The remaining public functions are prototyped in c-common.h, for the
     benefit of stub-objc.c and objc-act.c.  */
Index: gcc/objc/objc-lang.c
===================================================================
*** gcc/objc/objc-lang.c.orig	2009-09-04 15:05:40.000000000 +0200
--- gcc/objc/objc-lang.c	2009-09-08 12:31:09.000000000 +0200
*************** static void objc_init_ts (void);
*** 50,55 ****
--- 50,62 ----
  #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS objc_init_ts
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH objc_init_exceptions
+ 
+ #ifndef OBJCPLUS
+ #undef LANG_HOOKS_EH_RUNTIME_TYPE
+ #define LANG_HOOKS_EH_RUNTIME_TYPE objc_eh_runtime_type
+ #endif
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/ada/gcc-interface/misc.c
===================================================================
*** gcc/ada/gcc-interface/misc.c.orig	2009-09-04 15:05:52.000000000 +0200
--- gcc/ada/gcc-interface/misc.c	2009-09-08 12:32:31.000000000 +0200
*************** gnat_init_gcc_eh (void)
*** 435,441 ****
  					     ? "__gnat_eh_personality_sj"
  					     : "__gnat_eh_personality");
    lang_eh_type_covers = gnat_eh_type_covers;
-   lang_eh_runtime_type = gnat_return_tree;
    default_init_unwind_resume_libfunc ();
  
    /* Turn on -fexceptions and -fnon-call-exceptions. The first one triggers
--- 435,440 ----
Index: gcc/cp/cp-lang.c
===================================================================
*** gcc/cp/cp-lang.c.orig	2009-09-04 15:05:51.000000000 +0200
--- gcc/cp/cp-lang.c	2009-09-08 12:26:24.000000000 +0200
*************** static enum classify_record cp_classify_
*** 71,76 ****
--- 71,78 ----
  #define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS cp_init_ts
+ #undef LANG_HOOKS_EH_RUNTIME_TYPE
+ #define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/cp/except.c
===================================================================
*** gcc/cp/except.c.orig	2009-08-31 15:50:38.000000000 +0200
--- gcc/cp/except.c	2009-09-08 12:50:35.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 43,49 ****
  
  static void push_eh_cleanup (tree);
  static tree prepare_eh_type (tree);
- static tree build_eh_type_type (tree);
  static tree do_begin_catch (void);
  static int dtor_nothrow (tree);
  static tree do_end_catch (tree);
--- 43,48 ----
*************** init_exception_processing (void)
*** 86,92 ****
    else
      default_init_unwind_resume_libfunc ();
  
-   lang_eh_runtime_type = build_eh_type_type;
    lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
  }
  
--- 85,90 ----
*************** eh_type_info (tree type)
*** 143,149 ****
  /* Build the address of a typeinfo decl for use in the runtime
     matching field of the exception model.  */
  
! static tree
  build_eh_type_type (tree type)
  {
    tree exp = eh_type_info (type);
--- 141,147 ----
  /* Build the address of a typeinfo decl for use in the runtime
     matching field of the exception model.  */
  
! tree
  build_eh_type_type (tree type)
  {
    tree exp = eh_type_info (type);
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig	2009-09-04 15:05:57.000000000 +0200
--- gcc/except.c	2009-09-08 12:23:57.000000000 +0200
*************** gimple (*lang_protect_cleanup_actions) (
*** 92,100 ****
  /* Return true if type A catches type B.  */
  int (*lang_eh_type_covers) (tree a, tree b);
  
- /* Map a type to a runtime object to match type.  */
- tree (*lang_eh_runtime_type) (tree);
- 
  /* A hash table of label to region number.  */
  
  struct GTY(()) ehl_map_entry {
--- 92,97 ----
*************** add_type_for_runtime (tree type)
*** 1696,1702 ****
  					    TREE_HASH (type), INSERT);
    if (*slot == NULL)
      {
!       tree runtime = (*lang_eh_runtime_type) (type);
        *slot = tree_cons (type, runtime, NULL_TREE);
      }
  }
--- 1693,1699 ----
  					    TREE_HASH (type), INSERT);
    if (*slot == NULL)
      {
!       tree runtime = lang_hooks.eh_runtime_type (type);
        *slot = tree_cons (type, runtime, NULL_TREE);
      }
  }
Index: gcc/except.h
===================================================================
*** gcc/except.h.orig	2009-09-04 15:05:57.000000000 +0200
--- gcc/except.h	2009-09-08 12:23:13.000000000 +0200
*************** extern gimple (*lang_protect_cleanup_act
*** 217,225 ****
  /* Return true if type A catches type B.  */
  extern int (*lang_eh_type_covers) (tree a, tree b);
  
- /* Map a type to a runtime object to match type.  */
- extern tree (*lang_eh_runtime_type) (tree);
- 
  
  /* Just because the user configured --with-sjlj-exceptions=no doesn't
     mean that we can use call frame exceptions.  Detect that the target
--- 217,222 ----
Index: gcc/java/decl.c
===================================================================
*** gcc/java/decl.c.orig	2009-08-31 15:50:38.000000000 +0200
--- gcc/java/decl.c	2009-09-08 12:29:15.000000000 +0200
*************** create_primitive_vtable (const char *nam
*** 510,521 ****
    return r;
  }
  
- static tree
- do_nothing (tree t)
- {
-   return t;
- }
- 
  /* Parse the version string and compute the ABI version number.  */
  static void
  parse_version (void)
--- 510,515 ----
*************** java_init_decl_processing (void)
*** 1203,1210 ****
    else
      default_init_unwind_resume_libfunc ();
  
-   lang_eh_runtime_type = do_nothing;
- 
    initialize_builtins ();
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  
--- 1197,1202 ----
Index: gcc/langhooks.c
===================================================================
*** gcc/langhooks.c.orig	2009-09-04 15:05:56.000000000 +0200
--- gcc/langhooks.c	2009-09-08 12:28:21.000000000 +0200
*************** lhd_do_nothing_t (tree ARG_UNUSED (t))
*** 53,58 ****
--- 53,65 ----
  {
  }
  
+ /* Pass through (tree).  */
+ tree
+ lhd_pass_through_t (tree t)
+ {
+   return t;
+ }
+ 
  /* Do nothing (int).  */
  
  void
Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h.orig	2009-09-04 15:05:51.000000000 +0200
--- gcc/cp/cp-tree.h	2009-09-08 12:51:08.000000000 +0200
*************** extern void choose_personality_routine
*** 4522,4527 ****
--- 4522,4528 ----
  extern tree eh_type_info			(tree);
  extern tree begin_eh_spec_block			(void);
  extern void finish_eh_spec_block		(tree, tree);
+ extern tree build_eh_type_type			(tree);
  
  /* in expr.c */
  extern tree cplus_expand_constant		(tree);


2009-09-04  Richard Guenther  <rguenther@suse.de>
	Rafael Avila de Espindola  <espindola@google.com>

	* c-decl.c (c_maybe_initialize_eh): Init eh_personality_decl
        instead of eh_personality_libfunc.
        (finish_decl): Don't call c_maybe_initialize_eh.
        * c-parser.c (c_parse_file): Call lang_hooks.init_eh.
        * dwarf2out.c (output_call_frame_info, dwarf2out_do_cfi_startproc,
	dwarf2out_begin_prologue): Use personality from current_function_decl.
        * except.c (sjlj_emit_function_enter, output_function_exception_table):
        Use personality from current_function_decl.
        * expr.h (build_personality_function, get_personality_function): New.
        * libfuncs.h (libfunc_index): Remove LTI_eh_personality.
        (eh_personality_libfunc): Remove.
        * optabs.c (build_libfunc_function): New function split out from ...
	(init_one_libfunc): ... here.
        * toplev.c (eh_personality_decl): New.
        * tree.c (make_node_stat):  Set DECL_FUNCTION_PERSONALITY.
        * tree.h (DECL_FUNCTION_PERSONALITY): New.
        (tree_function_decl): Add personality.
        (eh_personality_decl): New.

	* langhooks-def.h (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_INITIALIZER): Adjust.
	* langhooks.h (struct lang_hooks): Add init_eh.
	* c-lang.c (LANG_HOOKS_INIT_EH): Define.

	objc/
	* objc-act.c (objc_init_exceptions): Export.  Move warning code ...
	(objc_begin_try_stmt): ... here
	(objc_build_throw_stmt): ... and here.
	* objc-act.h (objc_init_exceptions): Declare.
	* objc-lang.c (LANG_HOOKS_INIT_EH): Define.

	cp/
	* except.c (init_exception_processing, choose_personality_routine):
	Init eh_personality_decl instead of eh_personality_libfunc.

	java/
	* decl.c (java_init_decl_processing): Init eh_personality_decl
	instead of eh_personality_libfunc.

	ada/
	* gcc-interface/misc.c (gnat_init_gcc_eh): Init eh_personality_decl
	instead of eh_personality_libfunc.

	fortran/
	* f95-lang.c (gfc_maybe_initialize_eh): Init eh_personality_decl
	instead of eh_personality_libfunc.

Index: gcc/java/decl.c
===================================================================
*** gcc/java/decl.c.orig	2009-09-08 15:27:29.000000000 +0200
--- gcc/java/decl.c	2009-09-08 15:27:39.000000000 +0200
*************** java_init_decl_processing (void)
*** 1189,1197 ****
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                                              ? "__gcj_personality_sj0"
!                                              : "__gcj_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
--- 1189,1200 ----
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
! 
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcj_personality_sj0"
! 				  : "__gcj_personality_v0");
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
Index: gcc/libfuncs.h
===================================================================
*** gcc/libfuncs.h.orig	2009-08-31 15:50:38.000000000 +0200
--- gcc/libfuncs.h	2009-09-08 15:27:39.000000000 +0200
*************** enum libfunc_index
*** 31,37 ****
    LTI_setbits,
  
    LTI_unwind_resume,
-   LTI_eh_personality,
    LTI_setjmp,
    LTI_longjmp,
    LTI_unwind_sjlj_register,
--- 31,36 ----
*************** extern GTY(()) rtx libfunc_table[LTI_MAX
*** 61,67 ****
  #define setbits_libfunc	(libfunc_table[LTI_setbits])
  
  #define unwind_resume_libfunc	(libfunc_table[LTI_unwind_resume])
- #define eh_personality_libfunc	(libfunc_table[LTI_eh_personality])
  #define setjmp_libfunc	(libfunc_table[LTI_setjmp])
  #define longjmp_libfunc	(libfunc_table[LTI_longjmp])
  #define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
--- 60,65 ----
Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c.orig	2009-08-31 15:50:38.000000000 +0200
--- gcc/optabs.c	2009-09-08 15:27:39.000000000 +0200
*************** libfunc_decl_eq (const void *entry1, con
*** 6023,6028 ****
--- 6023,6050 ----
    return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
  }
  
+ /* Build a decl for a libfunc named NAME. */
+ 
+ tree
+ build_libfunc_function (const char *name)
+ {
+   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+ 			  get_identifier (name),
+                           build_function_type (integer_type_node, NULL_TREE));
+   /* ??? We don't have any type information except for this is
+      a function.  Pretend this is "int foo()".  */
+   DECL_ARTIFICIAL (decl) = 1;
+   DECL_EXTERNAL (decl) = 1;
+   TREE_PUBLIC (decl) = 1;
+   gcc_assert (DECL_ASSEMBLER_NAME (decl));
+ 
+   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
+      are the flags assigned by targetm.encode_section_info.  */
+   SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
+ 
+   return decl;
+ }
+ 
  rtx
  init_one_libfunc (const char *name)
  {
*************** init_one_libfunc (const char *name)
*** 6043,6061 ****
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       /* ??? We don't have any type information except for this is
! 	 a function.  Pretend this is "int foo()".  */
!       decl = build_decl (UNKNOWN_LOCATION,
! 			 FUNCTION_DECL, get_identifier (name),
! 			 build_function_type (integer_type_node, NULL_TREE));
!       DECL_ARTIFICIAL (decl) = 1;
!       DECL_EXTERNAL (decl) = 1;
!       TREE_PUBLIC (decl) = 1;
! 
!       /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
! 	 are the flags assigned by targetm.encode_section_info.  */
!       SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
! 
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
--- 6065,6071 ----
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       decl = build_libfunc_function (name);
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2009-09-04 15:05:56.000000000 +0200
--- gcc/tree.h	2009-09-08 15:27:39.000000000 +0200
*************** struct GTY(()) tree_decl_minimal {
*** 2533,2538 ****
--- 2533,2541 ----
  #define DECL_DEBUG_EXPR_IS_FROM(NODE) \
    (DECL_COMMON_CHECK (NODE)->decl_common.debug_expr_is_from)
  
+ #define DECL_FUNCTION_PERSONALITY(NODE) \
+   (FUNCTION_DECL_CHECK (NODE)->function_decl.personality)
+ 
  /* Nonzero for a given ..._DECL node means that the name of this node should
     be ignored for symbolic debug purposes.  */
  #define DECL_IGNORED_P(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.ignored_flag)
*************** struct GTY(()) tree_function_decl {
*** 3183,3188 ****
--- 3186,3194 ----
  
    struct function *f;
  
+   /* The personality function. Used for stack unwinding. */
+   tree personality;
+ 
    /* Function specific options that are used by this function.  */
    tree function_specific_target;	/* target options */
    tree function_specific_optimization;	/* optimization options */
*************** extern int pedantic_lvalues;
*** 4556,4561 ****
--- 4562,4570 ----
  
  extern GTY(()) tree current_function_decl;
  
+ /* The eh personally function that this FE wants to use. */
+ extern GTY(()) tree eh_personality_decl;
+ 
  /* Nonzero means a FUNC_BEGIN label was emitted.  */
  extern GTY(()) const char * current_function_func_begin_label;
  \f
Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c.orig	2009-09-08 15:27:29.000000000 +0200
--- gcc/objc/objc-act.c	2009-09-08 15:28:39.000000000 +0200
*************** objc_init_exceptions (void)
*** 3508,3518 ****
  #ifndef OBJCPLUS
    if (!flag_objc_sjlj_exceptions)
      {
!       c_eh_initialized_p = true;
!       eh_personality_libfunc
! 	= init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 			    ? "__gnu_objc_personality_sj0"
! 			    : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
      }
--- 3508,3517 ----
  #ifndef OBJCPLUS
    if (!flag_objc_sjlj_exceptions)
      {
!       eh_personality_decl
! 	= build_personality_function (USING_SJLJ_EXCEPTIONS
! 				      ? "__gnu_objc_personality_sj0"
! 				      : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
      }
Index: gcc/toplev.c
===================================================================
*** gcc/toplev.c.orig	2009-09-04 21:19:48.000000000 +0200
--- gcc/toplev.c	2009-09-08 15:27:39.000000000 +0200
*************** int optimize_size = 0;
*** 202,207 ****
--- 202,210 ----
     or 0 if between functions.  */
  tree current_function_decl;
  
+ /* The EH personality function that this FE wants to use. */
+ tree eh_personality_decl;
+ 
  /* Set to the FUNC_BEGIN label of the current function, or NULL
     if none.  */
  const char * current_function_func_begin_label;
Index: gcc/cp/except.c
===================================================================
*** gcc/cp/except.c.orig	2009-09-08 15:27:29.000000000 +0200
--- gcc/cp/except.c	2009-09-08 15:27:39.000000000 +0200
*************** init_exception_processing (void)
*** 77,85 ****
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 					     ? "__gxx_personality_sj0"
! 					     : "__gxx_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
--- 77,87 ----
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gxx_personality_sj0"
! 				  : "__gxx_personality_v0");
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
*************** decl_is_java_type (tree decl, int err)
*** 311,317 ****
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_libfunc is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
--- 313,319 ----
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_decl is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
*************** choose_personality_routine (enum languag
*** 352,360 ****
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 						 ? "__gcj_personality_sj0"
! 						 : "__gcj_personality_v0");
        break;
  
      default:
--- 354,363 ----
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_decl
! 	= build_personality_function (USING_SJLJ_EXCEPTIONS
! 				      ? "__gcj_personality_sj0"
! 				      : "__gcj_personality_v0");
        break;
  
      default:
Index: gcc/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c.orig	2009-09-04 15:05:56.000000000 +0200
--- gcc/dwarf2out.c	2009-09-08 15:27:39.000000000 +0200
*************** static GTY(()) section *debug_str_sectio
*** 216,221 ****
--- 216,225 ----
  static GTY(()) section *debug_ranges_section;
  static GTY(()) section *debug_frame_section;
  
+ /* Personality decl of current unit.  Used only when assembler does not support
+    personality CFI.  */
+ static GTY(()) rtx current_unit_personality;
+ 
  /* How to start an assembler comment.  */
  #ifndef ASM_COMMENT_START
  #define ASM_COMMENT_START ";#"
*************** output_call_frame_info (int for_eh)
*** 3599,3604 ****
--- 3603,3609 ----
    int per_encoding = DW_EH_PE_absptr;
    int lsda_encoding = DW_EH_PE_absptr;
    int return_reg;
+   rtx personality = NULL;
    int dw_cie_version;
  
    /* Don't emit a CIE if there won't be any FDEs.  */
*************** output_call_frame_info (int for_eh)
*** 3684,3689 ****
--- 3689,3696 ----
  
    augmentation[0] = 0;
    augmentation_size = 0;
+ 
+   personality = current_unit_personality;
    if (for_eh)
      {
        char *p;
*************** output_call_frame_info (int for_eh)
*** 3703,3713 ****
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (eh_personality_libfunc)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (eh_personality_libfunc);
  	}
        if (any_lsda_needed)
  	{
--- 3710,3720 ----
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (personality)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (personality);
  	}
        if (any_lsda_needed)
  	{
*************** output_call_frame_info (int for_eh)
*** 3726,3732 ****
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
--- 3733,3739 ----
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (personality && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
*************** output_call_frame_info (int for_eh)
*** 3760,3771 ****
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (eh_personality_libfunc)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   eh_personality_libfunc,
  					   true, NULL);
  	}
  
--- 3767,3778 ----
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (personality)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   personality,
  					   true, NULL);
  	}
  
*************** dwarf2out_do_cfi_startproc (bool second)
*** 3824,3836 ****
  {
    int enc;
    rtx ref;
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (eh_personality_libfunc)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = eh_personality_libfunc;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
--- 3831,3844 ----
  {
    int enc;
    rtx ref;
+   rtx personality = get_personality_function (current_function_decl);
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (personality)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = personality;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
*************** dwarf2out_begin_prologue (unsigned int l
*** 3873,3878 ****
--- 3881,3887 ----
    char label[MAX_ARTIFICIAL_LABEL_BYTES];
    char * dup_label;
    dw_fde_ref fde;
+   rtx personality;
    section *fnsec;
  
    current_function_func_begin_label = NULL;
*************** dwarf2out_begin_prologue (unsigned int l
*** 3967,3974 ****
--- 3976,3992 ----
      dwarf2out_source_line (line, file, 0, true);
  #endif
  
+   personality = get_personality_function (current_function_decl);
    if (dwarf2out_do_cfi_asm ())
      dwarf2out_do_cfi_startproc (false);
+   else
+     {
+       if (!current_unit_personality || current_unit_personality == personality)
+         current_unit_personality = personality;
+       else
+ 	sorry ("Multiple EH personalities are supported only with assemblers "
+ 	       "supporting .cfi.personality directive.");
+     }
  }
  
  /* Output a marker (i.e. a label) for the absolute end of the generated code
Index: gcc/expr.h
===================================================================
*** gcc/expr.h.orig	2009-09-04 15:05:56.000000000 +0200
--- gcc/expr.h	2009-09-08 15:27:39.000000000 +0200
*************** extern void init_all_optabs (void);
*** 814,819 ****
--- 814,845 ----
  extern rtx init_one_libfunc (const char *);
  extern rtx set_user_assembler_libfunc (const char *, const char *);
  
+ /* Build a decl for a libfunc named NAME. */
+ extern tree build_libfunc_function (const char *);
+ 
+ /* Build a decl for a personality function named NAME. */
+ static inline tree
+ build_personality_function (const char *name)
+ {
+   return build_libfunc_function (name);
+ }
+ 
+ /* Extracts the personality function of DECL and returns the corresponding
+    libfunc. */
+ 
+ static inline rtx
+ get_personality_function (tree decl)
+ {
+   tree personality = DECL_FUNCTION_PERSONALITY (decl);
+   tree name;
+   if (!personality)
+     return NULL;
+ 
+   name = DECL_ASSEMBLER_NAME (personality);
+ 
+   return init_one_libfunc (IDENTIFIER_POINTER (name));
+ }
+ 
  extern int vector_mode_valid_p (enum machine_mode);
  
  #endif /* GCC_EXPR_H */
Index: gcc/ada/gcc-interface/misc.c
===================================================================
*** gcc/ada/gcc-interface/misc.c.orig	2009-09-08 15:27:29.000000000 +0200
--- gcc/ada/gcc-interface/misc.c	2009-09-08 15:27:39.000000000 +0200
*************** gnat_init_gcc_eh (void)
*** 431,439 ****
       right exception regions.  */
    using_eh_for_cleanups ();
  
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 					     ? "__gnat_eh_personality_sj"
! 					     : "__gnat_eh_personality");
    lang_eh_type_covers = gnat_eh_type_covers;
    default_init_unwind_resume_libfunc ();
  
--- 431,441 ----
       right exception regions.  */
    using_eh_for_cleanups ();
  
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gnat_eh_personality_sj"
! 				  : "__gnat_eh_personality");
! 
    lang_eh_type_covers = gnat_eh_type_covers;
    default_init_unwind_resume_libfunc ();
  
Index: gcc/c-decl.c
===================================================================
*** gcc/c-decl.c.orig	2009-09-08 15:27:29.000000000 +0200
--- gcc/c-decl.c	2009-09-08 15:29:22.000000000 +0200
*************** tree pending_invalid_xref;
*** 92,100 ****
  /* File and line to appear in the eventual error message.  */
  location_t pending_invalid_xref_location;
  
- /* True means we've initialized exception handling.  */
- bool c_eh_initialized_p;
- 
  /* The file and line that the prototype came from if this is an
     old-style definition; used for diagnostics in
     store_parm_decls_oldstyle.  */
--- 92,97 ----
*************** merge_decls (tree newdecl, tree olddecl,
*** 2365,2371 ****
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID and DECL_CONTEXT.  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
--- 2362,2369 ----
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
!      DECL_ARGUMENTS (if appropriate).  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
*************** start_decl (struct c_declarator *declara
*** 4048,4061 ****
  void
  c_maybe_initialize_eh (void)
  {
    if (!flag_exceptions || c_eh_initialized_p)
      return;
  
    c_eh_initialized_p = true;
!   eh_personality_libfunc
!     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 			? "__gcc_personality_sj0"
! 			: "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 4046,4062 ----
  void
  c_maybe_initialize_eh (void)
  {
+   static bool c_eh_initialized_p = false;
+ 
    if (!flag_exceptions || c_eh_initialized_p)
      return;
  
    c_eh_initialized_p = true;
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcc_personality_sj0"
! 				  : "__gcc_personality_v0");
! 
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
Index: gcc/fortran/f95-lang.c
===================================================================
*** gcc/fortran/f95-lang.c.orig	2009-09-08 15:27:21.000000000 +0200
--- gcc/fortran/f95-lang.c	2009-09-08 15:27:39.000000000 +0200
*************** gfc_maybe_initialize_eh (void)
*** 1155,1164 ****
      return;
  
    gfc_eh_initialized_p = true;
!   eh_personality_libfunc
!     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                        ? "__gcc_personality_sj0"
!                        : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 1155,1164 ----
      return;
  
    gfc_eh_initialized_p = true;
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcc_personality_sj0"
! 				  : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig	2009-09-08 15:27:29.000000000 +0200
--- gcc/except.c	2009-09-08 15:27:39.000000000 +0200
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2421,2426 ****
--- 2421,2427 ----
  {
    rtx fn_begin, fc, mem, seq;
    bool fn_begin_outside_block;
+   rtx personality = get_personality_function (current_function_decl);
  
    fc = crtl->eh.sjlj_fc;
  
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2429,2437 ****
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (eh_personality_libfunc);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, eh_personality_libfunc);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
--- 2430,2438 ----
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (personality);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, personality);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
*************** output_ttype (tree type, int tt_format,
*** 4391,4397 ****
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section)
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
--- 4392,4398 ----
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section, rtx ARG_UNUSED (personality))
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
*************** output_one_function_exception_table (con
*** 4407,4413 ****
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, eh_personality_libfunc);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
--- 4408,4414 ----
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, personality);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
*************** output_one_function_exception_table (con
*** 4577,4592 ****
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (eh_personality_libfunc)
!     assemble_external_libcall (eh_personality_libfunc);
  
!   output_one_function_exception_table (fnname, 0);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1);
  
    switch_to_section (current_function_section ());
  }
--- 4578,4595 ----
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
+   rtx personality = get_personality_function (current_function_decl);
+ 
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (personality)
!     assemble_external_libcall (personality);
  
!   output_one_function_exception_table (fnname, 0, personality);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1, personality);
  
    switch_to_section (current_function_section ());
  }
Index: gcc/c-tree.h
===================================================================
*** gcc/c-tree.h.orig	2009-08-20 18:08:09.000000000 +0200
--- gcc/c-tree.h	2009-09-08 15:29:33.000000000 +0200
*************** extern int system_header_p;
*** 589,597 ****
  
  extern bool c_override_global_bindings_to_false;
  
- /* True means we've initialized exception handling.  */
- extern bool c_eh_initialized_p;
- 
  /* In c-decl.c */
  extern void c_finish_incomplete_decl (tree);
  extern void c_write_global_declarations (void);
--- 589,594 ----
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c.orig	2009-09-08 15:27:21.000000000 +0200
--- gcc/tree-eh.c	2009-09-08 15:30:35.000000000 +0200
*************** lower_eh_constructs (void)
*** 1939,1944 ****
--- 1939,1948 ----
    htab_delete (finally_tree);
  
    collect_eh_region_array ();
+ 
+   /* ??? If eh tree is non-empty.  */
+   DECL_FUNCTION_PERSONALITY (current_function_decl) = eh_personality_decl;
+ 
    return 0;
  }
  

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-08 12:37       ` Richard Guenther
  2009-09-08 15:20         ` Richard Guenther
@ 2009-09-08 15:48         ` Richard Henderson
  2009-09-08 16:04           ` Richard Guenther
  1 sibling, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2009-09-08 15:48 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/08/2009 05:37 AM, Richard Guenther wrote:
> Hmm, ok.  So how about setting DECL_EH_PERSONALITY during eh-lowering
> and only for functions with a non-empty EH tree.  We then would
> disallow inlining functions with different non-NULL personality.

I suppose we could do better than that -- only record the
personality if there are runtime types involved.  So that
if there are only cleanups we don't prevent merging.  And
if we get to the end and find personality is still unset,
then we can use the default C personality from libgcc.

I might think we'd record this in cfun->eh, not on the
decl though...

>> The only thing I can think of is to record the fact that the
>> GIMPLE_TRY came from c++/java in the eh_region tree, which would
>> allow the RESX expander to emit the proper function for this
>> particular region.  It's not elegant, but it should work.
>
> With your EH rewrite we could make this function explicit in the IL,
> can we?

We can.  Though I was considering recording a flag rather than
the exact decl.  I do not want to encourage ABIs to muck about
with the generic EH representation.


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-08 15:20         ` Richard Guenther
@ 2009-09-08 15:49           ` Richard Henderson
  2009-09-10 13:12             ` Richard Guenther
  2009-09-08 17:38           ` Eric Botcazou
  1 sibling, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2009-09-08 15:49 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/08/2009 08:20 AM, Richard Guenther wrote:
>> Ok.  I'll modify the patch to make this a true langhook and maybe move
>> the eh-personality also to a langhook called from eh lowering.
>
> The latter is difficult as C++ is playing some tricks with Java vs.
> non-Java personality, so I leave that alone for now.

Ew.

> FYI the following two patches would implement the above (untested).

Looks good.


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-08 15:48         ` Richard Henderson
@ 2009-09-08 16:04           ` Richard Guenther
  2009-09-09  9:34             ` Richard Guenther
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-08 16:04 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Tue, 8 Sep 2009, Richard Henderson wrote:

> On 09/08/2009 05:37 AM, Richard Guenther wrote:
> > Hmm, ok.  So how about setting DECL_EH_PERSONALITY during eh-lowering
> > and only for functions with a non-empty EH tree.  We then would
> > disallow inlining functions with different non-NULL personality.
> 
> I suppose we could do better than that -- only record the
> personality if there are runtime types involved.  So that

Yeah, something for further enhancement.

> if there are only cleanups we don't prevent merging.  And
> if we get to the end and find personality is still unset,
> then we can use the default C personality from libgcc.

Or none at all.  The unwinder seems to check for NULL personality
before calling it.

> I might think we'd record this in cfun->eh, not on the
> decl though...

That occured to me as well ... I'll see what I can do tomorrow.

> > > The only thing I can think of is to record the fact that the
> > > GIMPLE_TRY came from c++/java in the eh_region tree, which would
> > > allow the RESX expander to emit the proper function for this
> > > particular region.  It's not elegant, but it should work.
> > 
> > With your EH rewrite we could make this function explicit in the IL,
> > can we?
> 
> We can.  Though I was considering recording a flag rather than
> the exact decl.  I do not want to encourage ABIs to muck about
> with the generic EH representation.

Ok, I'll leave this one alone for now, too.

Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-08 15:20         ` Richard Guenther
  2009-09-08 15:49           ` Richard Henderson
@ 2009-09-08 17:38           ` Eric Botcazou
  1 sibling, 0 replies; 39+ messages in thread
From: Eric Botcazou @ 2009-09-08 17:38 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Richard Henderson, Diego Novillo

> 	ada/
> 	* gcc-interface/misc.c (gnat_init_gcc_eh): Do not set
> 	lang_eh_runtime_type.

doesn't seem to be in keeping with the change:

> Index: gcc/ada/gcc-interface/misc.c
> ===================================================================
> *** gcc/ada/gcc-interface/misc.c.orig	2009-09-08 15:27:29.000000000 +0200
> --- gcc/ada/gcc-interface/misc.c	2009-09-08 15:27:39.000000000 +0200
> *************** gnat_init_gcc_eh (void)
> *** 431,439 ****
>        right exception regions.  */
>     using_eh_for_cleanups ();
>
> !   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
> ! 					     ? "__gnat_eh_personality_sj"
> ! 					     : "__gnat_eh_personality");
>     lang_eh_type_covers = gnat_eh_type_covers;
>     default_init_unwind_resume_libfunc ();
>
> --- 431,441 ----
>        right exception regions.  */
>     using_eh_for_cleanups ();
>
> !   eh_personality_decl
> !     = build_personality_function (USING_SJLJ_EXCEPTIONS
> ! 				  ? "__gnat_eh_personality_sj"
> ! 				  : "__gnat_eh_personality");
> !
>     lang_eh_type_covers = gnat_eh_type_covers;
>     default_init_unwind_resume_libfunc ();

-- 
Eric Botcazou

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-08 16:04           ` Richard Guenther
@ 2009-09-09  9:34             ` Richard Guenther
  2009-09-09 15:24               ` Richard Henderson
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-09  9:34 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Tue, 8 Sep 2009, Richard Guenther wrote:

> On Tue, 8 Sep 2009, Richard Henderson wrote:
> 
> > On 09/08/2009 05:37 AM, Richard Guenther wrote:
> > > Hmm, ok.  So how about setting DECL_EH_PERSONALITY during eh-lowering
> > > and only for functions with a non-empty EH tree.  We then would
> > > disallow inlining functions with different non-NULL personality.
> > 
> > I suppose we could do better than that -- only record the
> > personality if there are runtime types involved.  So that
> 
> Yeah, something for further enhancement.
> 
> > if there are only cleanups we don't prevent merging.  And
> > if we get to the end and find personality is still unset,
> > then we can use the default C personality from libgcc.
> 
> Or none at all.  The unwinder seems to check for NULL personality
> before calling it.
> 
> > I might think we'd record this in cfun->eh, not on the
> > decl though...
> 
> That occured to me as well ... I'll see what I can do tomorrow.

As we need the information to decide inlining it would be at least
an inconvenience to LTO to also read in (parts of) EH data in the
IPA phase.  So I'll leave that alone for now.

Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-09  9:34             ` Richard Guenther
@ 2009-09-09 15:24               ` Richard Henderson
  2009-09-09 15:26                 ` Richard Guenther
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2009-09-09 15:24 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/09/2009 02:34 AM, Richard Guenther wrote:
> As we need the information to decide inlining it would be at least
> an inconvenience to LTO to also read in (parts of) EH data in the
> IPA phase.  So I'll leave that alone for now.

Given that IPA needs that EH data to actually perform the inlining,
how is that an inconvenience?


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-09 15:24               ` Richard Henderson
@ 2009-09-09 15:26                 ` Richard Guenther
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Guenther @ 2009-09-09 15:26 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Wed, 9 Sep 2009, Richard Henderson wrote:

> On 09/09/2009 02:34 AM, Richard Guenther wrote:
> > As we need the information to decide inlining it would be at least
> > an inconvenience to LTO to also read in (parts of) EH data in the
> > IPA phase.  So I'll leave that alone for now.
> 
> Given that IPA needs that EH data to actually perform the inlining,
> how is that an inconvenience?

The inlining plan is computed by just looking at the callgraph and
the sizes computed by the local information gathering.  We need to
reject cgraph edges which cross EH personality in this phase.  Only
at the time the inlining decisions are committed (again in a local
phase) we have the function bodies and EH data available.

Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-08 15:49           ` Richard Henderson
@ 2009-09-10 13:12             ` Richard Guenther
  2009-09-10 14:37               ` Richard Guenther
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-10 13:12 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Tue, 8 Sep 2009, Richard Henderson wrote:

> On 09/08/2009 08:20 AM, Richard Guenther wrote:
> > > Ok.  I'll modify the patch to make this a true langhook and maybe move
> > > the eh-personality also to a langhook called from eh lowering.
> > 
> > The latter is difficult as C++ is playing some tricks with Java vs.
> > non-Java personality, so I leave that alone for now.
> 
> Ew.
> 
> > FYI the following two patches would implement the above (untested).
> 
> Looks good.

I've been playing a bit with optimizing setting of 
DECL_FUNCTION_EH_PERSONALITY only if the function uses EH types
instead of just checking for an empty EH region tree.  It doesn't look
like its very simple - even a catch (...) needs a personality routine.

So I am now testing the following - the ERT_ALLOWED_EXCEPTIONS case
is required to get diagnostics from g++.dg/torture/pr34850.C which
requires inlining memset into clear_mem.

If that doesn't work out I'll refrain from optimizing at all and
just disable cross different EH personality TU inlining completely
(that already passed bootstrapping and testing, it would be
-  if (function_needs_eh_personality (cfun))
-    DECL_FUNCTION_PERSONALITY (current_function_decl) = 
eh_personality_decl;
+  DECL_FUNCTION_PERSONALITY (current_function_decl) = 
eh_personality_decl;
meaning no functional change as far as trunk is concerned)

Ok for trunk if bootstrapping and testing succeeds?

Thanks,
Richard.

2009-09-10  Richard Guenther  <rguenther@suse.de>
	Rafael Avila de Espindola  <espindola@google.com>

	* langhooks-def.h (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.
	(LANG_HOOKS_INITIALIZER): Adjust.
	(lhd_pass_through_t): Declare.
	* langhooks.h (struct lang_hooks): Add init_eh and eh_runtime_type.
	* langhooks.c (lhd_pass_through_t): New function.

        * dwarf2out.c (output_call_frame_info, dwarf2out_do_cfi_startproc,
	dwarf2out_begin_prologue): Use personality from current_function_decl.
        * expr.h (build_personality_function): Declare.
	(get_personality_function): Likewise.
        * libfuncs.h (libfunc_index): Remove LTI_eh_personality.
        (eh_personality_libfunc): Remove.
        * optabs.c (build_libfunc_function): New function split out from ...
	(init_one_libfunc): ... here.
        * toplev.c (eh_personality_decl): New.
        * tree.h (DECL_FUNCTION_PERSONALITY): New.
        (tree_function_decl): Add personality.
        (eh_personality_decl): New.
	* except.h (lang_eh_runtime_type): Remove.
	(function_needs_eh_personality): Declare.
        * except.c (lang_eh_runtime_type): Remove.
	(function_needs_eh_personality): New function.
	(add_type_for_runtime): Call lang_hooks.type_for_runtime instead.
        (sjlj_emit_function_enter, output_function_exception_table):
        Use personality from current_function_decl.
	* tree-eh.c (lower_eh_constructs): Set DECL_FUNCTION_PERSONALITY.
	* tree-inline.c (tree_can_inline_p): Do not inline across different
	EH personalities.

	* c-lang.c (LANG_HOOKS_INIT_EH): Define.
	* c-tree.h (c_eh_initialized_p): Remove.
	* c-decl.c (finish_decl): Don't call c_maybe_initialize_eh.
	Init eh_personality_decl instead of eh_personality_libfunc.
	(finish_decl): Don't call c_maybe_initialize_eh.
	(c_eh_initialized_p): Make local to ...
	(c_maybe_initialize_eh): ... this function.
	Init eh_personality_decl instead of eh_personality_libfunc.
        * c-parser.c (c_parser_omp_construct): Likewise.
	(c_parse_file): Call lang_hooks.init_eh.

	objc/
	* objc-act.c (objc_eh_runtime_type): Export.
	(objc_init_exceptions): Export.
	Init eh_personality_decl instead of eh_personality_libfunc.
	Do not set objc_init_exceptions.  Move warning code ...
	(objc_begin_try_stmt): ... here
	(objc_build_throw_stmt): ... and here.
	* objc-act.h (objc_init_exceptions): Declare.
	(objc_eh_runtime_type): Likewise.
	* objc-lang.c (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.

	cp/
	* except.c (init_exception_processing): Do not set
	lang_eh_runtime_type.
	Init eh_personality_decl instead of eh_personality_libfunc.
	* cp-lang.c (LANG_HOOKS_EH_RUNTIME_TYPE): Define.

	java/
	* decl.c (do_nothing): Remove.
	(java_init_decl_processing): Do not set lang_eh_runtime_type.
	Init eh_personality_decl instead of eh_personality_libfunc.

	ada/
	* gcc-interface/misc.c (gnat_init_gcc_eh): Do not set
	lang_eh_runtime_type.
	Init eh_personality_decl instead of eh_personality_libfunc.

	fortran/
	* f95-lang.c (gfc_maybe_initialize_eh): Init eh_personality_decl
	instead of eh_personality_libfunc.

Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/objc/objc-act.c	2009-09-10 14:18:42.000000000 +0200
*************** static struct objc_try_context *cur_try_
*** 3488,3494 ****
  /* ??? Isn't there a class object or some such?  Is it easy to get?  */
  
  #ifndef OBJCPLUS
! static tree
  objc_eh_runtime_type (tree type)
  {
    return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
--- 3488,3494 ----
  /* ??? Isn't there a class object or some such?  Is it easy to get?  */
  
  #ifndef OBJCPLUS
! tree
  objc_eh_runtime_type (tree type)
  {
    return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
*************** objc_eh_runtime_type (tree type)
*** 3497,3503 ****
  
  /* Initialize exception handling.  */
  
! static void
  objc_init_exceptions (void)
  {
    static bool done = false;
--- 3497,3503 ----
  
  /* Initialize exception handling.  */
  
! void
  objc_init_exceptions (void)
  {
    static bool done = false;
*************** objc_init_exceptions (void)
*** 3505,3529 ****
      return;
    done = true;
  
-   if (flag_objc_sjlj_exceptions)
-     {
-       /* On Darwin, ObjC exceptions require a sufficiently recent
- 	 version of the runtime, so the user must ask for them explicitly.  */
-       if (!flag_objc_exceptions)
- 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
- 		 "exception syntax");
-     }
  #ifndef OBJCPLUS
!   else
      {
!       c_eh_initialized_p = true;
!       eh_personality_libfunc
! 	= init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 			    ? "__gnu_objc_personality_sj0"
! 			    : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
-       lang_eh_runtime_type = objc_eh_runtime_type;
      }
  #endif
  }
--- 3505,3519 ----
      return;
    done = true;
  
  #ifndef OBJCPLUS
!   if (!flag_objc_sjlj_exceptions)
      {
!       eh_personality_decl
! 	= build_personality_function (USING_SJLJ_EXCEPTIONS
! 				      ? "__gnu_objc_personality_sj0"
! 				      : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
      }
  #endif
  }
*************** objc_begin_try_stmt (location_t try_locu
*** 3824,3830 ****
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   objc_init_exceptions ();
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
--- 3814,3827 ----
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
*************** objc_build_throw_stmt (location_t loc, t
*** 3973,3979 ****
  {
    tree args;
  
!   objc_init_exceptions ();
  
    if (throw_expr == NULL)
      {
--- 3970,3983 ----
  {
    tree args;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (throw_expr == NULL)
      {
Index: gcc/c-decl.c
===================================================================
*** gcc/c-decl.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/c-decl.c	2009-09-10 14:18:42.000000000 +0200
*************** tree pending_invalid_xref;
*** 92,100 ****
  /* File and line to appear in the eventual error message.  */
  location_t pending_invalid_xref_location;
  
- /* True means we've initialized exception handling.  */
- bool c_eh_initialized_p;
- 
  /* The file and line that the prototype came from if this is an
     old-style definition; used for diagnostics in
     store_parm_decls_oldstyle.  */
--- 92,97 ----
*************** merge_decls (tree newdecl, tree olddecl,
*** 2365,2371 ****
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID and DECL_CONTEXT.  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
--- 2362,2369 ----
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
!      DECL_ARGUMENTS (if appropriate).  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
*************** start_decl (struct c_declarator *declara
*** 4048,4061 ****
  void
  c_maybe_initialize_eh (void)
  {
    if (!flag_exceptions || c_eh_initialized_p)
      return;
  
    c_eh_initialized_p = true;
!   eh_personality_libfunc
!     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 			? "__gcc_personality_sj0"
! 			: "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 4046,4062 ----
  void
  c_maybe_initialize_eh (void)
  {
+   static bool c_eh_initialized_p = false;
+ 
    if (!flag_exceptions || c_eh_initialized_p)
      return;
  
    c_eh_initialized_p = true;
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcc_personality_sj0"
! 				  : "__gcc_personality_v0");
! 
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
*************** finish_decl (tree decl, location_t init_
*** 4360,4368 ****
  	  TREE_USED (decl) = 1;
  	  TREE_USED (cleanup_decl) = 1;
  
- 	  /* Initialize EH, if we've been told to do so.  */
- 	  c_maybe_initialize_eh ();
- 
  	  push_cleanup (decl, cleanup, false);
  	}
      }
--- 4361,4366 ----
Index: gcc/c-parser.c
===================================================================
*** gcc/c-parser.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/c-parser.c	2009-09-10 14:18:42.000000000 +0200
*************** c_parser_omp_construct (c_parser *parser
*** 8489,8500 ****
    p_kind = c_parser_peek_token (parser)->pragma_kind;
    c_parser_consume_pragma (parser);
  
-   /* For all constructs below except #pragma omp atomic
-      MUST_NOT_THROW catch handlers are needed when exceptions
-      are enabled.  */
-   if (p_kind != PRAGMA_OMP_ATOMIC)
-     c_maybe_initialize_eh ();
- 
    switch (p_kind)
      {
      case PRAGMA_OMP_ATOMIC:
--- 8489,8494 ----
*************** c_parse_file (void)
*** 8607,8612 ****
--- 8601,8609 ----
    the_parser = GGC_NEW (c_parser);
    *the_parser = tparser;
  
+   /* Initialize EH, if we've been told to do so.  */
+   lang_hooks.init_eh ();
+ 
    c_parser_translation_unit (the_parser);
    the_parser = NULL;
  }
Index: gcc/c-lang.c
===================================================================
*** gcc/c-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/c-lang.c	2009-09-10 14:18:42.000000000 +0200
*************** enum c_language_kind c_language = clk_c;
*** 44,49 ****
--- 44,51 ----
  #define LANG_HOOKS_NAME "GNU C"
  #undef LANG_HOOKS_INIT
  #define LANG_HOOKS_INIT c_objc_common_init
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH c_maybe_initialize_eh
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/langhooks-def.h
===================================================================
*** gcc/langhooks-def.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/langhooks-def.h	2009-09-10 14:18:42.000000000 +0200
*************** extern void lhd_do_nothing (void);
*** 40,45 ****
--- 40,46 ----
  extern void lhd_do_nothing_t (tree);
  extern void lhd_do_nothing_i (int);
  extern void lhd_do_nothing_f (struct function *);
+ extern tree lhd_pass_through_t (tree);
  extern bool lhd_post_options (const char **);
  extern alias_set_type lhd_get_alias_set (tree);
  extern tree lhd_return_null_tree_v (void);
*************** extern void lhd_omp_firstprivatize_type_
*** 107,112 ****
--- 108,115 ----
  #define LANG_HOOKS_EXPR_TO_DECL		lhd_expr_to_decl
  #define LANG_HOOKS_TO_TARGET_CHARSET	lhd_to_target_charset
  #define LANG_HOOKS_INIT_TS		lhd_do_nothing
+ #define LANG_HOOKS_INIT_EH		NULL
+ #define LANG_HOOKS_EH_RUNTIME_TYPE	lhd_pass_through_t
  
  /* Attribute hooks.  */
  #define LANG_HOOKS_ATTRIBUTE_TABLE		NULL
*************** extern tree lhd_make_node (enum tree_cod
*** 271,276 ****
--- 274,281 ----
    LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
    LANG_HOOKS_INIT_TS,          \
    LANG_HOOKS_EXPR_TO_DECL, \
+   LANG_HOOKS_INIT_EH, \
+   LANG_HOOKS_EH_RUNTIME_TYPE, \
  }
  
  #endif /* GCC_LANG_HOOKS_DEF_H */
Index: gcc/langhooks.h
===================================================================
*** gcc/langhooks.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/langhooks.h	2009-09-10 14:18:42.000000000 +0200
*************** struct lang_hooks
*** 414,419 ****
--- 414,425 ----
       if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating.  */
    tree (*expr_to_decl) (tree expr, bool *tc, bool *se);
  
+   /* Called to initialize the exception handing personality.  */
+   void (*init_eh) (void);
+ 
+   /* Map a type to a runtime object to match type.  */
+   tree (*eh_runtime_type) (tree);
+ 
    /* Whenever you add entries here, make sure you adjust langhooks-def.h
       and langhooks.c accordingly.  */
  };
Index: gcc/objc/objc-act.h
===================================================================
*** gcc/objc/objc-act.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/objc/objc-act.h	2009-09-10 14:18:42.000000000 +0200
*************** const char *objc_printable_name (tree, i
*** 32,37 ****
--- 32,39 ----
  void objc_finish_file (void);
  tree objc_fold_obj_type_ref (tree, tree);
  int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+ void objc_init_exceptions (void);
+ tree objc_eh_runtime_type (tree);
  
  /* NB: The remaining public functions are prototyped in c-common.h, for the
     benefit of stub-objc.c and objc-act.c.  */
Index: gcc/objc/objc-lang.c
===================================================================
*** gcc/objc/objc-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/objc/objc-lang.c	2009-09-10 14:18:42.000000000 +0200
*************** static void objc_init_ts (void);
*** 50,55 ****
--- 50,62 ----
  #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS objc_init_ts
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH objc_init_exceptions
+ 
+ #ifndef OBJCPLUS
+ #undef LANG_HOOKS_EH_RUNTIME_TYPE
+ #define LANG_HOOKS_EH_RUNTIME_TYPE objc_eh_runtime_type
+ #endif
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/ada/gcc-interface/misc.c
===================================================================
*** gcc/ada/gcc-interface/misc.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/ada/gcc-interface/misc.c	2009-09-10 14:18:42.000000000 +0200
*************** gnat_init_gcc_eh (void)
*** 431,441 ****
       right exception regions.  */
    using_eh_for_cleanups ();
  
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 					     ? "__gnat_eh_personality_sj"
! 					     : "__gnat_eh_personality");
    lang_eh_type_covers = gnat_eh_type_covers;
-   lang_eh_runtime_type = gnat_return_tree;
    default_init_unwind_resume_libfunc ();
  
    /* Turn on -fexceptions and -fnon-call-exceptions. The first one triggers
--- 431,442 ----
       right exception regions.  */
    using_eh_for_cleanups ();
  
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gnat_eh_personality_sj"
! 				  : "__gnat_eh_personality");
! 
    lang_eh_type_covers = gnat_eh_type_covers;
    default_init_unwind_resume_libfunc ();
  
    /* Turn on -fexceptions and -fnon-call-exceptions. The first one triggers
Index: gcc/cp/cp-lang.c
===================================================================
*** gcc/cp/cp-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/cp/cp-lang.c	2009-09-10 14:18:42.000000000 +0200
*************** static enum classify_record cp_classify_
*** 71,76 ****
--- 71,78 ----
  #define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS cp_init_ts
+ #undef LANG_HOOKS_EH_RUNTIME_TYPE
+ #define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/cp/except.c
===================================================================
*** gcc/cp/except.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/cp/except.c	2009-09-10 14:18:42.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 43,49 ****
  
  static void push_eh_cleanup (tree);
  static tree prepare_eh_type (tree);
- static tree build_eh_type_type (tree);
  static tree do_begin_catch (void);
  static int dtor_nothrow (tree);
  static tree do_end_catch (tree);
--- 43,48 ----
*************** init_exception_processing (void)
*** 78,92 ****
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 					     ? "__gxx_personality_sj0"
! 					     : "__gxx_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
-   lang_eh_runtime_type = build_eh_type_type;
    lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
  }
  
--- 77,92 ----
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gxx_personality_sj0"
! 				  : "__gxx_personality_v0");
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
    lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
  }
  
*************** eh_type_info (tree type)
*** 143,149 ****
  /* Build the address of a typeinfo decl for use in the runtime
     matching field of the exception model.  */
  
! static tree
  build_eh_type_type (tree type)
  {
    tree exp = eh_type_info (type);
--- 143,149 ----
  /* Build the address of a typeinfo decl for use in the runtime
     matching field of the exception model.  */
  
! tree
  build_eh_type_type (tree type)
  {
    tree exp = eh_type_info (type);
*************** decl_is_java_type (tree decl, int err)
*** 313,319 ****
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_libfunc is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
--- 313,319 ----
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_decl is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
*************** choose_personality_routine (enum languag
*** 354,362 ****
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 						 ? "__gcj_personality_sj0"
! 						 : "__gcj_personality_v0");
        break;
  
      default:
--- 354,363 ----
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_decl
! 	= build_personality_function (USING_SJLJ_EXCEPTIONS
! 				      ? "__gcj_personality_sj0"
! 				      : "__gcj_personality_v0");
        break;
  
      default:
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/except.c	2009-09-10 14:57:22.000000000 +0200
*************** gimple (*lang_protect_cleanup_actions) (
*** 92,100 ****
  /* Return true if type A catches type B.  */
  int (*lang_eh_type_covers) (tree a, tree b);
  
- /* Map a type to a runtime object to match type.  */
- tree (*lang_eh_runtime_type) (tree);
- 
  /* A hash table of label to region number.  */
  
  struct GTY(()) ehl_map_entry {
--- 92,97 ----
*************** add_type_for_runtime (tree type)
*** 1696,1702 ****
  					    TREE_HASH (type), INSERT);
    if (*slot == NULL)
      {
!       tree runtime = (*lang_eh_runtime_type) (type);
        *slot = tree_cons (type, runtime, NULL_TREE);
      }
  }
--- 1693,1699 ----
  					    TREE_HASH (type), INSERT);
    if (*slot == NULL)
      {
!       tree runtime = lang_hooks.eh_runtime_type (type);
        *slot = tree_cons (type, runtime, NULL_TREE);
      }
  }
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2424,2429 ****
--- 2421,2427 ----
  {
    rtx fn_begin, fc, mem, seq;
    bool fn_begin_outside_block;
+   rtx personality = get_personality_function (current_function_decl);
  
    fc = crtl->eh.sjlj_fc;
  
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2432,2440 ****
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (eh_personality_libfunc);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, eh_personality_libfunc);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
--- 2430,2438 ----
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (personality);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, personality);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
*************** output_ttype (tree type, int tt_format,
*** 4394,4400 ****
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section)
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
--- 4392,4398 ----
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section, rtx ARG_UNUSED (personality))
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
*************** output_one_function_exception_table (con
*** 4410,4416 ****
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, eh_personality_libfunc);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
--- 4408,4414 ----
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, personality);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
*************** output_one_function_exception_table (con
*** 4580,4595 ****
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (eh_personality_libfunc)
!     assemble_external_libcall (eh_personality_libfunc);
  
!   output_one_function_exception_table (fnname, 0);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1);
  
    switch_to_section (current_function_section ());
  }
--- 4578,4595 ----
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
+   rtx personality = get_personality_function (current_function_decl);
+ 
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (personality)
!     assemble_external_libcall (personality);
  
!   output_one_function_exception_table (fnname, 0, personality);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1, personality);
  
    switch_to_section (current_function_section ());
  }
*************** get_eh_throw_stmt_table (struct function
*** 4606,4611 ****
--- 4606,4662 ----
    return fun->eh->throw_stmt_table;
  }
  
+ /* Return true if the function deeds a EH personality function.  */
+ 
+ bool
+ function_needs_eh_personality (struct function *fn)
+ {
+   struct eh_region_d *i;
+   int depth = 0;
+ 
+   i = fn->eh->region_tree;
+   if (!i)
+     return false;
+ 
+   while (1)
+     {
+       switch (i->type)
+ 	{
+ 	case ERT_CATCH:
+ 	  return true;
+ 
+ 	case ERT_ALLOWED_EXCEPTIONS:
+ 	  if (i->u.allowed.type_list)
+ 	    return true;
+ 	  break;
+ 
+ 	default:
+ 	  break;
+ 	}
+       /* If there are sub-regions, process them.  */
+       if (i->inner)
+ 	i = i->inner, depth++;
+       /* If there are peers, process them.  */
+       else if (i->next_peer)
+ 	i = i->next_peer;
+       /* Otherwise, step back up the tree to the next peer.  */
+       else
+ 	{
+ 	  do
+ 	    {
+ 	      i = i->outer;
+ 	      depth--;
+ 	      if (i == NULL)
+ 		return false;
+ 	    }
+ 	  while (i->next_peer == NULL);
+ 	  i = i->next_peer;
+ 	}
+     }
+ 
+   return false;
+ }
+ 
  /* Dump EH information to OUT.  */
  
  void
Index: gcc/except.h
===================================================================
*** gcc/except.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/except.h	2009-09-10 14:50:26.000000000 +0200
*************** extern gimple (*lang_protect_cleanup_act
*** 217,225 ****
  /* Return true if type A catches type B.  */
  extern int (*lang_eh_type_covers) (tree a, tree b);
  
- /* Map a type to a runtime object to match type.  */
- extern tree (*lang_eh_runtime_type) (tree);
- 
  
  /* Just because the user configured --with-sjlj-exceptions=no doesn't
     mean that we can use call frame exceptions.  Detect that the target
--- 217,222 ----
*************** extern int num_eh_regions (void);
*** 277,279 ****
--- 274,277 ----
  extern bitmap must_not_throw_labels (void);
  extern struct eh_region_d *redirect_eh_edge_to_label (struct edge_def *, tree, bool, bool, int);
  extern int get_next_region_sharing_label (int);
+ extern bool function_needs_eh_personality (struct function *);
Index: gcc/java/decl.c
===================================================================
*** gcc/java/decl.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/java/decl.c	2009-09-10 14:18:42.000000000 +0200
*************** create_primitive_vtable (const char *nam
*** 510,521 ****
    return r;
  }
  
- static tree
- do_nothing (tree t)
- {
-   return t;
- }
- 
  /* Parse the version string and compute the ABI version number.  */
  static void
  parse_version (void)
--- 510,515 ----
*************** java_init_decl_processing (void)
*** 1195,1210 ****
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                                              ? "__gcj_personality_sj0"
!                                              : "__gcj_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
-   lang_eh_runtime_type = do_nothing;
- 
    initialize_builtins ();
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  
--- 1189,1205 ----
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
! 
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcj_personality_sj0"
! 				  : "__gcj_personality_v0");
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
    initialize_builtins ();
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  
Index: gcc/langhooks.c
===================================================================
*** gcc/langhooks.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/langhooks.c	2009-09-10 14:18:42.000000000 +0200
*************** lhd_do_nothing_t (tree ARG_UNUSED (t))
*** 53,58 ****
--- 53,65 ----
  {
  }
  
+ /* Pass through (tree).  */
+ tree
+ lhd_pass_through_t (tree t)
+ {
+   return t;
+ }
+ 
  /* Do nothing (int).  */
  
  void
Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/cp/cp-tree.h	2009-09-10 14:18:42.000000000 +0200
*************** extern void choose_personality_routine
*** 4521,4526 ****
--- 4521,4527 ----
  extern tree eh_type_info			(tree);
  extern tree begin_eh_spec_block			(void);
  extern void finish_eh_spec_block		(tree, tree);
+ extern tree build_eh_type_type			(tree);
  
  /* in expr.c */
  extern tree cplus_expand_constant		(tree);
Index: gcc/libfuncs.h
===================================================================
*** gcc/libfuncs.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/libfuncs.h	2009-09-10 14:18:42.000000000 +0200
*************** enum libfunc_index
*** 31,37 ****
    LTI_setbits,
  
    LTI_unwind_resume,
-   LTI_eh_personality,
    LTI_setjmp,
    LTI_longjmp,
    LTI_unwind_sjlj_register,
--- 31,36 ----
*************** extern GTY(()) rtx libfunc_table[LTI_MAX
*** 61,67 ****
  #define setbits_libfunc	(libfunc_table[LTI_setbits])
  
  #define unwind_resume_libfunc	(libfunc_table[LTI_unwind_resume])
- #define eh_personality_libfunc	(libfunc_table[LTI_eh_personality])
  #define setjmp_libfunc	(libfunc_table[LTI_setjmp])
  #define longjmp_libfunc	(libfunc_table[LTI_longjmp])
  #define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
--- 60,65 ----
Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/optabs.c	2009-09-10 14:18:42.000000000 +0200
*************** libfunc_decl_eq (const void *entry1, con
*** 6023,6028 ****
--- 6023,6050 ----
    return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
  }
  
+ /* Build a decl for a libfunc named NAME. */
+ 
+ tree
+ build_libfunc_function (const char *name)
+ {
+   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+ 			  get_identifier (name),
+                           build_function_type (integer_type_node, NULL_TREE));
+   /* ??? We don't have any type information except for this is
+      a function.  Pretend this is "int foo()".  */
+   DECL_ARTIFICIAL (decl) = 1;
+   DECL_EXTERNAL (decl) = 1;
+   TREE_PUBLIC (decl) = 1;
+   gcc_assert (DECL_ASSEMBLER_NAME (decl));
+ 
+   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
+      are the flags assigned by targetm.encode_section_info.  */
+   SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
+ 
+   return decl;
+ }
+ 
  rtx
  init_one_libfunc (const char *name)
  {
*************** init_one_libfunc (const char *name)
*** 6043,6061 ****
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       /* ??? We don't have any type information except for this is
! 	 a function.  Pretend this is "int foo()".  */
!       decl = build_decl (UNKNOWN_LOCATION,
! 			 FUNCTION_DECL, get_identifier (name),
! 			 build_function_type (integer_type_node, NULL_TREE));
!       DECL_ARTIFICIAL (decl) = 1;
!       DECL_EXTERNAL (decl) = 1;
!       TREE_PUBLIC (decl) = 1;
! 
!       /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
! 	 are the flags assigned by targetm.encode_section_info.  */
!       SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
! 
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
--- 6065,6071 ----
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       decl = build_libfunc_function (name);
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/tree.h	2009-09-10 14:18:42.000000000 +0200
*************** struct GTY(()) tree_decl_minimal {
*** 2538,2543 ****
--- 2538,2546 ----
  #define DECL_DEBUG_EXPR_IS_FROM(NODE) \
    (DECL_COMMON_CHECK (NODE)->decl_common.debug_expr_is_from)
  
+ #define DECL_FUNCTION_PERSONALITY(NODE) \
+   (FUNCTION_DECL_CHECK (NODE)->function_decl.personality)
+ 
  /* Nonzero for a given ..._DECL node means that the name of this node should
     be ignored for symbolic debug purposes.  */
  #define DECL_IGNORED_P(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.ignored_flag)
*************** struct GTY(()) tree_function_decl {
*** 3188,3193 ****
--- 3191,3199 ----
  
    struct function *f;
  
+   /* The personality function. Used for stack unwinding. */
+   tree personality;
+ 
    /* Function specific options that are used by this function.  */
    tree function_specific_target;	/* target options */
    tree function_specific_optimization;	/* optimization options */
*************** extern int pedantic_lvalues;
*** 4557,4562 ****
--- 4563,4571 ----
  
  extern GTY(()) tree current_function_decl;
  
+ /* The eh personally function that this FE wants to use. */
+ extern GTY(()) tree eh_personality_decl;
+ 
  /* Nonzero means a FUNC_BEGIN label was emitted.  */
  extern GTY(()) const char * current_function_func_begin_label;
  \f
Index: gcc/toplev.c
===================================================================
*** gcc/toplev.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/toplev.c	2009-09-10 14:18:42.000000000 +0200
*************** int optimize_size = 0;
*** 202,207 ****
--- 202,210 ----
     or 0 if between functions.  */
  tree current_function_decl;
  
+ /* The EH personality function that this FE wants to use. */
+ tree eh_personality_decl;
+ 
  /* Set to the FUNC_BEGIN label of the current function, or NULL
     if none.  */
  const char * current_function_func_begin_label;
Index: gcc/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/dwarf2out.c	2009-09-10 14:18:42.000000000 +0200
*************** static GTY(()) section *debug_str_sectio
*** 216,221 ****
--- 216,225 ----
  static GTY(()) section *debug_ranges_section;
  static GTY(()) section *debug_frame_section;
  
+ /* Personality decl of current unit.  Used only when assembler does not support
+    personality CFI.  */
+ static GTY(()) rtx current_unit_personality;
+ 
  /* How to start an assembler comment.  */
  #ifndef ASM_COMMENT_START
  #define ASM_COMMENT_START ";#"
*************** output_call_frame_info (int for_eh)
*** 3599,3604 ****
--- 3603,3609 ----
    int per_encoding = DW_EH_PE_absptr;
    int lsda_encoding = DW_EH_PE_absptr;
    int return_reg;
+   rtx personality = NULL;
    int dw_cie_version;
  
    /* Don't emit a CIE if there won't be any FDEs.  */
*************** output_call_frame_info (int for_eh)
*** 3684,3689 ****
--- 3689,3696 ----
  
    augmentation[0] = 0;
    augmentation_size = 0;
+ 
+   personality = current_unit_personality;
    if (for_eh)
      {
        char *p;
*************** output_call_frame_info (int for_eh)
*** 3703,3713 ****
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (eh_personality_libfunc)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (eh_personality_libfunc);
  	}
        if (any_lsda_needed)
  	{
--- 3710,3720 ----
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (personality)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (personality);
  	}
        if (any_lsda_needed)
  	{
*************** output_call_frame_info (int for_eh)
*** 3726,3732 ****
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
--- 3733,3739 ----
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (personality && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
*************** output_call_frame_info (int for_eh)
*** 3760,3771 ****
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (eh_personality_libfunc)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   eh_personality_libfunc,
  					   true, NULL);
  	}
  
--- 3767,3778 ----
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (personality)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   personality,
  					   true, NULL);
  	}
  
*************** dwarf2out_do_cfi_startproc (bool second)
*** 3824,3836 ****
  {
    int enc;
    rtx ref;
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (eh_personality_libfunc)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = eh_personality_libfunc;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
--- 3831,3844 ----
  {
    int enc;
    rtx ref;
+   rtx personality = get_personality_function (current_function_decl);
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (personality)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = personality;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
*************** dwarf2out_begin_prologue (unsigned int l
*** 3873,3878 ****
--- 3881,3887 ----
    char label[MAX_ARTIFICIAL_LABEL_BYTES];
    char * dup_label;
    dw_fde_ref fde;
+   rtx personality;
    section *fnsec;
  
    current_function_func_begin_label = NULL;
*************** dwarf2out_begin_prologue (unsigned int l
*** 3967,3974 ****
--- 3976,3992 ----
      dwarf2out_source_line (line, file, 0, true);
  #endif
  
+   personality = get_personality_function (current_function_decl);
    if (dwarf2out_do_cfi_asm ())
      dwarf2out_do_cfi_startproc (false);
+   else
+     {
+       if (!current_unit_personality || current_unit_personality == personality)
+         current_unit_personality = personality;
+       else
+ 	sorry ("Multiple EH personalities are supported only with assemblers "
+ 	       "supporting .cfi.personality directive.");
+     }
  }
  
  /* Output a marker (i.e. a label) for the absolute end of the generated code
Index: gcc/expr.h
===================================================================
*** gcc/expr.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/expr.h	2009-09-10 14:18:42.000000000 +0200
*************** extern void init_all_optabs (void);
*** 814,819 ****
--- 814,845 ----
  extern rtx init_one_libfunc (const char *);
  extern rtx set_user_assembler_libfunc (const char *, const char *);
  
+ /* Build a decl for a libfunc named NAME. */
+ extern tree build_libfunc_function (const char *);
+ 
+ /* Build a decl for a personality function named NAME. */
+ static inline tree
+ build_personality_function (const char *name)
+ {
+   return build_libfunc_function (name);
+ }
+ 
+ /* Extracts the personality function of DECL and returns the corresponding
+    libfunc. */
+ 
+ static inline rtx
+ get_personality_function (tree decl)
+ {
+   tree personality = DECL_FUNCTION_PERSONALITY (decl);
+   tree name;
+   if (!personality)
+     return NULL;
+ 
+   name = DECL_ASSEMBLER_NAME (personality);
+ 
+   return init_one_libfunc (IDENTIFIER_POINTER (name));
+ }
+ 
  extern int vector_mode_valid_p (enum machine_mode);
  
  #endif /* GCC_EXPR_H */
Index: gcc/fortran/f95-lang.c
===================================================================
*** gcc/fortran/f95-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/fortran/f95-lang.c	2009-09-10 14:18:42.000000000 +0200
*************** gfc_maybe_initialize_eh (void)
*** 1155,1164 ****
      return;
  
    gfc_eh_initialized_p = true;
!   eh_personality_libfunc
!     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                        ? "__gcc_personality_sj0"
!                        : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 1155,1164 ----
      return;
  
    gfc_eh_initialized_p = true;
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcc_personality_sj0"
! 				  : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
Index: gcc/c-tree.h
===================================================================
*** gcc/c-tree.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/c-tree.h	2009-09-10 14:18:42.000000000 +0200
*************** extern int system_header_p;
*** 589,597 ****
  
  extern bool c_override_global_bindings_to_false;
  
- /* True means we've initialized exception handling.  */
- extern bool c_eh_initialized_p;
- 
  /* In c-decl.c */
  extern void c_finish_incomplete_decl (tree);
  extern void c_write_global_declarations (void);
--- 589,594 ----
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/tree-eh.c	2009-09-10 14:50:38.000000000 +0200
*************** lower_eh_constructs (void)
*** 1939,1944 ****
--- 1939,1948 ----
    htab_delete (finally_tree);
  
    collect_eh_region_array ();
+ 
+   if (function_needs_eh_personality (cfun))
+     DECL_FUNCTION_PERSONALITY (current_function_decl) = eh_personality_decl;
+ 
    return 0;
  }
  
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/tree-inline.c	2009-09-10 14:21:01.000000000 +0200
*************** tree_can_inline_p (struct cgraph_edge *e
*** 4999,5004 ****
--- 4999,5019 ----
    caller = e->caller->decl;
    callee = e->callee->decl;
  
+   /* We cannot inline a function that uses a different EH personality
+      than the caller.  Restrict inlining functions with either no EH
+      personality or calls with matching personality in the caller
+      and callee for now, that will not require personality changes
+      in the caller.  Everything more advanced needs to be taken into
+      account during the inline plan computation.  */
+   if (DECL_FUNCTION_PERSONALITY (callee)
+       && (DECL_FUNCTION_PERSONALITY (caller)
+ 	  != DECL_FUNCTION_PERSONALITY (callee)))
+     {
+       e->inline_failed = CIF_UNSPECIFIED;
+       gimple_call_set_cannot_inline (e->call_stmt, true);
+       return false;
+     }
+ 
    /* Allow the backend to decide if inlining is ok.  */
    if (!targetm.target_option.can_inline_p (caller, callee))
      {

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 13:12             ` Richard Guenther
@ 2009-09-10 14:37               ` Richard Guenther
  2009-09-10 14:52                 ` Richard Guenther
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-10 14:37 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Thu, 10 Sep 2009, Richard Guenther wrote:

> On Tue, 8 Sep 2009, Richard Henderson wrote:
> 
> > On 09/08/2009 08:20 AM, Richard Guenther wrote:
> > > > Ok.  I'll modify the patch to make this a true langhook and maybe move
> > > > the eh-personality also to a langhook called from eh lowering.
> > > 
> > > The latter is difficult as C++ is playing some tricks with Java vs.
> > > non-Java personality, so I leave that alone for now.
> > 
> > Ew.
> > 
> > > FYI the following two patches would implement the above (untested).
> > 
> > Looks good.
> 
> I've been playing a bit with optimizing setting of 
> DECL_FUNCTION_EH_PERSONALITY only if the function uses EH types
> instead of just checking for an empty EH region tree.  It doesn't look
> like its very simple - even a catch (...) needs a personality routine.
> 
> So I am now testing the following - the ERT_ALLOWED_EXCEPTIONS case
> is required to get diagnostics from g++.dg/torture/pr34850.C which
> requires inlining memset into clear_mem.
> 
> If that doesn't work out I'll refrain from optimizing at all and
> just disable cross different EH personality TU inlining completely
> (that already passed bootstrapping and testing, it would be
> -  if (function_needs_eh_personality (cfun))
> -    DECL_FUNCTION_PERSONALITY (current_function_decl) = 
> eh_personality_decl;
> +  DECL_FUNCTION_PERSONALITY (current_function_decl) = 
> eh_personality_decl;
> meaning no functional change as far as trunk is concerned)

Doesn't seem to work.  Instead I tried to fall back to
the gcc personality for detecting empty type lists, again setting
a cfi personality for all functions we emit.  But that doesn't work
either (it seems catch (...) doesn't work with the gcc personality,
g++.dg/eh/loop1.C fails).

Bah.

So, ok without trying to be clever about inlining cross personality
for now?

Thanks,
Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 14:37               ` Richard Guenther
@ 2009-09-10 14:52                 ` Richard Guenther
  2009-09-10 15:50                   ` Richard Henderson
  2009-09-10 15:50                   ` Richard Guenther
  0 siblings, 2 replies; 39+ messages in thread
From: Richard Guenther @ 2009-09-10 14:52 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Thu, 10 Sep 2009, Richard Guenther wrote:

> On Thu, 10 Sep 2009, Richard Guenther wrote:
> 
> > On Tue, 8 Sep 2009, Richard Henderson wrote:
> > 
> > > On 09/08/2009 08:20 AM, Richard Guenther wrote:
> > > > > Ok.  I'll modify the patch to make this a true langhook and maybe move
> > > > > the eh-personality also to a langhook called from eh lowering.
> > > > 
> > > > The latter is difficult as C++ is playing some tricks with Java vs.
> > > > non-Java personality, so I leave that alone for now.
> > > 
> > > Ew.
> > > 
> > > > FYI the following two patches would implement the above (untested).
> > > 
> > > Looks good.
> > 
> > I've been playing a bit with optimizing setting of 
> > DECL_FUNCTION_EH_PERSONALITY only if the function uses EH types
> > instead of just checking for an empty EH region tree.  It doesn't look
> > like its very simple - even a catch (...) needs a personality routine.
> > 
> > So I am now testing the following - the ERT_ALLOWED_EXCEPTIONS case
> > is required to get diagnostics from g++.dg/torture/pr34850.C which
> > requires inlining memset into clear_mem.
> > 
> > If that doesn't work out I'll refrain from optimizing at all and
> > just disable cross different EH personality TU inlining completely
> > (that already passed bootstrapping and testing, it would be
> > -  if (function_needs_eh_personality (cfun))
> > -    DECL_FUNCTION_PERSONALITY (current_function_decl) = 
> > eh_personality_decl;
> > +  DECL_FUNCTION_PERSONALITY (current_function_decl) = 
> > eh_personality_decl;
> > meaning no functional change as far as trunk is concerned)
> 
> Doesn't seem to work.  Instead I tried to fall back to
> the gcc personality for detecting empty type lists, again setting
> a cfi personality for all functions we emit.  But that doesn't work
> either (it seems catch (...) doesn't work with the gcc personality,
> g++.dg/eh/loop1.C fails).

Which would be the following patch.

Richard.

2009-09-10  Richard Guenther  <rguenther@suse.de>
	Rafael Avila de Espindola  <espindola@google.com>

	* langhooks-def.h (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.
	(LANG_HOOKS_INITIALIZER): Adjust.
	(lhd_pass_through_t): Declare.
	* langhooks.h (struct lang_hooks): Add init_eh and eh_runtime_type.
	* langhooks.c (lhd_pass_through_t): New function.

        * dwarf2out.c (output_call_frame_info, dwarf2out_do_cfi_startproc,
	dwarf2out_begin_prologue): Use personality from current_function_decl.
        * expr.h (build_personality_function): Declare.
	(get_personality_function): Likewise.
	* expr.c (get_personality_function): New function.
        * libfuncs.h (libfunc_index): Remove LTI_eh_personality.
        (eh_personality_libfunc): Remove.
        * optabs.c (build_libfunc_function): New function split out from ...
	(init_one_libfunc): ... here.
        * toplev.c (eh_personality_decl): New.
        * tree.h (DECL_FUNCTION_PERSONALITY): New.
        (tree_function_decl): Add personality.
        (eh_personality_decl): New.
	* except.h (lang_eh_runtime_type): Remove.
	(function_needs_eh_personality): Declare.
        * except.c (lang_eh_runtime_type): Remove.
	(function_needs_eh_personality): New function.
	(add_type_for_runtime): Call lang_hooks.type_for_runtime instead.
        (sjlj_emit_function_enter, output_function_exception_table):
        Use personality from current_function_decl.
	* tree-eh.c (lower_eh_constructs): Set DECL_FUNCTION_PERSONALITY.
	* tree-inline.c (tree_can_inline_p): Do not inline across different
	EH personalities.

	* c-lang.c (LANG_HOOKS_INIT_EH): Define.
	* c-tree.h (c_eh_initialized_p): Remove.
	* c-decl.c (finish_decl): Don't call c_maybe_initialize_eh.
	Init eh_personality_decl instead of eh_personality_libfunc.
	(finish_decl): Don't call c_maybe_initialize_eh.
	(c_eh_initialized_p): Make local to ...
	(c_maybe_initialize_eh): ... this function.
	Init eh_personality_decl instead of eh_personality_libfunc.
        * c-parser.c (c_parser_omp_construct): Likewise.
	(c_parse_file): Call lang_hooks.init_eh.

	objc/
	* objc-act.c (objc_eh_runtime_type): Export.
	(objc_init_exceptions): Export.
	Init eh_personality_decl instead of eh_personality_libfunc.
	Do not set objc_init_exceptions.  Move warning code ...
	(objc_begin_try_stmt): ... here
	(objc_build_throw_stmt): ... and here.
	* objc-act.h (objc_init_exceptions): Declare.
	(objc_eh_runtime_type): Likewise.
	* objc-lang.c (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.

	cp/
	* except.c (init_exception_processing): Do not set
	lang_eh_runtime_type.
	Init eh_personality_decl instead of eh_personality_libfunc.
	* cp-lang.c (LANG_HOOKS_EH_RUNTIME_TYPE): Define.

	java/
	* decl.c (do_nothing): Remove.
	(java_init_decl_processing): Do not set lang_eh_runtime_type.
	Init eh_personality_decl instead of eh_personality_libfunc.

	ada/
	* gcc-interface/misc.c (gnat_init_gcc_eh): Do not set
	lang_eh_runtime_type.
	Init eh_personality_decl instead of eh_personality_libfunc.

	fortran/
	* f95-lang.c (gfc_maybe_initialize_eh): Init eh_personality_decl
	instead of eh_personality_libfunc.

Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/objc/objc-act.c	2009-09-10 14:18:42.000000000 +0200
*************** static struct objc_try_context *cur_try_
*** 3488,3494 ****
  /* ??? Isn't there a class object or some such?  Is it easy to get?  */
  
  #ifndef OBJCPLUS
! static tree
  objc_eh_runtime_type (tree type)
  {
    return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
--- 3488,3494 ----
  /* ??? Isn't there a class object or some such?  Is it easy to get?  */
  
  #ifndef OBJCPLUS
! tree
  objc_eh_runtime_type (tree type)
  {
    return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
*************** objc_eh_runtime_type (tree type)
*** 3497,3503 ****
  
  /* Initialize exception handling.  */
  
! static void
  objc_init_exceptions (void)
  {
    static bool done = false;
--- 3497,3503 ----
  
  /* Initialize exception handling.  */
  
! void
  objc_init_exceptions (void)
  {
    static bool done = false;
*************** objc_init_exceptions (void)
*** 3505,3529 ****
      return;
    done = true;
  
-   if (flag_objc_sjlj_exceptions)
-     {
-       /* On Darwin, ObjC exceptions require a sufficiently recent
- 	 version of the runtime, so the user must ask for them explicitly.  */
-       if (!flag_objc_exceptions)
- 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
- 		 "exception syntax");
-     }
  #ifndef OBJCPLUS
!   else
      {
!       c_eh_initialized_p = true;
!       eh_personality_libfunc
! 	= init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 			    ? "__gnu_objc_personality_sj0"
! 			    : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
-       lang_eh_runtime_type = objc_eh_runtime_type;
      }
  #endif
  }
--- 3505,3519 ----
      return;
    done = true;
  
  #ifndef OBJCPLUS
!   if (!flag_objc_sjlj_exceptions)
      {
!       eh_personality_decl
! 	= build_personality_function (USING_SJLJ_EXCEPTIONS
! 				      ? "__gnu_objc_personality_sj0"
! 				      : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
      }
  #endif
  }
*************** objc_begin_try_stmt (location_t try_locu
*** 3824,3830 ****
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   objc_init_exceptions ();
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
--- 3814,3827 ----
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
*************** objc_build_throw_stmt (location_t loc, t
*** 3973,3979 ****
  {
    tree args;
  
!   objc_init_exceptions ();
  
    if (throw_expr == NULL)
      {
--- 3970,3983 ----
  {
    tree args;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (throw_expr == NULL)
      {
Index: gcc/c-decl.c
===================================================================
*** gcc/c-decl.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/c-decl.c	2009-09-10 14:18:42.000000000 +0200
*************** tree pending_invalid_xref;
*** 92,100 ****
  /* File and line to appear in the eventual error message.  */
  location_t pending_invalid_xref_location;
  
- /* True means we've initialized exception handling.  */
- bool c_eh_initialized_p;
- 
  /* The file and line that the prototype came from if this is an
     old-style definition; used for diagnostics in
     store_parm_decls_oldstyle.  */
--- 92,97 ----
*************** merge_decls (tree newdecl, tree olddecl,
*** 2365,2371 ****
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID and DECL_CONTEXT.  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
--- 2362,2369 ----
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
!      DECL_ARGUMENTS (if appropriate).  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
*************** start_decl (struct c_declarator *declara
*** 4048,4061 ****
  void
  c_maybe_initialize_eh (void)
  {
    if (!flag_exceptions || c_eh_initialized_p)
      return;
  
    c_eh_initialized_p = true;
!   eh_personality_libfunc
!     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 			? "__gcc_personality_sj0"
! 			: "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 4046,4062 ----
  void
  c_maybe_initialize_eh (void)
  {
+   static bool c_eh_initialized_p = false;
+ 
    if (!flag_exceptions || c_eh_initialized_p)
      return;
  
    c_eh_initialized_p = true;
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcc_personality_sj0"
! 				  : "__gcc_personality_v0");
! 
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
*************** finish_decl (tree decl, location_t init_
*** 4360,4368 ****
  	  TREE_USED (decl) = 1;
  	  TREE_USED (cleanup_decl) = 1;
  
- 	  /* Initialize EH, if we've been told to do so.  */
- 	  c_maybe_initialize_eh ();
- 
  	  push_cleanup (decl, cleanup, false);
  	}
      }
--- 4361,4366 ----
Index: gcc/c-parser.c
===================================================================
*** gcc/c-parser.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/c-parser.c	2009-09-10 14:18:42.000000000 +0200
*************** c_parser_omp_construct (c_parser *parser
*** 8489,8500 ****
    p_kind = c_parser_peek_token (parser)->pragma_kind;
    c_parser_consume_pragma (parser);
  
-   /* For all constructs below except #pragma omp atomic
-      MUST_NOT_THROW catch handlers are needed when exceptions
-      are enabled.  */
-   if (p_kind != PRAGMA_OMP_ATOMIC)
-     c_maybe_initialize_eh ();
- 
    switch (p_kind)
      {
      case PRAGMA_OMP_ATOMIC:
--- 8489,8494 ----
*************** c_parse_file (void)
*** 8607,8612 ****
--- 8601,8609 ----
    the_parser = GGC_NEW (c_parser);
    *the_parser = tparser;
  
+   /* Initialize EH, if we've been told to do so.  */
+   lang_hooks.init_eh ();
+ 
    c_parser_translation_unit (the_parser);
    the_parser = NULL;
  }
Index: gcc/c-lang.c
===================================================================
*** gcc/c-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/c-lang.c	2009-09-10 14:18:42.000000000 +0200
*************** enum c_language_kind c_language = clk_c;
*** 44,49 ****
--- 44,51 ----
  #define LANG_HOOKS_NAME "GNU C"
  #undef LANG_HOOKS_INIT
  #define LANG_HOOKS_INIT c_objc_common_init
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH c_maybe_initialize_eh
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/langhooks-def.h
===================================================================
*** gcc/langhooks-def.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/langhooks-def.h	2009-09-10 14:18:42.000000000 +0200
*************** extern void lhd_do_nothing (void);
*** 40,45 ****
--- 40,46 ----
  extern void lhd_do_nothing_t (tree);
  extern void lhd_do_nothing_i (int);
  extern void lhd_do_nothing_f (struct function *);
+ extern tree lhd_pass_through_t (tree);
  extern bool lhd_post_options (const char **);
  extern alias_set_type lhd_get_alias_set (tree);
  extern tree lhd_return_null_tree_v (void);
*************** extern void lhd_omp_firstprivatize_type_
*** 107,112 ****
--- 108,115 ----
  #define LANG_HOOKS_EXPR_TO_DECL		lhd_expr_to_decl
  #define LANG_HOOKS_TO_TARGET_CHARSET	lhd_to_target_charset
  #define LANG_HOOKS_INIT_TS		lhd_do_nothing
+ #define LANG_HOOKS_INIT_EH		NULL
+ #define LANG_HOOKS_EH_RUNTIME_TYPE	lhd_pass_through_t
  
  /* Attribute hooks.  */
  #define LANG_HOOKS_ATTRIBUTE_TABLE		NULL
*************** extern tree lhd_make_node (enum tree_cod
*** 271,276 ****
--- 274,281 ----
    LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
    LANG_HOOKS_INIT_TS,          \
    LANG_HOOKS_EXPR_TO_DECL, \
+   LANG_HOOKS_INIT_EH, \
+   LANG_HOOKS_EH_RUNTIME_TYPE, \
  }
  
  #endif /* GCC_LANG_HOOKS_DEF_H */
Index: gcc/langhooks.h
===================================================================
*** gcc/langhooks.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/langhooks.h	2009-09-10 14:18:42.000000000 +0200
*************** struct lang_hooks
*** 414,419 ****
--- 414,425 ----
       if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating.  */
    tree (*expr_to_decl) (tree expr, bool *tc, bool *se);
  
+   /* Called to initialize the exception handing personality.  */
+   void (*init_eh) (void);
+ 
+   /* Map a type to a runtime object to match type.  */
+   tree (*eh_runtime_type) (tree);
+ 
    /* Whenever you add entries here, make sure you adjust langhooks-def.h
       and langhooks.c accordingly.  */
  };
Index: gcc/objc/objc-act.h
===================================================================
*** gcc/objc/objc-act.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/objc/objc-act.h	2009-09-10 14:18:42.000000000 +0200
*************** const char *objc_printable_name (tree, i
*** 32,37 ****
--- 32,39 ----
  void objc_finish_file (void);
  tree objc_fold_obj_type_ref (tree, tree);
  int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+ void objc_init_exceptions (void);
+ tree objc_eh_runtime_type (tree);
  
  /* NB: The remaining public functions are prototyped in c-common.h, for the
     benefit of stub-objc.c and objc-act.c.  */
Index: gcc/objc/objc-lang.c
===================================================================
*** gcc/objc/objc-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/objc/objc-lang.c	2009-09-10 14:18:42.000000000 +0200
*************** static void objc_init_ts (void);
*** 50,55 ****
--- 50,62 ----
  #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS objc_init_ts
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH objc_init_exceptions
+ 
+ #ifndef OBJCPLUS
+ #undef LANG_HOOKS_EH_RUNTIME_TYPE
+ #define LANG_HOOKS_EH_RUNTIME_TYPE objc_eh_runtime_type
+ #endif
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/ada/gcc-interface/misc.c
===================================================================
*** gcc/ada/gcc-interface/misc.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/ada/gcc-interface/misc.c	2009-09-10 14:18:42.000000000 +0200
*************** gnat_init_gcc_eh (void)
*** 431,441 ****
       right exception regions.  */
    using_eh_for_cleanups ();
  
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 					     ? "__gnat_eh_personality_sj"
! 					     : "__gnat_eh_personality");
    lang_eh_type_covers = gnat_eh_type_covers;
-   lang_eh_runtime_type = gnat_return_tree;
    default_init_unwind_resume_libfunc ();
  
    /* Turn on -fexceptions and -fnon-call-exceptions. The first one triggers
--- 431,442 ----
       right exception regions.  */
    using_eh_for_cleanups ();
  
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gnat_eh_personality_sj"
! 				  : "__gnat_eh_personality");
! 
    lang_eh_type_covers = gnat_eh_type_covers;
    default_init_unwind_resume_libfunc ();
  
    /* Turn on -fexceptions and -fnon-call-exceptions. The first one triggers
Index: gcc/cp/cp-lang.c
===================================================================
*** gcc/cp/cp-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/cp/cp-lang.c	2009-09-10 14:18:42.000000000 +0200
*************** static enum classify_record cp_classify_
*** 71,76 ****
--- 71,78 ----
  #define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS cp_init_ts
+ #undef LANG_HOOKS_EH_RUNTIME_TYPE
+ #define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/cp/except.c
===================================================================
*** gcc/cp/except.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/cp/except.c	2009-09-10 14:18:42.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 43,49 ****
  
  static void push_eh_cleanup (tree);
  static tree prepare_eh_type (tree);
- static tree build_eh_type_type (tree);
  static tree do_begin_catch (void);
  static int dtor_nothrow (tree);
  static tree do_end_catch (tree);
--- 43,48 ----
*************** init_exception_processing (void)
*** 78,92 ****
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 					     ? "__gxx_personality_sj0"
! 					     : "__gxx_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
-   lang_eh_runtime_type = build_eh_type_type;
    lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
  }
  
--- 77,92 ----
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gxx_personality_sj0"
! 				  : "__gxx_personality_v0");
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
    lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
  }
  
*************** eh_type_info (tree type)
*** 143,149 ****
  /* Build the address of a typeinfo decl for use in the runtime
     matching field of the exception model.  */
  
! static tree
  build_eh_type_type (tree type)
  {
    tree exp = eh_type_info (type);
--- 143,149 ----
  /* Build the address of a typeinfo decl for use in the runtime
     matching field of the exception model.  */
  
! tree
  build_eh_type_type (tree type)
  {
    tree exp = eh_type_info (type);
*************** decl_is_java_type (tree decl, int err)
*** 313,319 ****
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_libfunc is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
--- 313,319 ----
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_decl is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
*************** choose_personality_routine (enum languag
*** 354,362 ****
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 						 ? "__gcj_personality_sj0"
! 						 : "__gcj_personality_v0");
        break;
  
      default:
--- 354,363 ----
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_decl
! 	= build_personality_function (USING_SJLJ_EXCEPTIONS
! 				      ? "__gcj_personality_sj0"
! 				      : "__gcj_personality_v0");
        break;
  
      default:
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/except.c	2009-09-10 16:20:09.000000000 +0200
*************** gimple (*lang_protect_cleanup_actions) (
*** 92,100 ****
  /* Return true if type A catches type B.  */
  int (*lang_eh_type_covers) (tree a, tree b);
  
- /* Map a type to a runtime object to match type.  */
- tree (*lang_eh_runtime_type) (tree);
- 
  /* A hash table of label to region number.  */
  
  struct GTY(()) ehl_map_entry {
--- 92,97 ----
*************** add_type_for_runtime (tree type)
*** 1696,1702 ****
  					    TREE_HASH (type), INSERT);
    if (*slot == NULL)
      {
!       tree runtime = (*lang_eh_runtime_type) (type);
        *slot = tree_cons (type, runtime, NULL_TREE);
      }
  }
--- 1693,1699 ----
  					    TREE_HASH (type), INSERT);
    if (*slot == NULL)
      {
!       tree runtime = lang_hooks.eh_runtime_type (type);
        *slot = tree_cons (type, runtime, NULL_TREE);
      }
  }
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2424,2429 ****
--- 2421,2427 ----
  {
    rtx fn_begin, fc, mem, seq;
    bool fn_begin_outside_block;
+   rtx personality = get_personality_function (current_function_decl);
  
    fc = crtl->eh.sjlj_fc;
  
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2432,2440 ****
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (eh_personality_libfunc);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, eh_personality_libfunc);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
--- 2430,2438 ----
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (personality);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, personality);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
*************** output_ttype (tree type, int tt_format,
*** 4394,4400 ****
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section)
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
--- 4392,4398 ----
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section, rtx ARG_UNUSED (personality))
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
*************** output_one_function_exception_table (con
*** 4410,4416 ****
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, eh_personality_libfunc);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
--- 4408,4414 ----
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, personality);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
*************** output_one_function_exception_table (con
*** 4580,4595 ****
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (eh_personality_libfunc)
!     assemble_external_libcall (eh_personality_libfunc);
  
!   output_one_function_exception_table (fnname, 0);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1);
  
    switch_to_section (current_function_section ());
  }
--- 4578,4595 ----
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
+   rtx personality = get_personality_function (current_function_decl);
+ 
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (personality)
!     assemble_external_libcall (personality);
  
!   output_one_function_exception_table (fnname, 0, personality);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1, personality);
  
    switch_to_section (current_function_section ());
  }
*************** get_eh_throw_stmt_table (struct function
*** 4606,4611 ****
--- 4606,4676 ----
    return fun->eh->throw_stmt_table;
  }
  
+ /* Return true if the function deeds a EH personality function.  */
+ 
+ bool
+ function_needs_eh_personality (struct function *fn)
+ {
+   struct eh_region_d *i;
+   int depth = 0;
+ 
+   i = fn->eh->region_tree;
+   if (!i)
+     return false;
+ 
+   while (1)
+     {
+       switch (i->type)
+ 	{
+ 	case ERT_TRY:
+ 	case ERT_THROW:
+ 	  /* Do not need a EH personality function.  */
+ 	  break;
+ 
+ 	case ERT_MUST_NOT_THROW:
+ 	case ERT_CLEANUP:
+ 	  /* Ok with the default C EH personality.  */
+ 	  break;
+ 
+ 	case ERT_CATCH:
+ 	  /* An empty type list is ok with the default C EH personality.  */
+ 	  if (i->u.eh_catch.type_list)
+ 	    return true;
+ 	  break;
+ 
+ 	case ERT_ALLOWED_EXCEPTIONS:
+ 	  /* An empty type list is ok with the default C EH personality.  */
+ 	  if (i->u.allowed.type_list)
+ 	    return true;
+ 	  break;
+ 
+ 	case ERT_UNKNOWN:
+ 	  return true;
+ 	}
+       /* If there are sub-regions, process them.  */
+       if (i->inner)
+ 	i = i->inner, depth++;
+       /* If there are peers, process them.  */
+       else if (i->next_peer)
+ 	i = i->next_peer;
+       /* Otherwise, step back up the tree to the next peer.  */
+       else
+ 	{
+ 	  do
+ 	    {
+ 	      i = i->outer;
+ 	      depth--;
+ 	      if (i == NULL)
+ 		return false;
+ 	    }
+ 	  while (i->next_peer == NULL);
+ 	  i = i->next_peer;
+ 	}
+     }
+ 
+   return false;
+ }
+ 
  /* Dump EH information to OUT.  */
  
  void
Index: gcc/except.h
===================================================================
*** gcc/except.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/except.h	2009-09-10 14:50:26.000000000 +0200
*************** extern gimple (*lang_protect_cleanup_act
*** 217,225 ****
  /* Return true if type A catches type B.  */
  extern int (*lang_eh_type_covers) (tree a, tree b);
  
- /* Map a type to a runtime object to match type.  */
- extern tree (*lang_eh_runtime_type) (tree);
- 
  
  /* Just because the user configured --with-sjlj-exceptions=no doesn't
     mean that we can use call frame exceptions.  Detect that the target
--- 217,222 ----
*************** extern int num_eh_regions (void);
*** 277,279 ****
--- 274,277 ----
  extern bitmap must_not_throw_labels (void);
  extern struct eh_region_d *redirect_eh_edge_to_label (struct edge_def *, tree, bool, bool, int);
  extern int get_next_region_sharing_label (int);
+ extern bool function_needs_eh_personality (struct function *);
Index: gcc/java/decl.c
===================================================================
*** gcc/java/decl.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/java/decl.c	2009-09-10 14:18:42.000000000 +0200
*************** create_primitive_vtable (const char *nam
*** 510,521 ****
    return r;
  }
  
- static tree
- do_nothing (tree t)
- {
-   return t;
- }
- 
  /* Parse the version string and compute the ABI version number.  */
  static void
  parse_version (void)
--- 510,515 ----
*************** java_init_decl_processing (void)
*** 1195,1210 ****
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                                              ? "__gcj_personality_sj0"
!                                              : "__gcj_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
-   lang_eh_runtime_type = do_nothing;
- 
    initialize_builtins ();
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  
--- 1189,1205 ----
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
! 
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcj_personality_sj0"
! 				  : "__gcj_personality_v0");
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
    initialize_builtins ();
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  
Index: gcc/langhooks.c
===================================================================
*** gcc/langhooks.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/langhooks.c	2009-09-10 14:18:42.000000000 +0200
*************** lhd_do_nothing_t (tree ARG_UNUSED (t))
*** 53,58 ****
--- 53,65 ----
  {
  }
  
+ /* Pass through (tree).  */
+ tree
+ lhd_pass_through_t (tree t)
+ {
+   return t;
+ }
+ 
  /* Do nothing (int).  */
  
  void
Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/cp/cp-tree.h	2009-09-10 14:18:42.000000000 +0200
*************** extern void choose_personality_routine
*** 4521,4526 ****
--- 4521,4527 ----
  extern tree eh_type_info			(tree);
  extern tree begin_eh_spec_block			(void);
  extern void finish_eh_spec_block		(tree, tree);
+ extern tree build_eh_type_type			(tree);
  
  /* in expr.c */
  extern tree cplus_expand_constant		(tree);
Index: gcc/libfuncs.h
===================================================================
*** gcc/libfuncs.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/libfuncs.h	2009-09-10 14:18:42.000000000 +0200
*************** enum libfunc_index
*** 31,37 ****
    LTI_setbits,
  
    LTI_unwind_resume,
-   LTI_eh_personality,
    LTI_setjmp,
    LTI_longjmp,
    LTI_unwind_sjlj_register,
--- 31,36 ----
*************** extern GTY(()) rtx libfunc_table[LTI_MAX
*** 61,67 ****
  #define setbits_libfunc	(libfunc_table[LTI_setbits])
  
  #define unwind_resume_libfunc	(libfunc_table[LTI_unwind_resume])
- #define eh_personality_libfunc	(libfunc_table[LTI_eh_personality])
  #define setjmp_libfunc	(libfunc_table[LTI_setjmp])
  #define longjmp_libfunc	(libfunc_table[LTI_longjmp])
  #define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
--- 60,65 ----
Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/optabs.c	2009-09-10 14:18:42.000000000 +0200
*************** libfunc_decl_eq (const void *entry1, con
*** 6023,6028 ****
--- 6023,6050 ----
    return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
  }
  
+ /* Build a decl for a libfunc named NAME. */
+ 
+ tree
+ build_libfunc_function (const char *name)
+ {
+   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+ 			  get_identifier (name),
+                           build_function_type (integer_type_node, NULL_TREE));
+   /* ??? We don't have any type information except for this is
+      a function.  Pretend this is "int foo()".  */
+   DECL_ARTIFICIAL (decl) = 1;
+   DECL_EXTERNAL (decl) = 1;
+   TREE_PUBLIC (decl) = 1;
+   gcc_assert (DECL_ASSEMBLER_NAME (decl));
+ 
+   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
+      are the flags assigned by targetm.encode_section_info.  */
+   SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
+ 
+   return decl;
+ }
+ 
  rtx
  init_one_libfunc (const char *name)
  {
*************** init_one_libfunc (const char *name)
*** 6043,6061 ****
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       /* ??? We don't have any type information except for this is
! 	 a function.  Pretend this is "int foo()".  */
!       decl = build_decl (UNKNOWN_LOCATION,
! 			 FUNCTION_DECL, get_identifier (name),
! 			 build_function_type (integer_type_node, NULL_TREE));
!       DECL_ARTIFICIAL (decl) = 1;
!       DECL_EXTERNAL (decl) = 1;
!       TREE_PUBLIC (decl) = 1;
! 
!       /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
! 	 are the flags assigned by targetm.encode_section_info.  */
!       SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
! 
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
--- 6065,6071 ----
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       decl = build_libfunc_function (name);
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/tree.h	2009-09-10 14:18:42.000000000 +0200
*************** struct GTY(()) tree_decl_minimal {
*** 2538,2543 ****
--- 2538,2546 ----
  #define DECL_DEBUG_EXPR_IS_FROM(NODE) \
    (DECL_COMMON_CHECK (NODE)->decl_common.debug_expr_is_from)
  
+ #define DECL_FUNCTION_PERSONALITY(NODE) \
+   (FUNCTION_DECL_CHECK (NODE)->function_decl.personality)
+ 
  /* Nonzero for a given ..._DECL node means that the name of this node should
     be ignored for symbolic debug purposes.  */
  #define DECL_IGNORED_P(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.ignored_flag)
*************** struct GTY(()) tree_function_decl {
*** 3188,3193 ****
--- 3191,3199 ----
  
    struct function *f;
  
+   /* The personality function. Used for stack unwinding. */
+   tree personality;
+ 
    /* Function specific options that are used by this function.  */
    tree function_specific_target;	/* target options */
    tree function_specific_optimization;	/* optimization options */
*************** extern int pedantic_lvalues;
*** 4557,4562 ****
--- 4563,4571 ----
  
  extern GTY(()) tree current_function_decl;
  
+ /* The eh personally function that this FE wants to use. */
+ extern GTY(()) tree eh_personality_decl;
+ 
  /* Nonzero means a FUNC_BEGIN label was emitted.  */
  extern GTY(()) const char * current_function_func_begin_label;
  \f
Index: gcc/toplev.c
===================================================================
*** gcc/toplev.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/toplev.c	2009-09-10 14:18:42.000000000 +0200
*************** int optimize_size = 0;
*** 202,207 ****
--- 202,210 ----
     or 0 if between functions.  */
  tree current_function_decl;
  
+ /* The EH personality function that this FE wants to use. */
+ tree eh_personality_decl;
+ 
  /* Set to the FUNC_BEGIN label of the current function, or NULL
     if none.  */
  const char * current_function_func_begin_label;
Index: gcc/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/dwarf2out.c	2009-09-10 14:18:42.000000000 +0200
*************** static GTY(()) section *debug_str_sectio
*** 216,221 ****
--- 216,225 ----
  static GTY(()) section *debug_ranges_section;
  static GTY(()) section *debug_frame_section;
  
+ /* Personality decl of current unit.  Used only when assembler does not support
+    personality CFI.  */
+ static GTY(()) rtx current_unit_personality;
+ 
  /* How to start an assembler comment.  */
  #ifndef ASM_COMMENT_START
  #define ASM_COMMENT_START ";#"
*************** output_call_frame_info (int for_eh)
*** 3599,3604 ****
--- 3603,3609 ----
    int per_encoding = DW_EH_PE_absptr;
    int lsda_encoding = DW_EH_PE_absptr;
    int return_reg;
+   rtx personality = NULL;
    int dw_cie_version;
  
    /* Don't emit a CIE if there won't be any FDEs.  */
*************** output_call_frame_info (int for_eh)
*** 3684,3689 ****
--- 3689,3696 ----
  
    augmentation[0] = 0;
    augmentation_size = 0;
+ 
+   personality = current_unit_personality;
    if (for_eh)
      {
        char *p;
*************** output_call_frame_info (int for_eh)
*** 3703,3713 ****
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (eh_personality_libfunc)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (eh_personality_libfunc);
  	}
        if (any_lsda_needed)
  	{
--- 3710,3720 ----
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (personality)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (personality);
  	}
        if (any_lsda_needed)
  	{
*************** output_call_frame_info (int for_eh)
*** 3726,3732 ****
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
--- 3733,3739 ----
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (personality && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
*************** output_call_frame_info (int for_eh)
*** 3760,3771 ****
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (eh_personality_libfunc)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   eh_personality_libfunc,
  					   true, NULL);
  	}
  
--- 3767,3778 ----
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (personality)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   personality,
  					   true, NULL);
  	}
  
*************** dwarf2out_do_cfi_startproc (bool second)
*** 3824,3836 ****
  {
    int enc;
    rtx ref;
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (eh_personality_libfunc)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = eh_personality_libfunc;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
--- 3831,3844 ----
  {
    int enc;
    rtx ref;
+   rtx personality = get_personality_function (current_function_decl);
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (personality)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = personality;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
*************** dwarf2out_begin_prologue (unsigned int l
*** 3873,3878 ****
--- 3881,3887 ----
    char label[MAX_ARTIFICIAL_LABEL_BYTES];
    char * dup_label;
    dw_fde_ref fde;
+   rtx personality;
    section *fnsec;
  
    current_function_func_begin_label = NULL;
*************** dwarf2out_begin_prologue (unsigned int l
*** 3967,3974 ****
--- 3976,3992 ----
      dwarf2out_source_line (line, file, 0, true);
  #endif
  
+   personality = get_personality_function (current_function_decl);
    if (dwarf2out_do_cfi_asm ())
      dwarf2out_do_cfi_startproc (false);
+   else
+     {
+       if (!current_unit_personality || current_unit_personality == personality)
+         current_unit_personality = personality;
+       else
+ 	sorry ("Multiple EH personalities are supported only with assemblers "
+ 	       "supporting .cfi.personality directive.");
+     }
  }
  
  /* Output a marker (i.e. a label) for the absolute end of the generated code
Index: gcc/expr.h
===================================================================
*** gcc/expr.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/expr.h	2009-09-10 16:28:30.000000000 +0200
*************** extern void init_all_optabs (void);
*** 814,819 ****
--- 814,832 ----
  extern rtx init_one_libfunc (const char *);
  extern rtx set_user_assembler_libfunc (const char *, const char *);
  
+ /* Build a decl for a libfunc named NAME. */
+ extern tree build_libfunc_function (const char *);
+ 
+ /* Build a decl for a personality function named NAME. */
+ static inline tree
+ build_personality_function (const char *name)
+ {
+   return build_libfunc_function (name);
+ }
+ 
+ /* Get the personality libfunc for a function decl.  */
+ rtx get_personality_function (tree);
+ 
  extern int vector_mode_valid_p (enum machine_mode);
  
  #endif /* GCC_EXPR_H */
Index: gcc/fortran/f95-lang.c
===================================================================
*** gcc/fortran/f95-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/fortran/f95-lang.c	2009-09-10 14:18:42.000000000 +0200
*************** gfc_maybe_initialize_eh (void)
*** 1155,1164 ****
      return;
  
    gfc_eh_initialized_p = true;
!   eh_personality_libfunc
!     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                        ? "__gcc_personality_sj0"
!                        : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 1155,1164 ----
      return;
  
    gfc_eh_initialized_p = true;
!   eh_personality_decl
!     = build_personality_function (USING_SJLJ_EXCEPTIONS
! 				  ? "__gcc_personality_sj0"
! 				  : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
Index: gcc/c-tree.h
===================================================================
*** gcc/c-tree.h.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/c-tree.h	2009-09-10 14:18:42.000000000 +0200
*************** extern int system_header_p;
*** 589,597 ****
  
  extern bool c_override_global_bindings_to_false;
  
- /* True means we've initialized exception handling.  */
- extern bool c_eh_initialized_p;
- 
  /* In c-decl.c */
  extern void c_finish_incomplete_decl (tree);
  extern void c_write_global_declarations (void);
--- 589,594 ----
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/tree-eh.c	2009-09-10 15:11:52.000000000 +0200
*************** lower_eh_constructs (void)
*** 1939,1944 ****
--- 1939,1948 ----
    htab_delete (finally_tree);
  
    collect_eh_region_array ();
+ 
+   if (function_needs_eh_personality (cfun))
+     DECL_FUNCTION_PERSONALITY (current_function_decl) = eh_personality_decl;
+ 
    return 0;
  }
  
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c.orig	2009-09-10 13:40:45.000000000 +0200
--- gcc/tree-inline.c	2009-09-10 14:21:01.000000000 +0200
*************** tree_can_inline_p (struct cgraph_edge *e
*** 4999,5004 ****
--- 4999,5019 ----
    caller = e->caller->decl;
    callee = e->callee->decl;
  
+   /* We cannot inline a function that uses a different EH personality
+      than the caller.  Restrict inlining functions with either no EH
+      personality or calls with matching personality in the caller
+      and callee for now, that will not require personality changes
+      in the caller.  Everything more advanced needs to be taken into
+      account during the inline plan computation.  */
+   if (DECL_FUNCTION_PERSONALITY (callee)
+       && (DECL_FUNCTION_PERSONALITY (caller)
+ 	  != DECL_FUNCTION_PERSONALITY (callee)))
+     {
+       e->inline_failed = CIF_UNSPECIFIED;
+       gimple_call_set_cannot_inline (e->call_stmt, true);
+       return false;
+     }
+ 
    /* Allow the backend to decide if inlining is ok.  */
    if (!targetm.target_option.can_inline_p (caller, callee))
      {
Index: gcc/expr.c
===================================================================
*** gcc/expr.c.orig	2009-09-10 10:49:08.000000000 +0200
--- gcc/expr.c	2009-09-10 16:28:58.000000000 +0200
*************** const_vector_from_tree (tree exp)
*** 10214,10217 ****
--- 10214,10241 ----
  
    return gen_rtx_CONST_VECTOR (mode, v);
  }
+ 
+ 
+ /* Extracts the personality function of DECL and returns the corresponding
+    libfunc.  */
+ 
+ rtx
+ get_personality_function (tree decl)
+ {
+   tree personality = DECL_FUNCTION_PERSONALITY (decl);
+   tree name;
+ 
+   if (!personality && !eh_personality_decl)
+     return NULL;
+ 
+   if (!personality)
+     return init_one_libfunc (USING_SJLJ_EXCEPTIONS
+ 			     ? "__gcc_personality_sj0"
+ 			     : "__gcc_personality_v0");
+ 
+   name = DECL_ASSEMBLER_NAME (personality);
+ 
+   return init_one_libfunc (IDENTIFIER_POINTER (name));
+ }
+ 
  #include "gt-expr.h"

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 14:52                 ` Richard Guenther
  2009-09-10 15:50                   ` Richard Henderson
@ 2009-09-10 15:50                   ` Richard Guenther
  2009-09-10 15:57                     ` Richard Henderson
  1 sibling, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-10 15:50 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Thu, 10 Sep 2009, Richard Guenther wrote:

> On Thu, 10 Sep 2009, Richard Guenther wrote:
> 
> > On Thu, 10 Sep 2009, Richard Guenther wrote:
> > 
> > > On Tue, 8 Sep 2009, Richard Henderson wrote:
> > > 
> > > > On 09/08/2009 08:20 AM, Richard Guenther wrote:
> > > > > > Ok.  I'll modify the patch to make this a true langhook and maybe move
> > > > > > the eh-personality also to a langhook called from eh lowering.
> > > > > 
> > > > > The latter is difficult as C++ is playing some tricks with Java vs.
> > > > > non-Java personality, so I leave that alone for now.
> > > > 
> > > > Ew.
> > > > 
> > > > > FYI the following two patches would implement the above (untested).
> > > > 
> > > > Looks good.
> > > 
> > > I've been playing a bit with optimizing setting of 
> > > DECL_FUNCTION_EH_PERSONALITY only if the function uses EH types
> > > instead of just checking for an empty EH region tree.  It doesn't look
> > > like its very simple - even a catch (...) needs a personality routine.
> > > 
> > > So I am now testing the following - the ERT_ALLOWED_EXCEPTIONS case
> > > is required to get diagnostics from g++.dg/torture/pr34850.C which
> > > requires inlining memset into clear_mem.
> > > 
> > > If that doesn't work out I'll refrain from optimizing at all and
> > > just disable cross different EH personality TU inlining completely
> > > (that already passed bootstrapping and testing, it would be
> > > -  if (function_needs_eh_personality (cfun))
> > > -    DECL_FUNCTION_PERSONALITY (current_function_decl) = 
> > > eh_personality_decl;
> > > +  DECL_FUNCTION_PERSONALITY (current_function_decl) = 
> > > eh_personality_decl;
> > > meaning no functional change as far as trunk is concerned)
> > 
> > Doesn't seem to work.  Instead I tried to fall back to
> > the gcc personality for detecting empty type lists, again setting
> > a cfi personality for all functions we emit.  But that doesn't work
> > either (it seems catch (...) doesn't work with the gcc personality,
> > g++.dg/eh/loop1.C fails).
> 
> Which would be the following patch.

On top of which the following seems to fix things.  Well "fix" in
that 1) C/C++ functions that do not need a personality don't get one,
thus a smaller .eh_frame, 2) we don't do invalid inlining 3) we still
inline enough.

Adjusting DECL_STRUCT_FUNCTION in tree_can_inline_p is of course a
hack, but well ... I don't feel like rewriting the inliner right now.

Hmm.  Testing in progress, results tomorrow.

Richard.

Index: gcc/except.c
===================================================================
--- gcc/except.c.orig	2009-09-10 17:47:02.000000000 +0200
+++ gcc/except.c	2009-09-10 17:14:25.000000000 +0200
@@ -4629,20 +4629,9 @@ function_needs_eh_personality (struct fu
 
 	case ERT_MUST_NOT_THROW:
 	case ERT_CLEANUP:
-	  /* Ok with the default C EH personality.  */
-	  break;
-
 	case ERT_CATCH:
-	  /* An empty type list is ok with the default C EH personality.  */
-	  if (i->u.eh_catch.type_list)
-	    return true;
-	  break;
-
 	case ERT_ALLOWED_EXCEPTIONS:
-	  /* An empty type list is ok with the default C EH personality.  */
-	  if (i->u.allowed.type_list)
-	    return true;
-	  break;
+	  return true;
 
 	case ERT_UNKNOWN:
 	  return true;
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c.orig	2009-09-10 17:47:02.000000000 +0200
+++ gcc/tree-inline.c	2009-09-10 17:45:48.000000000 +0200
@@ -5000,12 +5000,10 @@ tree_can_inline_p (struct cgraph_edge *e
   callee = e->callee->decl;
 
   /* We cannot inline a function that uses a different EH personality
-     than the caller.  Restrict inlining functions with either no EH
-     personality or calls with matching personality in the caller
-     and callee for now, that will not require personality changes
-     in the caller.  Everything more advanced needs to be taken into
-     account during the inline plan computation.  */
-  if (DECL_FUNCTION_PERSONALITY (callee)
+     than the caller.  If we have functions without a specified EH
+     personality adjust them to reflect this possible inlining decision.  */
+  if (DECL_FUNCTION_PERSONALITY (caller)
+      && DECL_FUNCTION_PERSONALITY (callee)
       && (DECL_FUNCTION_PERSONALITY (caller)
 	  != DECL_FUNCTION_PERSONALITY (callee)))
     {
@@ -5013,6 +5011,19 @@ tree_can_inline_p (struct cgraph_edge *e
       gimple_call_set_cannot_inline (e->call_stmt, true);
       return false;
     }
+  else if (DECL_FUNCTION_PERSONALITY (caller)
+	   != DECL_FUNCTION_PERSONALITY (callee))
+    {
+      /* If the callee has callers we have to avoid mismatched inlining
+         into it.  */
+      if (DECL_FUNCTION_PERSONALITY (caller)
+	  && e->callee->callers)
+	DECL_FUNCTION_PERSONALITY (callee) = DECL_FUNCTION_PERSONALITY (caller);
+      /* If the callee has a personality avoid mismatched inlining into
+         the caller.  */
+      else if (DECL_FUNCTION_PERSONALITY (callee))
+	DECL_FUNCTION_PERSONALITY (caller) = DECL_FUNCTION_PERSONALITY (callee);
+    }
 
   /* Allow the backend to decide if inlining is ok.  */
   if (!targetm.target_option.can_inline_p (caller, callee))
Index: gcc/expr.c
===================================================================
--- gcc/expr.c.orig	2009-09-10 17:47:02.000000000 +0200
+++ gcc/expr.c	2009-09-10 17:40:14.000000000 +0200
@@ -10225,14 +10225,10 @@ get_personality_function (tree decl)
   tree personality = DECL_FUNCTION_PERSONALITY (decl);
   tree name;
 
-  if (!personality && !eh_personality_decl)
+  if (!personality
+      || !function_needs_eh_personality (DECL_STRUCT_FUNCTION (decl)))
     return NULL;
 
-  if (!personality)
-    return init_one_libfunc (USING_SJLJ_EXCEPTIONS
-			     ? "__gcc_personality_sj0"
-			     : "__gcc_personality_v0");
-
   name = DECL_ASSEMBLER_NAME (personality);
 
   return init_one_libfunc (IDENTIFIER_POINTER (name));

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 14:52                 ` Richard Guenther
@ 2009-09-10 15:50                   ` Richard Henderson
  2009-09-10 16:02                     ` Richard Guenther
  2009-09-10 15:50                   ` Richard Guenther
  1 sibling, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2009-09-10 15:50 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/10/2009 07:52 AM, Richard Guenther wrote:
>> Doesn't seem to work.  Instead I tried to fall back to
>> the gcc personality for detecting empty type lists, again setting
>> a cfi personality for all functions we emit.  But that doesn't work
>> either (it seems catch (...) doesn't work with the gcc personality,
>> g++.dg/eh/loop1.C fails).

Interesting.  I wouldn't have expected that.  Though your patch
doesn't seem to indicate that:

> + 	case ERT_CATCH:
> + 	  /* An empty type list is ok with the default C EH personality.  */
> + 	  if (i->u.eh_catch.type_list)
> + 	    return true;
> + 	  break;

> 	* langhooks-def.h (LANG_HOOKS_INIT_EH): Define.
> 	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.
> 	(LANG_HOOKS_INITIALIZER): Adjust.
> 	(lhd_pass_through_t): Declare.
> 	* langhooks.h (struct lang_hooks): Add init_eh and eh_runtime_type.
> 	* langhooks.c (lhd_pass_through_t): New function.
...
>          * toplev.c (eh_personality_decl): New.

I'm surprised you're not taking the opportunity to make
the eh_personality_thingy a proper lang hook.

> + 	case ERT_MUST_NOT_THROW:
> + 	case ERT_CLEANUP:
> + 	  /* Ok with the default C EH personality.  */
> + 	  break;

MUST_NOT_THROW is not ok with default personality.
You'll wind up invoking abort instead of std::terminate.

> *** gcc/fortran/f95-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
> --- gcc/fortran/f95-lang.c	2009-09-10 14:18:42.000000000 +0200
> *************** gfc_maybe_initialize_eh (void)
> *** 1155,1164 ****
>        return;
>
>      gfc_eh_initialized_p = true;
> !   eh_personality_libfunc
> !     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
> !                        ? "__gcc_personality_sj0"
> !                        : "__gcc_personality_v0");
>      default_init_unwind_resume_libfunc ();
>      using_eh_for_cleanups ();
>    }
> --- 1155,1164 ----
>        return;
>
>      gfc_eh_initialized_p = true;
> !   eh_personality_decl
> !     = build_personality_function (USING_SJLJ_EXCEPTIONS
> ! 				  ? "__gcc_personality_sj0"
> ! 				  : "__gcc_personality_v0");

Surely Fortran can simply avoid setting this up at all?

> + rtx
> + get_personality_function (tree decl)
> + {
> +   tree personality = DECL_FUNCTION_PERSONALITY (decl);
> +   tree name;
> +
> +   if (!personality&&  !eh_personality_decl)
> +     return NULL;
> +
> +   if (!personality)
> +     return init_one_libfunc (USING_SJLJ_EXCEPTIONS
> + 			     ? "__gcc_personality_sj0"
> + 			     : "__gcc_personality_v0");
> +
> +   name = DECL_ASSEMBLER_NAME (personality);
> +
> +   return init_one_libfunc (IDENTIFIER_POINTER (name));
> + }

Why in the world are you extracting the name and invoking 
init_one_libfunc instead of using the DECL_RTL of the function_decl? And 
what's with the eh_personality_decl check at this point?


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 15:50                   ` Richard Guenther
@ 2009-09-10 15:57                     ` Richard Henderson
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2009-09-10 15:57 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/10/2009 08:50 AM, Richard Guenther wrote:
> @@ -10225,14 +10225,10 @@ get_personality_function (tree decl)
>     tree personality = DECL_FUNCTION_PERSONALITY (decl);
>     tree name;
>
> -  if (!personality&&  !eh_personality_decl)
> +  if (!personality
> +      || !function_needs_eh_personality (DECL_STRUCT_FUNCTION (decl)))
>       return NULL;

On the bright side, I'm happier with this test.  :-)


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 15:50                   ` Richard Henderson
@ 2009-09-10 16:02                     ` Richard Guenther
  2009-09-10 16:06                       ` Richard Guenther
  2009-09-10 16:12                       ` Richard Henderson
  0 siblings, 2 replies; 39+ messages in thread
From: Richard Guenther @ 2009-09-10 16:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Thu, 10 Sep 2009, Richard Henderson wrote:

> On 09/10/2009 07:52 AM, Richard Guenther wrote:
> > > Doesn't seem to work.  Instead I tried to fall back to
> > > the gcc personality for detecting empty type lists, again setting
> > > a cfi personality for all functions we emit.  But that doesn't work
> > > either (it seems catch (...) doesn't work with the gcc personality,
> > > g++.dg/eh/loop1.C fails).
> 
> Interesting.  I wouldn't have expected that.  Though your patch
> doesn't seem to indicate that:
> 
> > + 	case ERT_CATCH:
> > + 	  /* An empty type list is ok with the default C EH personality.  */
> > + 	  if (i->u.eh_catch.type_list)
> > + 	    return true;
> > + 	  break;

Yep - it's the patch that doesn't work, just to explain things.

> > 	* langhooks-def.h (LANG_HOOKS_INIT_EH): Define.
> > 	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.
> > 	(LANG_HOOKS_INITIALIZER): Adjust.
> > 	(lhd_pass_through_t): Declare.
> > 	* langhooks.h (struct lang_hooks): Add init_eh and eh_runtime_type.
> > 	* langhooks.c (lhd_pass_through_t): New function.
> ...
> >          * toplev.c (eh_personality_decl): New.
> 
> I'm surprised you're not taking the opportunity to make
> the eh_personality_thingy a proper lang hook.

I can do that.

> > + 	case ERT_MUST_NOT_THROW:
> > + 	case ERT_CLEANUP:
> > + 	  /* Ok with the default C EH personality.  */
> > + 	  break;
> 
> MUST_NOT_THROW is not ok with default personality.
> You'll wind up invoking abort instead of std::terminate.

Fixed.

> > *** gcc/fortran/f95-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
> > --- gcc/fortran/f95-lang.c	2009-09-10 14:18:42.000000000 +0200
> > *************** gfc_maybe_initialize_eh (void)
> > *** 1155,1164 ****
> >        return;
> > 
> >      gfc_eh_initialized_p = true;
> > !   eh_personality_libfunc
> > !     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
> > !                        ? "__gcc_personality_sj0"
> > !                        : "__gcc_personality_v0");
> >      default_init_unwind_resume_libfunc ();
> >      using_eh_for_cleanups ();
> >    }
> > --- 1155,1164 ----
> >        return;
> > 
> >      gfc_eh_initialized_p = true;
> > !   eh_personality_decl
> > !     = build_personality_function (USING_SJLJ_EXCEPTIONS
> > ! 				  ? "__gcc_personality_sj0"
> > ! 				  : "__gcc_personality_v0");
> 
> Surely Fortran can simply avoid setting this up at all?

Good question - I'll check.

> > + rtx
> > + get_personality_function (tree decl)
> > + {
> > +   tree personality = DECL_FUNCTION_PERSONALITY (decl);
> > +   tree name;
> > +
> > +   if (!personality&&  !eh_personality_decl)
> > +     return NULL;
> > +
> > +   if (!personality)
> > +     return init_one_libfunc (USING_SJLJ_EXCEPTIONS
> > + 			     ? "__gcc_personality_sj0"
> > + 			     : "__gcc_personality_v0");
> > +
> > +   name = DECL_ASSEMBLER_NAME (personality);
> > +
> > +   return init_one_libfunc (IDENTIFIER_POINTER (name));
> > + }
> 
> Why in the world are you extracting the name and invoking init_one_libfunc
> instead of using the DECL_RTL of the function_decl? And what's with the
> eh_personality_decl check at this point?

It doesn't seem to work - I get ICEs in


#2  0x00000000006d897b in output_addr_const (file=0x163c040, 
x=0x2aaaacaa5c80)
    at /space/rguenther/src/svn/trunk/gcc/final.c:3619
3619          output_operand_lossage ("invalid expression as operand");

(gdb) call debug_rtx (x)
(mem:QI (symbol_ref:DI ("__gcc_personality_v0") [flags 0x41]) [0 S1 A8])

#3  0x000000000064d3fd in dwarf2out_do_cfi_startproc (second=0 '\000')
    at /space/rguenther/src/svn/trunk/gcc/dwarf2out.c:3851
3851          output_addr_const (asm_out_file, ref);


Thanks,
Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 16:02                     ` Richard Guenther
@ 2009-09-10 16:06                       ` Richard Guenther
  2009-09-10 16:23                         ` Richard Henderson
  2009-09-10 16:12                       ` Richard Henderson
  1 sibling, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-10 16:06 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Thu, 10 Sep 2009, Richard Guenther wrote:

> On Thu, 10 Sep 2009, Richard Henderson wrote:
> 
> > > *** gcc/fortran/f95-lang.c.orig	2009-09-10 13:40:45.000000000 +0200
> > > --- gcc/fortran/f95-lang.c	2009-09-10 14:18:42.000000000 +0200
> > > *************** gfc_maybe_initialize_eh (void)
> > > *** 1155,1164 ****
> > >        return;
> > > 
> > >      gfc_eh_initialized_p = true;
> > > !   eh_personality_libfunc
> > > !     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
> > > !                        ? "__gcc_personality_sj0"
> > > !                        : "__gcc_personality_v0");
> > >      default_init_unwind_resume_libfunc ();
> > >      using_eh_for_cleanups ();
> > >    }
> > > --- 1155,1164 ----
> > >        return;
> > > 
> > >      gfc_eh_initialized_p = true;
> > > !   eh_personality_decl
> > > !     = build_personality_function (USING_SJLJ_EXCEPTIONS
> > > ! 				  ? "__gcc_personality_sj0"
> > > ! 				  : "__gcc_personality_v0");
> > 
> > Surely Fortran can simply avoid setting this up at all?
> 
> Good question - I'll check.

No.  It needs it for OMP and the MUST_NOT_THROW regions that generates.

Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 16:02                     ` Richard Guenther
  2009-09-10 16:06                       ` Richard Guenther
@ 2009-09-10 16:12                       ` Richard Henderson
  1 sibling, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2009-09-10 16:12 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/10/2009 09:02 AM, Richard Guenther wrote:
> It doesn't seem to work - I get ICEs in
>
>
> #2  0x00000000006d897b in output_addr_const (file=0x163c040,
> x=0x2aaaacaa5c80)
>      at /space/rguenther/src/svn/trunk/gcc/final.c:3619
> 3619          output_operand_lossage ("invalid expression as operand");
>
> (gdb) call debug_rtx (x)
> (mem:QI (symbol_ref:DI ("__gcc_personality_v0") [flags 0x41]) [0 S1 A8])
>
> #3  0x000000000064d3fd in dwarf2out_do_cfi_startproc (second=0 '\000')
>      at /space/rguenther/src/svn/trunk/gcc/dwarf2out.c:3851
> 3851          output_addr_const (asm_out_file, ref);

You have to drop the MEM, of course, i.e.

   return XEXP (DECL_RTL (decl), 0);

Also ideally, we'd give a proper prototype for the personality function. 
  Getting the struct and enum parameters right would be neigh impossible 
of course, but we could at least give it

   int personality(int, int, unsigned long long, void*, void*)


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 16:06                       ` Richard Guenther
@ 2009-09-10 16:23                         ` Richard Henderson
  2009-09-11 13:25                           ` Richard Guenther
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2009-09-10 16:23 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/10/2009 09:05 AM, Richard Guenther wrote:
> No.  It needs it for OMP and the MUST_NOT_THROW regions that generates.

Ah, but we just need *some* personality, not any particular personality, 
since we don't have a language spec telling us that we have to call a 
particular abort function.  Same goes for C.

So you have C and Fortran leave its lang.eh_personality NULL, which 
leaves DECL_EH_PERSONALITY NULL, which allows your inliner change to 
drop in the C++ (or Ada, etc) personality when needed.

If we arrive at assembly output time in get_personality_function and 
find that the function has a non-NULL fun->eh->region_tree, then we 
supply the default __gcc_personality_v0.  (Note the non-null region_tree 
here, since we need *some* personality even to handle cleanup regions at 
runtime.  But *any* personality can handle cleanup regions, which is why 
we don't want to select a DECL_EH_PERSONALITY too early for that case.)


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-10 16:23                         ` Richard Henderson
@ 2009-09-11 13:25                           ` Richard Guenther
  2009-09-11 15:41                             ` Richard Henderson
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-11 13:25 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Diego Novillo

On Thu, 10 Sep 2009, Richard Henderson wrote:

> On 09/10/2009 09:05 AM, Richard Guenther wrote:
> > No.  It needs it for OMP and the MUST_NOT_THROW regions that generates.
> 
> Ah, but we just need *some* personality, not any particular personality, since
> we don't have a language spec telling us that we have to call a particular
> abort function.  Same goes for C.
> 
> So you have C and Fortran leave its lang.eh_personality NULL, which leaves
> DECL_EH_PERSONALITY NULL, which allows your inliner change to drop in the C++
> (or Ada, etc) personality when needed.
> 
> If we arrive at assembly output time in get_personality_function and find that
> the function has a non-NULL fun->eh->region_tree, then we supply the default
> __gcc_personality_v0.  (Note the non-null region_tree here, since we need
> *some* personality even to handle cleanup regions at runtime.  But *any*
> personality can handle cleanup regions, which is why we don't want to select a
> DECL_EH_PERSONALITY too early for that case.)

Ok, so the following implements that, creates a langhook to query the
units personality, properly uses DECL_RTL in get_personality_function
and moves the inlining fixups to the inliner, not changing the
personalities in the edge predicate.  It also adds personality setting
to late functions coming via cgraph_add_new_function (which fixes a
bunch of OMP ICEs I get otherwise).

Boostrapped and tested a slightly older version ok, re-bootstrap and
test running on x86_64-unknown-linux-gnu.

The C++ FE handling of Java vs. C++ personality could need some cleanup
now that we can have per-function personalities.

Ok for trunk?

Thanks,
Richard.

2009-09-10  Richard Guenther  <rguenther@suse.de>
	Rafael Avila de Espindola  <espindola@google.com>

	* langhooks-def.h (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.
	(LANG_HOOKS_EH_PERSONALITY): Likewise.
	(LANG_HOOKS_INITIALIZER): Adjust.
	(lhd_pass_through_t): Declare.
	* langhooks.h (struct lang_hooks): Add init_eh, eh_runtime_type and
	eh_personality.
	* langhooks.c (lhd_pass_through_t): New function.

        * dwarf2out.c (output_call_frame_info, dwarf2out_do_cfi_startproc,
	dwarf2out_begin_prologue): Use personality from current_function_decl.
        * expr.h (get_personality_function): Declare.
	* expr.c (get_personality_function): New function.
	(build_personality_function): Likewise.
        * libfuncs.h (libfunc_index): Remove LTI_eh_personality.
        (eh_personality_libfunc): Remove.
        * optabs.c (build_libfunc_function): New function split out from ...
	(init_one_libfunc): ... here.
        * tree.h (DECL_FUNCTION_PERSONALITY): New.
        (tree_function_decl): Add personality.
	(lhd_gcc_personality): Declare.
	(build_personality_function): Likewise.
	* tree.c (gcc_eh_personality_decl): New.
	(lhd_gcc_personality): New function.
	* except.h (lang_eh_runtime_type): Remove.
	(enum eh_personality_kind): New.
	(build_personality_function): Declare.
	(function_needs_eh_personality): Declare.
        * except.c (lang_eh_runtime_type): Remove.
	(function_needs_eh_personality): New function.
	(add_type_for_runtime): Call lang_hooks.type_for_runtime instead.
        (sjlj_emit_function_enter, output_function_exception_table):
        Use personality from current_function_decl.
	* tree-eh.c (lower_eh_constructs): Set DECL_FUNCTION_PERSONALITY.
	* tree-inline.c (tree_can_inline_p): Do not inline across different
	EH personalities.
	(expand_call_inline): Likewise.  Adjust the callers EH personality.
	(tree_function_versioning): Copy DECL_FUNCTION_PERSONALITY.
	* cgraph.c (cgraph_add_new_function): Set DECL_FUNCTION_PERSONALITY.
	* Makefile.in (cgraph.o): Add $(EXCEPT_H) dependency.

	* c-lang.c (LANG_HOOKS_INIT_EH): Define.
	* c-tree.h (c_eh_initialized_p): Remove.
	* c-decl.c (finish_decl): Don't call c_maybe_initialize_eh.
	(finish_decl): Don't call c_maybe_initialize_eh.
	(c_eh_initialized_p): Make local to ...
	(c_maybe_initialize_eh): ... this function.
	Init eh_personality_decl instead of eh_personality_libfunc.
        * c-parser.c (c_parser_omp_construct): Likewise.
	(c_parse_file): Call lang_hooks.init_eh.

	objc/
	* objc-act.c (objc_eh_runtime_type): Export.
	(objc_init_exceptions): Export.
	Do not set objc_init_exceptions.  Move warning code ...
	(objc_begin_try_stmt): ... here
	(objc_build_throw_stmt): ... and here.
	(objc_eh_personality_decl): New.
	(objc_eh_personality): New function.
	* objc-act.h (objc_init_exceptions): Declare.
	(objc_eh_runtime_type): Likewise.
	(objc_eh_personality): Likewise.
	* objc-lang.c (LANG_HOOKS_INIT_EH): Define.
	(LANG_HOOKS_EH_RUNTIME_TYPE): Likewise.
	(LANG_HOOKS_EH_PERSONALITY): Likewise.

	cp/
	* except.c (init_exception_processing): Do not set
	lang_eh_runtime_type.
	(choose_personality_routine): Do not set eh_personality_decl,
	set pragma_java_exceptions.
	* cp-lang.c (LANG_HOOKS_EH_RUNTIME_TYPE): Define.
	(LANG_HOOKS_EH_PERSONALITY): Likewise.
	(cp_eh_personality_decl): New.
	(cp_eh_personality): Likewise.
	* Make-lang.in (cp-lang.o): Add $(EXPR_H) and $(EXCEPT_H)
	dependencies.

	java/
	* decl.c (do_nothing): Remove.
	(java_init_decl_processing): Do not set lang_eh_runtime_type.
	* Make-lang.in (lang.o): Add $(EXCEPT_H) dependency.
	* lang.c (java_eh_personality): New.
	(java_eh_personality_decl): Likewise.
	(LANG_HOOKS_EH_PERSONALITY): Define.

	ada/
	* gcc-interface/misc.c (gnat_init_gcc_eh): Do not set
	lang_eh_runtime_type.
	(LANG_HOOKS_EH_PERSONALITY): Define.
	(gnat_eh_personality_decl): New.
	(gnat_eh_personality): Likewise.
	* Make-lang.in (misc.o): Add gt-ada-misc.h dependency.
	* config-lang.in (gtfiles): Add misc.c.

	fortran/
	* f95-lang.c (gfc_maybe_initialize_eh): Do not init
	eh_personality_libfunc.

Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/objc/objc-act.c	2009-09-11 13:58:30.000000000 +0200
*************** struct objc_try_context
*** 3483,3503 ****
  
  static struct objc_try_context *cur_try_context;
  
  /* This hook, called via lang_eh_runtime_type, generates a runtime object
     that represents TYPE.  For Objective-C, this is just the class name.  */
  /* ??? Isn't there a class object or some such?  Is it easy to get?  */
  
  #ifndef OBJCPLUS
! static tree
  objc_eh_runtime_type (tree type)
  {
    return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
  }
  #endif
  
  /* Initialize exception handling.  */
  
! static void
  objc_init_exceptions (void)
  {
    static bool done = false;
--- 3483,3518 ----
  
  static struct objc_try_context *cur_try_context;
  
+ static GTY(()) tree objc_eh_personality_decl;
+ 
  /* This hook, called via lang_eh_runtime_type, generates a runtime object
     that represents TYPE.  For Objective-C, this is just the class name.  */
  /* ??? Isn't there a class object or some such?  Is it easy to get?  */
  
  #ifndef OBJCPLUS
! tree
  objc_eh_runtime_type (tree type)
  {
    return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
  }
+ 
+ tree
+ objc_eh_personality (void)
+ {
+   if (!flag_objc_sjlj_exceptions
+       && !objc_eh_personality_decl)
+     objc_eh_personality_decl
+       = build_personality_function (USING_SJLJ_EXCEPTIONS
+ 				    ? "__gnu_objc_personality_sj0"
+ 				    : "__gnu_objc_personality_v0");
+ 
+   return objc_eh_personality_decl;
+ }
  #endif
  
  /* Initialize exception handling.  */
  
! void
  objc_init_exceptions (void)
  {
    static bool done = false;
*************** objc_init_exceptions (void)
*** 3505,3529 ****
      return;
    done = true;
  
-   if (flag_objc_sjlj_exceptions)
-     {
-       /* On Darwin, ObjC exceptions require a sufficiently recent
- 	 version of the runtime, so the user must ask for them explicitly.  */
-       if (!flag_objc_exceptions)
- 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
- 		 "exception syntax");
-     }
  #ifndef OBJCPLUS
!   else
      {
-       c_eh_initialized_p = true;
-       eh_personality_libfunc
- 	= init_one_libfunc (USING_SJLJ_EXCEPTIONS
- 			    ? "__gnu_objc_personality_sj0"
- 			    : "__gnu_objc_personality_v0");
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
-       lang_eh_runtime_type = objc_eh_runtime_type;
      }
  #endif
  }
--- 3520,3530 ----
      return;
    done = true;
  
  #ifndef OBJCPLUS
!   if (!flag_objc_sjlj_exceptions)
      {
        default_init_unwind_resume_libfunc ();
        using_eh_for_cleanups ();
      }
  #endif
  }
*************** objc_begin_try_stmt (location_t try_locu
*** 3824,3830 ****
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   objc_init_exceptions ();
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
--- 3825,3838 ----
    c->end_try_locus = input_location;
    cur_try_context = c;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (flag_objc_sjlj_exceptions)
      objc_mark_locals_volatile (NULL);
*************** objc_build_throw_stmt (location_t loc, t
*** 3973,3979 ****
  {
    tree args;
  
!   objc_init_exceptions ();
  
    if (throw_expr == NULL)
      {
--- 3981,3994 ----
  {
    tree args;
  
!   if (flag_objc_sjlj_exceptions)
!     {
!       /* On Darwin, ObjC exceptions require a sufficiently recent
! 	 version of the runtime, so the user must ask for them explicitly.  */
!       if (!flag_objc_exceptions)
! 	warning (0, "use %<-fobjc-exceptions%> to enable Objective-C "
! 		 "exception syntax");
!     }
  
    if (throw_expr == NULL)
      {
Index: gcc/c-decl.c
===================================================================
*** gcc/c-decl.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/c-decl.c	2009-09-11 13:58:30.000000000 +0200
*************** tree pending_invalid_xref;
*** 92,100 ****
  /* File and line to appear in the eventual error message.  */
  location_t pending_invalid_xref_location;
  
- /* True means we've initialized exception handling.  */
- bool c_eh_initialized_p;
- 
  /* The file and line that the prototype came from if this is an
     old-style definition; used for diagnostics in
     store_parm_decls_oldstyle.  */
--- 92,97 ----
*************** merge_decls (tree newdecl, tree olddecl,
*** 2365,2371 ****
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID and DECL_CONTEXT.  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
--- 2362,2369 ----
      TREE_USED (olddecl) = 1;
  
    /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
!      But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
!      DECL_ARGUMENTS (if appropriate).  */
    {
      unsigned olddecl_uid = DECL_UID (olddecl);
      tree olddecl_context = DECL_CONTEXT (olddecl);
*************** start_decl (struct c_declarator *declara
*** 4048,4061 ****
  void
  c_maybe_initialize_eh (void)
  {
    if (!flag_exceptions || c_eh_initialized_p)
      return;
  
    c_eh_initialized_p = true;
-   eh_personality_libfunc
-     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- 			? "__gcc_personality_sj0"
- 			: "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 4046,4057 ----
  void
  c_maybe_initialize_eh (void)
  {
+   static bool c_eh_initialized_p = false;
+ 
    if (!flag_exceptions || c_eh_initialized_p)
      return;
  
    c_eh_initialized_p = true;
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
*************** finish_decl (tree decl, location_t init_
*** 4360,4368 ****
  	  TREE_USED (decl) = 1;
  	  TREE_USED (cleanup_decl) = 1;
  
- 	  /* Initialize EH, if we've been told to do so.  */
- 	  c_maybe_initialize_eh ();
- 
  	  push_cleanup (decl, cleanup, false);
  	}
      }
--- 4356,4361 ----
Index: gcc/c-parser.c
===================================================================
*** gcc/c-parser.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/c-parser.c	2009-09-11 13:58:30.000000000 +0200
*************** c_parser_omp_construct (c_parser *parser
*** 8489,8500 ****
    p_kind = c_parser_peek_token (parser)->pragma_kind;
    c_parser_consume_pragma (parser);
  
-   /* For all constructs below except #pragma omp atomic
-      MUST_NOT_THROW catch handlers are needed when exceptions
-      are enabled.  */
-   if (p_kind != PRAGMA_OMP_ATOMIC)
-     c_maybe_initialize_eh ();
- 
    switch (p_kind)
      {
      case PRAGMA_OMP_ATOMIC:
--- 8489,8494 ----
*************** c_parse_file (void)
*** 8607,8612 ****
--- 8601,8609 ----
    the_parser = GGC_NEW (c_parser);
    *the_parser = tparser;
  
+   /* Initialize EH, if we've been told to do so.  */
+   lang_hooks.init_eh ();
+ 
    c_parser_translation_unit (the_parser);
    the_parser = NULL;
  }
Index: gcc/c-lang.c
===================================================================
*** gcc/c-lang.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/c-lang.c	2009-09-11 13:58:30.000000000 +0200
*************** enum c_language_kind c_language = clk_c;
*** 44,49 ****
--- 44,51 ----
  #define LANG_HOOKS_NAME "GNU C"
  #undef LANG_HOOKS_INIT
  #define LANG_HOOKS_INIT c_objc_common_init
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH c_maybe_initialize_eh
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/langhooks-def.h
===================================================================
*** gcc/langhooks-def.h.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/langhooks-def.h	2009-09-11 13:58:30.000000000 +0200
*************** extern void lhd_do_nothing (void);
*** 40,45 ****
--- 40,46 ----
  extern void lhd_do_nothing_t (tree);
  extern void lhd_do_nothing_i (int);
  extern void lhd_do_nothing_f (struct function *);
+ extern tree lhd_pass_through_t (tree);
  extern bool lhd_post_options (const char **);
  extern alias_set_type lhd_get_alias_set (tree);
  extern tree lhd_return_null_tree_v (void);
*************** extern void lhd_omp_firstprivatize_type_
*** 107,112 ****
--- 108,116 ----
  #define LANG_HOOKS_EXPR_TO_DECL		lhd_expr_to_decl
  #define LANG_HOOKS_TO_TARGET_CHARSET	lhd_to_target_charset
  #define LANG_HOOKS_INIT_TS		lhd_do_nothing
+ #define LANG_HOOKS_INIT_EH		NULL
+ #define LANG_HOOKS_EH_PERSONALITY	lhd_gcc_personality
+ #define LANG_HOOKS_EH_RUNTIME_TYPE	lhd_pass_through_t
  
  /* Attribute hooks.  */
  #define LANG_HOOKS_ATTRIBUTE_TABLE		NULL
*************** extern tree lhd_make_node (enum tree_cod
*** 271,276 ****
--- 275,283 ----
    LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
    LANG_HOOKS_INIT_TS,          \
    LANG_HOOKS_EXPR_TO_DECL, \
+   LANG_HOOKS_INIT_EH, \
+   LANG_HOOKS_EH_PERSONALITY, \
+   LANG_HOOKS_EH_RUNTIME_TYPE, \
  }
  
  #endif /* GCC_LANG_HOOKS_DEF_H */
Index: gcc/langhooks.h
===================================================================
*** gcc/langhooks.h.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/langhooks.h	2009-09-11 13:58:30.000000000 +0200
*************** struct lang_hooks
*** 414,419 ****
--- 414,428 ----
       if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating.  */
    tree (*expr_to_decl) (tree expr, bool *tc, bool *se);
  
+   /* Called to initialize the exception handing personality.  */
+   void (*init_eh) (void);
+ 
+   /* The EH personality function decl.  */
+   tree (*eh_personality) (void);
+ 
+   /* Map a type to a runtime object to match type.  */
+   tree (*eh_runtime_type) (tree);
+ 
    /* Whenever you add entries here, make sure you adjust langhooks-def.h
       and langhooks.c accordingly.  */
  };
Index: gcc/objc/objc-act.h
===================================================================
*** gcc/objc/objc-act.h.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/objc/objc-act.h	2009-09-11 13:58:30.000000000 +0200
*************** const char *objc_printable_name (tree, i
*** 32,37 ****
--- 32,40 ----
  void objc_finish_file (void);
  tree objc_fold_obj_type_ref (tree, tree);
  int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+ void objc_init_exceptions (void);
+ tree objc_eh_runtime_type (tree);
+ tree objc_eh_personality (void);
  
  /* NB: The remaining public functions are prototyped in c-common.h, for the
     benefit of stub-objc.c and objc-act.c.  */
Index: gcc/objc/objc-lang.c
===================================================================
*** gcc/objc/objc-lang.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/objc/objc-lang.c	2009-09-11 13:58:30.000000000 +0200
*************** static void objc_init_ts (void);
*** 50,55 ****
--- 50,64 ----
  #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS objc_init_ts
+ #undef LANG_HOOKS_INIT_EH
+ #define LANG_HOOKS_INIT_EH objc_init_exceptions
+ 
+ #ifndef OBJCPLUS
+ #undef LANG_HOOKS_EH_PERSONALITY
+ #define LANG_HOOKS_EH_PERSONALITY objc_eh_personality
+ #undef LANG_HOOKS_EH_RUNTIME_TYPE
+ #define LANG_HOOKS_EH_RUNTIME_TYPE objc_eh_runtime_type
+ #endif
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: gcc/ada/gcc-interface/misc.c
===================================================================
*** gcc/ada/gcc-interface/misc.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/ada/gcc-interface/misc.c	2009-09-11 13:58:30.000000000 +0200
*************** static void gnat_parse_file		(int);
*** 79,84 ****
--- 79,85 ----
  static void internal_error_function	(const char *, va_list *);
  static tree gnat_type_max_size		(const_tree);
  static void gnat_get_subrange_bounds	(const_tree, tree *, tree *);
+ static tree gnat_eh_personality		(void);
  
  /* Definitions for our language-specific hooks.  */
  
*************** static void gnat_get_subrange_bounds	(co
*** 129,135 ****
  #undef  LANG_HOOKS_ATTRIBUTE_TABLE
  #define LANG_HOOKS_ATTRIBUTE_TABLE	gnat_internal_attribute_table
  #undef  LANG_HOOKS_BUILTIN_FUNCTION
! #define LANG_HOOKS_BUILTIN_FUNCTION        gnat_builtin_function
  
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
  
--- 130,138 ----
  #undef  LANG_HOOKS_ATTRIBUTE_TABLE
  #define LANG_HOOKS_ATTRIBUTE_TABLE	gnat_internal_attribute_table
  #undef  LANG_HOOKS_BUILTIN_FUNCTION
! #define LANG_HOOKS_BUILTIN_FUNCTION	gnat_builtin_function
! #undef  LANG_HOOKS_EH_PERSONALITY
! #define LANG_HOOKS_EH_PERSONALITY	gnat_eh_personality
  
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
  
*************** gnat_init_gcc_eh (void)
*** 431,441 ****
       right exception regions.  */
    using_eh_for_cleanups ();
  
-   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- 					     ? "__gnat_eh_personality_sj"
- 					     : "__gnat_eh_personality");
    lang_eh_type_covers = gnat_eh_type_covers;
-   lang_eh_runtime_type = gnat_return_tree;
    default_init_unwind_resume_libfunc ();
  
    /* Turn on -fexceptions and -fnon-call-exceptions. The first one triggers
--- 434,440 ----
*************** fp_size_to_prec (int size)
*** 811,813 ****
--- 810,828 ----
  
    gcc_unreachable ();
  }
+ 
+ static GTY(()) tree gnat_eh_personality_decl;
+ 
+ static tree
+ gnat_eh_personality (void)
+ {
+   if (!gnat_eh_personality_decl)
+     gnat_eh_personality_decl
+       = build_personality_function (USING_SJLJ_EXCEPTIONS
+ 				    ? "__gnat_eh_personality_sj"
+ 				    : "__gnat_eh_personality");
+ 
+   return gnat_eh_personality_decl;
+ }
+ 
+ #include "gt-ada-misc.h"
Index: gcc/cp/cp-lang.c
===================================================================
*** gcc/cp/cp-lang.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/cp/cp-lang.c	2009-09-11 13:58:30.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 32,42 ****
--- 32,45 ----
  #include "debug.h"
  #include "cp-objcp-common.h"
  #include "hashtab.h"
+ #include "except.h"
+ #include "expr.h"
  
  enum c_language_kind c_language = clk_cxx;
  static void cp_init_ts (void);
  static const char * cxx_dwarf_name (tree t, int verbosity);
  static enum classify_record cp_classify_record (tree type);
+ static tree cp_eh_personality (void);
  
  /* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
     consequently, there should be very few hooks below.  */
*************** static enum classify_record cp_classify_
*** 71,76 ****
--- 74,83 ----
  #define LANG_HOOKS_FOLD_OBJ_TYPE_REF cp_fold_obj_type_ref
  #undef LANG_HOOKS_INIT_TS
  #define LANG_HOOKS_INIT_TS cp_init_ts
+ #undef LANG_HOOKS_EH_PERSONALITY
+ #define LANG_HOOKS_EH_PERSONALITY cp_eh_personality
+ #undef LANG_HOOKS_EH_RUNTIME_TYPE
+ #define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type
  
  /* Each front end provides its own lang hook initializer.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
*************** finish_file (void)
*** 145,148 ****
--- 152,177 ----
  {
  }
  
+ static GTY(()) tree cp_eh_personality_decl;
+ 
+ static tree
+ cp_eh_personality (void)
+ {
+   if (!cp_eh_personality_decl)
+     {
+       if (!pragma_java_exceptions)
+ 	cp_eh_personality_decl
+ 	  = build_personality_function (USING_SJLJ_EXCEPTIONS
+ 					? "__gxx_personality_sj0"
+ 					: "__gxx_personality_v0");
+       else
+ 	cp_eh_personality_decl
+ 	  = build_personality_function (USING_SJLJ_EXCEPTIONS
+ 					? "__gcj_personality_sj0"
+ 					: "__gcj_personality_v0");
+     }
+ 
+   return cp_eh_personality_decl;
+ }
+ 
  #include "gtype-cp.h"
Index: gcc/cp/except.c
===================================================================
*** gcc/cp/except.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/cp/except.c	2009-09-11 13:58:30.000000000 +0200
*************** along with GCC; see the file COPYING3.
*** 43,49 ****
  
  static void push_eh_cleanup (tree);
  static tree prepare_eh_type (tree);
- static tree build_eh_type_type (tree);
  static tree do_begin_catch (void);
  static int dtor_nothrow (tree);
  static tree do_end_catch (tree);
--- 43,48 ----
*************** init_exception_processing (void)
*** 78,92 ****
    call_unexpected_node
      = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
  
-   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- 					     ? "__gxx_personality_sj0"
- 					     : "__gxx_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
-   lang_eh_runtime_type = build_eh_type_type;
    lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
  }
  
--- 77,87 ----
*************** eh_type_info (tree type)
*** 143,149 ****
  /* Build the address of a typeinfo decl for use in the runtime
     matching field of the exception model.  */
  
! static tree
  build_eh_type_type (tree type)
  {
    tree exp = eh_type_info (type);
--- 138,144 ----
  /* Build the address of a typeinfo decl for use in the runtime
     matching field of the exception model.  */
  
! tree
  build_eh_type_type (tree type)
  {
    tree exp = eh_type_info (type);
*************** decl_is_java_type (tree decl, int err)
*** 313,319 ****
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_libfunc is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
--- 308,314 ----
  /* Select the personality routine to be used for exception handling,
     or issue an error if we need two different ones in the same
     translation unit.
!    ??? At present eh_personality_decl is set to
     __gxx_personality_(sj|v)0 in init_exception_processing - should it
     be done here instead?  */
  void
*************** choose_personality_routine (enum languag
*** 354,362 ****
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
! 						 ? "__gcj_personality_sj0"
! 						 : "__gcj_personality_v0");
        break;
  
      default:
--- 349,355 ----
      case lang_java:
        state = chose_java;
        terminate_node = built_in_decls [BUILT_IN_ABORT];
!       pragma_java_exceptions = true;
        break;
  
      default:
Index: gcc/except.c
===================================================================
*** gcc/except.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/except.c	2009-09-11 13:58:30.000000000 +0200
*************** gimple (*lang_protect_cleanup_actions) (
*** 92,100 ****
  /* Return true if type A catches type B.  */
  int (*lang_eh_type_covers) (tree a, tree b);
  
- /* Map a type to a runtime object to match type.  */
- tree (*lang_eh_runtime_type) (tree);
- 
  /* A hash table of label to region number.  */
  
  struct GTY(()) ehl_map_entry {
--- 92,97 ----
*************** add_type_for_runtime (tree type)
*** 1696,1702 ****
  					    TREE_HASH (type), INSERT);
    if (*slot == NULL)
      {
!       tree runtime = (*lang_eh_runtime_type) (type);
        *slot = tree_cons (type, runtime, NULL_TREE);
      }
  }
--- 1693,1699 ----
  					    TREE_HASH (type), INSERT);
    if (*slot == NULL)
      {
!       tree runtime = lang_hooks.eh_runtime_type (type);
        *slot = tree_cons (type, runtime, NULL_TREE);
      }
  }
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2424,2429 ****
--- 2421,2427 ----
  {
    rtx fn_begin, fc, mem, seq;
    bool fn_begin_outside_block;
+   rtx personality = get_personality_function (current_function_decl);
  
    fc = crtl->eh.sjlj_fc;
  
*************** sjlj_emit_function_enter (rtx dispatch_l
*** 2432,2440 ****
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (eh_personality_libfunc);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, eh_personality_libfunc);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
--- 2430,2438 ----
    /* We're storing this libcall's address into memory instead of
       calling it directly.  Thus, we must call assemble_external_libcall
       here, as we can not depend on emit_library_call to do it for us.  */
!   assemble_external_libcall (personality);
    mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
!   emit_move_insn (mem, personality);
  
    mem = adjust_address (fc, Pmode, sjlj_fc_lsda_ofs);
    if (crtl->uses_eh_lsda)
*************** output_ttype (tree type, int tt_format,
*** 4394,4400 ****
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section)
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
--- 4392,4398 ----
  
  static void
  output_one_function_exception_table (const char * ARG_UNUSED (fnname),
! 				     int section, rtx ARG_UNUSED (personality))
  {
    int tt_format, cs_format, lp_format, i, n;
  #ifdef HAVE_AS_LEB128
*************** output_one_function_exception_table (con
*** 4410,4416 ****
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, eh_personality_libfunc);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
--- 4408,4414 ----
  #ifdef TARGET_UNWIND_INFO
    /* TODO: Move this into target file.  */
    fputs ("\t.personality\t", asm_out_file);
!   output_addr_const (asm_out_file, personality);
    fputs ("\n\t.handlerdata\n", asm_out_file);
    /* Note that varasm still thinks we're in the function's code section.
       The ".endp" directive that will immediately follow will take us back.  */
*************** output_one_function_exception_table (con
*** 4580,4595 ****
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (eh_personality_libfunc)
!     assemble_external_libcall (eh_personality_libfunc);
  
!   output_one_function_exception_table (fnname, 0);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1);
  
    switch_to_section (current_function_section ());
  }
--- 4578,4595 ----
  void
  output_function_exception_table (const char * ARG_UNUSED (fnname))
  {
+   rtx personality = get_personality_function (current_function_decl);
+ 
    /* Not all functions need anything.  */
    if (! crtl->uses_eh_lsda)
      return;
  
!   if (personality)
!     assemble_external_libcall (personality);
  
!   output_one_function_exception_table (fnname, 0, personality);
    if (crtl->eh.call_site_record[1] != NULL)
!     output_one_function_exception_table (fnname, 1, personality);
  
    switch_to_section (current_function_section ());
  }
*************** get_eh_throw_stmt_table (struct function
*** 4606,4611 ****
--- 4606,4675 ----
    return fun->eh->throw_stmt_table;
  }
  
+ /* Return true if the function deeds a EH personality function.  */
+ 
+ enum eh_personality_kind
+ function_needs_eh_personality (struct function *fn)
+ {
+   struct eh_region_d *i;
+   int depth = 0;
+   enum eh_personality_kind kind = eh_personality_none;
+ 
+   i = fn->eh->region_tree;
+   if (!i)
+     return eh_personality_none;
+ 
+   while (1)
+     {
+       switch (i->type)
+ 	{
+ 	case ERT_TRY:
+ 	case ERT_THROW:
+ 	  /* Do not need a EH personality function.  */
+ 	  break;
+ 
+ 	case ERT_MUST_NOT_THROW:
+ 	  /* Always needs a EH personality function.  */
+ 	  return eh_personality_lang;
+ 
+ 	case ERT_CLEANUP:
+ 	  /* Can do with any personality including the generic C one.  */
+ 	  kind = eh_personality_any;
+ 	  break;
+ 
+ 	case ERT_CATCH:
+ 	case ERT_ALLOWED_EXCEPTIONS:
+ 	  /* Always needs a EH personality function.  The generic C
+ 	     personality doesn't handle these even for empty type lists.  */
+ 	  return eh_personality_lang;
+ 
+ 	case ERT_UNKNOWN:
+ 	  return eh_personality_lang;
+ 	}
+       /* If there are sub-regions, process them.  */
+       if (i->inner)
+ 	i = i->inner, depth++;
+       /* If there are peers, process them.  */
+       else if (i->next_peer)
+ 	i = i->next_peer;
+       /* Otherwise, step back up the tree to the next peer.  */
+       else
+ 	{
+ 	  do
+ 	    {
+ 	      i = i->outer;
+ 	      depth--;
+ 	      if (i == NULL)
+ 		return kind;
+ 	    }
+ 	  while (i->next_peer == NULL);
+ 	  i = i->next_peer;
+ 	}
+     }
+ 
+   return kind;
+ }
+ 
  /* Dump EH information to OUT.  */
  
  void
Index: gcc/except.h
===================================================================
*** gcc/except.h.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/except.h	2009-09-11 13:58:30.000000000 +0200
*************** extern gimple (*lang_protect_cleanup_act
*** 217,225 ****
  /* Return true if type A catches type B.  */
  extern int (*lang_eh_type_covers) (tree a, tree b);
  
- /* Map a type to a runtime object to match type.  */
- extern tree (*lang_eh_runtime_type) (tree);
- 
  
  /* Just because the user configured --with-sjlj-exceptions=no doesn't
     mean that we can use call frame exceptions.  Detect that the target
--- 217,222 ----
*************** extern int num_eh_regions (void);
*** 277,279 ****
--- 274,285 ----
  extern bitmap must_not_throw_labels (void);
  extern struct eh_region_d *redirect_eh_edge_to_label (struct edge_def *, tree, bool, bool, int);
  extern int get_next_region_sharing_label (int);
+ 
+ enum eh_personality_kind {
+   eh_personality_none,
+   eh_personality_any,
+   eh_personality_lang
+ };
+ 
+ extern enum eh_personality_kind
+ function_needs_eh_personality (struct function *);
Index: gcc/java/decl.c
===================================================================
*** gcc/java/decl.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/java/decl.c	2009-09-11 13:58:30.000000000 +0200
*************** create_primitive_vtable (const char *nam
*** 510,521 ****
    return r;
  }
  
- static tree
- do_nothing (tree t)
- {
-   return t;
- }
- 
  /* Parse the version string and compute the ABI version number.  */
  static void
  parse_version (void)
--- 510,515 ----
*************** java_init_decl_processing (void)
*** 1195,1210 ****
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
!   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
!                                              ? "__gcj_personality_sj0"
!                                              : "__gcj_personality_v0");
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
-   lang_eh_runtime_type = do_nothing;
- 
    initialize_builtins ();
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  
--- 1189,1200 ----
  			    0, NOT_BUILT_IN, NULL, NULL_TREE);
  
    /* Initialize variables for except.c.  */
! 
    if (targetm.arm_eabi_unwinder)
      unwind_resume_libfunc = init_one_libfunc ("__cxa_end_cleanup");
    else
      default_init_unwind_resume_libfunc ();
  
    initialize_builtins ();
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  
Index: gcc/langhooks.c
===================================================================
*** gcc/langhooks.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/langhooks.c	2009-09-11 13:58:30.000000000 +0200
*************** lhd_do_nothing_t (tree ARG_UNUSED (t))
*** 53,58 ****
--- 53,65 ----
  {
  }
  
+ /* Pass through (tree).  */
+ tree
+ lhd_pass_through_t (tree t)
+ {
+   return t;
+ }
+ 
  /* Do nothing (int).  */
  
  void
Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/cp/cp-tree.h	2009-09-11 13:58:30.000000000 +0200
*************** extern void choose_personality_routine
*** 4521,4526 ****
--- 4521,4527 ----
  extern tree eh_type_info			(tree);
  extern tree begin_eh_spec_block			(void);
  extern void finish_eh_spec_block		(tree, tree);
+ extern tree build_eh_type_type			(tree);
  
  /* in expr.c */
  extern tree cplus_expand_constant		(tree);
Index: gcc/libfuncs.h
===================================================================
*** gcc/libfuncs.h.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/libfuncs.h	2009-09-11 13:58:30.000000000 +0200
*************** enum libfunc_index
*** 31,37 ****
    LTI_setbits,
  
    LTI_unwind_resume,
-   LTI_eh_personality,
    LTI_setjmp,
    LTI_longjmp,
    LTI_unwind_sjlj_register,
--- 31,36 ----
*************** extern GTY(()) rtx libfunc_table[LTI_MAX
*** 61,67 ****
  #define setbits_libfunc	(libfunc_table[LTI_setbits])
  
  #define unwind_resume_libfunc	(libfunc_table[LTI_unwind_resume])
- #define eh_personality_libfunc	(libfunc_table[LTI_eh_personality])
  #define setjmp_libfunc	(libfunc_table[LTI_setjmp])
  #define longjmp_libfunc	(libfunc_table[LTI_longjmp])
  #define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
--- 60,65 ----
Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/optabs.c	2009-09-11 13:58:30.000000000 +0200
*************** libfunc_decl_eq (const void *entry1, con
*** 6023,6028 ****
--- 6023,6050 ----
    return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
  }
  
+ /* Build a decl for a libfunc named NAME. */
+ 
+ tree
+ build_libfunc_function (const char *name)
+ {
+   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+ 			  get_identifier (name),
+                           build_function_type (integer_type_node, NULL_TREE));
+   /* ??? We don't have any type information except for this is
+      a function.  Pretend this is "int foo()".  */
+   DECL_ARTIFICIAL (decl) = 1;
+   DECL_EXTERNAL (decl) = 1;
+   TREE_PUBLIC (decl) = 1;
+   gcc_assert (DECL_ASSEMBLER_NAME (decl));
+ 
+   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
+      are the flags assigned by targetm.encode_section_info.  */
+   SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
+ 
+   return decl;
+ }
+ 
  rtx
  init_one_libfunc (const char *name)
  {
*************** init_one_libfunc (const char *name)
*** 6043,6061 ****
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       /* ??? We don't have any type information except for this is
! 	 a function.  Pretend this is "int foo()".  */
!       decl = build_decl (UNKNOWN_LOCATION,
! 			 FUNCTION_DECL, get_identifier (name),
! 			 build_function_type (integer_type_node, NULL_TREE));
!       DECL_ARTIFICIAL (decl) = 1;
!       DECL_EXTERNAL (decl) = 1;
!       TREE_PUBLIC (decl) = 1;
! 
!       /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
! 	 are the flags assigned by targetm.encode_section_info.  */
!       SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
! 
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
--- 6065,6071 ----
      {
        /* Create a new decl, so that it can be passed to
  	 targetm.encode_section_info.  */
!       decl = build_libfunc_function (name);
        *slot = decl;
      }
    return XEXP (DECL_RTL (decl), 0);
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2009-09-11 13:57:36.000000000 +0200
--- gcc/tree.h	2009-09-11 13:58:30.000000000 +0200
*************** struct GTY(()) tree_decl_minimal {
*** 2538,2543 ****
--- 2538,2546 ----
  #define DECL_DEBUG_EXPR_IS_FROM(NODE) \
    (DECL_COMMON_CHECK (NODE)->decl_common.debug_expr_is_from)
  
+ #define DECL_FUNCTION_PERSONALITY(NODE) \
+   (FUNCTION_DECL_CHECK (NODE)->function_decl.personality)
+ 
  /* Nonzero for a given ..._DECL node means that the name of this node should
     be ignored for symbolic debug purposes.  */
  #define DECL_IGNORED_P(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.ignored_flag)
*************** struct GTY(()) tree_function_decl {
*** 3190,3195 ****
--- 3193,3201 ----
  
    struct function *f;
  
+   /* The personality function. Used for stack unwinding. */
+   tree personality;
+ 
    /* Function specific options that are used by this function.  */
    tree function_specific_target;	/* target options */
    tree function_specific_optimization;	/* optimization options */
*************** extern bool auto_var_in_fn_p (const_tree
*** 4652,4657 ****
--- 4658,4664 ----
  extern tree build_low_bits_mask (tree, unsigned);
  extern tree tree_strip_nop_conversions (tree);
  extern tree tree_strip_sign_nop_conversions (tree);
+ extern tree lhd_gcc_personality (void);
  \f
  /* In cgraph.c */
  extern void change_decl_assembler_name (tree, tree);
*************** extern unsigned HOST_WIDE_INT compute_bu
*** 5263,5268 ****
--- 5270,5276 ----
  
  /* In expr.c.  */
  extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree);
+ extern tree build_personality_function (const char *);
  
  /* In tree-inline.c.  */
  
Index: gcc/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/dwarf2out.c	2009-09-11 13:58:30.000000000 +0200
*************** static GTY(()) section *debug_str_sectio
*** 216,221 ****
--- 216,225 ----
  static GTY(()) section *debug_ranges_section;
  static GTY(()) section *debug_frame_section;
  
+ /* Personality decl of current unit.  Used only when assembler does not support
+    personality CFI.  */
+ static GTY(()) rtx current_unit_personality;
+ 
  /* How to start an assembler comment.  */
  #ifndef ASM_COMMENT_START
  #define ASM_COMMENT_START ";#"
*************** output_call_frame_info (int for_eh)
*** 3599,3604 ****
--- 3603,3609 ----
    int per_encoding = DW_EH_PE_absptr;
    int lsda_encoding = DW_EH_PE_absptr;
    int return_reg;
+   rtx personality = NULL;
    int dw_cie_version;
  
    /* Don't emit a CIE if there won't be any FDEs.  */
*************** output_call_frame_info (int for_eh)
*** 3684,3689 ****
--- 3689,3696 ----
  
    augmentation[0] = 0;
    augmentation_size = 0;
+ 
+   personality = current_unit_personality;
    if (for_eh)
      {
        char *p;
*************** output_call_frame_info (int for_eh)
*** 3703,3713 ****
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (eh_personality_libfunc)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (eh_personality_libfunc);
  	}
        if (any_lsda_needed)
  	{
--- 3710,3720 ----
        lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
  
        p = augmentation + 1;
!       if (personality)
  	{
  	  *p++ = 'P';
  	  augmentation_size += 1 + size_of_encoded_value (per_encoding);
! 	  assemble_external_libcall (personality);
  	}
        if (any_lsda_needed)
  	{
*************** output_call_frame_info (int for_eh)
*** 3726,3732 ****
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
--- 3733,3739 ----
  	}
  
        /* Ug.  Some platforms can't do unaligned dynamic relocations at all.  */
!       if (personality && per_encoding == DW_EH_PE_aligned)
  	{
  	  int offset = (  4		/* Length */
  			+ 4		/* CIE Id */
*************** output_call_frame_info (int for_eh)
*** 3760,3771 ****
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (eh_personality_libfunc)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   eh_personality_libfunc,
  					   true, NULL);
  	}
  
--- 3767,3778 ----
    if (augmentation[0])
      {
        dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
!       if (personality)
  	{
  	  dw2_asm_output_data (1, per_encoding, "Personality (%s)",
  			       eh_data_format_name (per_encoding));
  	  dw2_asm_output_encoded_addr_rtx (per_encoding,
! 					   personality,
  					   true, NULL);
  	}
  
*************** dwarf2out_do_cfi_startproc (bool second)
*** 3824,3836 ****
  {
    int enc;
    rtx ref;
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (eh_personality_libfunc)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = eh_personality_libfunc;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
--- 3831,3844 ----
  {
    int enc;
    rtx ref;
+   rtx personality = get_personality_function (current_function_decl);
  
    fprintf (asm_out_file, "\t.cfi_startproc\n");
  
!   if (personality)
      {
        enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
!       ref = personality;
  
        /* ??? The GAS support isn't entirely consistent.  We have to
  	 handle indirect support ourselves, but PC-relative is done
*************** dwarf2out_begin_prologue (unsigned int l
*** 3873,3878 ****
--- 3881,3887 ----
    char label[MAX_ARTIFICIAL_LABEL_BYTES];
    char * dup_label;
    dw_fde_ref fde;
+   rtx personality;
    section *fnsec;
  
    current_function_func_begin_label = NULL;
*************** dwarf2out_begin_prologue (unsigned int l
*** 3967,3974 ****
--- 3976,3992 ----
      dwarf2out_source_line (line, file, 0, true);
  #endif
  
+   personality = get_personality_function (current_function_decl);
    if (dwarf2out_do_cfi_asm ())
      dwarf2out_do_cfi_startproc (false);
+   else
+     {
+       if (!current_unit_personality || current_unit_personality == personality)
+         current_unit_personality = personality;
+       else
+ 	sorry ("Multiple EH personalities are supported only with assemblers "
+ 	       "supporting .cfi.personality directive.");
+     }
  }
  
  /* Output a marker (i.e. a label) for the absolute end of the generated code
Index: gcc/expr.h
===================================================================
*** gcc/expr.h.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/expr.h	2009-09-11 13:58:30.000000000 +0200
*************** extern void init_all_optabs (void);
*** 814,819 ****
--- 814,825 ----
  extern rtx init_one_libfunc (const char *);
  extern rtx set_user_assembler_libfunc (const char *, const char *);
  
+ /* Build a decl for a libfunc named NAME. */
+ extern tree build_libfunc_function (const char *);
+ 
+ /* Get the personality libfunc for a function decl.  */
+ rtx get_personality_function (tree);
+ 
  extern int vector_mode_valid_p (enum machine_mode);
  
  #endif /* GCC_EXPR_H */
Index: gcc/fortran/f95-lang.c
===================================================================
*** gcc/fortran/f95-lang.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/fortran/f95-lang.c	2009-09-11 13:58:30.000000000 +0200
*************** gfc_maybe_initialize_eh (void)
*** 1155,1164 ****
      return;
  
    gfc_eh_initialized_p = true;
-   eh_personality_libfunc
-     = init_one_libfunc (USING_SJLJ_EXCEPTIONS
-                        ? "__gcc_personality_sj0"
-                        : "__gcc_personality_v0");
    default_init_unwind_resume_libfunc ();
    using_eh_for_cleanups ();
  }
--- 1155,1160 ----
Index: gcc/c-tree.h
===================================================================
*** gcc/c-tree.h.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/c-tree.h	2009-09-11 13:58:30.000000000 +0200
*************** extern int system_header_p;
*** 589,597 ****
  
  extern bool c_override_global_bindings_to_false;
  
- /* True means we've initialized exception handling.  */
- extern bool c_eh_initialized_p;
- 
  /* In c-decl.c */
  extern void c_finish_incomplete_decl (tree);
  extern void c_write_global_declarations (void);
--- 589,594 ----
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/tree-eh.c	2009-09-11 13:58:30.000000000 +0200
*************** lower_eh_constructs (void)
*** 1939,1944 ****
--- 1939,1952 ----
    htab_delete (finally_tree);
  
    collect_eh_region_array ();
+ 
+   /* If this function needs a language specific EH personality routine
+      and the frontend didn't already set one do so now.  */
+   if (function_needs_eh_personality (cfun) == eh_personality_lang
+       && !DECL_FUNCTION_PERSONALITY (current_function_decl))
+     DECL_FUNCTION_PERSONALITY (current_function_decl)
+       = lang_hooks.eh_personality ();
+ 
    return 0;
  }
  
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c.orig	2009-09-11 13:57:36.000000000 +0200
--- gcc/tree-inline.c	2009-09-11 13:58:30.000000000 +0200
*************** expand_call_inline (basic_block bb, gimp
*** 3505,3510 ****
--- 3505,3517 ----
  
    cg_edge = cgraph_edge (id->dst_node, stmt);
  
+   /* Don't inline functions with different EH personalities.  */
+   if (DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl)
+       && DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl)
+       && (DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl)
+ 	  != DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl)))
+     goto egress;
+ 
    /* Don't try to inline functions that are not well-suited to
       inlining.  */
    if (!cgraph_inline_p (cg_edge, &reason))
*************** expand_call_inline (basic_block bb, gimp
*** 3546,3551 ****
--- 3553,3563 ----
    /* We will be inlining this callee.  */
    id->eh_region = lookup_stmt_eh_region (stmt);
  
+   /* Update the callers EH personality.  */
+   if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl))
+     DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl)
+       = DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl);
+ 
    /* Split the block holding the GIMPLE_CALL.  */
    e = split_block (bb, stmt);
    bb = e->src;
*************** tree_function_versioning (tree old_decl,
*** 4730,4735 ****
--- 4742,4748 ----
  
    DECL_ARTIFICIAL (new_decl) = 1;
    DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl);
+   DECL_FUNCTION_PERSONALITY (new_decl) = DECL_FUNCTION_PERSONALITY (old_decl);
  
    /* Prepare the data structures for the tree copy.  */
    memset (&id, 0, sizeof (id));
*************** tree_can_inline_p (struct cgraph_edge *e
*** 5000,5005 ****
--- 5013,5030 ----
    caller = e->caller->decl;
    callee = e->callee->decl;
  
+   /* We cannot inline a function that uses a different EH personality
+      than the caller.  */
+   if (DECL_FUNCTION_PERSONALITY (caller)
+       && DECL_FUNCTION_PERSONALITY (callee)
+       && (DECL_FUNCTION_PERSONALITY (caller)
+ 	  != DECL_FUNCTION_PERSONALITY (callee)))
+     {
+       e->inline_failed = CIF_UNSPECIFIED;
+       gimple_call_set_cannot_inline (e->call_stmt, true);
+       return false;
+     }
+ 
    /* Allow the backend to decide if inlining is ok.  */
    if (!targetm.target_option.can_inline_p (caller, callee))
      {
Index: gcc/expr.c
===================================================================
*** gcc/expr.c.orig	2009-09-11 13:57:36.000000000 +0200
--- gcc/expr.c	2009-09-11 13:58:30.000000000 +0200
*************** const_vector_from_tree (tree exp)
*** 10214,10217 ****
--- 10214,10265 ----
  
    return gen_rtx_CONST_VECTOR (mode, v);
  }
+ 
+ 
+ /* Build a decl for a EH personality function named NAME. */
+ 
+ tree
+ build_personality_function (const char *name)
+ {
+   tree decl, type;
+ 
+   type = build_function_type_list (integer_type_node, integer_type_node,
+ 				   long_long_unsigned_type_node,
+ 				   ptr_type_node, ptr_type_node, NULL_TREE);
+   decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+ 		     get_identifier (name), type);
+   DECL_ARTIFICIAL (decl) = 1;
+   DECL_EXTERNAL (decl) = 1;
+   TREE_PUBLIC (decl) = 1;
+ 
+   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
+      are the flags assigned by targetm.encode_section_info.  */
+   SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
+ 
+   return decl;
+ }
+ 
+ /* Extracts the personality function of DECL and returns the corresponding
+    libfunc.  */
+ 
+ rtx
+ get_personality_function (tree decl)
+ {
+   tree personality = DECL_FUNCTION_PERSONALITY (decl);
+   enum eh_personality_kind pk;
+ 
+   pk = function_needs_eh_personality (DECL_STRUCT_FUNCTION (decl));
+   if (pk == eh_personality_none)
+     return NULL;
+ 
+   if (!personality
+       && pk == eh_personality_any)
+     personality = lang_hooks.eh_personality ();
+ 
+   if (pk == eh_personality_lang)
+     gcc_assert (personality != NULL_TREE);
+ 
+   return XEXP (DECL_RTL (personality), 0);
+ }
+ 
  #include "gt-expr.h"
Index: gcc/ada/gcc-interface/Make-lang.in
===================================================================
*** gcc/ada/gcc-interface/Make-lang.in.orig	2009-09-11 13:57:35.000000000 +0200
--- gcc/ada/gcc-interface/Make-lang.in	2009-09-11 13:58:30.000000000 +0200
*************** ada/misc.o : ada/gcc-interface/misc.c $(
*** 1072,1078 ****
     $(LANGHOOKS_DEF_H) opts.h options.h $(TREE_INLINE_H) \
     ada/gcc-interface/ada.h ada/adadecode.h ada/types.h ada/atree.h \
     ada/elists.h ada/namet.h ada/nlists.h ada/stringt.h ada/uintp.h ada/fe.h \
!    ada/sinfo.h ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h
  	$(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
  
  ada/targtyps.o : ada/gcc-interface/targtyps.c $(CONFIG_H) $(SYSTEM_H) \
--- 1072,1079 ----
     $(LANGHOOKS_DEF_H) opts.h options.h $(TREE_INLINE_H) \
     ada/gcc-interface/ada.h ada/adadecode.h ada/types.h ada/atree.h \
     ada/elists.h ada/namet.h ada/nlists.h ada/stringt.h ada/uintp.h ada/fe.h \
!    ada/sinfo.h ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h \
!    gt-ada-misc.h
  	$(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
  
  ada/targtyps.o : ada/gcc-interface/targtyps.c $(CONFIG_H) $(SYSTEM_H) \
Index: gcc/ada/gcc-interface/config-lang.in
===================================================================
*** gcc/ada/gcc-interface/config-lang.in.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/ada/gcc-interface/config-lang.in	2009-09-11 13:58:30.000000000 +0200
*************** boot_language_boot_flags='ADAFLAGS="$(BO
*** 32,38 ****
  
  compilers="gnat1\$(exeext)"
  
! gtfiles="\$(srcdir)/ada/gcc-interface/ada-tree.h \$(srcdir)/ada/gcc-interface/gigi.h \$(srcdir)/ada/gcc-interface/decl.c \$(srcdir)/ada/gcc-interface/trans.c \$(srcdir)/ada/gcc-interface/utils.c"
  
  outputs="ada/gcc-interface/Makefile ada/Makefile"
  
--- 32,38 ----
  
  compilers="gnat1\$(exeext)"
  
! gtfiles="\$(srcdir)/ada/gcc-interface/ada-tree.h \$(srcdir)/ada/gcc-interface/gigi.h \$(srcdir)/ada/gcc-interface/decl.c \$(srcdir)/ada/gcc-interface/trans.c \$(srcdir)/ada/gcc-interface/utils.c \$(srcdir)/ada/gcc-interface/misc.c"
  
  outputs="ada/gcc-interface/Makefile ada/Makefile"
  
Index: gcc/cp/Make-lang.in
===================================================================
*** gcc/cp/Make-lang.in.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/cp/Make-lang.in	2009-09-11 13:58:30.000000000 +0200
*************** cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H)
*** 250,256 ****
    $(C_PRAGMA_H) toplev.h output.h input.h cp/operators.def $(TM_P_H)
  cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h debug.h langhooks.h \
    $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h \
!   $(DIAGNOSTIC_H) cp/cp-objcp-common.h
  cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
    output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \
    cp/operators.def $(TM_P_H) $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(C_PRAGMA_H) \
--- 250,256 ----
    $(C_PRAGMA_H) toplev.h output.h input.h cp/operators.def $(TM_P_H)
  cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h debug.h langhooks.h \
    $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h \
!   $(DIAGNOSTIC_H) cp/cp-objcp-common.h $(EXPR_H) $(EXCEPT_H)
  cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
    output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \
    cp/operators.def $(TM_P_H) $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(C_PRAGMA_H) \
Index: gcc/java/Make-lang.in
===================================================================
*** gcc/java/Make-lang.in.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/java/Make-lang.in	2009-09-11 13:58:30.000000000 +0200
*************** java/jvgenmain.o: java/jvgenmain.c $(CON
*** 284,290 ****
    coretypes.h $(TM_H) intl.h
  java/lang.o: java/lang.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h input.h \
    toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(EXPR_H) $(DIAGNOSTIC_H) \
!   langhooks.h $(LANGHOOKS_DEF_H) gt-java-lang.h opts.h options.h
  java/mangle.o: java/mangle.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) $(SYSTEM_H) \
    coretypes.h $(TM_H) toplev.h $(GGC_H) gt-java-mangle.h $(LANGHOOKS_DEF_H)
  java/mangle_name.o: java/mangle_name.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) \
--- 284,290 ----
    coretypes.h $(TM_H) intl.h
  java/lang.o: java/lang.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h input.h \
    toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(EXPR_H) $(DIAGNOSTIC_H) \
!   langhooks.h $(LANGHOOKS_DEF_H) gt-java-lang.h opts.h options.h $(EXCEPT_H)
  java/mangle.o: java/mangle.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) $(SYSTEM_H) \
    coretypes.h $(TM_H) toplev.h $(GGC_H) gt-java-mangle.h $(LANGHOOKS_DEF_H)
  java/mangle_name.o: java/mangle_name.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) \
Index: gcc/java/lang.c
===================================================================
*** gcc/java/lang.c.orig	2009-09-11 13:56:48.000000000 +0200
--- gcc/java/lang.c	2009-09-11 13:58:30.000000000 +0200
*************** The Free Software Foundation is independ
*** 45,50 ****
--- 45,51 ----
  #include "tree-dump.h"
  #include "opts.h"
  #include "options.h"
+ #include "except.h"
  
  static bool java_init (void);
  static void java_finish (void);
*************** static bool java_decl_ok_for_sibcall (co
*** 64,69 ****
--- 65,72 ----
  
  static enum classify_record java_classify_record (tree type);
  
+ static tree java_eh_personality (void);
+ 
  #ifndef TARGET_OBJECT_SUFFIX
  # define TARGET_OBJECT_SUFFIX ".o"
  #endif
*************** struct GTY(()) language_function {
*** 158,163 ****
--- 161,169 ----
  #undef LANG_HOOKS_ATTRIBUTE_TABLE
  #define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table
  
+ #undef LANG_HOOKS_EH_PERSONALITY
+ #define LANG_HOOKS_EH_PERSONALITY java_eh_personality
+ 
  /* Each front end provides its own.  */
  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
  
*************** java_classify_record (tree type)
*** 880,883 ****
--- 886,903 ----
    return RECORD_IS_CLASS;
  }
  
+ static GTY(()) tree java_eh_personality_decl;
+ 
+ static tree
+ java_eh_personality (void)
+ {
+   if (!java_eh_personality_decl)
+     java_eh_personality_decl
+       = build_personality_function (USING_SJLJ_EXCEPTIONS
+ 				    ? "__gcj_personality_sj0"
+ 				    : "__gcj_personality_v0");
+ 
+   return java_eh_personality_decl;
+ }
+ 
  #include "gt-java-lang.h"
Index: gcc/tree.c
===================================================================
*** gcc/tree.c.orig	2009-09-11 13:57:36.000000000 +0200
--- gcc/tree.c	2009-09-11 13:58:30.000000000 +0200
*************** tree_strip_sign_nop_conversions (tree ex
*** 10566,10570 ****
--- 10566,10585 ----
    return exp;
  }
  
+ static GTY(()) tree gcc_eh_personality_decl;
+ 
+ /* Return the GCC personality function decl.  */
+ 
+ tree
+ lhd_gcc_personality (void)
+ {
+   if (!gcc_eh_personality_decl)
+     gcc_eh_personality_decl
+       = build_personality_function (USING_SJLJ_EXCEPTIONS
+ 				    ? "__gcc_personality_sj0"
+ 				    : "__gcc_personality_v0");
+ 
+   return gcc_eh_personality_decl;
+ }
  
  #include "gt-tree.h"
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in.orig	2009-09-09 11:28:58.000000000 +0200
--- gcc/Makefile.in	2009-09-11 15:12:28.000000000 +0200
*************** simplify-rtx.o : simplify-rtx.c $(CONFIG
*** 2767,2773 ****
  cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h $(TOPLEV_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
     gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
!    $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) value-prof.h
  cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(TREE_H) langhooks.h $(TREE_INLINE_H) $(TOPLEV_H) $(FLAGS_H) $(GGC_H) \
     $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
--- 2767,2773 ----
  cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h $(TOPLEV_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
     gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
!    $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) value-prof.h $(EXCEPT_H)
  cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(TREE_H) langhooks.h $(TREE_INLINE_H) $(TOPLEV_H) $(FLAGS_H) $(GGC_H) \
     $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
Index: gcc/cgraph.c
===================================================================
*** gcc/cgraph.c.orig	2009-09-04 15:05:56.000000000 +0200
--- gcc/cgraph.c	2009-09-11 15:10:55.000000000 +0200
*************** The callgraph:
*** 84,89 ****
--- 84,90 ----
  #include "tree-dump.h"
  #include "tree-flow.h"
  #include "value-prof.h"
+ #include "except.h"
  
  static void cgraph_node_remove_callers (struct cgraph_node *node);
  static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
*************** cgraph_add_new_function (tree fndecl, bo
*** 1953,1958 ****
--- 1954,1965 ----
  	current_function_decl = NULL;
  	break;
      }
+ 
+   /* Set a personality if required and we already passed EH lowering.  */
+   if (lowered
+       && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl))
+ 	  == eh_personality_lang))
+     DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
  }
  
  /* Return true if NODE can be made local for API change.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-11 13:25                           ` Richard Guenther
@ 2009-09-11 15:41                             ` Richard Henderson
  2009-09-11 16:41                               ` Richard Guenther
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2009-09-11 15:41 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Diego Novillo

On 09/11/2009 06:24 AM, Richard Guenther wrote:
> Ok for trunk?

Looks good.


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-11 15:41                             ` Richard Henderson
@ 2009-09-11 16:41                               ` Richard Guenther
  2009-09-11 17:05                                 ` Richard Henderson
  2009-09-13 22:57                                 ` H.J. Lu
  0 siblings, 2 replies; 39+ messages in thread
From: Richard Guenther @ 2009-09-11 16:41 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Richard Guenther, gcc-patches, Diego Novillo

On Fri, Sep 11, 2009 at 5:41 PM, Richard Henderson <rth@redhat.com> wrote:
> On 09/11/2009 06:24 AM, Richard Guenther wrote:
>>
>> Ok for trunk?
>
> Looks good.

Thanks.  I'll wait until Monday for comments from FE maintainers.

How big is the overlap with the EH gimple re-write?  Do you want to be first
or second?

Richard.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-11 16:41                               ` Richard Guenther
@ 2009-09-11 17:05                                 ` Richard Henderson
  2009-09-13 22:57                                 ` H.J. Lu
  1 sibling, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2009-09-11 17:05 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Richard Guenther, gcc-patches, Diego Novillo

On 09/11/2009 09:41 AM, Richard Guenther wrote:
> How big is the overlap with the EH gimple re-write?  Do you want to be first
> or second?

It's pretty small.  Just a few lines here and there.
You've got the timezone advantage -- you go first.


r~

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-11 16:41                               ` Richard Guenther
  2009-09-11 17:05                                 ` Richard Henderson
@ 2009-09-13 22:57                                 ` H.J. Lu
  2010-12-29  5:30                                   ` H.J. Lu
  1 sibling, 1 reply; 39+ messages in thread
From: H.J. Lu @ 2009-09-13 22:57 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Richard Henderson, Richard Guenther, gcc-patches, Diego Novillo

On Fri, Sep 11, 2009 at 9:41 AM, Richard
Guenther<richard.guenther@gmail.com> wrote:
> On Fri, Sep 11, 2009 at 5:41 PM, Richard Henderson <rth@redhat.com> wrote:
>> On 09/11/2009 06:24 AM, Richard Guenther wrote:
>>>
>>> Ok for trunk?
>>
>> Looks good.
>
> Thanks.  I'll wait until Monday for comments from FE maintainers.
>
> How big is the overlap with the EH gimple re-write?  Do you want to be first
> or second?
>

It caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41352

-- 
H.J.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-13 22:57                                 ` H.J. Lu
@ 2010-12-29  5:30                                   ` H.J. Lu
  2010-12-29  5:36                                     ` H.J. Lu
  0 siblings, 1 reply; 39+ messages in thread
From: H.J. Lu @ 2010-12-29  5:30 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Richard Henderson, Richard Guenther, gcc-patches, Diego Novillo

On Sun, Sep 13, 2009 at 3:57 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Sep 11, 2009 at 9:41 AM, Richard
> Guenther<richard.guenther@gmail.com> wrote:
>> On Fri, Sep 11, 2009 at 5:41 PM, Richard Henderson <rth@redhat.com> wrote:
>>> On 09/11/2009 06:24 AM, Richard Guenther wrote:
>>>>
>>>> Ok for trunk?
>>>
>>> Looks good.
>>
>> Thanks.  I'll wait until Monday for comments from FE maintainers.
>>
>> How big is the overlap with the EH gimple re-write?  Do you want to be first
>> or second?
>>
>
> It caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41352
>

This also caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47086


-- 
H.J.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2010-12-29  5:30                                   ` H.J. Lu
@ 2010-12-29  5:36                                     ` H.J. Lu
  2011-02-08  2:06                                       ` H.J. Lu
  0 siblings, 1 reply; 39+ messages in thread
From: H.J. Lu @ 2010-12-29  5:36 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Richard Henderson, Richard Guenther, gcc-patches, Diego Novillo

On Tue, Dec 28, 2010 at 6:51 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sun, Sep 13, 2009 at 3:57 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Fri, Sep 11, 2009 at 9:41 AM, Richard
>> Guenther<richard.guenther@gmail.com> wrote:
>>> On Fri, Sep 11, 2009 at 5:41 PM, Richard Henderson <rth@redhat.com> wrote:
>>>> On 09/11/2009 06:24 AM, Richard Guenther wrote:
>>>>>
>>>>> Ok for trunk?
>>>>
>>>> Looks good.
>>>
>>> Thanks.  I'll wait until Monday for comments from FE maintainers.
>>>
>>> How big is the overlap with the EH gimple re-write?  Do you want to be first
>>> or second?
>>>
>>
>> It caused:
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41352
>>
>
> This also caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47086
>

This also caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47087

-- 
H.J.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2010-12-29  5:36                                     ` H.J. Lu
@ 2011-02-08  2:06                                       ` H.J. Lu
  0 siblings, 0 replies; 39+ messages in thread
From: H.J. Lu @ 2011-02-08  2:06 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Richard Henderson, Richard Guenther, gcc-patches, Diego Novillo

On Tue, Dec 28, 2010 at 6:54 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Dec 28, 2010 at 6:51 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Sun, Sep 13, 2009 at 3:57 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> On Fri, Sep 11, 2009 at 9:41 AM, Richard
>>> Guenther<richard.guenther@gmail.com> wrote:
>>>> On Fri, Sep 11, 2009 at 5:41 PM, Richard Henderson <rth@redhat.com> wrote:
>>>>> On 09/11/2009 06:24 AM, Richard Guenther wrote:
>>>>>>
>>>>>> Ok for trunk?
>>>>>
>>>>> Looks good.
>>>>
>>>> Thanks.  I'll wait until Monday for comments from FE maintainers.
>>>>
>>>> How big is the overlap with the EH gimple re-write?  Do you want to be first
>>>> or second?
>>>>
>>>
>>> It caused:
>>>
>>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41352
>>>
>>
>> This also caused:
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47086
>>
>
> This also caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47087

This also caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47639

-- 
H.J.

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-15  8:15   ` Gerald Pfeifer
@ 2009-09-15 11:48     ` David Edelsohn
  0 siblings, 0 replies; 39+ messages in thread
From: David Edelsohn @ 2009-09-15 11:48 UTC (permalink / raw)
  To: Gerald Pfeifer
  Cc: Richard Guenther, Richard Guenther, Richard Henderson,
	gcc-patches, Diego Novillo

On Tue, Sep 15, 2009 at 4:15 AM, Gerald Pfeifer <gerald@pfeifer.com> wrote:
> On Mon, 14 Sep 2009, Richard Guenther wrote:
>>> This patch broke bootstrap on AIX:
>> Doh, I forgot about that path.  Fixed like the following, committed as
>> obvious.  Can you verify this restores bootstrap?
>
> I cannot test on AIX, but FreeBSD is back to working.  Thanks for the
> quick fix, Richi!

I told Richi on IRC that the patch fixed AIX.

David

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-14  9:37 ` Richard Guenther
@ 2009-09-15  8:15   ` Gerald Pfeifer
  2009-09-15 11:48     ` David Edelsohn
  0 siblings, 1 reply; 39+ messages in thread
From: Gerald Pfeifer @ 2009-09-15  8:15 UTC (permalink / raw)
  To: Richard Guenther
  Cc: David Edelsohn, Richard Guenther, Richard Henderson, gcc-patches,
	Diego Novillo

On Mon, 14 Sep 2009, Richard Guenther wrote:
>> This patch broke bootstrap on AIX:
> Doh, I forgot about that path.  Fixed like the following, committed as 
> obvious.  Can you verify this restores bootstrap?

I cannot test on AIX, but FreeBSD is back to working.  Thanks for the
quick fix, Richi!

Gerald

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-14  2:43 David Edelsohn
  2009-09-14  5:38 ` Gerald Pfeifer
@ 2009-09-14  9:37 ` Richard Guenther
  2009-09-15  8:15   ` Gerald Pfeifer
  1 sibling, 1 reply; 39+ messages in thread
From: Richard Guenther @ 2009-09-14  9:37 UTC (permalink / raw)
  To: David Edelsohn
  Cc: Richard Guenther, Richard Henderson, gcc-patches, Diego Novillo

On Sun, 13 Sep 2009, David Edelsohn wrote:

> This patch broke bootstrap on AIX:
> 
> /farm/dje/src/src/libstdc++-v3/libsupc++/eh_ptr.cc: In destructor
> 'std::__exception_ptr::exception_ptr::~exception_ptr()':
> /farm/dje/src/src/libstdc++-v3/libsupc++/eh_ptr.cc:67:1: sorry,
> unimplemented: Multiple EH personalities are supported only with
> assemblers supporting .cfi.personality directive.
> make[2]: *** [eh_ptr.lo] Error 1

Doh, I forgot about that path.  Fixed like the following, committed
as obvious.  Can you verify this restores bootstrap?

Thanks,
Richard.

2009-09-14  Richard Guenther  <rguenther@suse.de>

	PR middle-end/41350
	* dwarf2out.c (dwarf2out_begin_prologue): Adjust non-CFI asm
	EH personality path.

	* g++.dg/debug/dwarf-eh-personality-1.C: New testcase.

Index: gcc/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c	(revision 151680)
--- gcc/dwarf2out.c	(working copy)
*************** dwarf2out_begin_prologue (unsigned int l
*** 3881,3887 ****
    char label[MAX_ARTIFICIAL_LABEL_BYTES];
    char * dup_label;
    dw_fde_ref fde;
-   rtx personality;
    section *fnsec;
  
    current_function_func_begin_label = NULL;
--- 3881,3886 ----
*************** dwarf2out_begin_prologue (unsigned int l
*** 3976,3989 ****
      dwarf2out_source_line (line, file, 0, true);
  #endif
  
-   personality = get_personality_function (current_function_decl);
    if (dwarf2out_do_cfi_asm ())
      dwarf2out_do_cfi_startproc (false);
    else
      {
!       if (!current_unit_personality || current_unit_personality == personality)
          current_unit_personality = personality;
!       else
  	sorry ("Multiple EH personalities are supported only with assemblers "
  	       "supporting .cfi.personality directive.");
      }
--- 3975,3993 ----
      dwarf2out_source_line (line, file, 0, true);
  #endif
  
    if (dwarf2out_do_cfi_asm ())
      dwarf2out_do_cfi_startproc (false);
    else
      {
!       rtx personality = get_personality_function (current_function_decl);
!       if (!current_unit_personality)
          current_unit_personality = personality;
! 
!       /* We cannot keep a current personality per function as without CFI
! 	 asm at the point where we emit the CFI data there is no current
! 	 function anymore.  */
!       if (personality
! 	  && current_unit_personality != personality)
  	sorry ("Multiple EH personalities are supported only with assemblers "
  	       "supporting .cfi.personality directive.");
      }
Index: gcc/testsuite/g++.dg/debug/dwarf-eh-personality-1.C
===================================================================
*** gcc/testsuite/g++.dg/debug/dwarf-eh-personality-1.C	(revision 0)
--- gcc/testsuite/g++.dg/debug/dwarf-eh-personality-1.C	(revision 0)
***************
*** 0 ****
--- 1,17 ----
+ // { dg-options "-fno-dwarf2-cfi-asm" }
+ 
+ extern void bar (void);
+ int foo (void)
+ {
+   try {
+       bar();
+   } catch (...) {
+       return 1;
+   }
+   return 0;
+ }
+ 
+ int foobar (void)
+ {
+ }
+ 

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

* Re: [PATCH] Merge from LTO: eh_personality changes
  2009-09-14  2:43 David Edelsohn
@ 2009-09-14  5:38 ` Gerald Pfeifer
  2009-09-14  9:37 ` Richard Guenther
  1 sibling, 0 replies; 39+ messages in thread
From: Gerald Pfeifer @ 2009-09-14  5:38 UTC (permalink / raw)
  To: David Edelsohn
  Cc: Richard Guenther, Richard Henderson, Richard Guenther,
	gcc-patches, Diego Novillo

On Sun, 13 Sep 2009, David Edelsohn wrote:
> This patch broke bootstrap on AIX:
> 
> /farm/dje/src/src/libstdc++-v3/libsupc++/eh_ptr.cc: In destructor
> 'std::__exception_ptr::exception_ptr::~exception_ptr()':
> /farm/dje/src/src/libstdc++-v3/libsupc++/eh_ptr.cc:67:1: sorry,
> unimplemented: Multiple EH personalities are supported only with
> assemblers supporting .cfi.personality directive.
> make[2]: *** [eh_ptr.lo] Error 1

FreeBSD and Darwin, too.  PR bootstrap/41350.

Gerald

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

* Re: [PATCH] Merge from LTO: eh_personality changes
@ 2009-09-14  2:43 David Edelsohn
  2009-09-14  5:38 ` Gerald Pfeifer
  2009-09-14  9:37 ` Richard Guenther
  0 siblings, 2 replies; 39+ messages in thread
From: David Edelsohn @ 2009-09-14  2:43 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Richard Henderson, Richard Guenther, gcc-patches, Diego Novillo

This patch broke bootstrap on AIX:

/farm/dje/src/src/libstdc++-v3/libsupc++/eh_ptr.cc: In destructor
'std::__exception_ptr::exception_ptr::~exception_ptr()':
/farm/dje/src/src/libstdc++-v3/libsupc++/eh_ptr.cc:67:1: sorry,
unimplemented: Multiple EH personalities are supported only with
assemblers supporting .cfi.personality directive.
make[2]: *** [eh_ptr.lo] Error 1

David

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

end of thread, other threads:[~2011-02-08  2:06 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-04 13:34 [PATCH] Merge from LTO: eh_personality changes Richard Guenther
2009-09-04 13:37 ` Diego Novillo
2009-09-04 13:41   ` Richard Guenther
2009-09-05 16:37 ` Richard Henderson
2009-09-05 16:38 ` Richard Henderson
2009-09-05 17:24   ` Richard Guenther
2009-09-05 18:11     ` Richard Henderson
2009-09-08 12:37       ` Richard Guenther
2009-09-08 15:20         ` Richard Guenther
2009-09-08 15:49           ` Richard Henderson
2009-09-10 13:12             ` Richard Guenther
2009-09-10 14:37               ` Richard Guenther
2009-09-10 14:52                 ` Richard Guenther
2009-09-10 15:50                   ` Richard Henderson
2009-09-10 16:02                     ` Richard Guenther
2009-09-10 16:06                       ` Richard Guenther
2009-09-10 16:23                         ` Richard Henderson
2009-09-11 13:25                           ` Richard Guenther
2009-09-11 15:41                             ` Richard Henderson
2009-09-11 16:41                               ` Richard Guenther
2009-09-11 17:05                                 ` Richard Henderson
2009-09-13 22:57                                 ` H.J. Lu
2010-12-29  5:30                                   ` H.J. Lu
2010-12-29  5:36                                     ` H.J. Lu
2011-02-08  2:06                                       ` H.J. Lu
2009-09-10 16:12                       ` Richard Henderson
2009-09-10 15:50                   ` Richard Guenther
2009-09-10 15:57                     ` Richard Henderson
2009-09-08 17:38           ` Eric Botcazou
2009-09-08 15:48         ` Richard Henderson
2009-09-08 16:04           ` Richard Guenther
2009-09-09  9:34             ` Richard Guenther
2009-09-09 15:24               ` Richard Henderson
2009-09-09 15:26                 ` Richard Guenther
2009-09-14  2:43 David Edelsohn
2009-09-14  5:38 ` Gerald Pfeifer
2009-09-14  9:37 ` Richard Guenther
2009-09-15  8:15   ` Gerald Pfeifer
2009-09-15 11:48     ` David Edelsohn

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