This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto] fix reading DW_TAG_variable_type
- From: Nathan Froyd <froydnj at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: zadeck at naturalbridge dot com
- Date: Fri, 19 Oct 2007 08:16:14 -0700
- Subject: [lto] fix reading DW_TAG_variable_type
The below patch fixes an issue with reading DW_TAG_variable DIEs. We
would run across debug information like:
<1><7e4>: Abbrev Number: 37 (DW_TAG_variable)
<7e5> DW_AT_name : last_id
<7ed> DW_AT_decl_file : 1
<7ee> DW_AT_decl_line : 62
<7ef> DW_AT_type : <1c4>
<7f3> DW_AT_declaration : 1
...
<1><818>: Abbrev Number: 38 (DW_TAG_variable)
<819> DW_AT_specification: <7e4>
<81d> DW_AT_location : 9 byte block: 3 0 0 0 0 0 0 0 0 (DW_OP_addr: 0)
When we read the DIE at 0x818, we would find that it had a null name and
type (since we didn't follow DW_AT_specification), which build_decl and
its callees would choke on.
We fix this by following DW_AT_specification and returning the decl
associated with that when appropriate.
This still leaves open the problem of what to do about cases like:
<2><524>: Abbrev Number: 27 (DW_TAG_variable)
<525> DW_AT_location : 9 byte block: 3 0 0 0 0 0 0 0 0 (DW_OP_addr: 0)
where we have no name, type, or specification. I think this may be a
bug in the DWARF generation. Suggestions on what causes this, how to
fix it, or outright fixes welcome.
Moderately non-trivial files (e.g. alloc-pool.c) are now round-trippable
through LTO.
Committed to the LTO branch.
-Nathan
2007-10-19 Nathan Froyd <froydnj@codesourcery.com>
* lto.c (lto_read_DIE_at_ptr): New function.
(lto_resolve_var_ref): Use it.
(lto_resolve_fn_ref): Use it.
(lto_resolve_field_ref): Use it.
(lto_read_variable_formal_parameter_constant_DIE): Follow
DW_AT_specification and return the associated decl when appropriate.
Index: lto.c
===================================================================
--- lto.c (revision 129458)
+++ lto.c (working copy)
@@ -201,6 +201,11 @@ lto_read_DIE (lto_info_fd *fd,
lto_context *context,
bool *more);
+static tree
+lto_read_DIE_at_ptr (lto_info_fd *fd,
+ lto_context *context,
+ lto_die_ptr ptr);
+
static void
lto_read_child_DIEs (lto_info_fd *fd,
const DWARF2_abbrev *abbrev,
@@ -1966,6 +1971,7 @@ lto_read_variable_formal_parameter_const
bool artificial;
enum tree_code code;
tree decl;
+ tree specification;
gcc_assert (abbrev->tag == DW_TAG_variable
|| abbrev->tag == DW_TAG_formal_parameter
@@ -1978,6 +1984,7 @@ lto_read_variable_formal_parameter_const
declaration = false;
code = ERROR_MARK;
decl = NULL_TREE;
+ specification = NULL_TREE;
LTO_BEGIN_READ_ATTRS ()
{
@@ -1990,10 +1997,15 @@ lto_read_variable_formal_parameter_const
case DW_AT_decl_line:
case DW_AT_abstract_origin:
case DW_AT_const_value:
- case DW_AT_specification:
/* Ignore. */
break;
+ case DW_AT_specification:
+ if (abbrev->tag == DW_TAG_variable)
+ specification = lto_read_DIE_at_ptr (fd, context,
+ attr_data.u.reference);
+ break;
+
case DW_AT_name:
name = lto_get_identifier (&attr_data);
/* Assume that the assembler name is the same as the source name
@@ -2063,6 +2075,14 @@ lto_read_variable_formal_parameter_const
;
else
{
+ /* Check for a specification. */
+ if (specification
+ && !name
+ && !type
+ && TREE_CODE (specification) == code)
+ return specification;
+
+
/* Build the tree node for this entity. */
decl = build_decl (code, name, type);
@@ -3372,6 +3392,25 @@ lto_resolve_type_ref (lto_info_fd *info_
return type;
}
+tree
+lto_read_DIE_at_ptr (lto_info_fd *info_fd,
+ lto_context *context,
+ lto_die_ptr ptr)
+{
+ lto_fd *fd = (lto_fd *)info_fd;
+ const char *saved_die = fd->cur;
+ tree result;
+
+ fd->cur = (const char *) ptr;
+ result = lto_read_DIE (info_fd, context, NULL);
+
+ if (!result)
+ lto_file_corrupt_error (fd);
+
+ fd->cur = saved_die;
+ return result;
+}
+
tree
lto_resolve_var_ref (lto_info_fd *info_fd,
lto_context *context,
@@ -3389,18 +3428,7 @@ lto_resolve_var_ref (lto_info_fd *info_f
/* Map DIE to a variable. */
var = lto_cache_lookup_DIE (info_fd, die, /*skip=*/false);
if (!var)
- {
- lto_fd *fd = (lto_fd *)info_fd;
- const char *saved_die = fd->cur;
-
- fd->cur = (const char *) die;
- var = lto_read_DIE (info_fd, context, NULL);
-
- if (!var)
- lto_file_corrupt_error (fd);
-
- fd->cur = saved_die;
- }
+ var = lto_read_DIE_at_ptr (info_fd, context, die);
if (TREE_CODE (var) != VAR_DECL)
lto_file_corrupt_error ((lto_fd *)info_fd);
@@ -3428,18 +3456,7 @@ lto_resolve_fn_ref (lto_info_fd *info_fd
/* Map DIE to a variable. */
fn = lto_cache_lookup_DIE (info_fd, die, /*skip=*/false);
if (!fn)
- {
- lto_fd *fd = (lto_fd *)info_fd;
- const char *saved_die = fd->cur;
-
- fd->cur = (const char *) die;
- fn = lto_read_DIE (info_fd, context, NULL);
-
- if (!fn)
- lto_file_corrupt_error (fd);
-
- fd->cur = saved_die;
- }
+ fn = lto_read_DIE_at_ptr (info_fd, context, die);
if (TREE_CODE (fn) != FUNCTION_DECL)
lto_file_corrupt_error ((lto_fd *)info_fd);
@@ -3467,18 +3484,7 @@ lto_resolve_field_ref (lto_info_fd *info
/* Map DIE to a variable. */
field = lto_cache_lookup_DIE (info_fd, die, /*skip=*/false);
if (!field)
- {
- lto_fd *fd = (lto_fd *)info_fd;
- const char *saved_die = fd->cur;
-
- fd->cur = (const char *) die;
- field = lto_read_DIE (info_fd, context, NULL);
-
- if (!field)
- lto_file_corrupt_error (fd);
-
- fd->cur = saved_die;
- }
+ field = lto_read_DIE_at_ptr (info_fd, context, die);
if (TREE_CODE (field) != FIELD_DECL)
lto_file_corrupt_error ((lto_fd *)info_fd);