Commit b20577ea by Iain Sandoe

re PR target/48108 (lto should be containerized in a single mach-o section on darwin)


gcc:

	PR target/48108
	* config/darwin.c (top level): Amend comments concerning LTO output.
	(lto_section_num): New variable.  (darwin_lto_section_e): New GTY.
	(LTO_SECTS_SECTION, LTO_INDEX_SECTION): New.
	(LTO_NAMES_SECTION): Rename.
	(darwin_asm_named_section): Record LTO section counts and switches
	in a vec of darwin_lto_section_e.
	(darwin_file_start): Remove unused code.
	(darwin_file_end): Put an LTO section termination label.  Handle
	output of the wrapped LTO sections, index and names table.

libiberty:

	PR target/48108
	* simple-object-mach-o.c  (GNU_WRAPPER_SECTS, GNU_WRAPPER_INDEX,
	GNU_WRAPPER_NAMES): New macros.
	(simple_object_mach_o_segment): Handle wrapper scheme.
	(simple_object_mach_o_write_section_header): Allow the segment name
	to be supplied.
	(simple_object_mach_o_write_segment): Handle wrapper scheme.  Ensure
	that the top-level segment name in the load command is empty.
	(simple_object_mach_o_write_to_file): Determine the number of
	sections during segment output, use that in writing the header.

From-SVN: r180523
parent d44b26bd
2011-10-14 Iain Sandoe <iains@gcc.gnu.org>
PR target/48108
* config/darwin.c (top level): Amend comments concerning LTO output.
(lto_section_num): New variable. (darwin_lto_section_e): New GTY.
(LTO_SECTS_SECTION, LTO_INDEX_SECTION): New.
(LTO_NAMES_SECTION): Rename.
(darwin_asm_named_section): Record LTO section counts and switches
in a vec of darwin_lto_section_e.
(darwin_file_start): Remove unused code.
(darwin_file_end): Put an LTO section termination label. Handle
output of the wrapped LTO sections, index and names table.
2011-10-26 Alan Modra <amodra@gmail.com> 2011-10-26 Alan Modra <amodra@gmail.com>
* config/rs6000/rs6000.c (rs6000_make_savres_rtx): Delete unneeded * config/rs6000/rs6000.c (rs6000_make_savres_rtx): Delete unneeded
...@@ -1753,19 +1753,51 @@ darwin_label_is_anonymous_local_objc_name (const char *name) ...@@ -1753,19 +1753,51 @@ darwin_label_is_anonymous_local_objc_name (const char *name)
return (!strncmp ((const char *)p, "_OBJC_", 6)); return (!strncmp ((const char *)p, "_OBJC_", 6));
} }
/* LTO support for Mach-O. */ /* LTO support for Mach-O.
/* Section names for LTO sections. */ This version uses three mach-o sections to encapsulate the (unlimited
static unsigned int lto_section_names_offset = 0; number of) lto sections.
/* This is the obstack which we use to allocate the many strings. */ __GNU_LTO, __lto_sections contains the concatented GNU LTO section data.
static struct obstack lto_section_names_obstack; __GNU_LTO, __section_names contains the GNU LTO section names.
__GNU_LTO, __section_index contains an array of values that index these.
/* Segment name for LTO sections. */ Indexed thus:
<section offset from the start of __GNU_LTO, __lto_sections>,
<section length>
<name offset from the start of __GNU_LTO, __section_names,
<name length>.
At present, for both m32 and m64 mach-o files each of these fields is
represented by a uint32_t. This is because, AFAICT, a mach-o object
cannot exceed 4Gb because the section_64 offset field (see below) is 32bits.
uint32_t offset;
"offset An integer specifying the offset to this section in the file." */
/* Count lto section numbers. */
static unsigned int lto_section_num = 0;
/* A vector of information about LTO sections, at present, we only have
the name. TODO: see if we can get the data length somehow. */
typedef struct GTY (()) darwin_lto_section_e {
const char *sectname;
} darwin_lto_section_e ;
DEF_VEC_O(darwin_lto_section_e);
DEF_VEC_ALLOC_O(darwin_lto_section_e, gc);
static GTY (()) VEC (darwin_lto_section_e, gc) * lto_section_names;
/* Segment for LTO data. */
#define LTO_SEGMENT_NAME "__GNU_LTO" #define LTO_SEGMENT_NAME "__GNU_LTO"
/* Section name for LTO section names section. */ /* Section wrapper scheme (used here to wrap the unlimited number of LTO
#define LTO_NAMES_SECTION "__section_names" sections into three Mach-O ones).
NOTE: These names MUST be kept in sync with those in
libiberty/simple-object-mach-o. */
#define LTO_SECTS_SECTION "__wrapper_sects"
#define LTO_NAMES_SECTION "__wrapper_names"
#define LTO_INDEX_SECTION "__wrapper_index"
/* File to temporarily store LTO data. This is appended to asm_out_file /* File to temporarily store LTO data. This is appended to asm_out_file
in darwin_end_file. */ in darwin_end_file. */
...@@ -1808,37 +1840,38 @@ darwin_asm_named_section (const char *name, ...@@ -1808,37 +1840,38 @@ darwin_asm_named_section (const char *name,
unsigned int flags, unsigned int flags,
tree decl ATTRIBUTE_UNUSED) tree decl ATTRIBUTE_UNUSED)
{ {
/* LTO sections go in a special segment __GNU_LTO. We want to replace the /* LTO sections go in a special section that encapsulates the (unlimited)
section name with something we can use to represent arbitrary-length number of GNU LTO sections within a single mach-o one. */
names (section names in Mach-O are at most 16 characters long). */
if (strncmp (name, LTO_SECTION_NAME_PREFIX, if (strncmp (name, LTO_SECTION_NAME_PREFIX,
strlen (LTO_SECTION_NAME_PREFIX)) == 0) strlen (LTO_SECTION_NAME_PREFIX)) == 0)
{ {
darwin_lto_section_e e;
/* We expect certain flags to be set... */ /* We expect certain flags to be set... */
gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED)) gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
== (SECTION_DEBUG | SECTION_NAMED)); == (SECTION_DEBUG | SECTION_NAMED));
/* Add the section name to the things to output when we end the /* Switch to our combined section. */
current assembler output file. fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
This is all not very efficient, but that doesn't matter -- this LTO_SEGMENT_NAME, LTO_SECTS_SECTION);
shouldn't be a hot path in the compiler... */ /* Output a label for the start of this sub-section. */
obstack_1grow (&lto_section_names_obstack, '\t'); fprintf (asm_out_file, "L_GNU_LTO%d:\t;# %s\n",
obstack_grow (&lto_section_names_obstack, ".ascii ", 7); lto_section_num, name);
obstack_1grow (&lto_section_names_obstack, '"'); /* We have to jump through hoops to get the values of the intra-section
obstack_grow (&lto_section_names_obstack, name, strlen (name)); offsets... */
obstack_grow (&lto_section_names_obstack, "\\0\"\n", 4); fprintf (asm_out_file, "\t.set L$gnu$lto$offs%d,L_GNU_LTO%d-L_GNU_LTO0\n",
lto_section_num, lto_section_num);
/* Output the dummy section name. */ fprintf (asm_out_file,
fprintf (asm_out_file, "\t# %s\n", name); "\t.set L$gnu$lto$size%d,L_GNU_LTO%d-L_GNU_LTO%d\n",
fprintf (asm_out_file, "\t.section %s,__%08X,regular,debug\n", lto_section_num, lto_section_num+1, lto_section_num);
LTO_SEGMENT_NAME, lto_section_names_offset); lto_section_num++;
e.sectname = xstrdup (name);
/* Update the offset for the next section name. Make sure we stay /* Keep the names, we'll need to make a table later.
within reasonable length. */ TODO: check that we do not revisit sections, that would break
lto_section_names_offset += strlen (name) + 1; the assumption of how this is done. */
gcc_assert (lto_section_names_offset > 0 if (lto_section_names == NULL)
&& lto_section_names_offset < ((unsigned) 1 << 31)); lto_section_names = VEC_alloc (darwin_lto_section_e, gc, 16);
} VEC_safe_push (darwin_lto_section_e, gc, lto_section_names, &e);
}
else if (strncmp (name, "__DWARF,", 8) == 0) else if (strncmp (name, "__DWARF,", 8) == 0)
darwin_asm_dwarf_section (name, flags, decl); darwin_asm_dwarf_section (name, flags, decl);
else else
...@@ -2711,16 +2744,12 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab, ...@@ -2711,16 +2744,12 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
darwin_asm_output_dwarf_delta (file, size, lab, sname); darwin_asm_output_dwarf_delta (file, size, lab, sname);
} }
/* Called from the within the TARGET_ASM_FILE_START for each target. /* Called from the within the TARGET_ASM_FILE_START for each target. */
Initialize the stuff we need for LTO long section names support. */
void void
darwin_file_start (void) darwin_file_start (void)
{ {
/* We fill this obstack with the complete section text for the lto section /* Nothing to do. */
names to write in darwin_file_end. */
obstack_init (&lto_section_names_obstack);
lto_section_names_offset = 0;
} }
/* Called for the TARGET_ASM_FILE_END hook. /* Called for the TARGET_ASM_FILE_END hook.
...@@ -2731,8 +2760,6 @@ darwin_file_start (void) ...@@ -2731,8 +2760,6 @@ darwin_file_start (void)
void void
darwin_file_end (void) darwin_file_end (void)
{ {
const char *lto_section_names;
machopic_finish (asm_out_file); machopic_finish (asm_out_file);
if (strcmp (lang_hooks.name, "GNU C++") == 0) if (strcmp (lang_hooks.name, "GNU C++") == 0)
{ {
...@@ -2762,6 +2789,13 @@ darwin_file_end (void) ...@@ -2762,6 +2789,13 @@ darwin_file_end (void)
lto_asm_txt = buf = (char *) xmalloc (n + 1); lto_asm_txt = buf = (char *) xmalloc (n + 1);
while (fgets (lto_asm_txt, n, lto_asm_out_file)) while (fgets (lto_asm_txt, n, lto_asm_out_file))
fputs (lto_asm_txt, asm_out_file); fputs (lto_asm_txt, asm_out_file);
/* Put a termination label. */
fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
LTO_SEGMENT_NAME, LTO_SECTS_SECTION);
fprintf (asm_out_file, "L_GNU_LTO%d:\t;# end of lto\n",
lto_section_num);
/* Make sure our termination label stays in this section. */
fputs ("\t.space\t1\n", asm_out_file);
} }
/* Remove the temporary file. */ /* Remove the temporary file. */
...@@ -2770,21 +2804,50 @@ darwin_file_end (void) ...@@ -2770,21 +2804,50 @@ darwin_file_end (void)
free (lto_asm_out_name); free (lto_asm_out_name);
} }
/* Finish the LTO section names obstack. Don't output anything if /* Output the names and indices. */
there are no recorded section names. */ if (lto_section_names && VEC_length (darwin_lto_section_e, lto_section_names))
obstack_1grow (&lto_section_names_obstack, '\0');
lto_section_names = XOBFINISH (&lto_section_names_obstack, const char *);
if (strlen (lto_section_names) > 0)
{ {
fprintf (asm_out_file, int count;
"\t.section %s,%s,regular,debug\n", darwin_lto_section_e *ref;
/* For now, we'll make the offsets 4 bytes and unaligned - we'll fix
the latter up ourselves. */
const char *op = integer_asm_op (4,0);
/* Emit the names. */
fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
LTO_SEGMENT_NAME, LTO_NAMES_SECTION); LTO_SEGMENT_NAME, LTO_NAMES_SECTION);
fprintf (asm_out_file, FOR_EACH_VEC_ELT (darwin_lto_section_e, lto_section_names, count, ref)
"\t# Section names in %s are offsets into this table\n", {
LTO_SEGMENT_NAME); fprintf (asm_out_file, "L_GNU_LTO_NAME%d:\n", count);
fprintf (asm_out_file, "%s\n", lto_section_names); /* We have to jump through hoops to get the values of the intra-section
offsets... */
fprintf (asm_out_file,
"\t.set L$gnu$lto$noff%d,L_GNU_LTO_NAME%d-L_GNU_LTO_NAME0\n",
count, count);
fprintf (asm_out_file,
"\t.set L$gnu$lto$nsiz%d,L_GNU_LTO_NAME%d-L_GNU_LTO_NAME%d\n",
count, count+1, count);
fprintf (asm_out_file, "\t.asciz\t\"%s\"\n", ref->sectname);
}
fprintf (asm_out_file, "L_GNU_LTO_NAME%d:\t;# end\n", lto_section_num);
/* make sure our termination label stays in this section. */
fputs ("\t.space\t1\n", asm_out_file);
/* Emit the Index. */
fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
LTO_SEGMENT_NAME, LTO_INDEX_SECTION);
fputs ("\t.align\t2\n", asm_out_file);
fputs ("# Section offset, Section length, Name offset, Name length\n",
asm_out_file);
FOR_EACH_VEC_ELT (darwin_lto_section_e, lto_section_names, count, ref)
{
fprintf (asm_out_file, "%s L$gnu$lto$offs%d\t;# %s\n",
op, count, ref->sectname);
fprintf (asm_out_file, "%s L$gnu$lto$size%d\n", op, count);
fprintf (asm_out_file, "%s L$gnu$lto$noff%d\n", op, count);
fprintf (asm_out_file, "%s L$gnu$lto$nsiz%d\n", op, count);
}
} }
obstack_free (&lto_section_names_obstack, NULL);
/* If we have section anchors, then we must prevent the linker from /* If we have section anchors, then we must prevent the linker from
re-arranging data. */ re-arranging data. */
......
2011-10-26 Iain Sandoe <iains@gcc.gnu.org>
PR target/48108
* simple-object-mach-o.c (GNU_WRAPPER_SECTS, GNU_WRAPPER_INDEX,
GNU_WRAPPER_NAMES): New macros.
(simple_object_mach_o_segment): Handle wrapper scheme.
(simple_object_mach_o_write_section_header): Allow the segment name
to be supplied.
(simple_object_mach_o_write_segment): Handle wrapper scheme. Ensure
that the top-level segment name in the load command is empty.
(simple_object_mach_o_write_to_file): Determine the number of
sections during segment output, use that in writing the header.
2011-10-10 Ian Lance Taylor <iant@google.com> 2011-10-10 Ian Lance Taylor <iant@google.com>
PR c++/48665 PR c++/48665
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment