public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PATCH: PR c++/16276: Group jump table with function
@ 2004-07-09 19:40 H. J. Lu
  2004-07-09 21:32 ` Richard Henderson
  0 siblings, 1 reply; 3+ messages in thread
From: H. J. Lu @ 2004-07-09 19:40 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 962 bytes --]

This patch tries to implement comdat group to properly fix the
second testcase in PR 16276.  There are still a few issues:

1. The latest binutils is needed. The current binutils in CVS doesn't
support mixing comdat and linkonce:

http://sources.redhat.com/bugzilla/show_bug.cgi?id=246

I do have a patch to fix it. It will be tricky to check if binutils is
OK.

2. It uses string functions to convert the linkonce section name into
comdat group. The interface isn't very elegant. But its advantages are

	a. Minimum change for gcc. Gcc supports more than ELF while
	comdat group is ELF specific.
	b. Section name is very significant in gcc. It is used for
	code generation among others. Also we may have to keep
	the same section naming scheme to support
	
		__attribute__ ((section (".foo")))

	Introducing a parallel section naming scheme for comdat group
	may be problematic.
	c. It is easy to put a section into a group by giving it the
	right name.


H.J.

[-- Attachment #2: gcc-3.4-comdat-7.patch --]
[-- Type: text/plain, Size: 19023 bytes --]

2004-07-08  H.J. Lu  <hongjiu.lu@intel.com>

	PR c++/16276
	* gcc/config/arm/arm.c (arm_elf_asm_named_section): Removed.
	(arm_elf_section): New.

	* config/arm/elf.h (TARGET_ASM_NAMED_SECTION): Removed.
	(TARGET_ASM_ELF_SECTION): defined.

	* config/sparc/sysv4.h (TARGET_ASM_NAMED_SECTION): Define only
	if HAVE_GAS_COMDAT_GROUP is not defined.

	* configure.ac: Check if assembler supports COMDAT group. 
	* configure: Regenerated.
	* config.in: Likewise.

	* doc/tm.texi (TARGET_ASM_NAMED_SECTION): Remove @var{align}.
	(TARGET_ASM_ELF_SECTION): Documented.

	* final.c (PUT_JUMP_TABLES_IN_TEXT_SECTION): New.
	(shorten_branches): Replace JUMP_TABLES_IN_TEXT_SECTION with
	PUT_JUMP_TABLES_IN_TEXT_SECTION.
	(final_scan_insn): Likewise.
	Call readonly_data_section_in_function_group instead of
	readonly_data_section if HAVE_GAS_COMDAT_GROUP is defined.

	* output.h (readonly_data_section_in_function_group): New
	prototype.
	(default_no_elf_section): Likewise.
	(default_elf_section): Likewise.

	* target-def.h (TARGET_ASM_ELF_SECTION): New.
	(TARGET_ASM_OUT): Add TARGET_ASM_ELF_SECTION.

	* target.h (asm_out): Add elf_section.

	* varasm.c (readonly_data_section_in_function_group): New.
	(default_no_elf_section): Likewise.
	(default_elf_section): Likewise.
	(elf_comdat_group): New.
	(default_elf_asm_named_section): Use COMDAT group if
	HAVE_GAS_COMDAT_GROUP is defined. Call
	targetm.asm_out.elf_section to output section directive.

--- gcc/config.in.comdat	2004-07-09 08:17:39.883292734 -0700
+++ gcc/config.in	2004-07-09 08:17:39.964282240 -0700
@@ -252,6 +252,9 @@
 /* Define if your assembler supports .balign and .p2align. */
 #undef HAVE_GAS_BALIGN_AND_P2ALIGN
 
+/* Define 0/1 if your assembler supports COMDAT group. */
+#undef HAVE_GAS_COMDAT_GROUP
+
 /* Define if your assembler uses the new HImode fild and fist notation. */
 #undef HAVE_GAS_FILDS_FISTS
 
--- gcc/config/arm/arm.c.comdat	2004-04-30 10:36:39.000000000 -0700
+++ gcc/config/arm/arm.c	2004-07-09 09:40:32.000000000 -0700
@@ -138,7 +138,9 @@ static rtx arm_expand_unop_builtin (enum
 static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
 
 #ifdef OBJECT_FORMAT_ELF
-static void arm_elf_asm_named_section (const char *, unsigned int);
+static void arm_elf_section (const char *, const char *,
+			     const char *, int,
+			     const char *, const char *);
 #endif
 #ifndef ARM_PE
 static void arm_encode_section_info (tree, rtx, int);
@@ -13145,57 +13147,30 @@ aof_file_end (void)
 #endif /* AOF_ASSEMBLER */
 
 #ifdef OBJECT_FORMAT_ELF
-/* Switch to an arbitrary section NAME with attributes as specified
-   by FLAGS.  ALIGN specifies any known alignment requirements for
-   the section; 0 if the default should be used.
+/* Output ELF section directive specified by NAME, FLAGS, TYPE,
+   ENTSIZE, GROUPNAME and LINKAGE in
 
-   Differs from the default elf version only in the prefix character
-   used before the section type.  */
+   .section NAME,"FLAGS",%TYPE,ENTSIZE,GROUPNAME,LINKAGE
 
+ */
 static void
-arm_elf_asm_named_section (const char *name, unsigned int flags)
-{
-  char flagchars[10], *f = flagchars;
-
-  if (! named_section_first_declaration (name))
-    {
-      fprintf (asm_out_file, "\t.section\t%s\n", name);
-      return;
-    }
-
-  if (!(flags & SECTION_DEBUG))
-    *f++ = 'a';
-  if (flags & SECTION_WRITE)
-    *f++ = 'w';
-  if (flags & SECTION_CODE)
-    *f++ = 'x';
-  if (flags & SECTION_SMALL)
-    *f++ = 's';
-  if (flags & SECTION_MERGE)
-    *f++ = 'M';
-  if (flags & SECTION_STRINGS)
-    *f++ = 'S';
-  if (flags & SECTION_TLS)
-    *f++ = 'T';
-  *f = '\0';
-
-  fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
-
-  if (!(flags & SECTION_NOTYPE))
-    {
-      const char *type;
-
-      if (flags & SECTION_BSS)
-	type = "nobits";
-      else
-	type = "progbits";
-
-      fprintf (asm_out_file, ",%%%s", type);
-
-      if (flags & SECTION_ENTSIZE)
-	fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
+arm_elf_section (const char *name, const char *flags,
+		 const char *type, int entsize,
+		 const char *groupname, const char *linkage)
+{
+  fprintf (asm_out_file, "\t.section\t%s", name);
+  if (flags)
+    fprintf (asm_out_file, ",\"%s\"", flags);
+  if (type)
+    fprintf (asm_out_file, ",%%%s", type);
+  if (entsize)
+    fprintf (asm_out_file, ",%d", entsize);
+  if (groupname)
+    {
+      fprintf (asm_out_file, ",%s", groupname);
+      if (linkage)
+	fprintf (asm_out_file, ",%s", linkage);
     }
-
   putc ('\n', asm_out_file);
 }
 #endif
--- gcc/config/arm/elf.h.comdat	2004-02-26 13:55:16.000000000 -0800
+++ gcc/config/arm/elf.h	2004-07-09 09:26:20.000000000 -0700
@@ -117,8 +117,8 @@
 #define TARGET_ASM_FILE_START_APP_OFF true
 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
 \f
-#undef  TARGET_ASM_NAMED_SECTION
-#define TARGET_ASM_NAMED_SECTION  arm_elf_asm_named_section
+#undef  TARGET_ASM_ELF_SECTION
+#define TARGET_ASM_ELF_SECTION  arm_elf_section
 \f
 
 /* For PIC code we need to explicitly specify (PLT) and (GOT) relocs.  */
--- gcc/config/sparc/sysv4.h.comdat	2003-06-17 17:03:32.000000000 -0700
+++ gcc/config/sparc/sysv4.h	2004-07-09 08:17:40.000000000 -0700
@@ -150,9 +150,13 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == 
 #undef DTORS_SECTION_ASM_OP
 #define DTORS_SECTION_ASM_OP    "\t.section\t\".dtors\",#alloc,#write"
 
+/* COMDAT group cannot be expressed in SPARC's section attributes
+   encoding style.  */
+#ifndef HAVE_GAS_COMDAT_GROUP
 /* Switch into a generic section.  */
 #undef TARGET_ASM_NAMED_SECTION
 #define TARGET_ASM_NAMED_SECTION  sparc_elf_asm_named_section
+#endif
 
 #undef ASM_OUTPUT_ALIGNED_BSS
 #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
--- gcc/configure.ac.comdat	2004-07-09 08:17:39.942285090 -0700
+++ gcc/configure.ac	2004-07-09 08:17:40.012276021 -0700
@@ -2070,6 +2070,13 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_MERGE,
   [`if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`],
 [Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.])
 
+gcc_GAS_CHECK_FEATURE(COMDAT group support, gcc_cv_as_comdat_group,
+ [elf,2,15,91], [--fatal-warnings],
+ [.section .text,"axG",@progbits,.foo,comdat])
+AC_DEFINE_UNQUOTED(HAVE_GAS_COMDAT_GROUP,
+  [`if test $gcc_cv_as_comdat_group = yes; then echo 1; else echo 0; fi`],
+[Define 0/1 if your assembler supports COMDAT group.])
+
 # Thread-local storage - the check is heavily parametrized.
 conftest_s=
 tls_first_major=
--- gcc/doc/tm.texi.comdat	2004-07-06 16:18:10.000000000 -0700
+++ gcc/doc/tm.texi	2004-07-09 09:03:26.740352255 -0700
@@ -6206,14 +6206,16 @@ A C statement to output something to the
 macro is not defined, nothing is output for a @samp{#ident} directive.
 @end defmac
 
-@deftypefn {Target Hook} void TARGET_ASM_NAMED_SECTION (const char *@var{name}, unsigned int @var{flags}, unsigned int @var{align})
+@deftypefn {Target Hook} void TARGET_ASM_NAMED_SECTION (const char *@var{name}, unsigned int @var{flags})
 Output assembly directives to switch to section @var{name}.  The section
 should have attributes as specified by @var{flags}, which is a bit mask
-of the @code{SECTION_*} flags defined in @file{output.h}.  If @var{align}
-is nonzero, it contains an alignment in bytes to be used for the section,
-otherwise some target default should be used.  Only targets that must
-specify an alignment within the section directive need pay attention to
-@var{align} -- we will still use @code{ASM_OUTPUT_ALIGN}.
+of the @code{SECTION_*} flags defined in @file{output.h}.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_ASM_ELF_SECTION (const char *@var{name}, const char *@var{flags}, const char *@var{type}, int @var{entsize}, const char *@var{groupname}, const char *@var{linkage})
+Output assembly ELF section directives for specified by @var{name},
+@var{flags}, @var{type}, @var{entsize}, @var{groupname} and
+@var{linkage}.
 @end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_HAVE_NAMED_SECTIONS
--- gcc/final.c.comdat	2004-02-23 13:24:09.000000000 -0800
+++ gcc/final.c	2004-07-09 08:17:40.040272393 -0700
@@ -105,6 +105,13 @@ Software Foundation, 59 Temple Place - S
 #define JUMP_TABLES_IN_TEXT_SECTION 0
 #endif
 
+#ifdef HAVE_GAS_COMDAT_GROUP
+#define PUT_JUMP_TABLES_IN_TEXT_SECTION JUMP_TABLES_IN_TEXT_SECTION
+#else
+#define PUT_JUMP_TABLES_IN_TEXT_SECTION \
+  (JUMP_TABLES_IN_TEXT_SECTION || DECL_ONE_ONLY (current_function_decl))
+#endif
+
 #if defined(READONLY_DATA_SECTION) || defined(READONLY_DATA_SECTION_ASM_OP)
 #define HAVE_READONLY_DATA_SECTION 1
 #else
@@ -835,7 +842,8 @@ shorten_branches (rtx first ATTRIBUTE_UN
 	  next = NEXT_INSN (insn);
 	  /* ADDR_VECs only take room if read-only data goes into the text
 	     section.  */
-	  if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
+	  if (PUT_JUMP_TABLES_IN_TEXT_SECTION
+	      || !HAVE_READONLY_DATA_SECTION)
 	    if (next && GET_CODE (next) == JUMP_INSN)
 	      {
 		rtx nextbody = PATTERN (next);
@@ -998,7 +1006,8 @@ shorten_branches (rtx first ATTRIBUTE_UN
 	{
 	  /* This only takes room if read-only data goes into the text
 	     section.  */
-	  if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
+	  if (PUT_JUMP_TABLES_IN_TEXT_SECTION
+	      || !HAVE_READONLY_DATA_SECTION)
 	    insn_lengths[uid] = (XVECLEN (body,
 					  GET_CODE (body) == ADDR_DIFF_VEC)
 				 * GET_MODE_SIZE (GET_MODE (body)));
@@ -1199,7 +1208,8 @@ shorten_branches (rtx first ATTRIBUTE_UN
 	      PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
 							max_addr - rel_addr,
 							body));
-	      if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
+	      if (PUT_JUMP_TABLES_IN_TEXT_SECTION
+		  || !HAVE_READONLY_DATA_SECTION)
 		{
 		  insn_lengths[uid]
 		    = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
@@ -1877,11 +1887,16 @@ final_scan_insn (rtx insn, FILE *file, i
 		 target, so don't output the label at all.  Leave that
 		 to the back end macros.  */
 #else
-	      if (! JUMP_TABLES_IN_TEXT_SECTION)
+	      if (! PUT_JUMP_TABLES_IN_TEXT_SECTION)
 		{
 		  int log_align;
 
+#ifdef HAVE_GAS_COMDAT_GROUP
+		  readonly_data_section_in_function_group
+		    (current_function_decl);
+#else
 		  readonly_data_section ();
+#endif
 
 #ifdef ADDR_VEC_ALIGN
 		  log_align = ADDR_VEC_ALIGN (NEXT_INSN (insn));
--- gcc/output.h.comdat	2004-03-26 09:25:41.000000000 -0800
+++ gcc/output.h	2004-03-26 09:25:41.000000000 -0800
@@ -475,6 +475,7 @@ extern void no_asm_to_stream (FILE *);
 #define SECTION_NOTYPE	 0x80000	/* don't output @progbits */
 #define SECTION_MACH_DEP 0x100000	/* subsequent bits reserved for target */
 
+extern void readonly_data_section_in_function_group (tree);
 extern unsigned int get_named_section_flags (const char *);
 extern bool set_named_section_flags (const char *, unsigned int);
 extern void named_section_flags (const char *, unsigned int);
@@ -487,6 +488,13 @@ extern void default_elf_asm_named_sectio
 extern void default_coff_asm_named_section (const char *, unsigned int);
 extern void default_pe_asm_named_section (const char *, unsigned int);
 
+extern void default_no_elf_section (const char *, const char *,
+				    const char *, int,
+				    const char *, const char *);
+extern void default_elf_section (const char *, const char *,
+				 const char *, int,
+				 const char *, const char *);
+
 extern void default_stabs_asm_out_destructor (rtx, int);
 extern void default_named_section_asm_out_destructor (rtx, int);
 extern void default_dtor_section_asm_out_destructor (rtx, int);
--- gcc/target-def.h.comdat	2004-03-16 08:52:57.000000000 -0800
+++ gcc/target-def.h	2004-07-09 08:51:33.337795670 -0700
@@ -124,6 +124,14 @@ Foundation, 59 Temple Place - Suite 330,
 #define TARGET_HAVE_NAMED_SECTIONS false
 #endif
 
+#ifndef TARGET_ASM_ELF_SECTION
+# ifdef OBJECT_FORMAT_ELF
+#  define TARGET_ASM_ELF_SECTION default_elf_section
+# else
+#  define TARGET_ASM_ELF_SECTION default_no_elf_section
+# endif
+#endif
+
 #ifndef TARGET_HAVE_TLS
 #define TARGET_HAVE_TLS false
 #endif
@@ -196,6 +204,7 @@ Foundation, 59 Temple Place - Suite 330,
 			TARGET_ASM_FUNCTION_BEGIN_EPILOGUE,	\
 			TARGET_ASM_FUNCTION_EPILOGUE,		\
 			TARGET_ASM_NAMED_SECTION,		\
+			TARGET_ASM_ELF_SECTION,			\
 			TARGET_ASM_EXCEPTION_SECTION,		\
 			TARGET_ASM_EH_FRAME_SECTION,		\
 			TARGET_ASM_SELECT_SECTION,		\
--- gcc/target.h.comdat	2004-03-16 08:52:57.000000000 -0800
+++ gcc/target.h	2004-07-09 09:03:44.668029169 -0700
@@ -97,6 +97,11 @@ struct gcc_target
        specified by FLAGS.  */
     void (* named_section) (const char *, unsigned int);
 
+    /* Output ELF section directive specified by NAME, FLAGS, TYPE,
+       ENTSIZE, GROUPNAME and LINKAGE.  */
+    void (* elf_section) (const char *, const char *, const char *,
+			  int, const char *, const char *);
+
     /* Switch to the section that holds the exception table.  */
     void (* exception_section) (void);
 
--- gcc/varasm.c.comdat	2004-04-16 16:59:51.000000000 -0700
+++ gcc/varasm.c	2004-04-16 16:59:51.000000000 -0700
@@ -180,6 +180,8 @@ static bool asm_emit_uninitialised (tree
 				    unsigned HOST_WIDE_INT,
 				    unsigned HOST_WIDE_INT);
 static void mark_weak (tree);
+static const char * elf_comdat_group (const char *, const char **,
+				      const char **);
 \f
 enum in_section { no_section, in_text, in_data, in_named
 #ifdef BSS_SECTION_ASM_OP
@@ -259,6 +261,49 @@ data_section (void)
     }
 }
 
+#ifdef HAVE_GAS_COMDAT_GROUP
+
+/* Tell assembler to switch to read-only data section in the same
+   comdat group as DECL.  */
+
+void
+readonly_data_section_in_function_group (tree decl)
+{
+  if (decl == NULL_TREE || !DECL_P (decl))
+    abort ();
+
+  if (DECL_SECTION_NAME (decl) == NULL_TREE
+      || ! DECL_ONE_ONLY (current_function_decl))
+    readonly_data_section ();
+  else
+#ifdef READONLY_DATA_SECTION_IN_FUNCTION_GROUP 
+    READONLY_DATA_SECTION_IN_FUNCTION_GROUP (decl);
+#else
+    {
+      char *rodata;
+      const char *section_name, *group_name;
+      const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+
+      if (!elf_comdat_group (name, &section_name, &group_name)
+	  || strcmp (section_name, ".text"))
+	abort ();
+
+      rodata = xmalloc (strlen (name) + 1);
+      rodata [sizeof (".gnu.linkonce.t") - 2] = 'r';
+      if (in_section != in_named
+	  || strcmp (rodata, in_named_name) != 0)
+	{
+	  in_named_name = ggc_strdup (rodata);
+	  in_section = in_named;
+	  (*targetm.asm_out.elf_section) (".rodata", "aG", "progbits",
+					  0, group_name, "comdat");
+	}
+      free (rodata);
+    }
+#endif
+}
+#endif
+
 /* Tell assembler to switch to read-only data section.  This is normally
    the text section.  */
 
@@ -4638,6 +4683,20 @@ default_section_type_flags_1 (tree decl,
   return flags;
 }
 
+/* Output ELF section directive specified by NAME, FLAGS, TYPE,
+   ENTSIZE, GROUPNAME and LINKAGE.  */
+
+void
+default_no_elf_section (const char *name ATTRIBUTE_UNUSED,
+			const char *flags ATTRIBUTE_UNUSED,
+			const char *type ATTRIBUTE_UNUSED,
+			int entsize ATTRIBUTE_UNUSED,
+			const char *groupname ATTRIBUTE_UNUSED,
+			const char *linkage ATTRIBUTE_UNUSED)
+{
+  abort ();
+}
+
 /* Output assembly to switch to section NAME with attribute FLAGS.
    Four variants for common object file formats.  */
 
@@ -4650,16 +4709,127 @@ default_no_named_section (const char *na
   abort ();
 }
 
+/* Output ELF section directive specified by NAME, FLAGS, TYPE,
+   ENTSIZE, GROUPNAME and LINKAGE in
+ 
+   .section NAME,"FLAGS",@TYPE,ENTSIZE,GROUPNAME,LINKAGE
+
+ */
+
+void
+default_elf_section (const char *name, const char *flags,
+		     const char *type, int entsize,
+		     const char *groupname, const char *linkage)
+{
+  fprintf (asm_out_file, "\t.section\t%s", name);
+  if (flags)
+    fprintf (asm_out_file, ",\"%s\"", flags);
+  if (type)
+    fprintf (asm_out_file, ",@%s", type);
+  if (entsize)
+    fprintf (asm_out_file, ",%d", entsize);
+  if (groupname)
+    {
+      fprintf (asm_out_file, ",%s", groupname);
+      if (linkage)
+	fprintf (asm_out_file, ",%s", linkage);
+    }
+  putc ('\n', asm_out_file);
+}
+
+/* Extract section name and group name from the linkonce section
+   name.  */
+
+static const char *
+elf_comdat_group (const char *name, const char **section,
+		  const char **group)
+{
+  const char *p;
+  const char *sec = NULL;
+  static const char *one [] = 
+    {
+      ".bss",		/* 'b'  */
+      NULL,		/* 'c'  */
+      ".data",		/* 'd'  */
+      NULL,		/* 'e'  */
+      NULL,		/* 'f'  */
+      NULL,		/* 'q'  */
+      NULL,		/* 'h'  */
+      NULL,		/* 'i'  */
+      NULL,		/* 'j'  */
+      NULL,		/* 'k'  */
+      NULL,		/* 'l'  */
+      NULL,		/* 'm'  */
+      NULL,		/* 'n'  */
+      NULL,		/* 'o'  */
+      NULL,		/* 'p'  */
+      NULL,		/* 'q'  */
+      ".rodata",	/* 'r'  */
+      ".sdata",		/* 's'  */
+      ".text"		/* 't'  */
+    };
+  
+  if (strncmp (name, ".gnu.linkonce.", 14) != 0)
+    return sec;
+
+  p = name + 14;
+  if (p [1] == '.')
+    {
+      if (p [0] > 'a' && p [0] < 'u')
+	sec = one [p [0] - 'b'];
+
+      if (sec)
+	*group = p + 1;
+    }
+  else if (p [2] == '.')
+    {
+      if (p [0] == 's')
+	{
+	  if (p [1] == '2')
+	    sec = ".sdata2";
+	  else if (p [1] == 'b')
+	    sec = ".sbss";
+	}
+      else if (p [0] == 't')
+	{
+	  if (p [1] == 'b')
+	    sec = ".tbss";
+	  else if (p [1] == 'd')
+	    sec = ".tdata";
+	}
+      else if (p [0] == 'w' && p [1] == 'i')
+	sec = ".debug_info";
+
+      if (sec)
+	*group = p + 2;
+    }
+  else if (strncmp (p, "sb2.", 4) == 0)
+    {
+      sec = ".sbss2";
+      *group = p + 3;
+    }
+
+  if (sec)
+    *section = sec;
+
+  return sec;
+}
+
 void
 default_elf_asm_named_section (const char *name, unsigned int flags)
 {
   char flagchars[10], *f = flagchars;
+  const char *section_name = NULL, *group_name = NULL;
+  const char *type = NULL;
+  int entsize = 0;
 
+#ifndef HAVE_GAS_COMDAT_GROUP
   if (! named_section_first_declaration (name))
     {
       fprintf (asm_out_file, "\t.section\t%s\n", name);
       return;
     }
+#endif
 
   if (!(flags & SECTION_DEBUG))
     *f++ = 'a';
@@ -4675,26 +4845,27 @@ default_elf_asm_named_section (const cha
     *f++ = 'S';
   if (flags & SECTION_TLS)
     *f++ = 'T';
+#ifdef HAVE_GAS_COMDAT_GROUP
+  if (elf_comdat_group (name, &section_name, &group_name))
+    *f++ = 'G';
+#endif
   *f = '\0';
 
-  fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
+  if (section_name)
+    name = section_name;
 
   if (!(flags & SECTION_NOTYPE))
     {
-      const char *type;
-
       if (flags & SECTION_BSS)
 	type = "nobits";
       else
 	type = "progbits";
-
-      fprintf (asm_out_file, ",@%s", type);
-
-      if (flags & SECTION_ENTSIZE)
-	fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
+      
+      entsize = flags & SECTION_ENTSIZE;
     }
-
-  putc ('\n', asm_out_file);
+  
+  (*targetm.asm_out.elf_section) (name, flagchars, type, entsize,
+				  group_name, "comdat");
 }
 
 void

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

* Re: PATCH: PR c++/16276: Group jump table with function
  2004-07-09 19:40 PATCH: PR c++/16276: Group jump table with function H. J. Lu
@ 2004-07-09 21:32 ` Richard Henderson
  2004-07-10  7:28   ` H. J. Lu
  0 siblings, 1 reply; 3+ messages in thread
From: Richard Henderson @ 2004-07-09 21:32 UTC (permalink / raw)
  To: H. J. Lu; +Cc: gcc-patches

On Fri, Jul 09, 2004 at 11:31:28AM -0700, H. J. Lu wrote:
> -  if (!(flags & SECTION_DEBUG))
> -    *f++ = 'a';
> -  if (flags & SECTION_WRITE)
> -    *f++ = 'w';
> -  if (flags & SECTION_CODE)
> -    *f++ = 'x';
> -  if (flags & SECTION_SMALL)
> -    *f++ = 's';
> -  if (flags & SECTION_MERGE)
> -    *f++ = 'M';
> -  if (flags & SECTION_STRINGS)
> -    *f++ = 'S';
> -  if (flags & SECTION_TLS)
> -    *f++ = 'T';
> -  *f = '\0';

I think you most certainly do not want to be pulling out the flags
as a string into the caller.  They do not line up 100% between the
targets.

> +#ifdef HAVE_GAS_COMDAT_GROUP
> +#define PUT_JUMP_TABLES_IN_TEXT_SECTION JUMP_TABLES_IN_TEXT_SECTION
> +#else
> +#define PUT_JUMP_TABLES_IN_TEXT_SECTION \
> +  (JUMP_TABLES_IN_TEXT_SECTION || DECL_ONE_ONLY (current_function_decl))
> +#endif

I think the !COMDAT case is wrong.

Suppose SUPPORTS_ONE_ONLY is false, but SUPPORTS_WEAK is true.  In that
case we don't actually have to worry about what section jump tables go in.

Suppose it's a strict harvard architecture machine.  In which case you 
can't go putting *any* data in the text section.

I think the only workable solution is to put all the private read-only
data for a function in an rodata linkonce section for the function.

> +#ifdef READONLY_DATA_SECTION_IN_FUNCTION_GROUP 
> +    READONLY_DATA_SECTION_IN_FUNCTION_GROUP (decl);
> +#else

Now I think you're inventing macros that no one will ever use.


r~

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

* Re: PATCH: PR c++/16276: Group jump table with function
  2004-07-09 21:32 ` Richard Henderson
@ 2004-07-10  7:28   ` H. J. Lu
  0 siblings, 0 replies; 3+ messages in thread
From: H. J. Lu @ 2004-07-10  7:28 UTC (permalink / raw)
  To: Richard Henderson, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1737 bytes --]

On Fri, Jul 09, 2004 at 01:54:29PM -0700, Richard Henderson wrote:
> On Fri, Jul 09, 2004 at 11:31:28AM -0700, H. J. Lu wrote:
> > -  if (!(flags & SECTION_DEBUG))
> > -    *f++ = 'a';
> > -  if (flags & SECTION_WRITE)
> > -    *f++ = 'w';
> > -  if (flags & SECTION_CODE)
> > -    *f++ = 'x';
> > -  if (flags & SECTION_SMALL)
> > -    *f++ = 's';
> > -  if (flags & SECTION_MERGE)
> > -    *f++ = 'M';
> > -  if (flags & SECTION_STRINGS)
> > -    *f++ = 'S';
> > -  if (flags & SECTION_TLS)
> > -    *f++ = 'T';
> > -  *f = '\0';
> 
> I think you most certainly do not want to be pulling out the flags
> as a string into the caller.  They do not line up 100% between the
> targets.

I changed readonly_data_section_in_function_group to call
named_section_flags instead.

> 
> > +#ifdef HAVE_GAS_COMDAT_GROUP
> > +#define PUT_JUMP_TABLES_IN_TEXT_SECTION JUMP_TABLES_IN_TEXT_SECTION
> > +#else
> > +#define PUT_JUMP_TABLES_IN_TEXT_SECTION \
> > +  (JUMP_TABLES_IN_TEXT_SECTION || DECL_ONE_ONLY (current_function_decl))
> > +#endif
> 
> I think the !COMDAT case is wrong.
> 
> Suppose SUPPORTS_ONE_ONLY is false, but SUPPORTS_WEAK is true.  In that
> case we don't actually have to worry about what section jump tables go in.
> 
> Suppose it's a strict harvard architecture machine.  In which case you 
> can't go putting *any* data in the text section.
> 
> I think the only workable solution is to put all the private read-only
> data for a function in an rodata linkonce section for the function.

OK.

> 
> > +#ifdef READONLY_DATA_SECTION_IN_FUNCTION_GROUP 
> > +    READONLY_DATA_SECTION_IN_FUNCTION_GROUP (decl);
> > +#else
> 
> Now I think you're inventing macros that no one will ever use.

Removed. Here is the new patch.


H.J.

[-- Attachment #2: gcc-3.4-comdat-9.patch --]
[-- Type: text/plain, Size: 8881 bytes --]

2004-07-09  H.J. Lu  <hongjiu.lu@intel.com>

	PR c++/16276
	* configure.ac: Check if assembler supports COMDAT group. 
	* configure: Regenerated.
	* config.in: Likewise.

	* final.c (final_scan_insn): When generating jump table, call
	readonly_data_section_in_function_group instead of
	readonly_data_section if HAVE_GAS_COMDAT_GROUP is defined.

	* output.h (elf_comdat_group): New.
	(readonly_data_section_in_function_group): Likewise.

	* varasm.c (readonly_data_section_in_function_group): New.
	(elf_comdat_group): Likewise.
	(default_elf_asm_named_section): Use COMDAT group if
	HAVE_GAS_COMDAT_GROUP is defined.
	* config/arm/arm.c (arm_elf_asm_named_section): Likewise.

	* config/sparc/sysv4.h (TARGET_ASM_NAMED_SECTION): Define only
	if HAVE_GAS_COMDAT_GROUP is not defined.

--- gcc/config.in.comdat	2004-07-09 17:37:29.000000000 -0700
+++ gcc/config.in	2004-07-09 17:37:29.000000000 -0700
@@ -252,6 +252,9 @@
 /* Define if your assembler supports .balign and .p2align. */
 #undef HAVE_GAS_BALIGN_AND_P2ALIGN
 
+/* Define 0/1 if your assembler supports COMDAT group. */
+#undef HAVE_GAS_COMDAT_GROUP
+
 /* Define if your assembler uses the new HImode fild and fist notation. */
 #undef HAVE_GAS_FILDS_FISTS
 
--- gcc/config/arm/arm.c.comdat	2004-04-30 10:36:39.000000000 -0700
+++ gcc/config/arm/arm.c	2004-07-09 17:37:29.000000000 -0700
@@ -13156,12 +13156,15 @@ static void
 arm_elf_asm_named_section (const char *name, unsigned int flags)
 {
   char flagchars[10], *f = flagchars;
+  const char *section_name = NULL, *group_name = NULL;
 
+#ifndef HAVE_GAS_COMDAT_GROUP
   if (! named_section_first_declaration (name))
     {
       fprintf (asm_out_file, "\t.section\t%s\n", name);
       return;
     }
+#endif
 
   if (!(flags & SECTION_DEBUG))
     *f++ = 'a';
@@ -13177,9 +13180,17 @@ arm_elf_asm_named_section (const char *n
     *f++ = 'S';
   if (flags & SECTION_TLS)
     *f++ = 'T';
+#ifdef HAVE_GAS_COMDAT_GROUP
+  if (elf_comdat_group (name, &section_name, &group_name))
+    *f++ = 'G';
+#endif
   *f = '\0';
 
-  fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
+  if (section_name)
+    fprintf (asm_out_file, "\t.section\t%s,\"%s\"", section_name,
+	     flagchars);
+  else
+    fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
 
   if (!(flags & SECTION_NOTYPE))
     {
@@ -13196,6 +13207,9 @@ arm_elf_asm_named_section (const char *n
 	fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
     }
 
+  if (group_name)
+    fprintf (asm_out_file, ",%s,comdat", group_name);
+
   putc ('\n', asm_out_file);
 }
 #endif
--- gcc/config/sparc/sysv4.h.comdat	2003-06-17 17:03:32.000000000 -0700
+++ gcc/config/sparc/sysv4.h	2004-07-09 17:37:29.000000000 -0700
@@ -150,9 +150,13 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == 
 #undef DTORS_SECTION_ASM_OP
 #define DTORS_SECTION_ASM_OP    "\t.section\t\".dtors\",#alloc,#write"
 
+/* COMDAT group cannot be expressed in SPARC's section attributes
+   encoding style.  */
+#ifndef HAVE_GAS_COMDAT_GROUP
 /* Switch into a generic section.  */
 #undef TARGET_ASM_NAMED_SECTION
 #define TARGET_ASM_NAMED_SECTION  sparc_elf_asm_named_section
+#endif
 
 #undef ASM_OUTPUT_ALIGNED_BSS
 #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
--- gcc/configure.ac.comdat	2004-07-09 17:37:29.000000000 -0700
+++ gcc/configure.ac	2004-07-09 17:37:29.000000000 -0700
@@ -2070,6 +2070,13 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_MERGE,
   [`if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`],
 [Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.])
 
+gcc_GAS_CHECK_FEATURE(COMDAT group support, gcc_cv_as_comdat_group,
+ [elf,2,15,91], [--fatal-warnings],
+ [.section .text,"axG",@progbits,.foo,comdat])
+AC_DEFINE_UNQUOTED(HAVE_GAS_COMDAT_GROUP,
+  [`if test $gcc_cv_as_comdat_group = yes; then echo 1; else echo 0; fi`],
+[Define 0/1 if your assembler supports COMDAT group.])
+
 # Thread-local storage - the check is heavily parametrized.
 conftest_s=
 tls_first_major=
--- gcc/final.c.comdat	2004-02-23 13:24:09.000000000 -0800
+++ gcc/final.c	2004-07-09 17:38:25.000000000 -0700
@@ -1881,7 +1881,12 @@ final_scan_insn (rtx insn, FILE *file, i
 		{
 		  int log_align;
 
+#ifdef HAVE_GAS_COMDAT_GROUP
+		  readonly_data_section_in_function_group
+		    (current_function_decl);
+#else
 		  readonly_data_section ();
+#endif
 
 #ifdef ADDR_VEC_ALIGN
 		  log_align = ADDR_VEC_ALIGN (NEXT_INSN (insn));
--- gcc/output.h.comdat	2004-03-26 09:25:41.000000000 -0800
+++ gcc/output.h	2004-07-09 17:37:29.771404795 -0700
@@ -475,6 +475,9 @@ extern void no_asm_to_stream (FILE *);
 #define SECTION_NOTYPE	 0x80000	/* don't output @progbits */
 #define SECTION_MACH_DEP 0x100000	/* subsequent bits reserved for target */
 
+extern const char *elf_comdat_group (const char *, const char **,
+				     const char **);
+extern void readonly_data_section_in_function_group (tree);
 extern unsigned int get_named_section_flags (const char *);
 extern bool set_named_section_flags (const char *, unsigned int);
 extern void named_section_flags (const char *, unsigned int);
--- gcc/varasm.c.comdat	2004-04-16 16:59:51.000000000 -0700
+++ gcc/varasm.c	2004-07-09 18:12:27.804157508 -0700
@@ -259,6 +259,35 @@ data_section (void)
     }
 }
 
+#ifdef HAVE_GAS_COMDAT_GROUP
+
+/* Tell assembler to switch to read-only data section in the same
+   comdat group as DECL.  */
+
+void
+readonly_data_section_in_function_group (tree decl)
+{
+  if (decl == NULL_TREE || !DECL_P (decl))
+    abort ();
+
+  if (DECL_SECTION_NAME (decl) == NULL_TREE || ! DECL_ONE_ONLY (decl))
+    readonly_data_section ();
+  else
+    {
+      char *rodata;
+      const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+
+      if (strncmp (name, ".gnu.linkonce.t.", 16) != 0)
+	abort ();
+
+      rodata = xstrdup (name);
+      rodata [14] = 'r';
+      named_section_flags (rodata, 0);
+      free (rodata);
+    }
+}
+#endif
+
 /* Tell assembler to switch to read-only data section.  This is normally
    the text section.  */
 
@@ -4650,16 +4679,97 @@ default_no_named_section (const char *na
   abort ();
 }
 
+/* Extract section name and group name from the linkonce section
+   name.  */
+
+const char *
+elf_comdat_group (const char *name, const char **section,
+		  const char **group)
+{
+  const char *p;
+  const char *sec = NULL;
+  static const char *one [] = 
+    {
+      ".bss",		/* 'b'  */
+      NULL,		/* 'c'  */
+      ".data",		/* 'd'  */
+      NULL,		/* 'e'  */
+      NULL,		/* 'f'  */
+      NULL,		/* 'q'  */
+      NULL,		/* 'h'  */
+      NULL,		/* 'i'  */
+      NULL,		/* 'j'  */
+      NULL,		/* 'k'  */
+      NULL,		/* 'l'  */
+      NULL,		/* 'm'  */
+      NULL,		/* 'n'  */
+      NULL,		/* 'o'  */
+      NULL,		/* 'p'  */
+      NULL,		/* 'q'  */
+      ".rodata",	/* 'r'  */
+      ".sdata",		/* 's'  */
+      ".text"		/* 't'  */
+    };
+  
+  if (strncmp (name, ".gnu.linkonce.", 14) != 0)
+    return sec;
+
+  p = name + 14;
+  if (p [1] == '.')
+    {
+      if (p [0] > 'a' && p [0] < 'u')
+	sec = one [p [0] - 'b'];
+
+      if (sec)
+	*group = p + 1;
+    }
+  else if (p [2] == '.')
+    {
+      if (p [0] == 's')
+	{
+	  if (p [1] == '2')
+	    sec = ".sdata2";
+	  else if (p [1] == 'b')
+	    sec = ".sbss";
+	}
+      else if (p [0] == 't')
+	{
+	  if (p [1] == 'b')
+	    sec = ".tbss";
+	  else if (p [1] == 'd')
+	    sec = ".tdata";
+	}
+      else if (p [0] == 'w' && p [1] == 'i')
+	sec = ".debug_info";
+
+      if (sec)
+	*group = p + 2;
+    }
+  else if (strncmp (p, "sb2.", 4) == 0)
+    {
+      sec = ".sbss2";
+      *group = p + 3;
+    }
+
+  if (sec)
+    *section = sec;
+
+  return sec;
+}
+
 void
 default_elf_asm_named_section (const char *name, unsigned int flags)
 {
   char flagchars[10], *f = flagchars;
+  const char *section_name = NULL, *group_name = NULL;
 
+#ifndef HAVE_GAS_COMDAT_GROUP
   if (! named_section_first_declaration (name))
     {
       fprintf (asm_out_file, "\t.section\t%s\n", name);
       return;
     }
+#endif
 
   if (!(flags & SECTION_DEBUG))
     *f++ = 'a';
@@ -4675,9 +4785,17 @@ default_elf_asm_named_section (const cha
     *f++ = 'S';
   if (flags & SECTION_TLS)
     *f++ = 'T';
+#ifdef HAVE_GAS_COMDAT_GROUP
+  if (elf_comdat_group (name, &section_name, &group_name))
+    *f++ = 'G';
+#endif
   *f = '\0';
 
-  fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
+  if (section_name)
+    fprintf (asm_out_file, "\t.section\t%s,\"%s\"", section_name,
+	     flagchars);
+  else
+    fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
 
   if (!(flags & SECTION_NOTYPE))
     {
@@ -4694,6 +4812,9 @@ default_elf_asm_named_section (const cha
 	fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
     }
 
+  if (group_name)
+    fprintf (asm_out_file, ",%s,comdat", group_name);
+
   putc ('\n', asm_out_file);
 }
 

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

end of thread, other threads:[~2004-07-10  3:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-09 19:40 PATCH: PR c++/16276: Group jump table with function H. J. Lu
2004-07-09 21:32 ` Richard Henderson
2004-07-10  7:28   ` H. J. Lu

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