aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@google.com>2009-04-22 17:47:46 +0000
committerDiego Novillo <dnovillo@google.com>2009-04-22 17:47:46 +0000
commitcfecc360cc6660be7f66d0928a41a0703fc10f64 (patch)
tree24f41ee282b72f587bad3b298910b33a00d5be6f /gcc
parent1bf6547b5535b5691e591169907ea9db8fe60fa7 (diff)
* lto-function-out.c (output_ssa_names): Do not emit
SSA names for memory symbols. (output_tree_with_context): Call decl_function_context to check if EXPR is a global symbol. * lto-function-in.c: Do not include cpplib.h (input_var_decl): Tidy. * lto-cgraph.c (input_node): Tidy. (input_cgraph_1): Tidy. (input_cgraph): Call lto_mark_file_for_ltrans. * lto-section-in.h: Include target.h and cgraph.h. (struct lto_file_decl_data): Tidy. Add field needs_ltrans_p. (lto_file_needs_ltrans_p): New. (lto_mark_file_for_ltrans): New. (cgraph_node_set_needs_ltrans_p): New. * Makefile.in (LTO_SECTION_IN_H): Add dependency on TARGET_H and CGRAPH_H. (LTO_SECTION_OUT_H): Fix incorrect dependencies. (lto-function-in.o): Remove dependency on dwarf2asm.h and dwarf2out.h. lto/ChangeLog * lto.c (free_section_data): Tidy. (lto_1_to_1_map): Tidy. (lto_add_all_inlinees): Tidy. (prefix_name_with_star): New. (get_filename_for_set): New. (lto_wpa_write_files): Call cgraph_node_set_needs_ltrans_p to determine what cgraph node sets to write. Call get_filename_for_set to compute temporary file names. (lto_execute_ltrans): Do not execute LTRANS on files with names that start with '*'. Move logic to execute LTRANS together so that LTRANS is invoked only if there are any files to compile. (do_whole_program_analysis): Only remove output files that do not start with '*'. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/lto@146606 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog.lto23
-rw-r--r--gcc/Makefile.in7
-rw-r--r--gcc/lto-cgraph.c8
-rw-r--r--gcc/lto-function-in.c10
-rw-r--r--gcc/lto-function-out.c8
-rw-r--r--gcc/lto-section-in.h55
-rw-r--r--gcc/lto/ChangeLog18
-rw-r--r--gcc/lto/lto.c283
8 files changed, 303 insertions, 109 deletions
diff --git a/gcc/ChangeLog.lto b/gcc/ChangeLog.lto
index e9c23529edf..04abd5bf222 100644
--- a/gcc/ChangeLog.lto
+++ b/gcc/ChangeLog.lto
@@ -1,3 +1,26 @@
+2009-04-22 Diego Novillo <dnovillo@google.com>
+
+ * lto-function-out.c (output_ssa_names): Do not emit
+ SSA names for memory symbols.
+ (output_tree_with_context): Call decl_function_context to
+ check if EXPR is a global symbol.
+ * lto-function-in.c: Do not include cpplib.h
+ (input_var_decl): Tidy.
+ * lto-cgraph.c (input_node): Tidy.
+ (input_cgraph_1): Tidy.
+ (input_cgraph): Call lto_mark_file_for_ltrans.
+ * lto-section-in.h: Include target.h and cgraph.h.
+ (struct lto_file_decl_data): Tidy.
+ Add field needs_ltrans_p.
+ (lto_file_needs_ltrans_p): New.
+ (lto_mark_file_for_ltrans): New.
+ (cgraph_node_set_needs_ltrans_p): New.
+ * Makefile.in (LTO_SECTION_IN_H): Add dependency on
+ TARGET_H and CGRAPH_H.
+ (LTO_SECTION_OUT_H): Fix incorrect dependencies.
+ (lto-function-in.o): Remove dependency on dwarf2asm.h and
+ dwarf2out.h.
+
2009-04-20 Diego Novillo <dnovillo@google.com>
Mainline merge @146424.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index acd335c5640..95dedca8179 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -881,8 +881,8 @@ DBGCNT_H = dbgcnt.h dbgcnt.def
EBIMAP_H = ebitmap.h sbitmap.h
LTO_TAGS_H = lto-tags.h tree.h sbitmap.h lto-header.h
LTO_SECTION_H = lto-section.h lto-header.h
-LTO_SECTION_IN_H = lto-section-in.h lto-header.h
-LTO_SECTION_OUT_H = lto-section-in.h lto-section.h lto-header.h
+LTO_SECTION_IN_H = lto-section-in.h lto-header.h $(TARGET_H) $(CGRAPH_H)
+LTO_SECTION_OUT_H = lto-section-out.h lto-section.h lto-header.h
LTO_TREE_IN_H = lto-tree-in.h $(LTO_SECTION_IN_H) $(PLUGIN_API_H)
LTO_OPTS_H = lto-section-in.h lto-opts.h
TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H)
@@ -2094,8 +2094,7 @@ lto-function-in.o: lto-function-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h tree-pass.h \
tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) except.h \
debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def $(LTO_TREE_IN_H) \
- lto-tree-tags.def $(LTO_SECTION_IN_H) output.h dwarf2asm.h dwarf2out.h \
- libfuncs.h lto-utils.h
+ lto-tree-tags.def $(LTO_SECTION_IN_H) output.h libfuncs.h lto-utils.h
lto-function-out.o : lto-function-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TOPLEV_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
$(VARRAY_H) $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h \
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 97728243f1e..b1f4a611fad 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -457,7 +457,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
Return the node read or overwriten. */
static struct cgraph_node *
-input_node (struct lto_file_decl_data* file_data,
+input_node (struct lto_file_decl_data *file_data,
struct lto_input_block *ib,
enum LTO_cgraph_tags tag)
{
@@ -634,7 +634,7 @@ input_edge (struct lto_input_block *ib, VEC(cgraph_node_ptr, heap) *nodes)
/* Input a cgraph from IB using the info in FILE_DATA. */
static void
-input_cgraph_1 (struct lto_file_decl_data* file_data,
+input_cgraph_1 (struct lto_file_decl_data *file_data,
struct lto_input_block *ib)
{
enum LTO_cgraph_tags tag;
@@ -717,6 +717,10 @@ input_cgraph (void)
input_cgraph_1 (file_data, ib);
lto_destroy_simple_input_block (file_data, LTO_section_cgraph,
ib, data, len);
+
+ /* Assume that every file read needs to be processed by LTRANS. */
+ if (flag_wpa)
+ lto_mark_file_for_ltrans (file_data);
}
/* Clear out the aux field that was used to store enough state to
diff --git a/gcc/lto-function-in.c b/gcc/lto-function-in.c
index 363391d2604..37513a4bd92 100644
--- a/gcc/lto-function-in.c
+++ b/gcc/lto-function-in.c
@@ -52,7 +52,6 @@ Boston, MA 02110-1301, USA. */
#include "lto-section-in.h"
#include "lto-tree-in.h"
#include "lto-utils.h"
-#include "cpplib.h"
tree input_tree (struct lto_input_block *, struct data_in *);
static tree input_tree_with_context (struct lto_input_block *ib,
@@ -2826,12 +2825,9 @@ input_var_decl (struct lto_input_block *ib, struct data_in *data_in)
SET_DECL_DEBUG_EXPR (decl, debug_expr);
}
- /* FIXME lto: Adapted from DWARF reader. Probably needs more thought.
- We are only interested in variables with static storage duration.
- I expected the test "DECL_FILE_SCOPE_P (decl)" to suffice below, but
- it does not work. In particular, the context of a vtable is the
- class to which it belongs. */
- if (!decl_function_context (decl))
+ /* Register symbols with file or global scope to mark what input
+ file has their definition. */
+ if (decl_function_context (decl) == NULL_TREE)
{
/* Variable has file scope, not local. Need to ensure static variables
between different files don't clash unexpectedly. */
diff --git a/gcc/lto-function-out.c b/gcc/lto-function-out.c
index bea2db0b35b..c85c495807f 100644
--- a/gcc/lto-function-out.c
+++ b/gcc/lto-function-out.c
@@ -1,4 +1,4 @@
-/* Write the gimple representation of a function and it's local
+/* Write the gimple representation of a function and its local
variables to a .o file.
Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
@@ -1557,7 +1557,9 @@ output_ssa_names (struct output_block *ob, struct function *fn)
{
tree ptr = VEC_index (tree, SSANAMES (fn), i);
- if (ptr == NULL_TREE || SSA_NAME_IN_FREE_LIST (ptr))
+ if (ptr == NULL_TREE
+ || SSA_NAME_IN_FREE_LIST (ptr)
+ || !is_gimple_reg (ptr))
continue;
output_uleb128 (ob, i);
@@ -3307,7 +3309,7 @@ output_tree_with_context (struct output_block *ob, tree expr, tree fn)
break;
case VAR_DECL:
- if (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
+ if (decl_function_context (expr) == NULL_TREE)
output_var_decl (ob, expr);
else
/* We should not be seeing local variables here. */
diff --git a/gcc/lto-section-in.h b/gcc/lto-section-in.h
index 1952da80984..a31eff23231 100644
--- a/gcc/lto-section-in.h
+++ b/gcc/lto-section-in.h
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_LTO_SECTION_IN_H
#define GCC_LTO_SECTION_IN_H
+#include "target.h"
+#include "cgraph.h"
#include "lto-header.h"
struct lto_input_block
@@ -51,10 +53,11 @@ struct lto_tree_ref_table {
unsigned int size; /* Size of array. */
};
-/* Structure to hold states of input scope. */
-struct lto_in_decl_state {
+/* Structure to hold states of input scope. */
+struct lto_in_decl_state
+{
/* Array of lto_in_decl_buffers to store type and decls streams. */
- struct lto_tree_ref_table streams[LTO_N_DECL_STREAMS];
+ struct lto_tree_ref_table streams[LTO_N_DECL_STREAMS];
/* If this in-decl state is associated with a function. FN_DECL
point to the FUNCTION_DECL. */
@@ -70,21 +73,21 @@ typedef struct lto_in_decl_state *lto_in_decl_state_ptr;
struct lto_file_decl_data
{
/* Decl state currently used. */
- struct lto_in_decl_state *current_decl_state;
+ struct lto_in_decl_state *current_decl_state;
/* Decl state corresponding to regions outside of any functions
in the compilation unit. */
- struct lto_in_decl_state *global_decl_state;
+ struct lto_in_decl_state *global_decl_state;
/* Hash table maps lto-related section names to location in file. */
htab_t function_decl_states;
- /* The .o file that these offsets relate to.
-
- FIXME!!! This will most likely have to be upgraded if the .o files
- have been archived. */
+ /* The .o file that these offsets relate to. */
const char *file_name;
+ /* Nonzero if this file should be recompiled with LTRANS. */
+ unsigned needs_ltrans_p : 1;
+
/* If the file is open, this is the fd of the mapped section. This
is -1 if the file has not yet been opened. */
int fd;
@@ -216,4 +219,38 @@ extern struct lto_in_decl_state *
extern void lto_debug_in_fun (struct lto_debug_context *, char);
#endif
+/* In lto-function-out.c */
+extern void lto_register_decl_definition (tree, struct lto_file_decl_data *);
+
+/* Return true if FILE needs to be compiled with LTRANS. */
+
+static inline bool
+lto_file_needs_ltrans_p (struct lto_file_decl_data *file)
+{
+ return file->needs_ltrans_p != 0;
+}
+
+/* Mark FILE to be compiled with LTRANS. */
+
+static inline void
+lto_mark_file_for_ltrans (struct lto_file_decl_data *file)
+{
+ file->needs_ltrans_p = 1;
+}
+
+/* Return true if any files in node set SET need to be compiled
+ with LTRANS. */
+
+static inline bool
+cgraph_node_set_needs_ltrans_p (cgraph_node_set set)
+{
+ cgraph_node_set_iterator csi;
+
+ for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ if (lto_file_needs_ltrans_p (csi_node (csi)->local.lto_file_data))
+ return true;
+
+ return false;
+}
+
#endif /* GCC_LTO_SECTION_IN_H */
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index dca7fb472ac..6e0d15ee791 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,21 @@
+2009-04-22 Diego Novillo <dnovillo@google.com>
+
+ * lto.c (free_section_data): Tidy.
+ (lto_1_to_1_map): Tidy.
+ (lto_add_all_inlinees): Tidy.
+ (prefix_name_with_star): New.
+ (get_filename_for_set): New.
+ (lto_wpa_write_files): Call cgraph_node_set_needs_ltrans_p
+ to determine what cgraph node sets to write.
+ Call get_filename_for_set to compute temporary file
+ names.
+ (lto_execute_ltrans): Do not execute LTRANS on files with
+ names that start with '*'.
+ Move logic to execute LTRANS together so that LTRANS is
+ invoked only if there are any files to compile.
+ (do_whole_program_analysis): Only remove output files
+ that do not start with '*'.
+
2009-04-06 Diego Novillo <dnovillo@google.com>
* lto-lang.c (lto_post_options): Set flag_excess_precision_cmdline.
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index ef4901ef105..183abf6b61a 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -503,15 +503,16 @@ free_section_data (struct lto_file_decl_data *file_data,
if (file_data->fd == -1)
return;
- computed_offset = ((intptr_t)offset) & page_mask;
- diff = (intptr_t)offset - computed_offset;
+ computed_offset = ((intptr_t) offset) & page_mask;
+ diff = (intptr_t) offset - computed_offset;
computed_len = len + diff;
- munmap ((void *)computed_offset, computed_len);
+ munmap ((void *) computed_offset, computed_len);
}
/* Vector of all cgraph node sets. */
-static GTY (()) VEC(cgraph_node_set ,gc) *lto_cgraph_node_sets;
+static GTY (()) VEC(cgraph_node_set, gc) *lto_cgraph_node_sets;
+
/* Group cgrah nodes by input files. This is used mainly for testing
right now. */
@@ -548,7 +549,7 @@ lto_1_to_1_map (void)
slot = pointer_map_contains (pmap, file_data);
if (slot)
- set = (cgraph_node_set) *slot;
+ set = (cgraph_node_set) *slot;
else
{
set = cgraph_node_set_new ();
@@ -556,6 +557,7 @@ lto_1_to_1_map (void)
*slot = set;
VEC_safe_push (cgraph_node_set, gc, lto_cgraph_node_sets, set);
}
+
cgraph_node_set_add (set, node);
}
@@ -570,7 +572,7 @@ finish:
/* Add inlined clone NODE and its master clone to SET, if NODE itself has
- inlined callee, recursively add the callees. */
+ inlined callees, recursively add the callees. */
static void
lto_add_inline_clones (cgraph_node_set set, struct cgraph_node *node,
@@ -594,8 +596,8 @@ lto_add_inline_clones (cgraph_node_set set, struct cgraph_node *node,
}
/* Compute the transitive closure of inlining of SET based on the
- information in the callgraph. Returns a bitmap of decls indexed
- by UID. */
+ information in the callgraph. Returns a bitmap of decls that have
+ been inlined into SET indexed by UID. */
static bitmap
lto_add_all_inlinees (cgraph_node_set set)
@@ -644,6 +646,8 @@ lto_add_all_inlinees (cgraph_node_set set)
}
while (changed);
+ /* Transitively add to SET all the inline clones for every node that
+ has been inlined. */
for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
{
node = csi_node (csi);
@@ -789,6 +793,7 @@ lto_scan_statics_in_cgraph_node (struct cgraph_node *node,
/* Return if the DECL of nodes has been visited before. */
if (bitmap_bit_p (context->seen_node_decls, DECL_UID (node->decl)))
return;
+
bitmap_set_bit (context->seen_node_decls, DECL_UID (node->decl));
state = lto_get_function_in_decl_state (node->local.lto_file_data,
@@ -834,7 +839,7 @@ lto_promote_cross_file_statics (void)
cgraph_node_set set;
cgraph_node_set_iterator csi;
globalize_context_t context;
-
+
memset (&context, 0, sizeof (context));
context.all_vars = lto_bitmap_alloc ();
context.all_static_vars = lto_bitmap_alloc ();
@@ -865,8 +870,76 @@ lto_promote_cross_file_statics (void)
lto_bitmap_free (context.all_static_vars);
}
+
+/* Given a file name FNAME, return a string with FNAME prefixed with '*'. */
+
+static char *
+prefix_name_with_star (const char *fname)
+{
+ char *star_fname;
+ size_t len;
+
+ len = strlen (fname) + 1 + 1;
+ star_fname = XNEWVEC (char, len);
+ snprintf (star_fname, len, "*%s", fname);
+
+ return star_fname;
+}
+
+/* Return a file name associated with cgraph node set SET. This may
+ be a new temporary file name if SET needs to be processed by
+ LTRANS, or the original file name if all the nodes in SET belong to
+ the same input file. */
+
+static char *
+get_filename_for_set (cgraph_node_set set)
+{
+ char *fname = NULL;
+ static const size_t max_suffix_len = 100;
+
+ if (cgraph_node_set_needs_ltrans_p (set))
+ {
+ /* Create a new temporary file to store SET. To facilitate
+ debugging, use file names from SET as part of the new
+ temporary file name. */
+ cgraph_node_set_iterator si;
+ struct pointer_set_t *pset = pointer_set_create ();
+ char *suffix = NULL;
+ for (si = csi_start (set); !csi_end_p (si); csi_next (&si))
+ {
+ struct cgraph_node *n = csi_node (si);
+ const char *f = lbasename (n->local.lto_file_data->file_name);
+ if (!pointer_set_insert (pset, n->local.lto_file_data))
+ suffix = reconcat (suffix, "-", f, suffix, NULL);
+ if (strlen (suffix) > max_suffix_len)
+ break;
+ }
+ pointer_set_destroy (pset);
+ suffix = reconcat (suffix, suffix, ".lto.o", NULL);
+ fname = make_cwd_temp_file (suffix);
+
+ /* If suffix proved to be too long, try something smaller. */
+ if (fname == NULL)
+ fname = make_cwd_temp_file (".lto.o");
+
+ gcc_assert (fname);
+ }
+ else
+ {
+ /* Since SET does not need to be processed by LTRANS, use
+ the original file name and mark it with a '*' prefix so that
+ lto_execute_ltrans knows not to send it to ltrans_driver. */
+ cgraph_node_set_iterator si = csi_start (set);
+ struct cgraph_node *first = csi_node (si);
+ fname = prefix_name_with_star (first->local.lto_file_data->file_name);
+ }
+
+ return fname;
+}
+
static lto_file *current_lto_file;
+
/* Write all output files in WPA mode. Returns a NULL-terminated array of
output file names. */
@@ -874,7 +947,7 @@ static char **
lto_wpa_write_files (void)
{
char **output_files;
- unsigned i, n_sets;
+ unsigned i, n_sets, last_out_file_ix, num_out_files;
lto_file *file;
cgraph_node_set set;
bitmap decls;
@@ -882,7 +955,10 @@ lto_wpa_write_files (void)
timevar_push (TV_WHOPR_WPA);
- /* Include all inlined functions. */
+ /* Include all inlined functions and determine what sets need to be
+ compiled by LTRANS. After this loop, only those sets that
+ contain callgraph nodes from more than one file will need to be
+ compiled by LTRANS. */
for (i = 0; VEC_iterate (cgraph_node_set, lto_cgraph_node_sets, i, set); i++)
{
decls = lto_add_all_inlinees (set);
@@ -899,39 +975,48 @@ lto_wpa_write_files (void)
timevar_push (TV_WHOPR_WPA_IO);
- output_files = XNEWVEC (char *, VEC_length (cgraph_node_set,
- lto_cgraph_node_sets) + 1);
+ /* The number of output files depends on the number of input files
+ and how many callgraph node sets we create. Reserve enough space
+ for the maximum of these two. */
+ num_out_files = MAX (VEC_length (cgraph_node_set, lto_cgraph_node_sets),
+ num_in_fnames);
+ output_files = XNEWVEC (char *, num_out_files + 1);
n_sets = VEC_length (cgraph_node_set, lto_cgraph_node_sets);
for (i = 0; i < n_sets; i++)
{
- char *temp_filename = make_cwd_temp_file (".lto.o");
+ char *temp_filename;
+ set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i);
+ temp_filename = get_filename_for_set (set);
output_files[i] = temp_filename;
- file = lto_elf_file_open (temp_filename, true);
- if (!file)
- fatal_error ("lto_elf_file_open() failed");
+ if (cgraph_node_set_needs_ltrans_p (set))
+ {
+ /* Write all the nodes in SET to TEMP_FILENAME. */
+ file = lto_elf_file_open (temp_filename, true);
+ if (!file)
+ fatal_error ("lto_elf_file_open() failed");
- lto_set_current_out_file (file);
- lto_new_extern_inline_states ();
+ lto_set_current_out_file (file);
+ lto_new_extern_inline_states ();
- decls = VEC_index (bitmap, inlined_decls, i);
- lto_force_functions_extern_inline (decls);
+ decls = VEC_index (bitmap, inlined_decls, i);
+ lto_force_functions_extern_inline (decls);
- /* Set AUX to 1 in the last LTRANS file. */
- set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i);
- set->aux = (void*) ((intptr_t) (i == (n_sets - 1)));
- ipa_write_summaries_of_cgraph_node_set (set);
- lto_delete_extern_inline_states ();
-
- lto_set_current_out_file (NULL);
- lto_elf_file_close (file);
+ ipa_write_summaries_of_cgraph_node_set (set);
+ lto_delete_extern_inline_states ();
+
+ lto_set_current_out_file (NULL);
+ lto_elf_file_close (file);
+ }
}
+ last_out_file_ix = n_sets;
+
lto_stats.num_output_files += n_sets;
- output_files[i] = NULL;
+ output_files[last_out_file_ix] = NULL;
for (i = 0; VEC_iterate (bitmap, inlined_decls, i, decls); i++)
lto_bitmap_free (decls);
@@ -967,31 +1052,6 @@ lto_execute_ltrans (char *const *files)
timevar_push (TV_WHOPR_WPA_LTRANS_EXEC);
- /* Set the CC environment variable. */
- env_val = getenv ("COLLECT_GCC");
- if (!env_val)
- fatal_error ("environment variable COLLECT_GCC must be set");
-
- obstack_init (&env_obstack);
- obstack_grow (&env_obstack, "CC=", sizeof ("CC=") - 1);
- obstack_grow (&env_obstack, env_val, strlen (env_val) + 1);
- putenv (XOBFINISH (&env_obstack, char *));
-
- /* Set the CFLAGS environment variable. */
- env_val = getenv ("COLLECT_GCC_OPTIONS");
- if (!env_val)
- fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set");
-
- obstack_init (&env_obstack);
- obstack_grow (&env_obstack, "CFLAGS=", sizeof ("CFLAGS=") - 1);
- obstack_grow (&env_obstack, env_val, strlen (env_val));
- obstack_grow (&env_obstack, extra_cflags, strlen (extra_cflags) + 1);
- putenv (XOBFINISH (&env_obstack, char *));
-
- pex = pex_init (0, "lto1", NULL);
- if (pex == NULL)
- fatal_error ("pex_init failed: %s", xstrerror (errno));
-
/* Initalize the arguments for the LTRANS driver. */
for (i = 0; files[i]; ++i);
argv = XNEWVEC (char *, i + 2);
@@ -1008,47 +1068,99 @@ lto_execute_ltrans (char *const *files)
*argv_ptr++ = ltrans_driver;
for (i = 0; files[i]; ++i)
{
- *argv_ptr++ = files[i];
-
- /* Replace the .o suffix with a .ltrans.o suffix and write the resulting
- name to the LTRANS output list. */
- if (ltrans_output_list_stream)
+ size_t len;
+
+ /* If the file is prefixed with a '*', it means that we do not
+ need to re-compile it with LTRANS because it has not been
+ modified by WPA. Skip it from the command line to
+ ltrans-driver, but add it to ltrans_output_list_stream so it
+ is linked after we are done. */
+ if (files[i][0] == '*')
{
- size_t len = strlen (files[i]) - 2;
+ size_t len = strlen (files[i]) - 1;
+ if (ltrans_output_list_stream)
+ if (fwrite (&files[i][1], 1, len, ltrans_output_list_stream) < len
+ || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1)
+ error ("writing to LTRANS output list %s: %m",
+ ltrans_output_list);
+ }
+ else
+ {
+ /* Otherwise, add FILES[I] to ltrans-driver's command line
+ and add the resulting file to LTRANS output list. */
+ *argv_ptr++ = files[i];
+
+ /* Replace the .o suffix with a .ltrans.o suffix and write
+ the resulting name to the LTRANS output list. */
+ if (ltrans_output_list_stream)
+ {
+ len = strlen (files[i]) - 2;
- if (fwrite (files[i], 1, len, ltrans_output_list_stream) < len
- || fwrite (".ltrans.o\n", 1, 10, ltrans_output_list_stream) < 10)
- error ("writing to LTRANS output list %s: %m", ltrans_output_list);
+ if (fwrite (files[i], 1, len, ltrans_output_list_stream) < len
+ || fwrite (".ltrans.o\n", 1, 10, ltrans_output_list_stream)
+ < 10)
+ error ("writing to LTRANS output list %s: %m",
+ ltrans_output_list);
+ }
}
}
+
*argv_ptr++ = NULL;
/* Close the LTRANS output list. */
if (ltrans_output_list_stream && fclose (ltrans_output_list_stream))
error ("closing LTRANS output list %s: %m", ltrans_output_list);
- /* Execute the LTRANS driver. */
- errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL, NULL,
- &err);
- if (errmsg)
- fatal_error ("%s: %s", errmsg, xstrerror (err));
-
- if (!pex_get_status (pex, 1, &status))
- fatal_error ("can't get program status: %s", xstrerror (errno));
-
- pex_free (pex);
-
- if (status)
+ /* If there are any files to compile, execute the LTRANS driver. */
+ if (argv[1] != NULL)
{
- if (WIFSIGNALED (status))
+ /* Set the CC environment variable. */
+ env_val = getenv ("COLLECT_GCC");
+ if (!env_val)
+ fatal_error ("environment variable COLLECT_GCC must be set");
+
+ obstack_init (&env_obstack);
+ obstack_grow (&env_obstack, "CC=", sizeof ("CC=") - 1);
+ obstack_grow (&env_obstack, env_val, strlen (env_val) + 1);
+ putenv (XOBFINISH (&env_obstack, char *));
+
+ /* Set the CFLAGS environment variable. */
+ env_val = getenv ("COLLECT_GCC_OPTIONS");
+ if (!env_val)
+ fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set");
+
+ obstack_init (&env_obstack);
+ obstack_grow (&env_obstack, "CFLAGS=", sizeof ("CFLAGS=") - 1);
+ obstack_grow (&env_obstack, env_val, strlen (env_val));
+ obstack_grow (&env_obstack, extra_cflags, strlen (extra_cflags) + 1);
+ putenv (XOBFINISH (&env_obstack, char *));
+
+ pex = pex_init (0, "lto1", NULL);
+ if (pex == NULL)
+ fatal_error ("pex_init failed: %s", xstrerror (errno));
+
+ errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL, NULL,
+ &err);
+ if (errmsg)
+ fatal_error ("%s: %s", errmsg, xstrerror (err));
+
+ if (!pex_get_status (pex, 1, &status))
+ fatal_error ("can't get program status: %s", xstrerror (errno));
+
+ if (status)
{
- int sig = WTERMSIG (status);
- fatal_error ("%s terminated with signal %d [%s]%s",
- argv[0], sig, strsignal (sig),
- WCOREDUMP (status) ? ", core dumped" : "");
+ if (WIFSIGNALED (status))
+ {
+ int sig = WTERMSIG (status);
+ fatal_error ("%s terminated with signal %d [%s]%s",
+ argv[0], sig, strsignal (sig),
+ WCOREDUMP (status) ? ", core dumped" : "");
+ }
+ else
+ fatal_error ("%s terminated with status %d", argv[0], status);
}
- else
- fatal_error ("%s terminated with status %d", argv[0], status);
+
+ pex_free (pex);
}
timevar_pop (TV_WHOPR_WPA_LTRANS_EXEC);
@@ -1677,9 +1789,12 @@ do_whole_program_analysis (void)
for (i = 0; output_files[i]; ++i)
{
- lto_maybe_unlink (output_files[i]);
+ if (output_files[i][0] != '*')
+ lto_maybe_unlink (output_files[i]);
+
free (output_files[i]);
}
+
XDELETEVEC (output_files);
}