Commit c082f9f3 by Steven Bosscher

configure.ac (--enable-lto): Add x86_64-apple-darwin* as a platform that supports LTO.

ChangeLog:
	* configure.ac (--enable-lto): Add x86_64-apple-darwin* as
	a platform that supports LTO.
	* configure: Regenerate.

gcc/ChangeLog:
	* config.gcc (i[34567]86-*-darwin*, x86_64-*-darwin*): Add
	lto-macho as lto_binary_reader.
	* target.h (struct gcc_target): New hooks lto_start and	lto_end.
	* target-def.h (TARGET_ASM_LTO_START, TARGET_ASM_LTO_END): Define.
	* cgraphunit.c (ipa_passes): Wrap LTO assembler output generation
	in lto_start and lto_end calls.
	(is_elf_or_coff): Rename to maybe_lto_object_file.  Add Mach-O
	magic numbers.
	(scan_prog_file): Update is_elf_or_coff call.
	* doc/tm.text (TARGET_ASM_LTO_START, TARGET_ASM_LTO_END): Document.

	* collect2.c (main): Fix enum comparison.

	* config/darwin-protos.h (darwin_asm_lto_start, darwin_asm_lto_end):
	Add prototypes.
	* darwin9.h (LINK_COMMAND_SPEC): Pass -flto and -fwhopr to the linker.
	* darwin.h (LINK_COMMAND_SPEC): Likewise.  Define TARGET_ASM_LTO_START
	and TARGET_ASM_LTO_END.
	* darwin.c: Include obstack.h and lto-streamer.h.
	(lto_section_names_offset, lto_section_names_obstack,
	lto_asm_out_file, lto_asm_out_name, saved_asm_out_file): New static
	global variables.
	(LTO_SEGMENT_NAME, LTO_NAMES_SECTION): New defines.
	(darwin_asm_lto_start): New function.  Redirect output to asm_out_file
	to a temporary file.
	(darwin_asm_lto_end): New function.  Restore asm_out_file.
	(darwin_asm_named_section): For LTO sections, replace the name with
	the offset of the section name in a string table, and build this
	table.
	(darwin_file_start): Initialize global vars for LTO support.
	(darwin_file_end): If output to asm_out_file was redirected, append it
	to the proper asm_out_file here.  Add the section names section.

lto/ChangeLog:
	* lto.h (struct lto_file_struct): Document offset member.
	* lto-endian.h: New file.
	* lto-macho.h: New file.
	* lto-macho.c: New file.
	* Make-lang.in: Add rule for lto-macho.o.

From-SVN: r159173
parent 18bc5398
2010-05-07 Steven Bosscher <steven@gcc.gnu.org>
* configure.ac (--enable-lto): Add x86_64-apple-darwin* as
a platform that supports LTO.
* configure: Regenerate.
2010-05-05 Sebastian Pop <sebastian.pop@amd.com> 2010-05-05 Sebastian Pop <sebastian.pop@amd.com>
* configure.ac: Allow all the versions greater than 0.10 of PPL. * configure.ac: Allow all the versions greater than 0.10 of PPL.
......
...@@ -6686,6 +6686,7 @@ else ...@@ -6686,6 +6686,7 @@ else
# -flto it won't be needed until after installation anyway. # -flto it won't be needed until after installation anyway.
case $target in case $target in
*-cygwin*|*-mingw*) ;; *-cygwin*|*-mingw*) ;;
x86_64-apple-darwin*) ;;
*) if test x"$enable_lto" = x"yes"; then *) if test x"$enable_lto" = x"yes"; then
as_fn_error "LTO support is not enabled for this target." "$LINENO" 5 as_fn_error "LTO support is not enabled for this target." "$LINENO" 5
fi fi
......
...@@ -1803,6 +1803,7 @@ fi],[if test x"$default_enable_lto" = x"yes" ; then ...@@ -1803,6 +1803,7 @@ fi],[if test x"$default_enable_lto" = x"yes" ; then
# -flto it won't be needed until after installation anyway. # -flto it won't be needed until after installation anyway.
case $target in case $target in
*-cygwin*|*-mingw*) ;; *-cygwin*|*-mingw*) ;;
x86_64-apple-darwin*) ;;
*) if test x"$enable_lto" = x"yes"; then *) if test x"$enable_lto" = x"yes"; then
AC_MSG_ERROR([LTO support is not enabled for this target.]) AC_MSG_ERROR([LTO support is not enabled for this target.])
fi fi
......
2010-05-07 Steven Bosscher <steven@gcc.gnu.org> 2010-05-07 Steven Bosscher <steven@gcc.gnu.org>
* config.gcc (i[34567]86-*-darwin*, x86_64-*-darwin*): Add
lto-macho as lto_binary_reader.
* target.h (struct gcc_target): New hooks lto_start and lto_end.
* target-def.h (TARGET_ASM_LTO_START, TARGET_ASM_LTO_END): Define.
* cgraphunit.c (ipa_passes): Wrap LTO assembler output generation
in lto_start and lto_end calls.
(is_elf_or_coff): Rename to maybe_lto_object_file. Add Mach-O
magic numbers.
(scan_prog_file): Update is_elf_or_coff call.
* doc/tm.text (TARGET_ASM_LTO_START, TARGET_ASM_LTO_END): Document.
* collect2.c (main): Fix enum comparison.
* config/darwin-protos.h (darwin_asm_lto_start, darwin_asm_lto_end):
Add prototypes.
* darwin9.h (LINK_COMMAND_SPEC): Pass -flto and -fwhopr to the linker.
* darwin.h (LINK_COMMAND_SPEC): Likewise. Define TARGET_ASM_LTO_START
and TARGET_ASM_LTO_END.
* darwin.c: Include obstack.h and lto-streamer.h.
(lto_section_names_offset, lto_section_names_obstack,
lto_asm_out_file, lto_asm_out_name, saved_asm_out_file): New static
global variables.
(LTO_SEGMENT_NAME, LTO_NAMES_SECTION): New defines.
(darwin_asm_lto_start): New function. Redirect output to asm_out_file
to a temporary file.
(darwin_asm_lto_end): New function. Restore asm_out_file.
(darwin_asm_named_section): For LTO sections, replace the name with
the offset of the section name in a string table, and build this
table.
(darwin_file_start): Initialize global vars for LTO support.
(darwin_file_end): If output to asm_out_file was redirected, append it
to the proper asm_out_file here. Add the section names section.
2010-05-07 Steven Bosscher <steven@gcc.gnu.org>
* c-pragma.c (pending_weak_d, pending_weak): New. * c-pragma.c (pending_weak_d, pending_weak): New.
(pending_weaks): Change the type to VEC((pending_weak,gc) *. (pending_weaks): Change the type to VEC((pending_weak,gc) *.
(maybe_apply_pragma_weak, maybe_apply_pending_pragma_weaks, (maybe_apply_pragma_weak, maybe_apply_pending_pragma_weaks,
......
...@@ -1866,11 +1866,19 @@ ipa_passes (void) ...@@ -1866,11 +1866,19 @@ ipa_passes (void)
execute_ipa_summary_passes execute_ipa_summary_passes
((struct ipa_opt_pass_d *) all_regular_ipa_passes); ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
} }
/* Some targets need to handle LTO assembler output specially. */
if (flag_generate_lto)
targetm.asm_out.lto_start ();
execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes); execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
if (!in_lto_p) if (!in_lto_p)
ipa_write_summaries (); ipa_write_summaries ();
if (flag_generate_lto)
targetm.asm_out.lto_end ();
if (!flag_ltrans) if (!flag_ltrans)
execute_ipa_pass_list (all_regular_ipa_passes); execute_ipa_pass_list (all_regular_ipa_passes);
invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL); invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
......
...@@ -1817,7 +1817,7 @@ main (int argc, char **argv) ...@@ -1817,7 +1817,7 @@ main (int argc, char **argv)
if (export_file != 0 && export_file[0]) if (export_file != 0 && export_file[0])
maybe_unlink (export_file); maybe_unlink (export_file);
#endif #endif
if (lto_mode) if (lto_mode != LTO_MODE_NONE)
maybe_run_lto_and_relink (ld1_argv, object_lst, object, false); maybe_run_lto_and_relink (ld1_argv, object_lst, object, false);
maybe_unlink (c_file); maybe_unlink (c_file);
...@@ -2563,16 +2563,23 @@ write_aix_file (FILE *stream, struct id *list) ...@@ -2563,16 +2563,23 @@ write_aix_file (FILE *stream, struct id *list)
#ifdef OBJECT_FORMAT_NONE #ifdef OBJECT_FORMAT_NONE
/* Check to make sure the file is an ELF file. LTO objects must /* Check to make sure the file is an LTO object file. */
be in ELF format. */
static bool static bool
is_elf_or_coff (const char *prog_name) maybe_lto_object_file (const char *prog_name)
{ {
FILE *f; FILE *f;
char buf[4]; unsigned char buf[4];
static char magic[4] = { 0x7f, 'E', 'L', 'F' }; int i;
static char coffmag[2] = { 0x4c, 0x01 };
static unsigned char elfmagic[4] = { 0x7f, 'E', 'L', 'F' };
static unsigned char coffmagic[2] = { 0x4c, 0x01 };
static unsigned char machomagic[4][4] = {
{ 0xcf, 0xfa, 0xed, 0xfe },
{ 0xce, 0xfa, 0xed, 0xfe },
{ 0xfe, 0xed, 0xfa, 0xcf },
{ 0xfe, 0xed, 0xfa, 0xce }
};
f = fopen (prog_name, "rb"); f = fopen (prog_name, "rb");
if (f == NULL) if (f == NULL)
...@@ -2580,8 +2587,15 @@ is_elf_or_coff (const char *prog_name) ...@@ -2580,8 +2587,15 @@ is_elf_or_coff (const char *prog_name)
if (fread (buf, sizeof (buf), 1, f) != 1) if (fread (buf, sizeof (buf), 1, f) != 1)
buf[0] = 0; buf[0] = 0;
fclose (f); fclose (f);
return memcmp (buf, magic, sizeof (magic)) == 0
|| memcmp (buf, coffmag, sizeof (coffmag)) == 0; if (memcmp (buf, elfmagic, sizeof (elfmagic)) == 0
|| memcmp (buf, coffmagic, sizeof (coffmagic)) == 0)
return true;
for (i = 0; i < 4; i++)
if (memcmp (buf, machomagic[i], sizeof (machomagic[i])) == 0)
return true;
return false;
} }
/* Generic version to scan the name list of the loaded program for /* Generic version to scan the name list of the loaded program for
...@@ -2611,7 +2625,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass, ...@@ -2611,7 +2625,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
/* LTO objects must be in a known format. This check prevents /* LTO objects must be in a known format. This check prevents
us from accepting an archive containing LTO objects, which us from accepting an archive containing LTO objects, which
gcc cannnot currently handle. */ gcc cannnot currently handle. */
if (which_pass == PASS_LTOINFO && !is_elf_or_coff (prog_name)) if (which_pass == PASS_LTOINFO && !maybe_lto_object_file (prog_name))
return; return;
/* If we do not have an `nm', complain. */ /* If we do not have an `nm', complain. */
......
...@@ -1077,11 +1077,13 @@ i[34567]86-*-darwin*) ...@@ -1077,11 +1077,13 @@ i[34567]86-*-darwin*)
# support. # support.
with_cpu=${with_cpu:-generic} with_cpu=${with_cpu:-generic}
tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm" tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm"
lto_binary_reader=lto-macho
;; ;;
x86_64-*-darwin*) x86_64-*-darwin*)
with_cpu=${with_cpu:-generic} with_cpu=${with_cpu:-generic}
tmake_file="${tmake_file} t-darwin ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm" tmake_file="${tmake_file} t-darwin ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
tm_file="${tm_file} ${cpu_type}/darwin64.h" tm_file="${tm_file} ${cpu_type}/darwin64.h"
lto_binary_reader=lto-macho
;; ;;
i[34567]86-*-elf*) i[34567]86-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h" tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
......
...@@ -71,6 +71,9 @@ extern void darwin_pragma_ms_struct (struct cpp_reader *); ...@@ -71,6 +71,9 @@ extern void darwin_pragma_ms_struct (struct cpp_reader *);
extern void darwin_file_start (void); extern void darwin_file_start (void);
extern void darwin_file_end (void); extern void darwin_file_end (void);
extern void darwin_asm_lto_start (void);
extern void darwin_asm_lto_end (void);
extern void darwin_mark_decl_preserved (const char *); extern void darwin_mark_decl_preserved (const char *);
extern tree darwin_handle_kext_attribute (tree *, tree, tree, int, bool *); extern tree darwin_handle_kext_attribute (tree *, tree, tree, int, bool *);
......
...@@ -46,6 +46,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -46,6 +46,8 @@ along with GCC; see the file COPYING3. If not see
#include "hashtab.h" #include "hashtab.h"
#include "df.h" #include "df.h"
#include "debug.h" #include "debug.h"
#include "obstack.h"
#include "lto-streamer.h"
/* Darwin supports a feature called fix-and-continue, which is used /* Darwin supports a feature called fix-and-continue, which is used
for rapid turn around debugging. When code is compiled with the for rapid turn around debugging. When code is compiled with the
...@@ -1387,12 +1389,88 @@ darwin_label_is_anonymous_local_objc_name (const char *name) ...@@ -1387,12 +1389,88 @@ 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. */
/* Section names for LTO sections. */
static unsigned int lto_section_names_offset = 0;
/* This is the obstack which we use to allocate the many strings. */
static struct obstack lto_section_names_obstack;
/* Segment name for LTO sections. */
#define LTO_SEGMENT_NAME "__GNU_LTO"
/* Section name for LTO section names section. */
#define LTO_NAMES_SECTION "__section_names"
/* File to temporarily store LTO data. This is appended to asm_out_file
in darwin_end_file. */
static FILE *lto_asm_out_file, *saved_asm_out_file;
static char *lto_asm_out_name;
/* Prepare asm_out_file for LTO output. For darwin, this means hiding
asm_out_file and switching to an alternative output file. */
void
darwin_asm_lto_start (void)
{
gcc_assert (! saved_asm_out_file);
saved_asm_out_file = asm_out_file;
if (! lto_asm_out_name)
lto_asm_out_name = make_temp_file (".lto.s");
lto_asm_out_file = fopen (lto_asm_out_name, "a");
if (lto_asm_out_file == NULL)
fatal_error ("failed to open temporary file %s for LTO output",
lto_asm_out_name);
asm_out_file = lto_asm_out_file;
}
/* Restore asm_out_file. */
void
darwin_asm_lto_end (void)
{
gcc_assert (saved_asm_out_file);
fclose (lto_asm_out_file);
asm_out_file = saved_asm_out_file;
saved_asm_out_file = NULL;
}
void void
darwin_asm_named_section (const char *name, darwin_asm_named_section (const char *name,
unsigned int flags ATTRIBUTE_UNUSED, unsigned int flags,
tree decl ATTRIBUTE_UNUSED) tree decl ATTRIBUTE_UNUSED)
{ {
fprintf (asm_out_file, "\t.section %s\n", name); /* LTO sections go in a special segment __GNU_LTO. We want to replace the
section name with something we can use to represent arbitrary-length
names (section names in Mach-O are at most 16 characters long). */
if (strncmp (name, LTO_SECTION_NAME_PREFIX,
strlen (LTO_SECTION_NAME_PREFIX)) == 0)
{
/* We expect certain flags to be set... */
gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
== (SECTION_DEBUG | SECTION_NAMED));
/* Add the section name to the things to output when we end the
current assembler output file.
This is all not very efficient, but that doesn't matter -- this
shouldn't be a hot path in the compiler... */
obstack_1grow (&lto_section_names_obstack, '\t');
obstack_grow (&lto_section_names_obstack, ".ascii ", 7);
obstack_1grow (&lto_section_names_obstack, '"');
obstack_grow (&lto_section_names_obstack, name, strlen (name));
obstack_grow (&lto_section_names_obstack, "\\0\"\n", 4);
/* Output the dummy section name. */
fprintf (asm_out_file, "\t.section %s,__%08X,regular,debug\t# %s\n",
LTO_SEGMENT_NAME, lto_section_names_offset, name);
/* Update the offset for the next section name. Make sure we stay
within reasonable length. */
lto_section_names_offset += strlen (name) + 1;
gcc_assert (lto_section_names_offset > 0
&& lto_section_names_offset < ((unsigned) 1 << 31));
}
else
fprintf (asm_out_file, "\t.section %s\n", name);
} }
void void
...@@ -1585,7 +1663,8 @@ darwin_asm_output_dwarf_delta (FILE *file, int size, ...@@ -1585,7 +1663,8 @@ darwin_asm_output_dwarf_delta (FILE *file, int size,
fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++); fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++);
} }
/* Output labels for the start of the DWARF sections if necessary. */ /* Output labels for the start of the DWARF sections if necessary.
Initialize the stuff we need for LTO long section names support. */
void void
darwin_file_start (void) darwin_file_start (void)
{ {
...@@ -1620,6 +1699,11 @@ darwin_file_start (void) ...@@ -1620,6 +1699,11 @@ darwin_file_start (void)
fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8); fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8);
} }
} }
/* We fill this obstack with the complete section text for the lto section
names to write in darwin_file_end. */
obstack_init (&lto_section_names_obstack);
lto_section_names_offset = 0;
} }
/* Output an offset in a DWARF section on Darwin. On Darwin, DWARF section /* Output an offset in a DWARF section on Darwin. On Darwin, DWARF section
...@@ -1646,6 +1730,8 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab, ...@@ -1646,6 +1730,8 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
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)
{ {
...@@ -1653,6 +1739,52 @@ darwin_file_end (void) ...@@ -1653,6 +1739,52 @@ darwin_file_end (void)
switch_to_section (darwin_sections[destructor_section]); switch_to_section (darwin_sections[destructor_section]);
ASM_OUTPUT_ALIGN (asm_out_file, 1); ASM_OUTPUT_ALIGN (asm_out_file, 1);
} }
/* If there was LTO assembler output, append it to asm_out_file. */
if (lto_asm_out_name)
{
int n;
char *buf, *lto_asm_txt;
/* Shouldn't be here if we failed to switch back. */
gcc_assert (! saved_asm_out_file);
lto_asm_out_file = fopen (lto_asm_out_name, "r");
if (lto_asm_out_file == NULL)
fatal_error ("failed to open temporary file %s with LTO output",
lto_asm_out_name);
fseek (lto_asm_out_file, 0, SEEK_END);
n = ftell (lto_asm_out_file);
if (n > 0)
{
fseek (lto_asm_out_file, 0, SEEK_SET);
lto_asm_txt = buf = (char *) xmalloc (n + 1);
while (fgets (lto_asm_txt, n, lto_asm_out_file))
fputs (lto_asm_txt, asm_out_file);
}
/* Remove the temporary file. */
fclose (lto_asm_out_file);
unlink_if_ordinary (lto_asm_out_name);
free (lto_asm_out_name);
}
/* Finish the LTO section names obstack. Don't output anything if
there are no recorded 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,
"\t.section %s,%s,regular,debug\n",
LTO_SEGMENT_NAME, LTO_NAMES_SECTION);
fprintf (asm_out_file,
"\t# Section names in %s are offsets into this table\n",
LTO_SEGMENT_NAME);
fprintf (asm_out_file, "%s\n", lto_section_names);
}
obstack_free (&lto_section_names_obstack, NULL);
fprintf (asm_out_file, "\t.subsections_via_symbols\n"); fprintf (asm_out_file, "\t.subsections_via_symbols\n");
} }
......
...@@ -273,6 +273,7 @@ extern GTY(()) int darwin_ms_struct; ...@@ -273,6 +273,7 @@ extern GTY(()) int darwin_ms_struct;
%{o*}%{!o:-o a.out} \ %{o*}%{!o:-o a.out} \
%{!A:%{!nostdlib:%{!nostartfiles:%S}}} \ %{!A:%{!nostdlib:%{!nostartfiles:%S}}} \
%{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \ %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \
%{flto} %{fwhopr} \
%{fopenmp|ftree-parallelize-loops=*: \ %{fopenmp|ftree-parallelize-loops=*: \
%{static|static-libgcc|static-libstdc++|static-libgfortran: libgomp.a%s; : -lgomp } } \ %{static|static-libgcc|static-libstdc++|static-libgfortran: libgomp.a%s; : -lgomp } } \
%{!nostdlib:%{!nodefaultlibs: %(link_ssp) %G %L }} \ %{!nostdlib:%{!nodefaultlibs: %(link_ssp) %G %L }} \
...@@ -581,6 +582,16 @@ extern GTY(()) int darwin_ms_struct; ...@@ -581,6 +582,16 @@ extern GTY(()) int darwin_ms_struct;
#undef TARGET_ASM_FILE_END #undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END darwin_file_end #define TARGET_ASM_FILE_END darwin_file_end
/* Because Mach-O relocations have a counter from 1 to 255 for the
section number they apply to, it is necessary to output all
normal sections before the LTO sections, to make sure that the
sections that may have relocations always have a section number
smaller than 255. */
#undef TARGET_ASM_LTO_START
#define TARGET_ASM_LTO_START darwin_asm_lto_start
#undef TARGET_ASM_LTO_END
#define TARGET_ASM_LTO_END darwin_asm_lto_end
#define ASM_OUTPUT_SKIP(FILE,SIZE) \ #define ASM_OUTPUT_SKIP(FILE,SIZE) \
fprintf (FILE, "\t.space "HOST_WIDE_INT_PRINT_UNSIGNED"\n", SIZE) fprintf (FILE, "\t.space "HOST_WIDE_INT_PRINT_UNSIGNED"\n", SIZE)
......
...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
%{o*}%{!o:-o a.out} \ %{o*}%{!o:-o a.out} \
%{!A:%{!nostdlib:%{!nostartfiles:%S}}} \ %{!A:%{!nostdlib:%{!nostartfiles:%S}}} \
%{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \ %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \
%{flto} %{fwhopr} \
%{fopenmp|ftree-parallelize-loops=*: \ %{fopenmp|ftree-parallelize-loops=*: \
%{static|static-libgcc|static-libstdc++|static-libgfortran: libgomp.a%s; : -lgomp } } \ %{static|static-libgcc|static-libstdc++|static-libgfortran: libgomp.a%s; : -lgomp } } \
%{!nostdlib:%{!nodefaultlibs: %(link_ssp) %G %L }} \ %{!nostdlib:%{!nodefaultlibs: %(link_ssp) %G %L }} \
......
...@@ -7184,6 +7184,18 @@ need to do other things in that hook, have your hook function call ...@@ -7184,6 +7184,18 @@ need to do other things in that hook, have your hook function call
this function. this function.
@end deftypefun @end deftypefun
@deftypefn {Target Hook} void TARGET_ASM_LTO_START (void)
Output to @code{asm_out_file} any text which the assembler expects
to find at the start of an LTO section. The default is to output
nothing.
@end deftypefn
@deftypefn {Target Hook} void TARGET_ASM_LTO_END (void)
Output to @code{asm_out_file} any text which the assembler expects
to find at the end of an LTO section. The default is to output
nothing.
@end deftypefn
@deftypefn {Target Hook} void TARGET_ASM_CODE_END (void) @deftypefn {Target Hook} void TARGET_ASM_CODE_END (void)
Output to @code{asm_out_file} any text which is needed before emitting Output to @code{asm_out_file} any text which is needed before emitting
unwind info and debug info at the end of a file. Some targets emit unwind info and debug info at the end of a file. Some targets emit
......
2010-05-07 Steven Bosscher <steven@gcc.gnu.org>
* lto.h (struct lto_file_struct): Document offset member.
* lto-endian.h: New file.
* lto-macho.h: New file.
* lto-macho.c: New file.
* Make-lang.in: Add rule for lto-macho.o.
2010-05-07 Richard Guenther <rguenther@suse.de> 2010-05-07 Richard Guenther <rguenther@suse.de>
PR lto/43857 PR lto/43857
......
...@@ -91,3 +91,6 @@ lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \ ...@@ -91,3 +91,6 @@ lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
lto/lto-coff.o: lto/lto-coff.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \ lto/lto-coff.o: lto/lto-coff.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H) \ toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H) \
lto/lto-coff.h lto/lto-coff.h
lto/lto-macho.o: lto/lto-macho.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H) \
lto/lto-macho.h lto/lto-endian.h
/* Very simple endian-ness layer for LTO object file handling
Copyright 2010 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* This header file provides a simple way to handle object files in
another endian-ness than the host machine. This is necesarry to
enable cross-compilation with LTO enabled. Targets that use the
ELF binary object format do not need this (libelf already handles
endian-ness) but for COFF and Mach-O the functions in this header
are used in the minimal binary object reader/writer.
For all functions in this header, the user is responsible for
making sure that the memory accesses are valid. */
#ifndef GCC_LTO_ENDIAN_H
#define GCC_LTO_ENDIAN_H
#include <stdint.h>
#include <inttypes.h>
static inline uint16_t
get_uint16_le (const unsigned char *ptr)
{
return ptr[0] | (ptr[1] << 8);
}
static inline uint32_t
get_uint32_le (const unsigned char *ptr)
{
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
}
static inline uint64_t
get_uint64_le (const unsigned char *ptr_)
{
#define ptr (uint64_t) ptr_
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24)
| (ptr[4] << 32) | (ptr[5] << 40) | (ptr[6] << 48) | (ptr[7] << 56);
#undef ptr
}
static inline uint16_t
get_uint16_be (const unsigned char *ptr)
{
return ptr[1] | (ptr[2] << 8);
}
static inline uint32_t
get_uint32_be (const unsigned char *ptr)
{
return ptr[3] | (ptr[2] << 8) | (ptr[1] << 16) | (ptr[0] << 24);
}
static inline uint64_t
get_uint64_be (const unsigned char *ptr_)
{
#define ptr (uint64_t) ptr_
return ptr[7] | (ptr[6] << 8) | (ptr[5] << 16) | (ptr[4] << 24)
| (ptr[3] << 32) | (ptr[2] << 40) | (ptr[1] << 48) | (ptr[0] << 56);
#undef ptr
}
static inline void
put_uint16_le (unsigned char *ptr, uint16_t data)
{
ptr[0] = data & 0xff;
ptr[1] = (data >> 8) & 0xff;
}
static inline void
put_uint32_le (unsigned char *ptr, uint32_t data)
{
ptr[0] = data & 0xff;
ptr[1] = (data >> 8) & 0xff;
ptr[2] = (data >> 16) & 0xff;
ptr[3] = (data >> 24) & 0xff;
}
static inline void
put_uint64_le (unsigned char *ptr, uint64_t data)
{
ptr[0] = data & 0xff;
ptr[1] = (data >> 8) & 0xff;
ptr[2] = (data >> 16) & 0xff;
ptr[3] = (data >> 24) & 0xff;
ptr[4] = (data >> 32) & 0xff;
ptr[5] = (data >> 40) & 0xff;
ptr[6] = (data >> 48) & 0xff;
ptr[7] = (data >> 56) & 0xff;
}
static inline void
put_uint16_be (unsigned char *ptr, uint16_t data)
{
ptr[1] = data & 0xff;
ptr[0] = (data >> 8) & 0xff;
}
static inline void
put_uint32_be (unsigned char *ptr, uint32_t data)
{
ptr[3] = data & 0xff;
ptr[2] = (data >> 8) & 0xff;
ptr[1] = (data >> 16) & 0xff;
ptr[0] = (data >> 24) & 0xff;
}
static inline void
put_uint64_be (unsigned char *ptr, uint64_t data)
{
ptr[7] = data & 0xff;
ptr[6] = (data >> 8) & 0xff;
ptr[5] = (data >> 16) & 0xff;
ptr[4] = (data >> 24) & 0xff;
ptr[3] = (data >> 32) & 0xff;
ptr[2] = (data >> 40) & 0xff;
ptr[1] = (data >> 48) & 0xff;
ptr[0] = (data >> 56) & 0xff;
}
static inline void
get_string (unsigned char *ptr, char *dest, size_t len)
{
memcpy (dest, ptr, len);
}
static inline void
put_string (unsigned char *ptr, char *src, size_t len)
{
memcpy (ptr, src, len);
}
/* Use the target macro BYTES_BIG_ENDIAN to choose. */
static inline uint16_t
get_uint16 (const unsigned char *ptr)
{
if (BYTES_BIG_ENDIAN)
return get_uint16_be (ptr);
else
return get_uint16_le (ptr);
}
static inline uint32_t
get_uint32 (const unsigned char *ptr)
{
if (BYTES_BIG_ENDIAN)
return get_uint32_be (ptr);
else
return get_uint32_le (ptr);
}
static inline uint64_t
get_uint64 (const unsigned char *ptr)
{
if (BYTES_BIG_ENDIAN)
return get_uint64_be (ptr);
else
return get_uint64_le (ptr);
}
static inline void
put_uint16 (unsigned char *ptr, uint16_t data)
{
if (BYTES_BIG_ENDIAN)
put_uint16_be (ptr, data);
else
put_uint16_le (ptr, data);
}
static inline void
put_uint32 (unsigned char *ptr, uint32_t data)
{
if (BYTES_BIG_ENDIAN)
put_uint32_be (ptr, data);
else
put_uint32_le (ptr, data);
}
static inline void
put_uint64 (unsigned char *ptr, uint64_t data)
{
if (BYTES_BIG_ENDIAN)
put_uint64_be (ptr, data);
else
put_uint64_le (ptr, data);
}
#endif /* GCC_LTO_ENDIAN_H */
/* LTO routines for Mach-O object files.
Copyright 2010 Free Software Foundation, Inc.
Contributed by Steven Bosscher.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef LTO_MACH_O_H
#define LTO_MACH_O_H
/* On-disk file structures. */
/* Mach-O header (32 bits version). */
struct mach_o_header_32
{
unsigned char magic[4]; /* Magic number. */
unsigned char cputype[4]; /* CPU that this object is for. */
unsigned char cpusubtype[4]; /* CPU subtype. */
unsigned char filetype[4]; /* Type of file. */
unsigned char ncmds[4]; /* Number of load commands. */
unsigned char sizeofcmds[4]; /* Total size of load commands. */
unsigned char flags[4]; /* Flags for special featues. */
};
typedef struct mach_o_header_32 mach_o_header_32;
/* Mach-O header (64 bits version). */
struct mach_o_header_64
{
unsigned char magic[4]; /* Magic number. */
unsigned char cputype[4]; /* CPU that this object is for. */
unsigned char cpusubtype[4]; /* CPU subtype. */
unsigned char filetype[4]; /* Type of file. */
unsigned char ncmds[4]; /* Number of load commands. */
unsigned char sizeofcmds[4]; /* Total size of load commands. */
unsigned char flags[4]; /* Flags for special featues. */
unsigned char reserved[4]; /* Reserved. Duh. */
};
typedef struct mach_o_header_64 mach_o_header_64;
/* Magic number. */
#define MACH_O_MH_MAGIC 0xfeedface
#define MACH_O_MH_CIGAM 0xcefaedfe
#define MACH_O_MH_MAGIC_64 0xfeedfacf
#define MACH_O_MH_CIGAM_64 0xcffaedfe
/* Supported CPU types. */
#define MACH_O_CPU_TYPE_I386 7
#define MACH_O_CPU_TYPE_X86_64 7 + 0x1000000
#define MACH_O_CPU_TYPE_POWERPC 18
#define MACH_O_CPU_TYPE_POWERPC_64 18 + 0x1000000
/* Supported file types. */
#define MACH_O_MH_OBJECT 0x01
/* Mach-O load command data structure. */
struct mach_o_load_command
{
unsigned char cmd[4]; /* The type of load command. */
unsigned char cmdsize[4]; /* Size in bytes of load command data structure. */
};
typedef struct mach_o_load_command mach_o_load_command;
/* Supported load commands. We support only the segment load commands. */
#define MACH_O_LC_SEGMENT 0x01
#define MACH_O_LC_SEGMENT_64 0x19
/* LC_SEGMENT load command. */
struct mach_o_segment_command_32
{
unsigned char cmd[4]; /* The type of load command (LC_SEGMENT). */
unsigned char cmdsize[4]; /* Size in bytes of load command data structure. */
unsigned char segname[16]; /* Name of this segment. */
unsigned char vmaddr[4]; /* Virtual memory address of this segment. */
unsigned char vmsize[4]; /* Size there, in bytes. */
unsigned char fileoff[4]; /* Offset in bytes of the data to be mapped. */
unsigned char filesize[4]; /* Size in bytes on disk. */
unsigned char maxprot[4]; /* Maximum permitted vmem protection. */
unsigned char initprot[4]; /* Initial vmem protection. */
unsigned char nsects[4]; /* Number of sections in this segment. */
unsigned char flags[4]; /* Flags that affect the loading. */
};
typedef struct mach_o_segment_command_32 mach_o_segment_command_32;
/* LC_SEGMENT_64 load command. Only nsects matters for us, really. */
struct mach_o_segment_command_64
{
unsigned char cmd[4]; /* The type of load command (LC_SEGMENT_64). */
unsigned char cmdsize[4]; /* Size in bytes of load command data structure. */
unsigned char segname[16]; /* Name of this segment. */
unsigned char vmaddr[8]; /* Virtual memory address of this segment. */
unsigned char vmsize[8]; /* Size there, in bytes. */
unsigned char fileoff[8]; /* Offset in bytes of the data to be mapped. */
unsigned char filesize[8]; /* Size in bytes on disk. */
unsigned char maxprot[4]; /* Maximum permitted vmem protection. */
unsigned char initprot[4]; /* Initial vmem protection. */
unsigned char nsects[4]; /* Number of sections in this segment. */
unsigned char flags[4]; /* Flags that affect the loading. */
};
typedef struct mach_o_segment_command_64 mach_o_segment_command_64;
/* A Mach-O 32-bits section. */
struct mach_o_section_32
{
unsigned char sectname[16]; /* Section name. */
unsigned char segname[16]; /* Segment that the section belongs to. */
unsigned char addr[4]; /* Address of this section in memory. */
unsigned char size[4]; /* Size in bytes of this section. */
unsigned char offset[4]; /* File offset of this section. */
unsigned char align[4]; /* log2 of this section's alignment. */
unsigned char reloff[4]; /* File offset of this section's relocs. */
unsigned char nreloc[4]; /* Number of relocs for this section. */
unsigned char flags[4]; /* Section flags/attributes. */
unsigned char reserved1[4];
unsigned char reserved2[4];
};
typedef struct mach_o_section_32 mach_o_section_32;
/* A Mach-O 64-bits section. */
struct mach_o_section_64
{
unsigned char sectname[16]; /* Section name. */
unsigned char segname[16]; /* Segment that the section belongs to. */
unsigned char addr[8]; /* Address of this section in memory. */
unsigned char size[8]; /* Size in bytes of this section. */
unsigned char offset[4]; /* File offset of this section. */
unsigned char align[4]; /* log2 of this section's alignment. */
unsigned char reloff[4]; /* File offset of this section's relocs. */
unsigned char nreloc[4]; /* Number of relocs for this section. */
unsigned char flags[4]; /* Section flags/attributes. */
unsigned char reserved1[4];
unsigned char reserved2[4];
unsigned char reserved3[4];
};
typedef struct mach_o_section_64 mach_o_section_64;
/* Flags for Mach-O sections. LTO sections are marked with S_ATTR_DEBUG
to instruct the linker to ignore the sections. */
#define MACH_O_S_ATTR_DEBUG 0x02000000
/* In-memory file structures. */
/* Section data in output files is made of these. */
struct lto_mach_o_data_d
{
/* Pointer to data block. */
void *d_buf;
/* Size of data block. */
ssize_t d_size;
/* Next data block for this section. */
struct lto_mach_o_data_d *next;
};
typedef struct lto_mach_o_data_d *lto_mach_o_data;
/* This struct tracks the data for a section. */
struct lto_mach_o_section_d
{
/* Singly-linked list of section's data blocks. */
lto_mach_o_data data_chain;
/* Offset in string table of the section name. */
size_t strtab_offs;
/* Section name. */
const char *name;
/* Number of trailing padding bytes needed. */
ssize_t pad_needed;
/* Raw section header data. */
size_t section_size;
union {
struct {
char sectname[16];
char segname[16];
} section;
mach_o_section_32 section_32;
mach_o_section_64 section_64;
} u;
/* Next section for this file. */
struct lto_mach_o_section_d *next;
};
typedef struct lto_mach_o_section_d *lto_mach_o_section;
DEF_VEC_P (lto_mach_o_section);
DEF_VEC_ALLOC_P (lto_mach_o_section, heap);
/* A Mach-O file. */
struct lto_mach_o_file_d
{
/* The base information. */
lto_file base;
/* Common file members: */
/* The system file descriptor for the file. */
int fd;
/* The file's overall header. */
union {
/* We make use here of the fact that section_32 and section_64
have the same layout (except for section_64.reserved3). We
read the struct of proper size, but only address the first
member of this union. */
mach_o_header_64 header;
mach_o_header_32 header_32;
mach_o_header_64 header_64;
} u;
/* All sections in a varray. */
VEC(lto_mach_o_section, heap) *section_vec;
/* Readable file members: */
/* File total size. */
off_t file_size;
/* True if this file is open for writing. */
bool writable;
/* Section containing the __section_names section. */
lto_mach_o_section section_names_section;
/* Writable file members: */
/* The currently active section. */
lto_mach_o_section scn;
/* Linked list of data which must be freed *after* the file has been
closed. This is an annoying limitation of libelf. Which has been
faithfully reproduced here. */
struct lto_char_ptr_base *data;
};
typedef struct lto_mach_o_file_d lto_mach_o_file;
#endif /* LTO_MACH_O_H */
/* LTO declarations. /* LTO declarations.
Copyright 2009 Free Software Foundation, Inc. Copyright 2009, 2010 Free Software Foundation, Inc.
Contributed by CodeSourcery, Inc. Contributed by CodeSourcery, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -28,6 +28,7 @@ typedef struct lto_file_struct ...@@ -28,6 +28,7 @@ typedef struct lto_file_struct
{ {
/* The name of the file. */ /* The name of the file. */
const char *filename; const char *filename;
/* The offset for the object inside an ar archive file (or zero). */
off_t offset; off_t offset;
} lto_file; } lto_file;
......
...@@ -204,6 +204,14 @@ ...@@ -204,6 +204,14 @@
#define TARGET_ASM_FILE_END hook_void_void #define TARGET_ASM_FILE_END hook_void_void
#endif #endif
#ifndef TARGET_ASM_LTO_START
#define TARGET_ASM_LTO_START hook_void_void
#endif
#ifndef TARGET_ASM_LTO_END
#define TARGET_ASM_LTO_END hook_void_void
#endif
#ifndef TARGET_ASM_CODE_END #ifndef TARGET_ASM_CODE_END
#define TARGET_ASM_CODE_END hook_void_void #define TARGET_ASM_CODE_END hook_void_void
#endif #endif
...@@ -296,6 +304,8 @@ ...@@ -296,6 +304,8 @@
TARGET_ASM_CAN_OUTPUT_MI_THUNK, \ TARGET_ASM_CAN_OUTPUT_MI_THUNK, \
TARGET_ASM_FILE_START, \ TARGET_ASM_FILE_START, \
TARGET_ASM_FILE_END, \ TARGET_ASM_FILE_END, \
TARGET_ASM_LTO_START, \
TARGET_ASM_LTO_END, \
TARGET_ASM_CODE_END, \ TARGET_ASM_CODE_END, \
TARGET_ASM_EXTERNAL_LIBCALL, \ TARGET_ASM_EXTERNAL_LIBCALL, \
TARGET_ASM_MARK_DECL_PRESERVED, \ TARGET_ASM_MARK_DECL_PRESERVED, \
......
...@@ -238,6 +238,14 @@ struct gcc_target ...@@ -238,6 +238,14 @@ struct gcc_target
translation unit. */ translation unit. */
void (*file_end) (void); void (*file_end) (void);
/* Output any boilerplate text needed at the beginning of an
LTO output stream. */
void (*lto_start) (void);
/* Output any boilerplate text needed at the end of an
LTO output stream. */
void (*lto_end) (void);
/* Output any boilerplace text needed at the end of a /* Output any boilerplace text needed at the end of a
translation unit before debug and unwind info is emitted. */ translation unit before debug and unwind info is emitted. */
void (*code_end) (void); void (*code_end) (void);
......
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