This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFA][lto merge]: support for gcc @file
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Ian Taylor <iant at google dot com>, Mark Mitchell <mark at codesourcery dot com>
- Date: Fri, 17 Apr 2009 15:58:55 -0400
- Subject: [RFA][lto merge]: support for gcc @file
This patch http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00063.html adds
support to the gcc driver to be invoked with @file to avoid
massive command lines that are sometimes generated in the context
of LTO.
This feature is not necessarily related to LTO, but we have found
it useful. I don't think we have maintainers for this area, so I
need global reviewers to approve it.
Bootstrapped and tested on x86_64. The feature is heavily tested
by -fwhopr, which I'm still not merging in.
Thanks. Diego.
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c (revision 146200)
+++ tree-pretty-print.c (working copy)
@@ -51,10 +51,10 @@ static void do_niy (pretty_printer *, co
#define NIY do_niy(buffer,node)
-#define PRINT_FUNCTION_NAME(NODE) pp_printf \
- (buffer, "%s", TREE_CODE (NODE) == NOP_EXPR ? \
- lang_hooks.decl_printable_name (TREE_OPERAND (NODE, 0), 1) : \
- lang_hooks.decl_printable_name (NODE, 1))
+#define PRINT_FUNCTION_NAME(NODE) pp_printf \
+ (buffer, "%s", TREE_CODE (NODE) == NOP_EXPR \
+ ? get_name (TREE_OPERAND (NODE, 0)) \
+ : get_name (NODE))
static pretty_printer buffer;
static int initialized = 0;
@@ -488,6 +488,7 @@ dump_generic_node (pretty_printer *buffe
case TREE_BINFO:
dump_generic_node (buffer, BINFO_TYPE (node), spc, flags, false);
+ break;
case TREE_VEC:
{
@@ -551,8 +552,7 @@ dump_generic_node (pretty_printer *buffe
else if (TREE_CODE (node) == VECTOR_TYPE)
{
pp_string (buffer, "vector ");
- dump_generic_node (buffer, TREE_TYPE (node),
- spc, flags, false);
+ dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
}
else if (TREE_CODE (node) == INTEGER_TYPE)
{
@@ -562,6 +562,24 @@ dump_generic_node (pretty_printer *buffe
pp_decimal_int (buffer, TYPE_PRECISION (node));
pp_string (buffer, ">");
}
+ else if (TREE_CODE (node) == COMPLEX_TYPE)
+ {
+ pp_string (buffer, "__complex__ ");
+ dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
+ }
+ else if (TREE_CODE (node) == REAL_TYPE)
+ {
+ pp_string (buffer, "<float:");
+ pp_decimal_int (buffer, TYPE_PRECISION (node));
+ pp_string (buffer, ">");
+ }
+ else if (TREE_CODE (node) == FIXED_POINT_TYPE)
+ {
+ pp_string (buffer, "<fixed-point-");
+ pp_string (buffer, TYPE_SATURATING (node) ? "sat:" : "nonsat:");
+ pp_decimal_int (buffer, TYPE_PRECISION (node));
+ pp_string (buffer, ">");
+ }
else
pp_string (buffer, "<unnamed type>");
}
@@ -572,7 +590,12 @@ dump_generic_node (pretty_printer *buffe
case REFERENCE_TYPE:
str = (TREE_CODE (node) == POINTER_TYPE ? "*" : "&");
- if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
+ if (TREE_TYPE (node) == NULL)
+ {
+ pp_string (buffer, str);
+ pp_string (buffer, "<null type>");
+ }
+ else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
{
tree fnode = TREE_TYPE (node);
@@ -612,11 +635,6 @@ dump_generic_node (pretty_printer *buffe
NIY;
break;
- case METHOD_TYPE:
- dump_decl_name (buffer, TYPE_NAME (TYPE_METHOD_BASETYPE (node)), flags);
- pp_string (buffer, "::");
- break;
-
case TARGET_MEM_REF:
{
const char *sep = "";
@@ -710,7 +728,12 @@ dump_generic_node (pretty_printer *buffe
if (TYPE_NAME (node))
dump_generic_node (buffer, TYPE_NAME (node), spc, flags, false);
- else
+ else if (!(flags & TDF_SLIM))
+ /* FIXME: If we eliminate the 'else' above and attempt
+ to show the fields for named types, we may get stuck
+ following a cycle of pointers to structs. The alleged
+ self-reference check in print_struct_decl will not detect
+ cycles involving more than one pointer or struct type. */
print_struct_decl (buffer, node, spc, flags);
break;
}
@@ -836,6 +859,23 @@ dump_generic_node (pretty_printer *buffe
break;
case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ dump_generic_node (buffer, TREE_TYPE (node), spc, flags, false);
+ pp_space (buffer);
+ if (TREE_CODE (node) == METHOD_TYPE)
+ {
+ if (TYPE_METHOD_BASETYPE (node))
+ dump_decl_name (buffer, TYPE_NAME (TYPE_METHOD_BASETYPE (node)),
+ flags);
+ else
+ pp_string (buffer, "<null method basetype>");
+ pp_string (buffer, "::");
+ }
+ if (TYPE_NAME (node) && DECL_NAME (TYPE_NAME (node)))
+ dump_decl_name (buffer, TYPE_NAME (node), flags);
+ else
+ pp_printf (buffer, "<T%x>", TYPE_UID (node));
+ dump_function_declaration (buffer, node, spc, flags);
break;
case FUNCTION_DECL:
@@ -2206,8 +2246,8 @@ print_struct_decl (pretty_printer *buffe
Maybe this could be solved by looking at the scope in which the
structure was declared. */
if (TREE_TYPE (tmp) != node
- || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
- && TREE_TYPE (TREE_TYPE (tmp)) != node))
+ && (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE
+ || TREE_TYPE (TREE_TYPE (tmp)) != node))
{
print_declaration (buffer, tmp, spc+2, flags);
pp_newline (buffer);
Index: cgraph.c
===================================================================
--- cgraph.c (revision 146200)
+++ cgraph.c (working copy)
@@ -1527,4 +1527,172 @@ cgraph_add_new_function (tree fndecl, bo
}
}
+/*
+ * A call-graph set is a collection of call-graph nodes. A node can
+ * appear in multiple sets. Call-graph sets are garbage-collected.
+ */
+
+/* Hash a cgraph node set element. */
+
+static hashval_t
+hash_cgraph_node_set_element (const void *p)
+{
+ const_cgraph_node_set_element element = (const_cgraph_node_set_element) p;
+ return htab_hash_pointer (element->node);
+}
+
+/* Compare two cgraph node set elements. */
+
+static int
+eq_cgraph_node_set_element (const void *p1, const void *p2)
+{
+ const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1;
+ const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2;
+
+ return e1->node == e2->node;
+}
+
+/* Create a new cgraph node set. */
+
+cgraph_node_set
+cgraph_node_set_new (void)
+{
+ cgraph_node_set new_node_set;
+
+ new_node_set = GGC_NEW (struct cgraph_node_set_def);
+ new_node_set->hashtab = htab_create_ggc (10,
+ hash_cgraph_node_set_element,
+ eq_cgraph_node_set_element,
+ NULL);
+ new_node_set->nodes = NULL;
+ return new_node_set;
+}
+
+/* Add cgraph_node NODE to cgraph_node_set SET. */
+
+void
+cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
+{
+ void **slot;
+ cgraph_node_set_element element;
+ struct cgraph_node_set_element_def dummy;
+
+ dummy.node = node;
+ slot = htab_find_slot (set->hashtab, &dummy, INSERT);
+
+ if (*slot != HTAB_EMPTY_ENTRY)
+ {
+#ifdef ENABLE_CHECKING
+ element = (cgraph_node_set_element) *slot;
+ gcc_assert (node == element->node
+ && (VEC_index (cgraph_node_ptr, set->nodes, element->index)
+ == node));
+#endif
+ return;
+ }
+
+ /* Insert node into hash table. */
+ element =
+ (cgraph_node_set_element) GGC_NEW (struct cgraph_node_set_element_def);
+ element->node = node;
+ element->index = VEC_length (cgraph_node_ptr, set->nodes);
+ *slot = element;
+
+ /* Insert into node vector. */
+ VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node);
+}
+
+/* Remove cgraph_node NODE from cgraph_node_set SET. */
+
+void
+cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
+{
+ void **slot, **last_slot;
+ cgraph_node_set_element element, last_element;
+ struct cgraph_node *last_node;
+ struct cgraph_node_set_element_def dummy;
+
+ dummy.node = node;
+ slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
+ if (slot == NULL)
+ return;
+
+ element = (cgraph_node_set_element) *slot;
+#ifdef ENABLE_CHECKING
+ gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
+ == node);
+#endif
+
+ /* Remove from vector. We do this by swapping node with the last element
+ of the vector. */
+ last_node = VEC_pop (cgraph_node_ptr, set->nodes);
+ if (last_node != node)
+ {
+ dummy.node = last_node;
+ last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
+ last_element = (cgraph_node_set_element) *last_slot;
+ gcc_assert (last_element);
+
+ /* Move the last element to the original spot of NODE. */
+ last_element->index = element->index;
+ VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
+ last_node);
+ }
+
+ /* Remove element from hash table. */
+ htab_clear_slot (set->hashtab, slot);
+ ggc_free (element);
+}
+
+/* Find NODE in SET and return an iterator to it if found. A null iterator
+ is returned if NODE is not in SET. */
+
+cgraph_node_set_iterator
+cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
+{
+ void **slot;
+ struct cgraph_node_set_element_def dummy;
+ cgraph_node_set_element element;
+ cgraph_node_set_iterator csi;
+
+ dummy.node = node;
+ slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
+ if (slot == NULL)
+ csi.index = (unsigned) ~0;
+ else
+ {
+ element = (cgraph_node_set_element) *slot;
+#ifdef ENABLE_CHECKING
+ gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
+ == node);
+#endif
+ csi.index = element->index;
+ }
+ csi.set = set;
+
+ return csi;
+}
+
+/* Dump content of SET to file F. */
+
+void
+dump_cgraph_node_set (FILE *f, cgraph_node_set set)
+{
+ cgraph_node_set_iterator iter;
+
+ for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
+ {
+ struct cgraph_node *node = csi_node (iter);
+ dump_cgraph_node (f, node);
+ }
+}
+
+/* Dump content of SET to stderr. */
+
+void
+debug_cgraph_node_set (cgraph_node_set set)
+{
+ dump_cgraph_node_set (stderr, set);
+}
+
#include "gt-cgraph.h"
Index: cgraph.h
===================================================================
--- cgraph.h (revision 146200)
+++ cgraph.h (working copy)
@@ -189,6 +189,12 @@ struct cgraph_node GTY((chain_next ("%h.
tree inline_decl;
};
+typedef struct cgraph_node *cgraph_node_ptr;
+
+DEF_VEC_P(cgraph_node_ptr);
+DEF_VEC_ALLOC_P(cgraph_node_ptr,heap);
+DEF_VEC_ALLOC_P(cgraph_node_ptr,gc);
+
#define DEFCIFCODE(code, string) CIF_ ## code,
/* Reasons for inlining failures. */
typedef enum {
@@ -302,6 +308,40 @@ extern GTY(()) struct cgraph_node *cgrap
extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
extern GTY(()) int cgraph_order;
+/* A cgraph node set is a collection of cgraph nodes. A cgraph node
+ can appear in multiple sets. */
+
+struct cgraph_node_set_def GTY(())
+{
+ htab_t GTY((param_is (struct cgraph_node_set_element_def))) hashtab;
+ VEC(cgraph_node_ptr, gc) *nodes;
+ PTR GTY ((skip)) aux;
+};
+
+typedef struct cgraph_node_set_def *cgraph_node_set;
+
+DEF_VEC_P(cgraph_node_set);
+DEF_VEC_ALLOC_P(cgraph_node_set,gc);
+DEF_VEC_ALLOC_P(cgraph_node_set,heap);
+
+/* A cgraph node set element contains an index in the vector of nodes in
+ the set. */
+
+struct cgraph_node_set_element_def GTY(())
+{
+ struct cgraph_node *node;
+ HOST_WIDE_INT index;
+};
+
+typedef struct cgraph_node_set_element_def *cgraph_node_set_element;
+typedef const struct cgraph_node_set_element_def
*const_cgraph_node_set_element;
+
+typedef struct
+{
+ cgraph_node_set set;
+ unsigned index;
+} cgraph_node_set_iterator;
+
/* In cgraph.c */
void dump_cgraph (FILE *);
void debug_cgraph (void);
@@ -341,6 +381,69 @@ enum availability cgraph_function_body_a
void cgraph_add_new_function (tree, bool);
const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
+cgraph_node_set cgraph_node_set_new (void);
+cgraph_node_set_iterator cgraph_node_set_find (cgraph_node_set set,
+ struct cgraph_node *node);
+void cgraph_node_set_add (cgraph_node_set, struct cgraph_node *);
+void cgraph_node_set_remove (cgraph_node_set, struct cgraph_node *);
+void dump_cgraph_node_set (FILE *f, cgraph_node_set);
+void debug_cgraph_node_set (cgraph_node_set);
+const char *cgraph_inline_failed_string (cgraph_inline_failed_t);
+
+/* Return true if iterator CSI points to nothing. */
+
+static inline bool
+csi_end_p (cgraph_node_set_iterator csi)
+{
+ return csi.index >= VEC_length (cgraph_node_ptr, csi.set->nodes);
+}
+
+/* Advance iterator CSI. */
+
+static inline void
+csi_next (cgraph_node_set_iterator *csi)
+{
+ csi->index++;
+}
+
+/* Return the node pointed to by CSI. */
+
+static inline struct cgraph_node *
+csi_node (cgraph_node_set_iterator csi)
+{
+ return VEC_index (cgraph_node_ptr, csi.set->nodes, csi.index);
+}
+
+/* Return an iterator to the first node in SET. */
+
+static inline cgraph_node_set_iterator
+csi_start (cgraph_node_set set)
+{
+ cgraph_node_set_iterator csi;
+
+ csi.set = set;
+ csi.index = 0;
+ return csi;
+}
+
+/* Return true if SET contains NODE. */
+
+static inline bool
+cgraph_node_in_set_p (struct cgraph_node *node, cgraph_node_set set)
+{
+ cgraph_node_set_iterator csi;
+ csi = cgraph_node_set_find (set, node);
+ return !csi_end_p (csi);
+}
+
+/* Return number of nodes in SET. */
+
+static inline size_t
+cgraph_node_set_size (cgraph_node_set set)
+{
+ return htab_elements (set->hashtab);
+}
+
/* In cgraphunit.c */
void cgraph_finalize_function (tree, bool);
void cgraph_mark_if_needed (tree);
Index: tree.h
===================================================================
--- tree.h (revision 146200)
+++ tree.h (working copy)
@@ -183,6 +183,22 @@ DEF_VEC_P(tree);
DEF_VEC_ALLOC_P(tree,gc);
DEF_VEC_ALLOC_P(tree,heap);
+/* We have to be able to tell cgraph about the needed-ness of the target
+ of an alias. This requires that the decl have been defined. Aliases
+ that precede their definition have to be queued for later processing. */
+
+typedef struct alias_pair GTY(())
+{
+ tree decl;
+ tree target;
+} alias_pair;
+
+/* Define gc'd vector type. */
+DEF_VEC_O(alias_pair);
+DEF_VEC_ALLOC_O(alias_pair,gc);
+
+extern GTY(()) VEC(alias_pair,gc) * alias_pairs;
+
/* Classify which part of the compiler has defined a given builtin function.
Note that we assume below that this is no more than two bits. */
@@ -1272,7 +1288,7 @@ extern void omp_clause_range_check_faile
This is interesting in an inline function, since it might not need
to be compiled separately.
Nonzero in a RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE or ENUMERAL_TYPE
- if the sdb debugging info for the type has been written.
+ if the debugging info for the type has been written.
In a BLOCK node, nonzero if reorder_blocks has already seen this block.
In an SSA_NAME node, nonzero if the SSA_NAME occurs in an abnormal
PHI node. */
@@ -2478,9 +2494,9 @@ struct function;
/* For FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
QUAL_UNION_TYPE node that the field is a member of. For VAR_DECL,
- PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, this
- points to either the FUNCTION_DECL for the containing function,
- the RECORD_TYPE or UNION_TYPE for the containing type, or
+ PARM_DECL, FUNCTION_DECL, LABEL_DECL, RESULT_DECL, and CONST_DECL
+ nodes, this points to either the FUNCTION_DECL for the containing
+ function, the RECORD_TYPE or UNION_TYPE for the containing type, or
NULL_TREE or a TRANSLATION_UNIT_DECL if the given decl has "file
scope". */
#define DECL_CONTEXT(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.context)
@@ -5027,6 +5043,7 @@ extern void process_pending_assemble_ext
extern void finish_aliases_1 (void);
extern void finish_aliases_2 (void);
extern tree emutls_decl (tree);
+extern void remove_unreachable_alias_pairs (void);
/* In stmt.c */
extern void expand_computed_goto (tree);
Index: tree-pass.h
===================================================================
--- tree-pass.h (revision 146200)
+++ tree-pass.h (working copy)
@@ -154,6 +154,7 @@ struct rtl_opt_pass
struct varpool_node;
struct cgraph_node;
+struct cgraph_node_set_def;
/* Description of IPA pass with generate summary, write, execute, read and
transform stages. */
@@ -166,7 +167,7 @@ struct ipa_opt_pass
void (*generate_summary) (void);
/* This hook is used to serialize IPA summaries on disk. */
- void (*write_summary) (void);
+ void (*write_summary) (struct cgraph_node_set_def *);
/* For most ipa passes, the information can only be deserialized in
one chunk. However, function bodies are read function at a time
Index: diagnostic.h
===================================================================
--- diagnostic.h (revision 146200)
+++ diagnostic.h (working copy)
@@ -238,4 +238,8 @@ extern void print_gimple_stmt (FILE *, g
extern void print_gimple_expr (FILE *, gimple, int, int);
extern void dump_gimple_stmt (pretty_printer *, gimple, int, int);
+/* In toplev.c */
+extern bool default_tree_printer (pretty_printer *, text_info *, const char *,
+ int, bool, bool, bool);
+
#endif /* ! GCC_DIAGNOSTIC_H */
Index: gcc.c
===================================================================
--- gcc.c (revision 146200)
+++ gcc.c (working copy)
@@ -4741,6 +4741,49 @@ spec_path (char *path, void *data)
return NULL;
}
+/* Create a temporary FILE with the contents of ARGV. Add @FILE to the
+ argument list. */
+
+static void
+create_at_file (char **argv)
+{
+ char *temp_file = make_temp_file ("");
+ char *at_argument = concat ("@", temp_file, NULL);
+ FILE *f = fopen (temp_file, "w");
+ int status;
+
+ if (f == NULL)
+ fatal ("could not open temporary response file %s",
+ temp_file);
+
+ status = writeargv (argv, f);
+
+ if (status)
+ fatal ("could not write to temporary response file %s",
+ temp_file);
+
+ status = fclose (f);
+
+ if (EOF == status)
+ fatal ("could not close temporary response file %s",
+ temp_file);
+
+ store_arg (at_argument, 0, 0);
+
+ record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+}
+
+/* True if we should compile INFILE. */
+
+static bool
+compile_input_file_p (struct infile *infile)
+{
+ if ((!infile->language) || (infile->language[0] != '*'))
+ if (infile->incompiler == input_file_compiler)
+ return true;
+ return false;
+}
+
/* Process the sub-spec SPEC as a portion of a larger spec.
This is like processing a whole spec except that we do
not initialize at the beginning and we do not supply a
@@ -5107,9 +5150,37 @@ do_spec_1 (const char *spec, int inswitc
case 'i':
if (combine_inputs)
{
- for (i = 0; (int) i < n_infiles; i++)
- if ((!infiles[i].language) || (infiles[i].language[0] != '*'))
- if (infiles[i].incompiler == input_file_compiler)
+ if (at_file_supplied)
+ {
+ /* We are going to expand `%i' to `@FILE', where FILE
+ is a newly-created temporary filename. The filenames
+ that would usually be expanded in place of %o will be
+ written to the temporary file. */
+ char **argv;
+ int n_files = 0;
+ int j;
+
+ for (i = 0; i < n_infiles; i++)
+ if (compile_input_file_p (&infiles[i]))
+ n_files++;
+
+ argv = (char **) alloca (sizeof (char *) * (n_files + 1));
+
+ /* Copy the strings over. */
+ for (i = 0, j = 0; i < n_infiles; i++)
+ if (compile_input_file_p (&infiles[i]))
+ {
+ argv[j] = CONST_CAST (char *, infiles[i].name);
+ infiles[i].compiled = true;
+ j++;
+ }
+ argv[j] = NULL;
+
+ create_at_file (argv);
+ }
+ else
+ for (i = 0; (int) i < n_infiles; i++)
+ if (compile_input_file_p (&infiles[i]))
{
store_arg (infiles[i].name, 0, 0);
infiles[i].compiled = true;
@@ -5187,14 +5258,8 @@ do_spec_1 (const char *spec, int inswitc
that would usually be expanded in place of %o will be
written to the temporary file. */
- char *temp_file = make_temp_file ("");
- char *at_argument;
char **argv;
- int n_files, j, status;
- FILE *f;
-
- at_argument = concat ("@", temp_file, NULL);
- store_arg (at_argument, 0, 0);
+ int n_files, j;
/* Convert OUTFILES into a form suitable for writeargv. */
@@ -5213,25 +5278,7 @@ do_spec_1 (const char *spec, int inswitc
}
argv[j] = NULL;
- f = fopen (temp_file, "w");
-
- if (f == NULL)
- fatal ("could not open temporary response file %s",
- temp_file);
-
- status = writeargv (argv, f);
-
- if (status)
- fatal ("could not write to temporary response file %s",
- temp_file);
-
- status = fclose (f);
-
- if (EOF == status)
- fatal ("could not close temporary response file %s",
- temp_file);
-
- record_temp_file (temp_file, !save_temps_flag,
!save_temps_flag);
+ create_at_file (argv);
}
else
for (i = 0; i < max; i++)
Index: omp-low.c
===================================================================
--- omp-low.c (revision 146200)
+++ omp-low.c (working copy)
@@ -1577,6 +1577,7 @@ create_omp_child_function (omp_context *
t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
DECL_ARTIFICIAL (t) = 1;
DECL_IGNORED_P (t) = 1;
+ DECL_CONTEXT (t) = decl;
DECL_RESULT (decl) = t;
t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
Index: toplev.c
===================================================================
--- toplev.c (revision 146200)
+++ toplev.c (working copy)
@@ -993,11 +993,6 @@ compile_file (void)
varpool_assemble_pending_decls ();
finish_aliases_2 ();
- /* This must occur after the loop to output deferred functions.
- Else the coverage initializer would not be emitted if all the
- functions in this compilation unit were deferred. */
- coverage_finish ();
-
/* Likewise for mudflap static object registrations. */
if (flag_mudflap)
mudflap_finish_file ();
@@ -1496,8 +1491,8 @@ default_pch_valid_p (const void *data_p,
}
/* Default tree printer. Handles declarations only. */
-static bool
-default_tree_printer (pretty_printer * pp, text_info *text, const char *spec,
+bool
+default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool hash)
{
tree t;
@@ -1508,6 +1503,15 @@ default_tree_printer (pretty_printer * p
switch (*spec)
{
+ case 'E':
+ t = va_arg (*text->args_ptr, tree);
+ if (TREE_CODE (t) == IDENTIFIER_NODE)
+ {
+ pp_string (pp, IDENTIFIER_POINTER (t));
+ return true;
+ }
+ break;
+
case 'D':
t = va_arg (*text->args_ptr, tree);
if (DECL_DEBUG_EXPR_IS_FROM (t) && DECL_DEBUG_EXPR (t))
@@ -2261,16 +2265,18 @@ do_compile (void)
It is not safe to call this function more than once. */
int
-toplev_main (unsigned int argc, const char **argv)
+toplev_main (int argc, char **argv)
{
- save_argv = argv;
+ expandargv (&argc, &argv);
+
+ save_argv = (const char **) argv;
/* Initialization of GCC's environment, and diagnostics. */
general_init (argv[0]);
/* Parse the options and do minimal processing; basically just
enough to default flags appropriately. */
- decode_options (argc, argv);
+ decode_options (argc, (const char **) argv);
init_local_tick ();
Index: toplev.h
===================================================================
--- toplev.h (revision 146200)
+++ toplev.h (working copy)
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.
#define skip_leading_substring(whole, part) \
(strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
-extern int toplev_main (unsigned int, const char **);
+extern int toplev_main (int, char **);
extern int read_integral_parameter (const char *, const char *, const int);
extern void strip_off_ending (char *, int);
extern const char *trim_filename (const char *);
Index: cgraphunit.c
===================================================================
--- cgraphunit.c (revision 146200)
+++ cgraphunit.c (working copy)
@@ -1043,8 +1043,6 @@ cgraph_expand_function (struct cgraph_no
gcc_assert (node->lowered);
/* Generate RTL for the body of DECL. */
- if (lang_hooks.callgraph.emit_associated_thunks)
- lang_hooks.callgraph.emit_associated_thunks (decl);
tree_rest_of_compilation (decl);
/* Make sure that BE didn't give up on compiling. */
@@ -1237,10 +1235,45 @@ ipa_passes (void)
current_function_decl = NULL;
gimple_register_cfg_hooks ();
bitmap_obstack_initialize (NULL);
+
+ /* Remove bodies of extern inline functions that we never inlined. */
+ cgraph_remove_unreachable_nodes (false, dump_file);
+
+ /* Generate coverage variables and constructors. */
+ coverage_finish ();
+
+ /* Process new functions added so far. */
+ set_cfun (NULL);
+ current_function_decl = NULL;
+ cgraph_process_new_functions ();
+
execute_ipa_pass_list (all_ipa_passes);
bitmap_obstack_release (NULL);
}
+
+/* Emit thunks for every node in the cgraph. */
+
+static void
+cgraph_emit_thunks (void)
+{
+ struct cgraph_node *n;
+
+ for (n = cgraph_nodes; n; n = n->next)
+ {
+ /* Only emit thunks on functions defined in this TU.
+ Note that this may emit more thunks than strictly necessary.
+ During optimization some nodes may disappear. It would be
+ nice to only emit thunks only for the functions that will be
+ emitted, but we cannot know that until the inliner and other
+ IPA passes have run (see the sequencing of the call to
+ cgraph_mark_functions_to_output in cgraph_optimize). */
+ if (!DECL_EXTERNAL (n->decl))
+ lang_hooks.callgraph.emit_associated_thunks (n->decl);
+ }
+}
+
+
/* Perform simple optimizations based on callgraph. */
void
@@ -1253,6 +1286,18 @@ cgraph_optimize (void)
verify_cgraph ();
#endif
+ /* Emit thunks, if needed. */
+ if (lang_hooks.callgraph.emit_associated_thunks)
+ {
+ cgraph_emit_thunks ();
+
+ /* Thunk emission may produce errors for thunks that
+ need varargs (since asm thunks have been disabled). This
+ shouldn't be needed after thunks are properly lowered. */
+ if (errorcount || sorrycount)
+ return;
+ }
+
/* Call functions declared with the "constructor" or "destructor"
attribute. */
cgraph_build_cdtor_fns ();
@@ -1276,9 +1321,6 @@ cgraph_optimize (void)
if (errorcount == 0 && sorrycount == 0)
ipa_passes ();
- /* This pass remove bodies of extern inline functions we never inlined.
- Do this later so other IPA passes see what is really going on. */
- cgraph_remove_unreachable_nodes (false, dump_file);
cgraph_global_info_ready = true;
if (cgraph_dump_file)
{
@@ -1369,6 +1411,7 @@ cgraph_build_static_cdtor (char which, t
resdecl = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_RESULT (decl) = resdecl;
+ DECL_CONTEXT (resdecl) = decl;
allocate_struct_function (decl, false);
Index: testsuite/gcc.c-torture/execute/builtins/strlen-3.c
===================================================================
--- testsuite/gcc.c-torture/execute/builtins/strlen-3.c (revision 146200)
+++ testsuite/gcc.c-torture/execute/builtins/strlen-3.c (working copy)
@@ -10,7 +10,7 @@ extern char *strcpy (char *, const char
static const char bar[] = "Hello, World!";
static const char baz[] = "hello, world?";
static const char larger[20] = "short string";
-extern volatile int inside_main;
+extern int inside_main;
int l1 = 1;
int x = 6;
Index: ada/gcc-interface/misc.c
===================================================================
--- ada/gcc-interface/misc.c (revision 146200)
+++ ada/gcc-interface/misc.c (working copy)
@@ -91,8 +91,6 @@ static const char *gnat_dwarf_name (tree
static tree gnat_return_tree (tree);
static int gnat_eh_type_covers (tree, tree);
static void gnat_parse_file (int);
-static rtx gnat_expand_expr (tree, rtx, enum machine_mode, int,
- rtx *);
static void internal_error_function (const char *, va_list *);
static tree gnat_type_max_size (const_tree);
@@ -124,8 +122,6 @@ static tree gnat_type_max_size (const_t
#define LANG_HOOKS_FINISH_INCOMPLETE_DECL gnat_finish_incomplete_decl
#undef LANG_HOOKS_GET_ALIAS_SET
#define LANG_HOOKS_GET_ALIAS_SET gnat_get_alias_set
-#undef LANG_HOOKS_EXPAND_EXPR
-#define LANG_HOOKS_EXPAND_EXPR gnat_expand_expr
#undef LANG_HOOKS_MARK_ADDRESSABLE
#define LANG_HOOKS_MARK_ADDRESSABLE gnat_mark_addressable
#undef LANG_HOOKS_PRINT_DECL
@@ -612,45 +608,6 @@ gnat_printable_name (tree decl, int verb
return ada_name;
}
-/* Expands GNAT-specific GCC tree nodes. The only ones we support
- here are and NULL_EXPR. */
-
-static rtx
-gnat_expand_expr (tree exp, rtx target, enum machine_mode tmode,
- int modifier, rtx *alt_rtl)
-{
- tree type = TREE_TYPE (exp);
- tree new;
-
- /* Update EXP to be the new expression to expand. */
- switch (TREE_CODE (exp))
- {
-#if 0
- case ALLOCATE_EXPR:
- return
- allocate_dynamic_stack_space
- (expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, TYPE_MODE (sizetype),
- EXPAND_NORMAL),
- NULL_RTX, tree_low_cst (TREE_OPERAND (exp, 1), 1));
-#endif
-
- case UNCONSTRAINED_ARRAY_REF:
- /* If we are evaluating just for side-effects, just evaluate our
- operand. Otherwise, abort since this code should never appear
- in a tree to be evaluated (objects aren't unconstrained). */
- if (target == const0_rtx || TREE_CODE (type) == VOID_TYPE)
- return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
- VOIDmode, modifier);
-
- /* ... fall through ... */
-
- default:
- gcc_unreachable ();
- }
-
- return expand_expr_real (new, target, tmode, modifier, alt_rtl);
-}
-
/* Do nothing (return the tree node passed). */
static tree
Index: ipa.c
===================================================================
--- ipa.c (revision 146200)
+++ ipa.c (working copy)
@@ -198,6 +198,11 @@ cgraph_remove_unreachable_nodes (bool be
#ifdef ENABLE_CHECKING
verify_cgraph ();
#endif
+
+ /* Reclaim alias pairs for functions that have disappeared from the
+ call graph. */
+ remove_unreachable_alias_pairs ();
+
return changed;
}
Index: tree-ssa-coalesce.c
===================================================================
--- tree-ssa-coalesce.c (revision 146200)
+++ tree-ssa-coalesce.c (working copy)
@@ -1351,7 +1351,8 @@ coalesce_ssa_name (void)
{
tree a = ssa_name (i);
- if (a && SSA_NAME_VAR (a) && !DECL_ARTIFICIAL (SSA_NAME_VAR (a)))
+ if (a && SSA_NAME_VAR (a) && !DECL_ARTIFICIAL (SSA_NAME_VAR (a))
+ && map->partition_to_var[i] != NULL)
{
tree *slot = (tree *) htab_find_slot (ssa_name_hash, a, INSERT);
Index: tree-dfa.c
===================================================================
--- tree-dfa.c (revision 146200)
+++ tree-dfa.c (working copy)
@@ -88,26 +88,10 @@ find_referenced_vars (void)
FOR_EACH_BB (bb)
{
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
- {
- size_t i;
- gimple stmt = gsi_stmt (si);
- for (i = 0; i < gimple_num_ops (stmt); i++)
- walk_tree (gimple_op_ptr (stmt, i), find_vars_r, NULL, NULL);
- }
+ find_referenced_vars_in (gsi_stmt (si));
for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
- {
- gimple phi = gsi_stmt (si);
- size_t i, len = gimple_phi_num_args (phi);
-
- walk_tree (gimple_phi_result_ptr (phi), find_vars_r, NULL, NULL);
-
- for (i = 0; i < len; i++)
- {
- tree arg = gimple_phi_arg_def (phi, i);
- walk_tree (&arg, find_vars_r, NULL, NULL);
- }
- }
+ find_referenced_vars_in (gsi_stmt (si));
}
return 0;
@@ -498,6 +482,33 @@ find_vars_r (tree *tp, int *walk_subtree
return NULL_TREE;
}
+/* Find referenced variables in STMT. In contrast with
+ find_new_referenced_vars, this function will not mark newly found
+ variables for renaming. */
+
+void
+find_referenced_vars_in (gimple stmt)
+{
+ size_t i;
+
+ if (gimple_code (stmt) != GIMPLE_PHI)
+ {
+ for (i = 0; i < gimple_num_ops (stmt); i++)
+ walk_tree (gimple_op_ptr (stmt, i), find_vars_r, NULL, NULL);
+ }
+ else
+ {
+ walk_tree (gimple_phi_result_ptr (stmt), find_vars_r, NULL, NULL);
+
+ for (i = 0; i < gimple_phi_num_args (stmt); i++)
+ {
+ tree arg = gimple_phi_arg_def (stmt, i);
+ walk_tree (&arg, find_vars_r, NULL, NULL);
+ }
+ }
+}
+
+
/* Lookup UID in the referenced_vars hashtable and return the associated
variable. */
Index: except.c
===================================================================
--- except.c (revision 146200)
+++ except.c (working copy)
@@ -114,119 +114,15 @@ static int sjlj_fc_personality_ofs;
static int sjlj_fc_lsda_ofs;
static int sjlj_fc_jbuf_ofs;
-/* Describes one exception region. */
-struct eh_region GTY(())
-{
- /* The immediately surrounding region. */
- struct eh_region *outer;
-
- /* The list of immediately contained regions. */
- struct eh_region *inner;
- struct eh_region *next_peer;
-
- /* An identifier for this region. */
- int region_number;
-
- /* When a region is deleted, its parents inherit the REG_EH_REGION
- numbers already assigned. */
- bitmap aka;
-
- /* Each region does exactly one thing. */
- enum eh_region_type
- {
- ERT_UNKNOWN = 0,
- ERT_CLEANUP,
- ERT_TRY,
- ERT_CATCH,
- ERT_ALLOWED_EXCEPTIONS,
- ERT_MUST_NOT_THROW,
- ERT_THROW
- } type;
-
- /* Holds the action to perform based on the preceding type. */
- union eh_region_u {
- /* A list of catch blocks, a surrounding try block,
- and the label for continuing after a catch. */
- struct eh_region_u_try {
- struct eh_region *eh_catch;
- struct eh_region *last_catch;
- } GTY ((tag ("ERT_TRY"))) eh_try;
-
- /* The list through the catch handlers, the list of type objects
- matched, and the list of associated filters. */
- struct eh_region_u_catch {
- struct eh_region *next_catch;
- struct eh_region *prev_catch;
- tree type_list;
- tree filter_list;
- } GTY ((tag ("ERT_CATCH"))) eh_catch;
-
- /* A tree_list of allowed types. */
- struct eh_region_u_allowed {
- tree type_list;
- int filter;
- } GTY ((tag ("ERT_ALLOWED_EXCEPTIONS"))) allowed;
-
- /* The type given by a call to "throw foo();", or discovered
- for a throw. */
- struct eh_region_u_throw {
- tree type;
- } GTY ((tag ("ERT_THROW"))) eh_throw;
-
- /* Retain the cleanup expression even after expansion so that
- we can match up fixup regions. */
- struct eh_region_u_cleanup {
- struct eh_region *prev_try;
- } GTY ((tag ("ERT_CLEANUP"))) cleanup;
- } GTY ((desc ("%0.type"))) u;
-
- /* Entry point for this region's handler before landing pads are built. */
- rtx label;
- tree tree_label;
-
- /* Entry point for this region's handler from the runtime eh library. */
- rtx landing_pad;
-
- /* Entry point for this region's handler from an inner region. */
- rtx post_landing_pad;
-
- /* The RESX insn for handing off control to the next outermost handler,
- if appropriate. */
- rtx resume;
-
- /* True if something in this region may throw. */
- unsigned may_contain_throw : 1;
-};
-
-typedef struct eh_region *eh_region;
struct call_site_record GTY(())
{
rtx landing_pad;
int action;
};
-
-DEF_VEC_P(eh_region);
-DEF_VEC_ALLOC_P(eh_region, gc);
-DEF_VEC_ALLOC_P(eh_region, heap);
-
-/* Used to save exception status for each function. */
-struct eh_status GTY(())
-{
- /* The tree of all regions for this function. */
- struct eh_region *region_tree;
-
- /* The same information as an indexable array. */
- VEC(eh_region,gc) *region_array;
- int last_region_number;
-
- htab_t GTY((param_is (struct throw_stmt_node))) throw_stmt_table;
-};
static int t2r_eq (const void *, const void *);
static hashval_t t2r_hash (const void *);
-static void add_type_for_runtime (tree);
-static tree lookup_type_for_runtime (tree);
static int ttypes_filter_eq (const void *, const void *);
static hashval_t ttypes_filter_hash (const void *);
@@ -1308,7 +1204,7 @@ t2r_hash (const void *pentry)
return TREE_HASH (TREE_PURPOSE (entry));
}
-static void
+void
add_type_for_runtime (tree type)
{
tree *slot;
@@ -1322,7 +1218,7 @@ add_type_for_runtime (tree type)
}
}
-static tree
+tree
lookup_type_for_runtime (tree type)
{
tree *slot;
@@ -2479,8 +2375,33 @@ check_handled (tree handled, tree type)
if (! lang_eh_type_covers)
{
for (t = handled; t ; t = TREE_CHAIN (t))
- if (TREE_VALUE (t) == type)
- return 1;
+ {
+ tree t1 = TREE_VALUE (t);
+ tree t2 = type;
+
+ /* If the types have been converted to runtime types (i.e.,
+ when the IL is being read from disk in an LTO
+ compilation), then T1 and T2 will be pointers to the
+ runtime type of the form '(void *) &<runtime_type>' (See
+ cp/except.c:build_eh_type_type). Strip the conversion
+ and the address. */
+ if (CONVERT_EXPR_P (t1))
+ {
+ STRIP_NOPS (t1);
+ gcc_assert (TREE_CODE (t1) == ADDR_EXPR);
+ t1 = TREE_OPERAND (t1, 0);
+ }
+
+ if (CONVERT_EXPR_P (t2))
+ {
+ STRIP_NOPS (t2);
+ gcc_assert (TREE_CODE (t2) == ADDR_EXPR);
+ t2 = TREE_OPERAND (t2, 0);
+ }
+
+ if (t1 == t2)
+ return 1;
+ }
}
else
{
@@ -3737,7 +3658,14 @@ output_ttype (tree type, int tt_format,
{
struct varpool_node *node;
- type = lookup_type_for_runtime (type);
+ /* FIXME lto. During LTO compiles, pass_ipa_free_lang_data
+ changes all types to runtime types so TYPE should already be
+ a runtime type reference. When pass_ipa_free_lang data is
+ made a default pass, we can then remove the call to
+ lookup_type_for_runtime below. */
+ if (TYPE_P (type))
+ type = lookup_type_for_runtime (type);
+
value = expand_expr (type, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
/* Let cgraph know that the rtti decl is used. Not all of the
@@ -4092,6 +4020,15 @@ dump_eh_tree (FILE * out, struct functio
}
}
+/* Dump the EH tree for FN on stderr. */
+
+void
+debug_eh_tree (struct function *fn)
+{
+ dump_eh_tree (stderr, fn);
+}
+
+
/* Verify EH region invariants. */
static bool
Index: except.h
===================================================================
--- except.h (revision 146200)
+++ except.h (working copy)
@@ -24,12 +24,109 @@ along with GCC; see the file COPYING3.
struct function;
-/* Per-function EH data. Used only in except.c, but GC and others
- manipulate pointers to the opaque type. */
-struct eh_status;
+/* Describes one exception region. */
+struct eh_region GTY(())
+{
+ /* The immediately surrounding region. */
+ struct eh_region *outer;
+
+ /* The list of immediately contained regions. */
+ struct eh_region *inner;
+ struct eh_region *next_peer;
+
+ /* An identifier for this region. */
+ int region_number;
+
+ /* When a region is deleted, its parents inherit the REG_EH_REGION
+ numbers already assigned. */
+ bitmap aka;
+
+ /* Each region does exactly one thing. */
+ enum eh_region_type
+ {
+ ERT_UNKNOWN = 0,
+ ERT_CLEANUP,
+ ERT_TRY,
+ ERT_CATCH,
+ ERT_ALLOWED_EXCEPTIONS,
+ ERT_MUST_NOT_THROW,
+ ERT_THROW
+ } type;
+
+ /* Holds the action to perform based on the preceding type. */
+ union eh_region_u {
+ /* A list of catch blocks, a surrounding try block,
+ and the label for continuing after a catch. */
+ struct eh_region_u_try {
+ struct eh_region *eh_catch;
+ struct eh_region *last_catch;
+ } GTY ((tag ("ERT_TRY"))) eh_try;
+
+ /* The list through the catch handlers, the list of type objects
+ matched, and the list of associated filters. */
+ struct eh_region_u_catch {
+ struct eh_region *next_catch;
+ struct eh_region *prev_catch;
+ tree type_list;
+ tree filter_list;
+ } GTY ((tag ("ERT_CATCH"))) eh_catch;
+
+ /* A tree_list of allowed types. */
+ struct eh_region_u_allowed {
+ tree type_list;
+ int filter;
+ } GTY ((tag ("ERT_ALLOWED_EXCEPTIONS"))) allowed;
+
+ /* The type given by a call to "throw foo();", or discovered
+ for a throw. */
+ struct eh_region_u_throw {
+ tree type;
+ } GTY ((tag ("ERT_THROW"))) eh_throw;
+
+ /* Retain the cleanup expression even after expansion so that
+ we can match up fixup regions. */
+ struct eh_region_u_cleanup {
+ struct eh_region *prev_try;
+ } GTY ((tag ("ERT_CLEANUP"))) cleanup;
+ } GTY ((desc ("%0.type"))) u;
+
+ /* Entry point for this region's handler before landing pads are built. */
+ rtx label;
+ tree tree_label;
+
+ /* Entry point for this region's handler from the runtime eh library. */
+ rtx landing_pad;
+
+ /* Entry point for this region's handler from an inner region. */
+ rtx post_landing_pad;
+
+ /* The RESX insn for handing off control to the next outermost handler,
+ if appropriate. */
+ rtx resume;
+
+ /* True if something in this region may throw. */
+ unsigned may_contain_throw : 1;
+};
+
+typedef struct eh_region *eh_region;
+DEF_VEC_P(eh_region);
+DEF_VEC_ALLOC_P(eh_region, gc);
+DEF_VEC_ALLOC_P(eh_region, heap);
+
+/* Per-function EH data. Used to save exception status for each
+ function. */
+struct eh_status GTY(())
+{
+ /* The tree of all regions for this function. */
+ struct eh_region *region_tree;
+
+ /* The same information as an indexable array. */
+ VEC(eh_region,gc) *region_array;
+ int last_region_number;
+
+ htab_t GTY((param_is (struct throw_stmt_node))) throw_stmt_table;
+};
-/* Internal structure describing a region. */
-struct eh_region;
/* Test: is exception handling turned on? */
extern int doing_eh (int);
@@ -108,8 +205,11 @@ extern void collect_eh_region_array (voi
extern void expand_resx_expr (tree);
extern void verify_eh_tree (struct function *);
extern void dump_eh_tree (FILE *, struct function *);
+void debug_eh_tree (struct function *);
extern bool eh_region_outer_p (struct function *, int, int);
extern int eh_region_outermost (struct function *, int, int);
+extern void add_type_for_runtime (tree);
+extern tree lookup_type_for_runtime (tree);
/* If non-NULL, this is a function that returns an expression to be
executed if an unhandled exception is propagated out of a cleanup
Index: tree-ssa-pre.c
===================================================================
--- tree-ssa-pre.c (revision 146200)
+++ tree-ssa-pre.c (working copy)
@@ -3003,6 +3003,7 @@ create_expression_by_pieces (basic_block
add_to_value (VN_INFO (forcedname)->value_id, nameexpr);
if (!in_fre)
bitmap_value_replace_in_set (NEW_SETS (block), nameexpr);
+ gcc_assert (AVAIL_OUT (block));
bitmap_value_replace_in_set (AVAIL_OUT (block), nameexpr);
}
mark_symbols_for_renaming (stmt);
Index: varasm.c
===================================================================
--- varasm.c (revision 146200)
+++ varasm.c (working copy)
@@ -5176,21 +5176,7 @@ globalize_decl (tree decl)
targetm.asm_out.globalize_decl_name (asm_out_file, decl);
}
-/* We have to be able to tell cgraph about the needed-ness of the target
- of an alias. This requires that the decl have been defined. Aliases
- that precede their definition have to be queued for later processing. */
-
-typedef struct alias_pair GTY(())
-{
- tree decl;
- tree target;
-} alias_pair;
-
-/* Define gc'd vector type. */
-DEF_VEC_O(alias_pair);
-DEF_VEC_ALLOC_O(alias_pair,gc);
-
-static GTY(()) VEC(alias_pair,gc) *alias_pairs;
+VEC(alias_pair,gc) *alias_pairs;
/* Given an assembly name, find the decl it is associated with. At the
same time, mark it needed for cgraph. */
@@ -5333,6 +5319,39 @@ do_assemble_alias (tree decl, tree targe
#endif
}
+
+/* Remove the alias pairing for functions that are no longer in the call
+ graph. */
+
+void
+remove_unreachable_alias_pairs (void)
+{
+ unsigned i;
+ alias_pair *p;
+
+ if (alias_pairs == NULL)
+ return;
+
+ for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); )
+ {
+ if (!DECL_EXTERNAL (p->decl))
+ {
+ struct cgraph_node *fnode = NULL;
+ struct varpool_node *vnode = NULL;
+ fnode = cgraph_node_for_asm (p->target);
+ vnode = (fnode == NULL) ? varpool_node_for_asm (p->target) : NULL;
+ if (fnode == NULL && vnode == NULL)
+ {
+ VEC_unordered_remove (alias_pair, alias_pairs, i);
+ continue;
+ }
+ }
+
+ i++;
+ }
+}
+
+
/* First pass of completing pending aliases. Make sure that cgraph knows
which symbols will be required. */
Index: tree-flow.h
===================================================================
--- tree-flow.h (revision 146200)
+++ tree-flow.h (working copy)
@@ -616,6 +616,7 @@ extern tree gimple_default_def (struct f
extern bool stmt_references_abnormal_ssa_name (gimple);
extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
HOST_WIDE_INT *, HOST_WIDE_INT *);
+extern void find_referenced_vars_in (gimple);
/* In tree-phinodes.c */
extern void reserve_phi_args_for_new_edge (basic_block);
Index: main.c
===================================================================
--- main.c (revision 146200)
+++ main.c (working copy)
@@ -32,5 +32,5 @@ int main (int argc, char **argv);
int
main (int argc, char **argv)
{
- return toplev_main (argc, (const char **) argv);
+ return toplev_main (argc, argv);
}
Index: Makefile.in
===================================================================
--- Makefile.in (revision 146200)
+++ Makefile.in (working copy)
@@ -829,7 +829,7 @@ CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $
IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H)
-CGRAPH_H = cgraph.h $(TREE_H) $(BASIC_BLOCK_H)
+CGRAPH_H = cgraph.h $(TREE_H) $(BASIC_BLOCK_H) cif-code.def
DF_H = df.h $(BITMAP_H) $(BASIC_BLOCK_H) alloc-pool.h
RESOURCE_H = resource.h hard-reg-set.h $(DF_H)
DDG_H = ddg.h sbitmap.h $(DF_H)
@@ -2056,7 +2056,8 @@ tree.o : tree.c $(CONFIG_H) $(SYSTEM_H)
all-tree.def $(FLAGS_H) $(FUNCTION_H) $(PARAMS_H) \
$(TOPLEV_H) $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H)
langhooks.h \
$(REAL_H) gt-tree.h tree-iterator.h $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
- $(OBSTACK_H) pointer-set.h fixed-value.h
+ $(OBSTACK_H) pointer-set.h fixed-value.h tree-pass.h langhooks-def.h \
+ $(DIAGNOSTIC_H) $(CGRAPH_H) $(TIMEVAR_H) except.h
tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TOPLEV_H) $(SPLAY_TREE_H) $(TREE_DUMP_H) \
tree-iterator.h tree-pass.h $(DIAGNOSTIC_H) $(REAL_H) fixed-value.h
@@ -2391,11 +2392,11 @@ tree-loop-distribution.o: tree-loop-dist
$(TM_H) $(GGC_H) $(OPTABS_H) $(TREE_H) $(RTL_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(TIMEVAR_H) $(CFGLOOP_H) \
tree-pass.h $(TREE_DATA_REF_H) $(SCEV_H) $(EXPR_H) \
- $(TARGET_H) tree-chrec.h langhooks.h tree-vectorizer.h
+ $(TARGET_H) tree-chrec.h langhooks.h $(TREE_VECTORIZER_H)
tree-parloops.o: tree-parloops.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_FLOW_H) $(TREE_H) $(RTL_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) $(GGC_H) \
$(DIAGNOSTIC_H) tree-pass.h $(SCEV_H) langhooks.h gt-tree-parloops.h \
- tree-vectorizer.h
+ $(TREE_VECTORIZER_H)
tree-stdarg.o: tree-stdarg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(FUNCTION_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-pass.h \
tree-stdarg.h $(TARGET_H) langhooks.h
@@ -2404,7 +2405,7 @@ tree-object-size.o: tree-object-size.c $
tree-ssa-propagate.h
gimple.o : gimple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
$(GGC_H) $(GIMPLE_H) $(GIMPLE_H) $(DIAGNOSTIC_H) gt-gimple.h \
- $(TREE_FLOW_H) value-prof.h $(FLAGS_H)
+ $(TREE_FLOW_H) value-prof.h $(FLAGS_H) $(TARGET_H)
gimple-pretty-print.o : gimple-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) $(DIAGNOSTIC_H) $(REAL_H) $(HASHTAB_H) $(TREE_FLOW_H) \
$(TM_H) coretypes.h tree-pass.h $(GIMPLE_H) value-prof.h
@@ -2594,22 +2595,23 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG
cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
langhooks.h $(TOPLEV_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
- $(TREE_INLINE_H) $(VARRAY_H) $(TREE_DUMP_H) $(TREE_FLOW_H) value-prof.h
+ $(TREE_INLINE_H) $(VARRAY_H) $(TREE_DUMP_H) $(TREE_FLOW_H) cif-code.def \
+ value-prof.h
cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) $(TOPLEV_H) $(FLAGS_H) $(GGC_H) \
$(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
$(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \
$(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) $(IPA_PROP_H) \
- gt-cgraphunit.h tree-iterator.h
+ gt-cgraphunit.h tree-iterator.h $(COVERAGE_H)
cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \
$(TREE_FLOW_H) tree-pass.h
varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(CGRAPH_H) langhooks.h $(DIAGNOSTIC_H) $(HASHTAB_H) \
$(GGC_H) $(TIMEVAR_H) debug.h $(TARGET_H) output.h $(GIMPLE_H) \
- $(TREE_FLOW_H) gt-varpool.h
+ $(TREE_FLOW_H) gt-varpool.h $(FLAGS_H)
ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) \
- tree-pass.h $(TIMEVAR_H)
+ tree-pass.h $(TIMEVAR_H) $(FLAGS_H)
ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(DIAGNOSTIC_H) \
$(TREE_FLOW_H) $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H) $(TREE_INLINE_H) \
@@ -3290,9 +3292,9 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/inp
$(srcdir)/dbxout.c $(srcdir)/ipa-struct-reorg.c
$(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \
$(srcdir)/tree-vect-generic.c \
$(srcdir)/dojump.c \
- $(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
+ $(srcdir)/emit-rtl.c $(srcdir)/except.h $(srcdir)/explow.c $(srcdir)/expr.c \
$(srcdir)/expr.h \
- $(srcdir)/function.c $(srcdir)/except.h \
+ $(srcdir)/function.c $(srcdir)/except.c \
$(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
$(srcdir)/profile.c $(srcdir)/reginfo.c $(srcdir)/mcf.c \
$(srcdir)/reg-stack.c $(srcdir)/cfglayout.c $(srcdir)/cfglayout.h \