This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ PATCH to emit_tinfo_decl


I'm applying the following patch.  In addition to my usual
i686-pc-linux-gnu testing, I've tested the same toolchain with flag_weak
turned off to simulate the behavior on a toolchain without weak support
(like the HP) and on a cross-compiler to mips-elf.

My earlier patch broke hpux because we were unconditionally calling
comdat_linkage for the tinfo nodes, which on hpux makes them file-local.
The proper thing is to give them the same linkage as the vtable, as in the
spec.  Unfortunately, this will be an ABI change from 3.1 on targets
without weak symbol support.

My earlier patch broke mips-elf because rtti.c lies to the backend,
pretending that all typeinfo nodes have type type_info, which has
sizeof==8.  So the mips-elf toolchain decides it can get to one with a
gp-relative reloc.  Of course, the node for bad_exception is actually of a
larger type.  And it is in a separate linkonce section.  Both of these
cause the optimization to be wrong; the second is easier to use in a fix.
So now we check DECL_COMDAT in the mips backend.

Should this patch also cause problems, any maintainer should feel free to
rip it out again.  I'm not sure I'll be online again before Sunday.

If this goes well, I'll apply a variant to the 3.1 branch which only
affects flag_weak targets.

2002-05-14  Jason Merrill  <jason@redhat.com>

	* cp/rtti.c (get_tinfo_decl): Don't call comdat_linkage.
	Do set DECL_COMDAT.
	(synthesize_tinfo_var): Take the public decl.
	(create_real_tinfo_var): Likewise.  Check DECL_COMDAT.
	(emit_tinfo_decl): Adjust.  Call import_export_decl.
	* cp/decl2.c (import_export_decl): Simplify tinfo decl handling.
	* config/mips/mips.c (mips_output_external): Don't do sdata
	optimization for a variable with DECL_COMDAT set.

*** ./config/mips/mips.c.~1~	Wed May 15 04:32:21 2002
--- ./config/mips/mips.c	Wed May 15 23:02:36 2002
*************** mips_output_external (file, decl, name)
*** 6035,6040 ****
--- 6035,6041 ----
  
    if (TARGET_GP_OPT
        && TREE_CODE (decl) != FUNCTION_DECL
+       && !DECL_COMDAT (decl)
        && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
        && ((section_name = DECL_SECTION_NAME (decl)) == NULL
  	  || strcmp (TREE_STRING_POINTER (section_name), ".sbss") == 0
*** ./cp/rtti.c.~1~	Wed May 15 04:32:50 2002
--- ./cp/rtti.c	Thu May 16 04:24:05 2002
*************** static tree dfs_class_hint_mark PARAMS (
*** 59,65 ****
  static tree dfs_class_hint_unmark PARAMS ((tree, void *));
  static int class_hint_flags PARAMS((tree));
  static tree class_initializer PARAMS((tree, tree, tree));
! static tree synthesize_tinfo_var PARAMS((tree, tree));
  static tree create_real_tinfo_var PARAMS((tree, tree, tree, tree, int));
  static tree create_pseudo_type_info PARAMS((const char *, int, ...));
  static tree get_vmi_pseudo_type_info PARAMS((int));
--- 59,65 ----
  static tree dfs_class_hint_unmark PARAMS ((tree, void *));
  static int class_hint_flags PARAMS((tree));
  static tree class_initializer PARAMS((tree, tree, tree));
! static tree synthesize_tinfo_var PARAMS((tree));
  static tree create_real_tinfo_var PARAMS((tree, tree, tree, tree, int));
  static tree create_pseudo_type_info PARAMS((const char *, int, ...));
  static tree get_vmi_pseudo_type_info PARAMS((int));
*************** get_tinfo_decl (type)
*** 309,317 ****
        TREE_STATIC (d) = 1;
        DECL_EXTERNAL (d) = 1;
        TREE_PUBLIC (d) = 1;
-       if (flag_weak || !typeinfo_in_lib_p (type))
- 	comdat_linkage (d);
        SET_DECL_ASSEMBLER_NAME (d, name);
        cp_finish_decl (d, NULL_TREE, NULL_TREE, 0);
  
        pushdecl_top_level (d);
--- 309,316 ----
        TREE_STATIC (d) = 1;
        DECL_EXTERNAL (d) = 1;
        TREE_PUBLIC (d) = 1;
        SET_DECL_ASSEMBLER_NAME (d, name);
+       DECL_COMDAT (d) = 1;
        cp_finish_decl (d, NULL_TREE, NULL_TREE, 0);
  
        pushdecl_top_level (d);
*************** typeinfo_in_lib_p (type)
*** 929,947 ****
  }
  
  /* Generate a pseudo_type_info VAR_DECL suitable for the supplied
!    TARGET_TYPE and given the REAL_NAME. This is the structure expected by
     the runtime, and therefore has additional fields.  If we need not emit a
     definition (because the runtime must contain it), return NULL_TREE,
     otherwise return the VAR_DECL.  */
  
  static tree
! synthesize_tinfo_var (target_type, real_name)
!      tree target_type;
!      tree real_name;
  {
    tree var_init = NULL_TREE;
    tree var_type = NULL_TREE;
    int non_public = 0;
    
    switch (TREE_CODE (target_type))
      {
--- 928,950 ----
  }
  
  /* Generate a pseudo_type_info VAR_DECL suitable for the supplied
!    TARGET_TYPE and corresponding to PUBLIC_DECL. This is the structure expected by
     the runtime, and therefore has additional fields.  If we need not emit a
     definition (because the runtime must contain it), return NULL_TREE,
     otherwise return the VAR_DECL.  */
  
  static tree
! synthesize_tinfo_var (public_decl)
!      tree public_decl;
  {
    tree var_init = NULL_TREE;
    tree var_type = NULL_TREE;
    int non_public = 0;
+   tree target_type = TREE_TYPE (DECL_NAME (public_decl));
+   my_friendly_assert (target_type != NULL_TREE, 20000120);
+   
+   /* Say we've dealt with it.  */
+   TREE_TYPE (DECL_NAME (public_decl)) = NULL_TREE;
    
    switch (TREE_CODE (target_type))
      {
*************** synthesize_tinfo_var (target_type, real_
*** 1079,1085 ****
      }
    
    return create_real_tinfo_var (target_type,
! 				real_name, TINFO_PSEUDO_TYPE (var_type),
                                  var_init, non_public);
  }
  
--- 1082,1088 ----
      }
    
    return create_real_tinfo_var (target_type,
! 				public_decl, TINFO_PSEUDO_TYPE (var_type),
                                  var_init, non_public);
  }
  
*************** synthesize_tinfo_var (target_type, real_
*** 1087,1095 ****
     make this variable public (comdat). */
  
  static tree
! create_real_tinfo_var (target_type, name, type, init, non_public)
       tree target_type;
!      tree name;
       tree type;
       tree init;
       int non_public;
--- 1090,1098 ----
     make this variable public (comdat). */
  
  static tree
! create_real_tinfo_var (target_type, public_decl, type, init, non_public)
       tree target_type;
!      tree public_decl;
       tree type;
       tree init;
       int non_public;
*************** create_real_tinfo_var (target_type, name
*** 1098,1103 ****
--- 1101,1107 ----
    tree decl;
    tree hidden_name;
    char hidden[30];
+   tree name = DECL_ASSEMBLER_NAME (public_decl);
  
    /* We cannot give this the name NAME, as that already is globally
       bound to the tinfo_decl we originally created for this type in
*************** create_real_tinfo_var (target_type, name
*** 1115,1121 ****
    if (!non_public)
      {
        TREE_PUBLIC (decl) = 1;
!       if (flag_weak || !typeinfo_in_lib_p (target_type))
  	comdat_linkage (decl);
      }
    SET_DECL_ASSEMBLER_NAME (decl, name);
--- 1119,1126 ----
    if (!non_public)
      {
        TREE_PUBLIC (decl) = 1;
!       if (flag_weak
! 	  || (DECL_COMDAT (public_decl) && !typeinfo_in_lib_p (target_type)))
  	comdat_linkage (decl);
      }
    SET_DECL_ASSEMBLER_NAME (decl, name);
*************** emit_tinfo_decl (decl_ptr, data)
*** 1457,1475 ****
       void *data ATTRIBUTE_UNUSED;
  {
    tree tinfo_decl = *decl_ptr;
!   tree tinfo_type, decl;
    
    my_friendly_assert (TREE_TYPE (tinfo_decl) == tinfo_decl_type, 20000121);
!   tinfo_type = TREE_TYPE (DECL_NAME (tinfo_decl));
!   my_friendly_assert (tinfo_type != NULL_TREE, 20000120);
!   
!   if (!DECL_NEEDED_P (tinfo_decl))
      return 0;
!   /* Say we've dealt with it.  */
!   TREE_TYPE (DECL_NAME (tinfo_decl)) = NULL_TREE;
!   
    create_tinfo_types ();
!   decl = synthesize_tinfo_var (tinfo_type, DECL_ASSEMBLER_NAME (tinfo_decl));
    
    return decl != 0;
  }
--- 1462,1477 ----
       void *data ATTRIBUTE_UNUSED;
  {
    tree tinfo_decl = *decl_ptr;
!   tree decl;
    
    my_friendly_assert (TREE_TYPE (tinfo_decl) == tinfo_decl_type, 20000121);
! 
!   import_export_decl (tinfo_decl);
!   if (DECL_REALLY_EXTERN (tinfo_decl) || !DECL_NEEDED_P (tinfo_decl))
      return 0;
! 
    create_tinfo_types ();
!   decl = synthesize_tinfo_var (tinfo_decl);
    
    return decl != 0;
  }
*** ./cp/decl2.c.~1~	Wed May 15 04:32:46 2002
--- ./cp/decl2.c	Wed May 15 23:03:13 2002
*************** import_export_decl (decl)
*** 2509,2514 ****
--- 2509,2519 ----
      }
    else if (tinfo_decl_p (decl, 0))
      {
+       /* Here, we only decide whether or not the tinfo node should be
+ 	 emitted with the vtable.  The decl we're considering isn't
+ 	 actually the one which gets emitted; that one is generated in
+ 	 create_real_tinfo_var.  */
+ 
        tree ctype = TREE_TYPE (DECL_NAME (decl));
  
        if (IS_AGGR_TYPE (ctype))
*************** import_export_decl (decl)
*** 2528,2547 ****
  	  && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
  	{
  	  DECL_NOT_REALLY_EXTERN (decl)
! 	    = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
! 		 || (DECL_DECLARED_INLINE_P (decl) 
! 		     && ! flag_implement_inlines
! 		     && !DECL_VINDEX (decl)));
! 
! 	  /* Always make artificials weak.  */
! 	  if (flag_weak)
! 	    comdat_linkage (decl);
  	}
-       else if (TYPE_BUILT_IN (ctype) 
- 	       && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
- 	DECL_NOT_REALLY_EXTERN (decl) = 0;
        else
! 	comdat_linkage (decl);
      } 
    else
      comdat_linkage (decl);
--- 2533,2546 ----
  	  && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
  	{
  	  DECL_NOT_REALLY_EXTERN (decl)
! 	    = ! CLASSTYPE_INTERFACE_ONLY (ctype);
! 	  DECL_COMDAT (decl) = 0;
  	}
        else
! 	{
! 	  DECL_NOT_REALLY_EXTERN (decl) = 1;
! 	  DECL_COMDAT (decl) = 1;
! 	}
      } 
    else
      comdat_linkage (decl);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]