PATCH: PR c++/16276: Group jump table with function

H. J. Lu hjl@lucon.org
Sat Jul 10 07:28:00 GMT 2004


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.
-------------- next part --------------
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);
 }
 


More information about the Gcc-patches mailing list