This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto] delay function materialization
- From: Nathan Froyd <froydnj at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: zadeck at naturalbridge dot com
- Date: Mon, 22 Oct 2007 15:28:42 -0700
- Subject: [lto] delay function materialization
The below patch fixes an issue with reading struct fields and an issue
with cgraph. We would occasionally get messages like:
preprocessed-gcc/global.o:0: sorry, unimplemented: member declaration not inside structure, class, or union
The DWARF we would be looking at would be something like:
<2><d5fe>: Abbrev Number: 36 (DW_TAG_structure_type)
<d5ff> DW_AT_byte_size : 8
<d600> DW_AT_decl_file : 1
<d601> DW_AT_decl_line : 377
<d603> DW_AT_sibling : <d626>
...
<3><d617>: Abbrev Number: 8 (DW_TAG_member)
<d618> DW_AT_name : to
<d61b> DW_AT_decl_file : 1
<d61c> DW_AT_decl_line : 377
<d61e> DW_AT_type : <52d>
<d622> DW_AT_data_member_location: 2 byte block: 23 4 (DW_OP_plus_uconst: 4)
And we would be asked for the FIELD_DECL corresponding to DIE 0xd617.
The problem is that we would attempt to read the DIE directly (usually
through a call chain like lto_read_function_body -> lto_read_body ->
input_globals -> lto_resolve_field_ref -> lto_read_DIE_at_ptr), ignoring
that it is meant to be read in a particular context, i.e. that of its
parent structure. When reading the field, we'd assert that we were in
such a context and fall over.
We could have fixed this by just removing the assert, since we really
did want just the field in this instance. I think this would have
eventually caused problems, since the field would not be "attached"
properly to its containing structure. The tack I took instead was to
delay reading in function bodies ("materialization") until we have read
all of the DWARF info. We therefore ensure that we read the DWARF in
the manner expected--tree-like--and that fields are properly attached to
their parents, etc. I think we wanted this for other reasons, but
fixing the above problem and reading DWARF properly seem like good
reasons to me.
The other bug this patch fixes is that we were not calling
init_ssa_operands like cgraph expected us to, so deep within cgraph,
we'd call fini_ssa_operands, which eventually led to problems after
several finalizations without the corresponding initializations. It
doesn't seem to matter whether we call init_ssa_operands before we read
in the function body or after, so I attempted to pick the most obvious
place.
Committed to the lto branch.
-Nathan
2007-10-22 Nathan Froyd <froydnj@codesourcery.com>
* lto.h (struct lto_info_fd): Add field unmaterialized_fndecls.
* lto.c (lto_info_fd_init): Initialize it.
(lto_info_fd_close): Free it.
(lto_materialize_function): New function.
(lto_read_subroutine_type_subprogram_DIE): Save the result decl on
unmaterialized_fndecls.
(lto_file_read): Read in all the function bodies after we have read
all of the DWARF info.
* lto-read.c (lto_read_body): Call init_ssa_operands if we are
reading a function body.
Index: lto.c
===================================================================
--- lto.c (revision 129550)
+++ lto.c (working copy)
@@ -247,6 +247,7 @@ lto_info_fd_init (lto_info_fd *fd, const
lto_cache_hash,
lto_cache_eq,
free);
+ fd->unmaterialized_fndecls = VEC_alloc (tree, heap, 32);
}
/* Initialize FD, a newly allocated file descriptor for a DWARF2
@@ -269,6 +270,10 @@ lto_info_fd_close (lto_info_fd *fd)
for (i = 0; i < fd->num_units; ++i)
XDELETE (fd->units[i]);
XDELETEVEC (fd->units);
+
+ /* Other people are holding references to the trees contained in this,
+ so just free the vector. */
+ VEC_free (tree, heap, fd->unmaterialized_fndecls);
}
/* Close FD. */
@@ -2388,6 +2393,42 @@ lto_read_abbrev (lto_info_fd *fd)
return abbrev;
}
+/* Read the function body for DECL out of FD if possible. */
+
+static void
+lto_materialize_function (lto_info_fd *fd,
+ lto_context *context,
+ tree decl)
+{
+ lto_file *file;
+ const void *body;
+ const char *name;
+
+ file = fd->base.file;
+ name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ body = file->vtable->map_fn_body (file, name);
+
+ if (body)
+ {
+ /* This function has a definition. */
+ TREE_STATIC (decl) = 1;
+ DECL_EXTERNAL (decl) = 0;
+
+ allocate_struct_function (decl);
+ lto_read_function_body (fd, context, decl, body);
+ file->vtable->unmap_fn_body (file, name, body);
+ }
+ else
+ DECL_EXTERNAL (decl) = 0;
+
+ /* Let the middle end know about the function. */
+ rest_of_decl_compilation (decl,
+ /*top_level=*/1,
+ /*at_end=*/0);
+ if (body)
+ cgraph_finalize_function (decl, /*nested=*/false);
+}
+
static tree
lto_read_subroutine_type_subprogram_DIE (lto_info_fd *fd,
lto_die_ptr die ATTRIBUTE_UNUSED,
@@ -2541,27 +2582,11 @@ lto_read_subroutine_type_subprogram_DIE
result = type;
else
{
- const void *body;
- lto_file *file;
- const char *name_str;
-
if (!name)
lto_file_corrupt_error ((lto_fd *)fd);
result = build_decl (FUNCTION_DECL, name, type);
TREE_PUBLIC (result) = external;
- /* Load the body of the function. */
- file = fd->base.file;
- name_str = IDENTIFIER_POINTER (name);
- body = file->vtable->map_fn_body (file, name_str);
- if (body)
- {
- /* This function has a definition. */
- TREE_STATIC (result) = 1;
- DECL_EXTERNAL (result) = 0;
- }
- else
- DECL_EXTERNAL (result) = 1;
if (inlined == DW_INL_declared_inlined
|| inlined == DW_INL_declared_not_inlined)
DECL_DECLARED_INLINE_P (result) = 1;
@@ -2574,27 +2599,18 @@ lto_read_subroutine_type_subprogram_DIE
declarations. */
result = lto_symtab_merge_fn (result);
if (result != error_mark_node)
- {
- /* Record this function in the DIE cache so that it can be
- resolved from the bodies of functions. */
- lto_cache_store_DIE (fd, die, result);
- /* If the function has a body, read it in. */
- if (body)
- {
- DECL_RESULT (result)
- = build_decl (RESULT_DECL, NULL_TREE,
- TYPE_MAIN_VARIANT (ret_type));
- allocate_struct_function (result);
- lto_read_function_body (fd, context, result, body);
- file->vtable->unmap_fn_body (file, name_str, body);
- }
- /* Let the middle end know about the function. */
- rest_of_decl_compilation (result,
- /*top_level=*/1,
- /*at_end=*/0);
- if (body)
- cgraph_finalize_function (result, /*nested=*/false);
- }
+ {
+ /* Record this function in the DIE cache so that it can be
+ resolved from the bodies of functions. */
+ lto_cache_store_DIE (fd, die, result);
+
+ DECL_RESULT (result)
+ = build_decl (RESULT_DECL, NULL_TREE,
+ TYPE_MAIN_VARIANT (ret_type));
+ }
+
+ /* Save it for later. */
+ VEC_safe_push (tree, heap, fd->unmaterialized_fndecls, result);
}
/* Read the child DIEs, which are in the scope of RESULT. */
@@ -3365,6 +3381,8 @@ lto_file_read (lto_file *file)
DWARF2_CompUnit *unit = file->debug_info.units[i];
/* The context information for this compilation unit. */
lto_context context;
+ size_t j;
+ tree decl;
/* Set up the context. */
lto_set_cu_context (&context, &file->debug_info, unit);
@@ -3380,6 +3398,14 @@ lto_file_read (lto_file *file)
/* Read DIEs. */
while (fd->cur < context.cu_end)
lto_read_DIE (&file->debug_info, &context, NULL);
+
+ /* Read in function bodies now that we have the full DWARF tree
+ available. */
+ for (j = 0;
+ VEC_iterate (tree, file->debug_info.unmaterialized_fndecls,
+ j, decl);
+ j++)
+ lto_materialize_function (&file->debug_info, &context, decl);
}
return true;
Index: lto.h
===================================================================
--- lto.h (revision 129550)
+++ lto.h (working copy)
@@ -26,6 +26,7 @@ Boston, MA 02110-1301, USA. */
#include "hashtab.h"
#include "tree.h"
+#include "vec.h"
#include <inttypes.h>
/* Forward Declarations */
@@ -66,6 +67,8 @@ typedef struct lto_info_fd
/* A map from DIEs to trees. The keys are offsets into the DWARF
information section; the values are trees. */
htab_t die_cache;
+ /* A vector of FUNCTION_DECLs whose bodies have not yet been read in. */
+ VEC (tree, heap) *unmaterialized_fndecls;
} lto_info_fd;
/* A file descriptor for reading from a DWARF abbreviation section. */
Index: lto-read.c
===================================================================
--- lto-read.c (revision 129550)
+++ lto-read.c (working copy)
@@ -1623,6 +1623,9 @@ lto_read_body (lto_info_fd *fd,
cfun = fn;
data_in.num_named_labels = header->num_named_labels;
+ /* cgraph expects this to be called once for each function. */
+ init_ssa_operands ();
+
#ifdef LTO_STREAM_DEBUGGING
lto_debug_context.current_data = &debug_label;
#endif