PATCH: Use COMDAT section group instead of gnu.linkonce

H. J. Lu hjl@lucon.org
Wed May 5 20:22:00 GMT 2004


On Wed, May 05, 2004 at 12:19:38PM -0700, Zack Weinberg wrote:
> "H. J. Lu" <hjl@lucon.org> writes:
> 
> >> Uh, surely there is a better way to do this than a long chain of
> >> strcmp() operations on the linkonce section name?
> >> 
> >
> > I want to keep my change to minimal and support existing source code.
> 
> Support existing source code, fine.  Minimal, no, not necessary; this
> is stage 1 development.
> 
> Unfortunately I don't know this part of GCC well enough to offer
> constructive advice.
> 

Here is an update. I fixed a few bugs in elf_comdat_group and removed
some strncmp. Glibc has some thing like

	const int r __attribute__((section(".gnu.linkonce.r.r")));

in C and

	.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits

in assembly. Since I had to change assembly code, I guess I can also
change C code.

If we don't need C source code compatibility, I will try to come up
with something better.

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

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

	* output.h (elf_comdat_group): New.

	* varasm.c (elf_comdat_group): New.
	(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-05-05 08:23:28.000000000 -0700
+++ gcc/config.in	2004-05-03 17:37:05.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-05-05 08:35:46.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-05-05 08:39:07.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-05-03 17:36:55.000000000 -0700
+++ gcc/configure.ac	2004-05-03 17:36:57.000000000 -0700
@@ -2054,6 +2054,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/output.h.comdat	2004-03-26 09:25:41.000000000 -0800
+++ gcc/output.h	2004-05-05 12:25:23.000000000 -0700
@@ -475,6 +475,8 @@ 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 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-05-05 12:30:37.000000000 -0700
@@ -4650,16 +4650,98 @@ 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 +4757,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 +4784,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);
 }
 



More information about the Gcc-patches mailing list