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]

RFC: PATCH: PR middle-end/20218: Can't use __attribute__ ((visibility ("hidden"))) to hide a symbol


This is the first attempt to to fix PR 20218. It keeps a list of
referenced global symbols and outputs non-default visibility at the
end. I only verified it on Linux/ia32, Linux/x86_64 and Linux/ia64.


H.J.
----
2005-02-28  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/20218
	* config/elfos.h (ASM_OUTPUT_EXTERNAL): New.
	(TARGET_ASM_FILE_END): New.

	* config/i386/i386-protos.h (ix86_elf_file_end): New.

	* config/i386/i386.c (ix86_elf_file_end): New.

	* config/i386/linux.h (TARGET_ASM_FILE_END): Defined.
	* config/i386/linux64.h (TARGET_ASM_FILE_END): Likewise.

	* config/ia64/hpux.h (TARGET_ASM_FILE_END): Removed.

	* config/ia64/ia64.c (ia64_hpux_add_extern_decl): Removed.
	(ia64_hpux_file_end): Renamed to ...
	(ia64_file_end): This. Handle symbol with non-default
	visibility.
	(TARGET_ASM_FILE_END): Defined.
	(ia64_asm_output_external): Rewritten.
	(extern_func_list): Removed.
	(extern_func_head): Likewise.

	* output.h (extern_symbol_list): New.
	(extern_symbol_head): New.
	(default_elf_asm_output_external): New.
	(default_elf_asm_output_external_1): New.
	(default_elf_asm_file_end): New.
	(maybe_assemble_visibility): New.

	* varasm.c (maybe_assemble_visibility): Make it extern and
	return int.
	(extern_symbol_head): New.
	(default_elf_asm_output_external_1): New.
	(default_elf_asm_output_external): New.
	(default_elf_asm_file_end): New.

--- gcc/config/elfos.h.global	2004-10-18 09:14:38.000000000 -0700
+++ gcc/config/elfos.h	2005-02-28 12:23:53.013906179 -0800
@@ -487,3 +487,17 @@ Boston, MA 02111-1307, USA.  */
         fprintf ((FILE), "\"\n");					\
     }									\
   while (0)
+
+/* A C statement (sans semicolon) to output to the stdio stream STREAM
+   any text necessary for declaring the name of an external symbol
+   named NAME whch is referenced in this compilation but not defined.
+   It is needed to properly support non-default visibility.  */
+
+#ifndef ASM_OUTPUT_EXTERNAL
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+  default_elf_asm_output_external (FILE, DECL, NAME)
+#endif
+
+#ifndef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END default_elf_asm_file_end
+#endif
--- gcc/config/i386/i386-protos.h.global	2005-02-01 17:41:25.000000000 -0800
+++ gcc/config/i386/i386-protos.h	2005-02-28 13:10:37.406053326 -0800
@@ -28,6 +28,7 @@ extern int ix86_frame_pointer_required (
 extern void ix86_setup_frame_addresses (void);
 
 extern void ix86_file_end (void);
+extern void ix86_elf_file_end (void);
 extern HOST_WIDE_INT ix86_initial_elimination_offset (int, int);
 extern void ix86_expand_prologue (void);
 extern void ix86_expand_epilogue (int);
--- gcc/config/i386/i386.c.global	2005-02-27 22:26:51.000000000 -0800
+++ gcc/config/i386/i386.c	2005-02-28 13:09:58.402099944 -0800
@@ -3937,6 +3937,13 @@ ix86_file_end (void)
     file_end_indicate_exec_stack ();
 }
 
+void
+ix86_elf_file_end (void)
+{
+  ix86_file_end ();
+  default_elf_asm_file_end ();
+}
+
 /* Emit code for the SET_GOT patterns.  */
 
 const char *
--- gcc/config/i386/linux.h.global	2004-11-28 17:04:42.000000000 -0800
+++ gcc/config/i386/linux.h	2005-02-28 13:12:28.068734976 -0800
@@ -185,3 +185,6 @@ Boston, MA 02111-1307, USA.  */
 
 /* This macro may be overridden in i386/k*bsd-gnu.h.  */
 #define REG_NAME(reg) reg
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END ix86_elf_file_end
--- gcc/config/i386/linux64.h.global	2004-11-28 17:04:42.000000000 -0800
+++ gcc/config/i386/linux64.h	2005-02-28 13:22:53.285839795 -0800
@@ -73,3 +73,6 @@ Boston, MA 02111-1307, USA.  */
 
 /* This macro may be overridden in i386/k*bsd-gnu.h.  */
 #define REG_NAME(reg) reg
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END ix86_elf_file_end
--- gcc/config/ia64/hpux.h.global	2005-02-27 22:10:57.000000000 -0800
+++ gcc/config/ia64/hpux.h	2005-02-28 11:28:57.000000000 -0800
@@ -152,10 +152,6 @@ do {								\
    definitions, so do not use them in gthr-posix.h.  */
 #define GTHREAD_USE_WEAK 0
 
-/* Put out the needed function declarations at the end.  */
-
-#define TARGET_ASM_FILE_END ia64_hpux_file_end
-
 #undef CTORS_SECTION_ASM_OP
 #define CTORS_SECTION_ASM_OP  "\t.section\t.init_array,\t\"aw\",\"init_array\""
 
--- gcc/config/ia64/ia64.c.global	2005-02-23 11:26:35.000000000 -0800
+++ gcc/config/ia64/ia64.c	2005-02-28 13:37:55.304919908 -0800
@@ -248,6 +248,7 @@ static void bundling (FILE *, int, rtx, 
 static void ia64_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
 				  HOST_WIDE_INT, tree);
 static void ia64_file_start (void);
+static void ia64_file_end (void);
 
 static void ia64_select_rtx_section (enum machine_mode, rtx,
 				     unsigned HOST_WIDE_INT);
@@ -259,10 +260,6 @@ static void ia64_rwreloc_select_rtx_sect
 					     unsigned HOST_WIDE_INT)
      ATTRIBUTE_UNUSED;
 static unsigned int ia64_section_type_flags (tree, const char *, int);
-static void ia64_hpux_add_extern_decl (tree decl)
-     ATTRIBUTE_UNUSED;
-static void ia64_hpux_file_end (void)
-     ATTRIBUTE_UNUSED;
 static void ia64_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
 static void ia64_hpux_init_libfuncs (void)
@@ -374,6 +371,9 @@ static const struct attribute_spec ia64_
 #undef TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START ia64_file_start
 
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END ia64_file_end
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS ia64_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -4493,41 +4493,21 @@ ia64_secondary_reload_class (enum reg_cl
 void
 ia64_asm_output_external (FILE *file, tree decl, const char *name)
 {
-  int save_referenced;
-
-  /* GNU as does not need anything here, but the HP linker does need
-     something for external functions.  */
-
-  if (TARGET_GNU_AS
-      && (!TARGET_HPUX_LD
-	  || TREE_CODE (decl) != FUNCTION_DECL
-	  || strstr (name, "__builtin_") == name))
-    return;
-
   /* ??? The Intel assembler creates a reference that needs to be satisfied by
      the linker when we do this, so we need to be careful not to do this for
      builtin functions which have no library equivalent.  Unfortunately, we
      can't tell here whether or not a function will actually be called by
      expand_expr, so we pull in library functions even if we may not need
      them later.  */
-  if (! strcmp (name, "__builtin_next_arg")
-      || ! strcmp (name, "alloca")
-      || ! strcmp (name, "__builtin_constant_p")
-      || ! strcmp (name, "__builtin_args_info"))
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && ((TARGET_GNU_AS && strstr (name, "__builtin_") == name)
+	  || (!strcmp (name, "__builtin_next_arg")
+	      || ! strcmp (name, "alloca")
+	      || ! strcmp (name, "__builtin_constant_p")
+	      || ! strcmp (name, "__builtin_args_info"))))
     return;
 
-  if (TARGET_HPUX_LD)
-    ia64_hpux_add_extern_decl (decl);
-  else
-    {
-      /* assemble_name will set TREE_SYMBOL_REFERENCED, so we must save and
-         restore it.  */
-      save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl));
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-        ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
-      (*targetm.asm_out.globalize_label) (file, name);
-      TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced;
-    }
+  default_elf_asm_output_external_1 (decl);
 }
 
 /* Parse the -mfixed-range= option string.  */
@@ -8472,36 +8452,16 @@ ia64_hpux_function_arg_padding (enum mac
    return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
 }
 
-/* Linked list of all external functions that are to be emitted by GCC.
-   We output the name if and only if TREE_SYMBOL_REFERENCED is set in
-   order to avoid putting out names that are never really used.  */
-
-struct extern_func_list GTY(())
-{
-  struct extern_func_list *next;
-  tree decl;
-};
-
-static GTY(()) struct extern_func_list *extern_func_head;
-
-static void
-ia64_hpux_add_extern_decl (tree decl)
-{
-  struct extern_func_list *p = ggc_alloc (sizeof (struct extern_func_list));
-
-  p->decl = decl;
-  p->next = extern_func_head;
-  extern_func_head = p;
-}
-
 /* Print out the list of used global functions.  */
 
 static void
-ia64_hpux_file_end (void)
+ia64_file_end (void)
 {
-  struct extern_func_list *p;
+  struct extern_symbol_list *p;
+  int hpld = TARGET_HPUX_LD;
+  int gas = TARGET_GNU_AS;
 
-  for (p = extern_func_head; p; p = p->next)
+  for (p = extern_symbol_head; p; p = p->next)
     {
       tree decl = p->decl;
       tree id = DECL_ASSEMBLER_NAME (decl);
@@ -8510,18 +8470,27 @@ ia64_hpux_file_end (void)
 	abort ();
 
       if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id))
-        {
+	{
+	  int vis = maybe_assemble_visibility (decl);
 	  const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
 
+	  /* GNU as does not need anything here, but the HP linker
+	     does need something for external functions.  */
+	  if ((hpld || !gas)
+	      && TREE_CODE (decl) == FUNCTION_DECL)
+	    {
+	      ASM_OUTPUT_TYPE_DIRECTIVE (asm_out_file, name,
+					 "function");
+	      (*targetm.asm_out.globalize_label) (asm_out_file, name);
+	    }
+	  else if (vis && !gas)
+	    (*targetm.asm_out.globalize_label) (asm_out_file, name);
+
 	  TREE_ASM_WRITTEN (decl) = 1;
-	  (*targetm.asm_out.globalize_label) (asm_out_file, name);
-	  fputs (TYPE_ASM_OP, asm_out_file);
-	  assemble_name (asm_out_file, name);
-	  fprintf (asm_out_file, "," TYPE_OPERAND_FMT "\n", "function");
         }
     }
 
-  extern_func_head = 0;
+  extern_symbol_head = 0;
 }
 
 /* Set SImode div/mod functions, init_integral_libfuncs only initializes
--- gcc/output.h.global	2005-01-19 09:55:57.000000000 -0800
+++ gcc/output.h	2005-02-28 13:20:05.017611574 -0800
@@ -517,6 +517,23 @@ extern void default_file_start (void);
 extern void file_end_indicate_exec_stack (void);
 extern bool default_valid_pointer_mode (enum machine_mode);
 
+/* Linked list of all external symbols that are to be emitted by
+   GCC.  */
+
+struct extern_symbol_list GTY(())
+{
+  struct extern_symbol_list *next;
+  tree decl;
+};
+
+extern GTY(()) struct extern_symbol_list *extern_symbol_head;
+
+extern void default_elf_asm_output_external (FILE *file, tree,
+					     const char *);
+extern void default_elf_asm_output_external_1 (tree);
+extern void default_elf_asm_file_end (void);
+extern int maybe_assemble_visibility (tree);
+
 extern int default_address_cost (rtx);
 
 /* dbxout helper functions */
--- gcc/varasm.c.global	2005-02-27 22:26:51.000000000 -0800
+++ gcc/varasm.c	2005-02-28 13:17:40.865263064 -0800
@@ -137,7 +137,6 @@ static unsigned HOST_WIDE_INT array_size
 static unsigned min_align (unsigned, unsigned);
 static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int);
 static void globalize_decl (tree);
-static void maybe_assemble_visibility (tree);
 static int in_named_entry_eq (const void *, const void *);
 static hashval_t in_named_entry_hash (const void *);
 #ifdef BSS_SECTION_ASM_OP
@@ -4535,13 +4534,18 @@ default_assemble_visibility (tree decl, 
 
 /* A helper function to call assemble_visibility when needed for a decl.  */
 
-static void
+int
 maybe_assemble_visibility (tree decl)
 {
   enum symbol_visibility vis = DECL_VISIBILITY (decl);
 
   if (vis != VISIBILITY_DEFAULT)
-    targetm.asm_out.visibility (decl, vis);
+    {
+      targetm.asm_out.visibility (decl, vis);
+      return 1;
+    }
+  else
+    return 0;
 }
 
 /* Returns 1 if the target configuration supports defining public symbols
@@ -5360,4 +5364,62 @@ file_end_indicate_exec_stack (void)
   named_section_flags (".note.GNU-stack", flags);
 }
 
+struct extern_symbol_list *extern_symbol_head;
+
+void
+default_elf_asm_output_external_1 (tree decl)
+{
+  struct extern_symbol_list *p
+    = ggc_alloc (sizeof (struct extern_symbol_list));
+
+  p->decl = decl;
+  p->next = extern_symbol_head;
+  extern_symbol_head = p;
+}
+
+/* Emit text to declare externally defined symbols. It is needed to
+   properly support non-default visibility.  */
+
+void
+default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED,
+				 tree decl,
+				 const char *name)
+{
+  /* Ignore builtin functions.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && strstr (name, "__builtin_") == name)
+    return;
+  else 
+    default_elf_asm_output_external_1 (decl);
+}
+
+/* Print out the list of referenced global symbols with non-default
+   visibility.  */
+
+void
+default_elf_asm_file_end (void)
+{
+  struct extern_symbol_list *p;
+
+  for (p = extern_symbol_head; p; p = p->next)
+    {
+      tree decl = p->decl;
+      tree id = DECL_ASSEMBLER_NAME (decl);
+
+      if (!id)
+	abort ();
+
+      /* We output the name if and only if TREE_SYMBOL_REFERENCED is
+	 set in order to avoid putting out names that are never really
+	 used.  */
+      if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id))
+	{
+	  maybe_assemble_visibility (decl);
+	  TREE_ASM_WRITTEN (decl) = 1;
+	}
+    }
+
+  extern_symbol_head = 0;
+}
+
 #include "gt-varasm.h"


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