aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog.lto4
-rw-r--r--gcc/lto-cgraph-in.c244
-rw-r--r--gcc/lto-cgraph-out.c359
-rw-r--r--gcc/lto-cgraph.c426
-rw-r--r--gcc/lto-cgraph.h53
-rw-r--r--gcc/lto-function-in.c1
-rw-r--r--gcc/lto-function-out.c73
-rw-r--r--gcc/lto-section-in.h2
-rw-r--r--gcc/lto-section-out.c13
-rw-r--r--gcc/lto/ChangeLog32
-rw-r--r--gcc/lto/lto.c12
11 files changed, 474 insertions, 745 deletions
diff --git a/gcc/ChangeLog.lto b/gcc/ChangeLog.lto
index deab6dfe4ce..29d80887efd 100644
--- a/gcc/ChangeLog.lto
+++ b/gcc/ChangeLog.lto
@@ -1,3 +1,7 @@
+2008-06-11 Diego Novillo <dnovillo@google.com>
+
+ Merge with lto r136640.
+
2008-06-10 Diego Novillo <dnovillo@google.com>
* lto-function-out.c (output_type_ref, output_expr_operand,
diff --git a/gcc/lto-cgraph-in.c b/gcc/lto-cgraph-in.c
deleted file mode 100644
index 6093f4ea81d..00000000000
--- a/gcc/lto-cgraph-in.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/* Read the cgraph from the memory mapped representation of a a .o file.
-
- Copyright 2008 Free Software Foundation, Inc.
- Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
-
-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 2, 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 COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "toplev.h"
-#include "tree.h"
-#include "expr.h"
-#include "flags.h"
-#include "params.h"
-#include "input.h"
-#include "varray.h"
-#include "hashtab.h"
-#include "langhooks.h"
-#include "basic-block.h"
-#include "tree-iterator.h"
-#include "tree-pass.h"
-#include "tree-flow.h"
-#include "cgraph.h"
-#include "function.h"
-#include "ggc.h"
-#include "diagnostic.h"
-#include "except.h"
-#include "debug.h"
-#include "vec.h"
-#include "timevar.h"
-#include "output.h"
-#include "lto-cgraph.h"
-#include "lto-section-in.h"
-#include <ctype.h>
-#include "cpplib.h"
-
-struct data_in
-{
- /* That global decls and types. */
- struct lto_file_decl_data* file_data;
-};
-
-
-/* Return 0 or 1 based on the last bit of FLAGS and right shift FLAGS
- by 1. */
-
-static unsigned int
-add_flag (unsigned int *flags)
-{
- unsigned int result = *flags & 1;
- *flags = *flags >> 1;
- return result;
-}
-
-/* Overwrite the information in NODE based on DATA_IN, TAG, FLAGS,
- STACK_SIZE and SELF_INSNS. This is called either to initialize
- NODE or to replace the values in it, for instance becasue the first
- time we saw it, the function body was not available but now it
- is. */
-static void
-overwrite_node (struct data_in *data_in,
- struct cgraph_node *node,
- enum LTO_cgraph_tags tag,
- unsigned int flags,
- unsigned int stack_size,
- unsigned int self_insns)
-{
- node->aux = (void *)tag;
- node->local.inline_summary.estimated_self_stack_size = stack_size;
- node->local.inline_summary.self_insns = self_insns;
- node->global.insns = self_insns;
- if (!node->local.lto_file_data)
- node->local.lto_file_data = xcalloc (1, sizeof (struct lto_file_decl_data));
-
- node->local.lto_file_data = data_in->file_data;
-
- /* This list must be in the reverse order that they are set in
- lto-section-out.c:outout_node. */
- node->local.vtable_method = add_flag (&flags);
- node->local.for_functions_valid = add_flag (&flags);
- node->local.redefined_extern_inline = add_flag (&flags);
- node->local.disregard_inline_limits = add_flag (&flags);
- node->local.inlinable = add_flag (&flags);
- node->local.finalized = add_flag (&flags);
- node->local.externally_visible = add_flag (&flags);
- node->local.local = add_flag (&flags);
- node->analyzed = node->local.finalized;
- node->lowered = node->local.finalized;
- if (cgraph_decide_is_function_needed (node))
- cgraph_mark_needed_node (node);
-}
-
-
-/* Input a cgraph from IB using the info in DATA_IN. */
-
-static void
-input_cgraph (struct lto_input_block *ib,
- struct data_in *data_in)
-{
- enum LTO_cgraph_tags tag;
- struct cgraph_node *last_caller = NULL;
-
- tag = lto_input_uleb128 (ib);
- while (tag)
- {
- LTO_DEBUG_INDENT (tag);
-
- if (tag == LTO_cgraph_edge)
- {
- tree callee_decl;
- struct cgraph_node *callee;
- struct cgraph_edge *edge;
- unsigned int stmt_id;
- unsigned int count;
- unsigned int freq;
- unsigned int nest;
-
- callee_decl = data_in->file_data->fn_decls [lto_input_uleb128 (ib)];
- LTO_DEBUG_FN_NAME (callee_decl);
- callee = cgraph_node (callee_decl);
-
- LTO_DEBUG_TOKEN ("stmt");
- stmt_id = lto_input_uleb128 (ib);
- LTO_DEBUG_TOKEN ("count");
- count = lto_input_uleb128 (ib);
- LTO_DEBUG_TOKEN ("frequency");
- freq = lto_input_uleb128 (ib);
- LTO_DEBUG_TOKEN ("loop_next");
- nest = lto_input_uleb128 (ib);
-
- edge = cgraph_create_edge (last_caller, callee, NULL, count, freq, nest);
- edge->lto_stmt_uid = stmt_id;
- }
- else
- {
- tree fn_decl;
- struct cgraph_node *node;
- unsigned int flags;
- int stack_size = 0;
- int self_insns = 0;
-
- fn_decl = data_in->file_data->fn_decls [lto_input_uleb128 (ib)];
- LTO_DEBUG_FN_NAME (fn_decl);
- LTO_DEBUG_TOKEN ("flags");
- flags = lto_input_uleb128 (ib);
-
- if (tag == LTO_cgraph_avail_node)
- {
- LTO_DEBUG_TOKEN ("stack_size");
- stack_size = lto_input_sleb128 (ib);
- LTO_DEBUG_TOKEN ("self_insns");
- self_insns = lto_input_sleb128 (ib);
- }
-
- node = cgraph_node (fn_decl);
-
- switch (tag)
- {
- case LTO_cgraph_avail_node:
- /* We cannot have two avail functions that are the same. */
- gcc_assert (((enum LTO_cgraph_tags)(node->aux)) != LTO_cgraph_avail_node);
- overwrite_node (data_in, node, tag, flags, stack_size, self_insns);
- break;
-
- case LTO_cgraph_unavail_node:
- /* We only overwrite the node if this is a brand new node. */
- if (!node->aux)
- overwrite_node (data_in, node, tag, flags, stack_size, self_insns);
- break;
-
- case LTO_cgraph_overwritable_node:
- /* FIXME!!!! This code is written to take the last
- overwrittable version. I do not speak linker but if the
- linker supposed to take the first one, then we need to
- change the test. */
- if (((enum LTO_cgraph_tags)(node->aux)) != LTO_cgraph_avail_node)
- overwrite_node (data_in, node, tag, flags, stack_size, self_insns);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- /* Set this up so that we can handle the edges which follow and
- only have the callee in them. */
- last_caller = node;
- }
- LTO_DEBUG_UNDENT();
- tag = lto_input_uleb128 (ib);
- }
-}
-
-/* Read the body form DATA using the symbols in FILE_DATA to
- reconstruct the part of the cgraph associated with FILE_DATA. */
-
-void
-lto_input_cgraph (struct lto_file_decl_data* file_data, const char *data)
-{
- const struct lto_cgraph_header * header
- = (const struct lto_cgraph_header *) data;
- struct data_in data_in;
- struct lto_input_block ib_main;
-
- int32_t main_offset = sizeof (struct lto_cgraph_header);
-#ifdef LTO_STREAM_DEBUGGING
- int32_t debug_main_offset = main_offset + header->main_size;
- struct lto_input_block debug_main;
-#endif
-
- LTO_INIT_INPUT_BLOCK (ib_main, data + main_offset,
- 0, header->main_size);
- memset (&data_in, 0, sizeof (struct data_in));
- data_in.file_data = file_data;
-
-#ifdef LTO_STREAM_DEBUGGING
- LTO_INIT_INPUT_BLOCK (debug_main, data + debug_main_offset,
- 0, header->debug_main_size);
- lto_debug_context.current_data = &debug_main;
- lto_debug_context.indent = 0;
- lto_debug_context.stream_name = "cgraph";
- lto_debug_context.tag_names = LTO_cgraph_tag_names;
-#endif
- /* Read in the cgraph for this file and merge it into the main
- one. */
- input_cgraph (&ib_main, &data_in);
-}
-
diff --git a/gcc/lto-cgraph-out.c b/gcc/lto-cgraph-out.c
deleted file mode 100644
index 7382c016970..00000000000
--- a/gcc/lto-cgraph-out.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* Write the cgraph to a .o file.
-
- Copyright 2008 Free Software Foundation, Inc.
- Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
-
-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 2, 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 COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "toplev.h"
-#include "tree.h"
-#include "expr.h"
-#include "flags.h"
-#include "params.h"
-#include "input.h"
-#include "varray.h"
-#include "hashtab.h"
-#include "langhooks.h"
-#include "basic-block.h"
-#include "tree-iterator.h"
-#include "tree-pass.h"
-#include "tree-flow.h"
-#include "cgraph.h"
-#include "function.h"
-#include "ggc.h"
-#include "diagnostic.h"
-#include "except.h"
-#include "debug.h"
-#include "vec.h"
-#include "tree-vectorizer.h"
-#include "timevar.h"
-#include "output.h"
-#include "lto-cgraph.h"
-#include "lto-section-out.h"
-#include <ctype.h>
-
-
-const char * LTO_cgraph_tag_names[LTO_cgraph_last_tag] =
-{"", "avail", "overwrite", "unavail", "edge"};
-
-
-struct output_block
-{
- enum lto_section_type section_type;
- struct lto_out_decl_state *decl_state;
-
- /* The stream that the main tree codes are written to. */
- struct lto_output_stream *main_stream;
-
-#ifdef LTO_STREAM_DEBUGGING
- /* The stream that contains the gimple debugging information. */
- struct lto_output_stream *debug_main_stream;
-#endif
-};
-
-
-/* Create the output block and return it. */
-
-static struct output_block *
-create_output_block (void)
-{
- struct output_block *ob = xcalloc (1, sizeof (struct output_block));
- ob->section_type = LTO_section_cgraph;
- ob->decl_state = lto_get_out_decl_state ();
- ob->main_stream = xcalloc (1, sizeof (struct lto_output_stream));
-
-#ifdef LTO_STREAM_DEBUGGING
- lto_debug_context.out = lto_debug_out_fun;
- lto_debug_context.indent = 0;
- lto_debug_context.tag_names = LTO_cgraph_tag_names;
-#endif
-
- return ob;
-}
-
-
-/* Destroy the output block OB. IS_FUNTION is true if this is for a
- function and false for a constructor. */
-
-static void
-destroy_output_block (struct output_block * ob)
-{
- free (ob->main_stream);
- LTO_CLEAR_DEBUGGING_STREAM (debug_main_stream);
- free (ob);
-}
-
-
-/* Output an unsigned LEB128 quantity to OB->main_stream. */
-
-static void
-output_uleb128 (struct output_block *ob, unsigned HOST_WIDE_INT work)
-{
- lto_output_uleb128_stream (ob->main_stream, work);
-}
-
-
-/* Output a signed LEB128 quantity to OB->main_stream. */
-
-static void
-output_sleb128 (struct output_block *ob, HOST_WIDE_INT work)
-{
- lto_output_sleb128_stream (ob->main_stream, work);
-}
-
-
-/* Output FUNCTION_DECL EXPR to output block OB. */
-
-static void
-output_fn_decl (struct output_block *ob, tree expr)
-{
- unsigned int index;
- bool new;
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->fn_decl_hash_table,
- &ob->decl_state->next_fn_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->fn_decls, expr);
-}
-
-
-/* Output the cgraph EDGE to OB. */
-
-static void
-output_edge (struct output_block *ob, struct cgraph_edge *edge)
-{
- output_uleb128 (ob, LTO_cgraph_edge);
- LTO_DEBUG_INDENT (LTO_cgraph_edge);
- output_fn_decl (ob, edge->callee->decl);
- LTO_DEBUG_FN_NAME (edge->callee->decl);
-
- LTO_DEBUG_TOKEN ("stmt");
- output_uleb128 (ob, gimple_stmt_uid (edge->call_stmt));
- LTO_DEBUG_TOKEN ("count");
- output_uleb128 (ob, edge->count);
- LTO_DEBUG_TOKEN ("frequency");
- output_uleb128 (ob, edge->frequency);
- LTO_DEBUG_TOKEN ("loop_next");
- output_uleb128 (ob, edge->loop_nest);
- LTO_DEBUG_UNDENT();
-}
-
-
-/* Add FLAG onto the end of BASE. */
-
-static void
-add_flag (unsigned int *base, unsigned int flag)
-{
- *base = *base << 1;
- if (flag)
- *base |= 1;
-}
-
-
-/* Output the cgraph NODE to OB. */
-
-static void
-output_node (struct output_block *ob, struct cgraph_node *node)
-{
- unsigned int tag;
- unsigned int flags = 0;
- struct cgraph_edge *callees = node->callees;
-
- switch (cgraph_function_body_availability (node))
- {
- case AVAIL_NOT_AVAILABLE:
- tag = LTO_cgraph_unavail_node;
- break;
-
- case AVAIL_AVAILABLE:
- case AVAIL_LOCAL:
- tag = LTO_cgraph_avail_node;
- break;
-
- case AVAIL_OVERWRITABLE:
- tag = LTO_cgraph_overwritable_node;
- break;
-
- default:
- gcc_unreachable();
- }
-
- output_uleb128 (ob, tag);
- LTO_DEBUG_INDENT (tag);
-
- output_fn_decl (ob, node->decl);
- LTO_DEBUG_FN_NAME (node->decl);
- add_flag (&flags, node->local.local);
- add_flag (&flags, node->local.externally_visible);
- add_flag (&flags, node->local.finalized);
- add_flag (&flags, node->local.inlinable);
- add_flag (&flags, node->local.disregard_inline_limits);
- add_flag (&flags, node->local.redefined_extern_inline);
- add_flag (&flags, node->local.for_functions_valid);
- add_flag (&flags, node->local.vtable_method);
-
- LTO_DEBUG_TOKEN ("flags");
- output_uleb128 (ob, flags);
-
- if (tag != LTO_cgraph_unavail_node)
- {
- LTO_DEBUG_TOKEN ("stack_size");
- output_sleb128 (ob, node->local.inline_summary.estimated_self_stack_size);
- LTO_DEBUG_TOKEN ("self_insns");
- output_sleb128 (ob, node->local.inline_summary.self_insns);
- }
-
- LTO_DEBUG_UNDENT();
-
-#ifdef LTO_STREAM_DEBUGGING
- gcc_assert (lto_debug_context.indent == 0);
-#endif
-
- while (callees)
- {
- output_edge (ob, callees);
- callees = callees->next_callee;
- }
-
-#ifdef LTO_STREAM_DEBUGGING
- gcc_assert (lto_debug_context.indent == 0);
-#endif
-}
-
-
-/* Produce the section that holds the cgraph. */
-
-static void
-produce_asm (struct output_block *ob)
-{
- struct lto_cgraph_header header;
- section *section = lto_get_section (LTO_section_cgraph, NULL);
-
- memset (&header, 0, sizeof (struct lto_cgraph_header));
-
- /* The entire header is stream computed here. */
- switch_to_section (section);
-
- /* Write the header which says how to decode the pieces of the
- t. */
- header.lto_header.major_version = LTO_major_version;
- header.lto_header.minor_version = LTO_minor_version;
- header.lto_header.section_type = LTO_section_cgraph;
-
- header.compressed_size = 0;
-
- header.main_size = ob->main_stream->total_size;
-#ifdef LTO_STREAM_DEBUGGING
- header.debug_main_size = ob->debug_main_stream->total_size;
-#else
- header.debug_main_size = -1;
-#endif
-
- assemble_string ((const char *)&header,
- sizeof (struct lto_cgraph_header));
-
- lto_write_stream (ob->main_stream);
-#ifdef LTO_STREAM_DEBUGGING
- lto_write_stream (ob->debug_main_stream);
-#endif
-}
-
-
-/* Output the cgraph. */
-
-static unsigned int
-lto_output_cgraph (void)
-{
- struct cgraph_node *node;
- section *saved_section = in_section;
- struct output_block *ob = create_output_block ();
-
- LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data);
-
- for (node = cgraph_nodes; node; node = node->next)
- {
- output_node (ob, node);
-
-#ifdef ENABLE_CHECKING
- /* Just a little sanity check to keep Honza honest. At the
- point where we stream out the functions there must only be
- master_clone nodes or nodes that have no function bodies. */
-
- switch (cgraph_function_body_availability (node))
- {
- case AVAIL_UNSET:
- fprintf (stderr, "found unset function\n.");
- gcc_assert (0);
- break;
-
- case AVAIL_NOT_AVAILABLE:
- break;
-
- case AVAIL_OVERWRITABLE:
- case AVAIL_AVAILABLE:
- case AVAIL_LOCAL:
- if (node != cgraph_master_clone (node, false))
- {
- fprintf (stderr, "found clone\n.");
- gcc_assert (0);
- }
- break;
- }
-#endif
- }
-
- output_uleb128 (ob, 0);
-
- /* Create a section to hold the pickled output the cgraph. */
- produce_asm (ob);
-
- destroy_output_block (ob);
-
- /* Put back the assembly section that was there before we started
- writing lto info. */
- if (saved_section)
- switch_to_section (saved_section);
-
- return 0;
-}
-
-struct simple_ipa_opt_pass pass_ipa_lto_cgraph_out =
-{
- {
- SIMPLE_IPA_PASS,
- "lto_cgraph_out", /* name */
- gate_lto_out, /* gate */
- lto_output_cgraph, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_IPA_LTO_OUT, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_dump_func /* todo_flags_finish */
- }
-};
-
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
new file mode 100644
index 00000000000..81eab87de40
--- /dev/null
+++ b/gcc/lto-cgraph.c
@@ -0,0 +1,426 @@
+/* Write and read the cgraph to the memory mapped representation of a
+ .o file.
+
+ Copyright 2008 Free Software Foundation, Inc.
+ Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
+
+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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "toplev.h"
+#include "tree.h"
+#include "expr.h"
+#include "flags.h"
+#include "params.h"
+#include "input.h"
+#include "varray.h"
+#include "hashtab.h"
+#include "langhooks.h"
+#include "basic-block.h"
+#include "tree-pass.h"
+#include "tree-flow.h"
+#include "cgraph.h"
+#include "function.h"
+#include "ggc.h"
+#include "diagnostic.h"
+#include "except.h"
+#include "debug.h"
+#include "vec.h"
+#include "timevar.h"
+#include "dwarf2asm.h"
+#include "dwarf2out.h"
+#include "output.h"
+#include "lto-section-in.h"
+#include "lto-section-out.h"
+#include <ctype.h>
+
+enum LTO_cgraph_tags
+{
+ /* Must leave 0 for the stopper. */
+ LTO_cgraph_avail_node = 1,
+ LTO_cgraph_overwritable_node,
+ LTO_cgraph_unavail_node,
+ LTO_cgraph_edge,
+ LTO_cgraph_last_tag
+};
+
+#ifdef LTO_STREAM_DEBUGGING
+static const char * LTO_cgraph_tag_names[LTO_cgraph_last_tag] =
+{"", "avail", "overwrite", "unavail", "edge"};
+#endif
+
+
+/* Output the cgraph EDGE to OB. */
+
+static void
+output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge)
+{
+ lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_edge);
+ LTO_DEBUG_INDENT (LTO_cgraph_edge);
+ lto_output_fn_decl_index (ob->decl_state, ob->main_stream, edge->callee->decl);
+ LTO_DEBUG_FN_NAME (edge->callee->decl);
+
+ LTO_DEBUG_TOKEN ("stmt");
+ lto_output_uleb128_stream (ob->main_stream, gimple_stmt_uid (edge->call_stmt));
+ LTO_DEBUG_TOKEN ("count");
+ lto_output_uleb128_stream (ob->main_stream, edge->count);
+ LTO_DEBUG_TOKEN ("frequency");
+ lto_output_uleb128_stream (ob->main_stream, edge->frequency);
+ LTO_DEBUG_TOKEN ("loop_next");
+ lto_output_uleb128_stream (ob->main_stream, edge->loop_nest);
+ LTO_DEBUG_UNDENT();
+}
+
+
+/* Output the cgraph NODE to OB. */
+
+static void
+output_node (struct lto_simple_output_block *ob, struct cgraph_node *node)
+{
+ unsigned int tag;
+ unsigned HOST_WIDEST_INT flags = 0;
+ struct cgraph_edge *callees = node->callees;
+
+ switch (cgraph_function_body_availability (node))
+ {
+ case AVAIL_NOT_AVAILABLE:
+ tag = LTO_cgraph_unavail_node;
+ break;
+
+ case AVAIL_AVAILABLE:
+ case AVAIL_LOCAL:
+ tag = LTO_cgraph_avail_node;
+ break;
+
+ case AVAIL_OVERWRITABLE:
+ tag = LTO_cgraph_overwritable_node;
+ break;
+
+ default:
+ gcc_unreachable();
+ }
+
+ lto_output_uleb128_stream (ob->main_stream, tag);
+ LTO_DEBUG_INDENT (tag);
+
+ lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
+ LTO_DEBUG_FN_NAME (node->decl);
+ lto_set_flag (&flags, node->local.local);
+ lto_set_flag (&flags, node->local.externally_visible);
+ lto_set_flag (&flags, node->local.finalized);
+ lto_set_flag (&flags, node->local.inlinable);
+ lto_set_flag (&flags, node->local.disregard_inline_limits);
+ lto_set_flag (&flags, node->local.redefined_extern_inline);
+ lto_set_flag (&flags, node->local.for_functions_valid);
+ lto_set_flag (&flags, node->local.vtable_method);
+
+ LTO_DEBUG_TOKEN ("flags");
+ lto_output_uleb128_stream (ob->main_stream, flags);
+
+ if (tag != LTO_cgraph_unavail_node)
+ {
+ LTO_DEBUG_TOKEN ("stack_size");
+ lto_output_sleb128_stream (ob->main_stream,
+ node->local.inline_summary.estimated_self_stack_size);
+ LTO_DEBUG_TOKEN ("self_insns");
+ lto_output_sleb128_stream (ob->main_stream,
+ node->local.inline_summary.self_insns);
+ }
+
+ LTO_DEBUG_UNDENT();
+
+#ifdef LTO_STREAM_DEBUGGING
+ gcc_assert (lto_debug_context.indent == 0);
+#endif
+
+ while (callees)
+ {
+ output_edge (ob, callees);
+ callees = callees->next_callee;
+ }
+
+#ifdef LTO_STREAM_DEBUGGING
+ gcc_assert (lto_debug_context.indent == 0);
+#endif
+}
+
+
+/* Output the cgraph. */
+
+static void
+output_cgraph (void)
+{
+ struct cgraph_node *node;
+ struct lto_simple_output_block *ob
+ = lto_create_simple_output_block (LTO_section_cgraph);
+ int i = 0;
+
+#ifdef LTO_STREAM_DEBUGGING
+ lto_debug_context.tag_names = LTO_cgraph_tag_names;
+ lto_debug_context.stream_name = "cgraph";
+#endif
+
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+#ifdef ENABLE_CHECKING
+ /* Just a little sanity check to keep Honza honest. At the
+ point where we stream out the functions there must only be
+ master_clone nodes or nodes that have no function bodies. */
+
+ switch (cgraph_function_body_availability (node))
+ {
+ case AVAIL_UNSET:
+ fprintf (stderr, "found unset function\n.");
+ gcc_assert (0);
+ break;
+
+ case AVAIL_NOT_AVAILABLE:
+ break;
+
+ case AVAIL_OVERWRITABLE:
+ case AVAIL_AVAILABLE:
+ case AVAIL_LOCAL:
+ if (node != cgraph_master_clone (node, false))
+ {
+ fprintf (stderr, "found clone\n.");
+ gcc_assert (0);
+ }
+ break;
+ }
+#endif
+ output_node (ob, node);
+ i++;
+ }
+
+ lto_output_uleb128_stream (ob->main_stream, 0);
+
+ /* Create a section to hold the pickled output the cgraph. */
+ lto_destroy_simple_output_block (ob);
+}
+
+
+/* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
+ STACK_SIZE and SELF_INSNS. This is called either to initialize
+ NODE or to replace the values in it, for instance becasue the first
+ time we saw it, the function body was not available but now it
+ is. */
+static void
+input_overwrite_node (struct lto_file_decl_data* file_data,
+ struct cgraph_node *node,
+ enum LTO_cgraph_tags tag,
+ unsigned HOST_WIDEST_INT flags,
+ unsigned int stack_size,
+ unsigned int self_insns)
+{
+ node->aux = (void *)tag;
+ node->local.inline_summary.estimated_self_stack_size = stack_size;
+ node->local.inline_summary.self_insns = self_insns;
+ node->global.insns = self_insns;
+ node->local.lto_file_data = file_data;
+
+ /* This list must be in the reverse order that they are set in
+ lto-section-out.c:outout_node. */
+ node->local.vtable_method = lto_get_flag (&flags);
+ node->local.for_functions_valid = lto_get_flag (&flags);
+ node->local.redefined_extern_inline = lto_get_flag (&flags);
+ node->local.disregard_inline_limits = lto_get_flag (&flags);
+ node->local.inlinable = lto_get_flag (&flags);
+ node->local.finalized = lto_get_flag (&flags);
+ node->local.externally_visible = lto_get_flag (&flags);
+ node->local.local = lto_get_flag (&flags);
+ node->analyzed = node->local.finalized;
+ node->lowered = node->local.finalized;
+ if (cgraph_decide_is_function_needed (node))
+ cgraph_mark_needed_node (node);
+}
+
+
+/* Input a cgraph from IB using the info in FILE_DATA. */
+
+static void
+input_cgraph_1 (struct lto_file_decl_data* file_data,
+ struct lto_input_block *ib)
+{
+ enum LTO_cgraph_tags tag;
+ struct cgraph_node *last_caller = NULL;
+
+ tag = lto_input_uleb128 (ib);
+ while (tag)
+ {
+ LTO_DEBUG_INDENT (tag);
+
+ if (tag == LTO_cgraph_edge)
+ {
+ tree callee_decl;
+ struct cgraph_node *callee;
+ struct cgraph_edge *edge;
+ unsigned int stmt_id;
+ unsigned int count;
+ unsigned int freq;
+ unsigned int nest;
+
+ callee_decl = file_data->fn_decls [lto_input_uleb128 (ib)];
+ LTO_DEBUG_FN_NAME (callee_decl);
+ callee = cgraph_node (callee_decl);
+
+ LTO_DEBUG_TOKEN ("stmt");
+ stmt_id = lto_input_uleb128 (ib);
+ LTO_DEBUG_TOKEN ("count");
+ count = lto_input_uleb128 (ib);
+ LTO_DEBUG_TOKEN ("frequency");
+ freq = lto_input_uleb128 (ib);
+ LTO_DEBUG_TOKEN ("loop_next");
+ nest = lto_input_uleb128 (ib);
+
+ edge = cgraph_create_edge (last_caller, callee, NULL, count, freq, nest);
+ edge->lto_stmt_uid = stmt_id;
+ }
+ else
+ {
+ tree fn_decl;
+ struct cgraph_node *node;
+ unsigned int flags;
+ int stack_size = 0;
+ int self_insns = 0;
+
+ fn_decl = file_data->fn_decls [lto_input_uleb128 (ib)];
+ LTO_DEBUG_FN_NAME (fn_decl);
+ LTO_DEBUG_TOKEN ("flags");
+ flags = lto_input_uleb128 (ib);
+
+ if (tag == LTO_cgraph_avail_node)
+ {
+ LTO_DEBUG_TOKEN ("stack_size");
+ stack_size = lto_input_sleb128 (ib);
+ LTO_DEBUG_TOKEN ("self_insns");
+ self_insns = lto_input_sleb128 (ib);
+ }
+
+ node = cgraph_node (fn_decl);
+
+ switch (tag)
+ {
+ case LTO_cgraph_avail_node:
+ /* We cannot have two avail functions that are the same. */
+ gcc_assert (((enum LTO_cgraph_tags)(node->aux)) != LTO_cgraph_avail_node);
+ input_overwrite_node (file_data, node, tag,
+ flags, stack_size, self_insns);
+ break;
+
+ case LTO_cgraph_unavail_node:
+ /* We only overwrite the node if this is a brand new node. */
+ if (!node->aux)
+ input_overwrite_node (file_data, node, tag,
+ flags, stack_size, self_insns);
+ break;
+
+ case LTO_cgraph_overwritable_node:
+ /* FIXME!!!! This code is written to take the last
+ overwrittable version. I do not speak linker but if the
+ linker supposed to take the first one, then we need to
+ change the test. */
+ if (((enum LTO_cgraph_tags)(node->aux)) != LTO_cgraph_avail_node)
+ input_overwrite_node (file_data, node, tag,
+ flags, stack_size, self_insns);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Set this up so that we can handle the edges which follow and
+ only have the callee in them. */
+ last_caller = node;
+ }
+ LTO_DEBUG_UNDENT();
+ tag = lto_input_uleb128 (ib);
+ }
+}
+
+
+/* Input and merge the cgraph from each of the .o files passed to
+ lto1. */
+
+static void
+input_cgraph (void)
+{
+ struct lto_file_decl_data ** file_data_vec
+ = lto_get_file_decl_data ();
+ struct lto_file_decl_data * file_data;
+ unsigned int j = 0;
+ struct cgraph_node *node;
+
+#ifdef LTO_STREAM_DEBUGGING
+ lto_debug_context.tag_names = LTO_cgraph_tag_names;
+ lto_debug_context.stream_name = "cgraph";
+#endif
+
+ while ((file_data = file_data_vec[j++]))
+ {
+ const char *data;
+ size_t len;
+ struct lto_input_block *ib
+ = lto_create_simple_input_block (file_data,
+ LTO_section_cgraph,
+ &data, &len);
+ input_cgraph_1 (file_data, ib);
+ lto_destroy_simple_input_block (file_data,
+ LTO_section_cgraph,
+ ib, data, len);
+ }
+
+ /* Clear out the aux field that was used to store enough state to
+ tell which nodes should be overwritten. */
+ for (node = cgraph_nodes; node; node = node->next)
+ {
+ gcc_assert (node->local.lto_file_data);
+ node->aux = NULL;
+ }
+}
+
+
+
+struct ipa_opt_pass pass_ipa_lto_cgraph =
+{
+ {
+ IPA_PASS,
+ "lto_cgraph", /* name */
+ gate_lto_out, /* gate */
+ NULL, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_IPA_LTO_OUT, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func /* todo_flags_finish */
+ },
+ NULL, /* generate_summary */
+ output_cgraph, /* write_summary */
+ input_cgraph, /* read_summary */
+ NULL, /* function_read_summary */
+ 0, /* TODOs */
+ NULL, /* function_transform */
+ NULL /* variable_transform */
+};
+
diff --git a/gcc/lto-cgraph.h b/gcc/lto-cgraph.h
deleted file mode 100644
index ef360a92237..00000000000
--- a/gcc/lto-cgraph.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Declarations and definitions relating to the encoding of the cgraph
- into the object files.
-
- Copyright (C) 2008 Free Software Foundation, Inc.
- Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
-
- 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 2, 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 COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-#ifndef GCC_LTO_CGRAPH_H
-#define GCC_LTO_CGRAPH_H
-
-#include "tree.h"
-#include "lto-header.h"
-
-enum LTO_cgraph_tags
-{
- /* Must leave 0 for the stopper. */
- LTO_cgraph_avail_node = 1,
- LTO_cgraph_overwritable_node,
- LTO_cgraph_unavail_node,
- LTO_cgraph_edge,
- LTO_cgraph_last_tag
-};
-
-/* The is the first part of the cgraph record in the .o file. */
-struct lto_cgraph_header
-{
- struct lto_header lto_header; /* The header for all types of sections. */
- int32_t main_size; /* Size of main gimple body of function. */
- int32_t debug_main_size; /* Size of main stream debugging information. */
- int32_t compressed_size;
-};
-
-#ifdef LTO_STREAM_DEBUGGING
-extern const char * LTO_cgraph_tag_names[LTO_cgraph_last_tag];
-#endif
-
-#endif /* GCC_LTO_CGRAPH_H */
diff --git a/gcc/lto-function-in.c b/gcc/lto-function-in.c
index 83e1a93fb94..7ed18617923 100644
--- a/gcc/lto-function-in.c
+++ b/gcc/lto-function-in.c
@@ -140,7 +140,6 @@ input_string_internal (struct data_in *data_in, unsigned int loc,
LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings,
loc, data_in->strings_len);
-
len = lto_input_uleb128 (&str_tab);
*rlen = len;
gcc_assert (str_tab.p + len <= data_in->strings_len);
diff --git a/gcc/lto-function-out.c b/gcc/lto-function-out.c
index 6e240aadbca..690fac4dc12 100644
--- a/gcc/lto-function-out.c
+++ b/gcc/lto-function-out.c
@@ -610,18 +610,8 @@ output_type_ref_1 (struct output_block *ob, tree node)
else
#endif
{
- bool new;
- unsigned int index;
-
output_record_start (ob, NULL, NULL, LTO_global_type_ref);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->type_hash_table,
- &ob->decl_state->next_type_index,
- node, &index);
-
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->types, node);
+ lto_output_type_ref_index (ob->decl_state, ob->main_stream, node);
}
LTO_DEBUG_UNDENT();
@@ -1048,16 +1038,8 @@ output_expr_operand (struct output_block *ob, tree expr)
case FIELD_DECL:
if (!field_decl_is_local (expr))
{
- unsigned int index;
- bool new;
output_record_start (ob, NULL, NULL, LTO_field_decl1);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->field_decl_hash_table,
- &ob->decl_state->next_field_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->field_decls, expr);
+ lto_output_field_decl_index (ob->decl_state, ob->main_stream, expr);
}
else
{
@@ -1070,34 +1052,15 @@ output_expr_operand (struct output_block *ob, tree expr)
case FUNCTION_DECL:
/* FIXME: Local FUNCTION_DECLS are possible, i.e.,
nested functions. */
- {
- unsigned int index;
- bool new;
- output_record_start (ob, NULL, NULL, tag);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->fn_decl_hash_table,
- &ob->decl_state->next_fn_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->fn_decls, expr);
- }
+ output_record_start (ob, NULL, NULL, tag);
+ lto_output_fn_decl_index (ob->decl_state, ob->main_stream, expr);
break;
case VAR_DECL:
if (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
{
- /* Static or extern VAR_DECLs. */
- unsigned int index;
- bool new;
output_record_start (ob, NULL, NULL, LTO_var_decl1);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->var_decl_hash_table,
- &ob->decl_state->next_var_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->var_decls, expr);
+ lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
}
else
{
@@ -1110,16 +1073,8 @@ output_expr_operand (struct output_block *ob, tree expr)
case TYPE_DECL:
if (!type_decl_is_local (expr))
{
- unsigned int index;
- bool new;
output_record_start (ob, NULL, NULL, LTO_type_decl1);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->type_decl_hash_table,
- &ob->decl_state->next_type_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->type_decls, expr);
+ lto_output_type_decl_index (ob->decl_state, ob->main_stream, expr);
}
else
{
@@ -1130,18 +1085,8 @@ output_expr_operand (struct output_block *ob, tree expr)
break;
case NAMESPACE_DECL:
- {
- unsigned int index;
- bool new;
- output_record_start (ob, NULL, NULL, tag);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->namespace_decl_hash_table,
- &ob->decl_state->next_namespace_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->namespace_decls, expr);
- }
+ output_record_start (ob, NULL, NULL, tag);
+ lto_output_namespace_decl_index (ob->decl_state, ob->main_stream, expr);
break;
case PARM_DECL:
@@ -2280,7 +2225,7 @@ output_function (struct cgraph_node* node)
else if (TYPE_P (context))
{
output_record_start (ob, NULL, NULL, LTO_type);
- output_type_ref_1 (ob, context);
+ lto_output_type_ref_index (ob->decl_state, ob->main_stream, context);
LTO_DEBUG_UNDENT ();
}
else
diff --git a/gcc/lto-section-in.h b/gcc/lto-section-in.h
index 2bcbba02e27..17582a0b8fe 100644
--- a/gcc/lto-section-in.h
+++ b/gcc/lto-section-in.h
@@ -77,6 +77,8 @@ struct lto_file_decl_data
htab_t section_hash_table;
};
+struct lto_file_decl_data;
+
/* Return a char pointer to the start of a data stream for an lto pass
or function. The first parameter is the file data that contains
the information. The second parameter is the type of information
diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c
index 5d4df6ad9b7..5a98a333ca8 100644
--- a/gcc/lto-section-out.c
+++ b/gcc/lto-section-out.c
@@ -618,11 +618,12 @@ lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
}
-/* This part is used to store all of the global decls and types that
- are serialized out in this file so that a table for this file can
- be built that allows the decls and types to be reconnected to the
- code or the ipa summary information. */
-
+/*****************************************************************************
+ This part is used to store all of the global decls and types that
+ are serialized out in this file so that a table for this file can be
+ built that allows the decls and types to be reconnected to the code
+ or the ipa summary information.
+*****************************************************************************/
struct lto_out_decl_state *
lto_get_out_decl_state (void)
{
@@ -802,7 +803,7 @@ produce_asm_for_decls (void)
/* Assign reference indices for predefined trees. These need not be
serialized. */
preload_common_nodes (ob);
-
+
memset (&header, 0, sizeof (struct lto_decl_header));
switch_to_section (decl_section);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index a288a0034ab..8cf2a09223d 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,19 +1,3 @@
-2008-06-07 Kenneth Zadeck <zadeck@naturalbridge.com>
- Jan Hubicka <jh@suse.cz>
-
- * lto.c (sys/mman.h, tree-pass.h): New includes.
- (lto_materialize_constructors_and_inits,
- lto_materialize_function): Keeps length of section.
- (lto_materialize_cgraph): Removed.
- (lto_read_decls): Initialize fd field.
- (lto_file_read): Different return type and removed much code to
- lto_main.
- (page_mask): New variable.
- (lto_read_section_data, get_section_data, free_section_data): New
- functions.
- (lto_main): Now calls pass manager, sets the hooks so that the ipa
- passes can get the section data.
-
2008-06-04 Ollie Wild <aaw@google.com>
* lto.c: Remove inclusion of dwarf2.h and dwarf2out.h.
@@ -79,6 +63,22 @@
* lto-section-out.h (lto_hash_global_slot_node, lto_eq_global_slot_node):
Declare.
+2008-06-07 Kenneth Zadeck <zadeck@naturalbridge.com>
+ Jan Hubicka <jh@suse.cz>
+
+ * lto.c (sys/mman.h, tree-pass.h): New includes.
+ (lto_materialize_constructors_and_inits,
+ lto_materialize_function): Keeps length of section.
+ (lto_materialize_cgraph): Removed.
+ (lto_read_decls): Initialize fd field.
+ (lto_file_read): Different return type and removed much code to
+ lto_main.
+ (page_mask): New variable.
+ (lto_read_section_data, get_section_data, free_section_data): New
+ functions.
+ (lto_main): Now calls pass manager, sets the hooks so that the ipa
+ passes can get the section data.
+
2008-05-27 Kenneth Zadeck <zadeck@naturalbridge.com>
* lto.h (lto_read_decls): Made local.
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 2b7e5a242e3..c996f6737b5 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -46,7 +46,7 @@ static void
lto_materialize_constructors_and_inits (struct lto_file_decl_data * file_data)
{
size_t len;
- const char *data = lto_get_section_data (file_data,
+ const char *data = lto_get_section_data (file_data,
LTO_section_static_initializer, NULL, &len);
lto_input_constructors_and_inits (file_data, data);
lto_free_section_data (file_data, LTO_section_static_initializer, NULL, data, len);
@@ -62,7 +62,7 @@ lto_materialize_function (struct cgraph_node *node)
const char *data;
size_t len;
tree step;
- const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
data = lto_get_section_data (file_data, LTO_section_function_body,
name, &len);
@@ -422,6 +422,7 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
/* Read all of the object files specified on the command line. */
for (i = 0; i < num_in_fnames; ++i)
{
+ htab_t section_hash_table;
current_lto_file = lto_elf_file_open (in_fnames[i]);
if (!current_lto_file)
break;
@@ -429,6 +430,9 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
if (!file_data)
break;
+ section_hash_table = lto_elf_build_section_table (current_lto_file);
+ file_data->section_hash_table = section_hash_table;
+
all_file_decl_data [j++] = file_data;
lto_elf_file_close (current_lto_file);
@@ -437,6 +441,10 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
all_file_decl_data [j] = NULL;
+ /* Set the hooks so that all of the ipa passes can read in their data. */
+ lto_set_in_hooks (all_file_decl_data, get_section_data,
+ free_section_data);
+
/* FIXME!!! This loop needs to be changed to use the pass manager to
call the ipa passes directly. */
for (i = 0; i < j; i++)