This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[lto] some reader fixes


The attached patch fixes a few problems with the LTO reader; we are now
able to write out and read in some of the simpler files in GCC itself,
although we still have a long way to go.

The fixes, in no particular order, are:

- We didn't handle structs with pointer members to the struct type
  well--we'd keep trying to read DWARF information for the struct over
  and over again, leading to infinite recursion.  Fixed by inserting the
  tree for the struct type into the cache prior to reading the members,
  so looking up the pointer types finds the thing we're modifying;

- GCC does, indeed, generate 0-dimensional array types, which we were
  asserting would not happen.  Fixed by following prior art in other
  parts of GCC;

- GCC generates incomplete type information for structures (e.g. when
  you have 'struct foo *', there might not be complete
  information--sizes, members, etc.--about 'struct foo'), so we have to
  be mindful of this case when reading type information;

- We now need to read more complex information about types when reading
  function parameter lists and so we need to be a little bit smarter
  about setting context->skip_${FOO};

- A few more attributes are now handled;

Problems that remain:

- We don't handle DW_TAG_lexical_block and DW_TAG_inlined_subroutine,
  and the reader complains, but continues chugging along;

- GCC doesn't output code for 'static inline' functions that were
  inlined at all call sites; the reader prints error messages about not
  being able to find the bodies for such functions even though it just
  keeps chugging through the file;

- input_globals calls lto_resolve_fn_ref for functions that have not
  been read in yet.  The quick and dirty solution of attempting to
  immediately read in the requested function did not work; something
  deeper is at work here;

- We are encountering problems reading the stream itself, e.g.:

lto/libexec/gcc/x86_64-unknown-linux-gnu/4.3.0/lto1 -O2 preprocessed-gcc/vec.o -o preprocessed-gcc/vec.x
preprocessed-gcc/vec.o:0: error: unable to find LTO data for 'trim_filename': 
preprocessed-gcc/vec.o:0: error: unable to find LTO data for 'internal_error': 
stream failure: looking for a '2' in the debug stream.
However the data translated into a '5' at position474

     0   -->><<--
     1   -->>(parm_decl_body2:U0x57U0x2"op"typeU0x0typeU0x0flagsU0x500alignU0x40size<<--
    73   -->> (integer_cst:typeU0x8flagsU0x4S0x40)<<--
   111   -->><<--
   112   -->> (integer_cst:typeU0x9flagsU0x4S0x8)<<--
   149   -->>)<<--
   151   -->><<--
   152   -->>(parm_decl_body2:U0x5aU0x4"file"typeU0x0typeU0x0flagsU0x500alignU0x40size<<--
   226   -->> (integer_cst:typeU0x8flagsU0x4S0x40)<<--
   264   -->><<--
   265   -->> (integer_cst:typeU0x9flagsU0x4S0x8)<<--
   302   -->>)<<--
   304   -->><<--
   305   -->>(local_var_decl_body2:U0x0typeU0x0flagsU0x1404000alignU0x40size<<--
   369   -->> (integer_cst:typeU0x8flagsU0x4S0x40)<<--
   407   -->><<--
   408   -->> (integer_cst:typeU0x9flagsU0x4S0x8)<<--
   445   -->>)<<--
   447   -->><<--
   448   -->>(parm_decl_body2:U0x57U0x57"struct_name"typeU0x0typeU0x0flagsU0x500alignU0x40size<<--
                                      ^
                                      |
   530   -->> (integer_cst:typeU0x8flagsU0x4S0x40)<<--
   568   -->><<--
   569   -->> (integer_cst:typeU0x9flagsU0x4S0x8)<<--
   606   -->>)<<--
   608   -->><<--
   609   -->>(parm_decl_body2:U0x5fU0x8"function"typeU0x0typeU0x0flagsU0x500alignU0x40size<<--
   687   -->> (integer_cst:typeU0x8flagsU0x4S0x40)<<--
   725   -->><<--
   726   -->> (integer_cst:typeU0x9flagsU0x4S0x8)<<--
   763   -->>)<<--
   765   -->><<--
   766   -->>(parm_decl_body2:U0x68U0x4"line"typeU0xatypeU0xaflagsU0x500alignU0x20size<<--
   840   -->> (integer_cst:typeU0x8flagsU0x4S0x20)<<--
   878   -->><<--
   879   -->> (integer_cst:typeU0x9flagsU0x4S0x4)<<--
   916   -->>)<<--
preprocessed-gcc/vec.o:0: internal compiler error: in debug_out_fun, at lto/lto-read.c:1754

- input_expr_operand segfaults on some inputs.  I think I know how to
  fix this, but have not yet tested my hypothesis.

- Probably others that I have forgotten or will be exposed by fixing the
  last three items above. :)

Committed to the lto branch.

-Nathan

2007-10-05  Nathan Froyd  <froydnj@codesourcery.com>

	gcc/
	* dwarf2out.h (dwarf_attr_name): Declare.
	* dwarf2out.c (dwarf_attr_name): Remove declaration and change
	definition accordingly.

	gcc/lto/
	* lto.c: Include dwarf2out.h.
	(lto_cache_store_DIE): Assert that we never change the value.
	(LTO_BEGIN_READ_ATTRS): Print an informative error message.
	(lto_read_compile_unit_DIE): Handle DW_AT_entry_pc.
	(lto_read_array_type_DIE): Don't error on ndims == 0; build a
	sensible type instead.
	(lto_read_structure_union_class_type_DIE): Store the newly
	created type prior to reading the members of the structure to
	avoid infinite recursion.  Avoid computing types and alignments
	for structures whose sizes are unknown.
	(lto_read_variable_formal_parameter_const): Handle DW_AT_artificial
	and set DECL_ARTIFICIAL accordingly.  Ignore DW_AT_abstract_origin,
	DW_AT_const_value, and DW_AT_specification.
	(lto_read_subroutine_type_subprogram_DIE): Handle DW_AT_declaration.
	Return early if we have already constructed the function type.
	(lto_read_typedef_DIE): Check to see if the type has been cached
	already.  Cache the type before reading any children.
	(lto_read_const_volatile_restrict_type_DIE): Handle DW_AT_name.
	(lto_read_DIE): Unset context->skip_non_parameters around reading
	the DIE.
	(lto_resolve_fn_ref): Delete trailing whitespace.
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 128824)
+++ gcc/dwarf2out.c	(working copy)
@@ -4080,7 +4080,6 @@ static int is_pseudo_reg (rtx);
 static tree type_main_variant (tree);
 static int is_tagged_type (tree);
 static const char *dwarf_tag_name (unsigned);
-static const char *dwarf_attr_name (unsigned);
 static const char *dwarf_form_name (unsigned);
 static tree decl_ultimate_origin (tree);
 static tree block_ultimate_origin (tree);
@@ -4607,7 +4606,7 @@ dwarf_tag_name (unsigned int tag)
 
 /* Convert a DWARF attribute code into its string name.  */
 
-static const char *
+const char *
 dwarf_attr_name (unsigned int attr)
 {
   switch (attr)
Index: gcc/dwarf2out.h
===================================================================
--- gcc/dwarf2out.h	(revision 128824)
+++ gcc/dwarf2out.h	(working copy)
@@ -27,6 +27,7 @@ extern void debug_dwarf (void);
 struct die_struct;
 extern void debug_dwarf_die (struct die_struct *);
 extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *));
+extern const char *dwarf_attr_name (unsigned);
 
 /* The LTO representations for the bodies of functions may refer to
    the LTO representations of global functions, variables, and
Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 128823)
+++ gcc/lto/lto.c	(working copy)
@@ -25,6 +25,7 @@ Boston, MA 02110-1301, USA.  */
 #include "opts.h"
 #include "toplev.h"
 #include "dwarf2.h"
+#include "dwarf2out.h"          /* For dwarf_attr_name.  */
 #include "tree.h"
 #include "tm.h"
 #include "cgraph.h"
@@ -1201,14 +1202,20 @@ lto_cache_store_DIE (lto_info_fd *fd,
   slot = htab_find_slot_with_hash (fd->die_cache, die, 
 				   htab_hash_pointer (die),
 				   INSERT);
-  /* There can only be one entry for a given DIE.  */
-  gcc_assert (!*slot);
-  /* Store the value.  */
-  entry = XNEW (lto_die_cache_entry);
-  entry->die = die;
-  entry->val = val;
-  entry->sibling = fd->base.cur;
-  *slot = entry;
+  if (!*slot)
+    {
+      /* Store the value.  */
+      entry = XNEW (lto_die_cache_entry);
+      entry->die = die;
+      entry->val = val;
+      entry->sibling = fd->base.cur;
+      *slot = entry;
+    }
+  else
+    {
+      /* We should not change the value once created.  */
+      gcc_assert (((lto_die_cache_entry *) *slot)->val == val);
+    }
 }
 
 /* If FD points to a DIE that has already been processed, return the
@@ -1373,6 +1380,7 @@ lto_find_integral_type (tree base_type, 
 #define LTO_BEGIN_READ_ATTRS()			\
   LTO_BEGIN_READ_ATTRS_UNCHECKED()		\
     default:					\
+      fprintf (stderr, "Unhandled attribute in %s: %s\n", __FUNCTION__, dwarf_attr_name (attr->name)); \
       lto_file_corrupt_error ((lto_fd *)fd);	\
       break;  
 
@@ -1485,6 +1493,7 @@ lto_read_compile_unit_DIE (lto_info_fd *
 
     case DW_AT_low_pc:
     case DW_AT_high_pc:
+    case DW_AT_entry_pc:
     case DW_AT_ranges:
     case DW_AT_name:
     case DW_AT_stmt_list:
@@ -1569,24 +1578,27 @@ lto_read_array_type_DIE (lto_info_fd *fd
 
   /* Construct and cache the array type object for our caller.  */
   if (ndims == 0)
-    lto_file_corrupt_error ((lto_fd *)fd);
-  if (order == -1)
-    {
-      istart = ndims - 1;
-      iend = -1;
-    }
+    type = build_array_type (type, NULL_TREE);
   else
     {
-      gcc_assert (order == 1);
-      istart = 0;
-      iend = ndims;
-    }
-  for (i = istart; i != iend; i += order)
-    {
-      tree dim = VEC_index (tree, dims, i);
-      if (!dim || ! INTEGRAL_TYPE_P (dim))
-	lto_file_corrupt_error ((lto_fd *)fd);	
-      type = build_array_type (type, dim);
+      if (order == -1)
+        {
+          istart = ndims - 1;
+          iend = -1;
+        }
+      else
+        {
+          gcc_assert (order == 1);
+          istart = 0;
+          iend = ndims;
+        }
+      for (i = istart; i != iend; i += order)
+        {
+          tree dim = VEC_index (tree, dims, i);
+          if (!dim || ! INTEGRAL_TYPE_P (dim))
+            lto_file_corrupt_error ((lto_fd *)fd);	
+          type = build_array_type (type, dim);
+        }
     }
   VEC_free (tree, heap, dims);
   return type;
@@ -1695,6 +1707,16 @@ lto_read_structure_union_class_type_DIE 
       TYPE_SIZE_UNIT (type) = size_int (size);
     }
 
+  /* Store this entry so that cases like:
+
+     struct foo {
+       struct foo *next;
+       ....
+     }
+
+     don't cause infinite recursion.  */
+  lto_cache_store_DIE (fd, die, type);
+
   /* Process the members.  */
   parentdata = context->parentdata;
   context->parentdata = type;
@@ -1777,12 +1799,16 @@ lto_read_structure_union_class_type_DIE 
     }
   VEC_free (tree, heap, children);
 
-  /* The type mode isn't encoded in the DWARF spec, either, so just recompute
-     it from scratch.  */
-  compute_record_mode (type);
-  if (GET_MODE_ALIGNMENT (TYPE_MODE (type)) > align)
-    align = GET_MODE_ALIGNMENT (TYPE_MODE (type));
-  TYPE_ALIGN (type) = align;
+  /* We might not have any information about how big the structure is.  */
+  if (size)
+    {
+      /* The type mode isn't encoded in the DWARF spec, either, so just
+         recompute it from scratch.  */
+      compute_record_mode (type);
+      if (GET_MODE_ALIGNMENT (TYPE_MODE (type)) > align)
+        align = GET_MODE_ALIGNMENT (TYPE_MODE (type));
+      TYPE_ALIGN (type) = align;
+    }
 
   /* Finish debugging output for this type.  */
   if (!declaration)
@@ -1932,6 +1958,7 @@ lto_read_variable_formal_parameter_const
   tree type;
   bool external;
   bool declaration;
+  bool artificial;
   enum tree_code code;
   tree decl;
 
@@ -1956,6 +1983,9 @@ lto_read_variable_formal_parameter_const
     case DW_AT_decl_column:
     case DW_AT_decl_file:
     case DW_AT_decl_line:
+    case DW_AT_abstract_origin:
+    case DW_AT_const_value:
+    case DW_AT_specification:
       /* Ignore.  */
       break;
 
@@ -1968,6 +1998,10 @@ lto_read_variable_formal_parameter_const
 	asm_name = name;
       break;
 
+    case DW_AT_artificial:
+      artificial = attr_data.u.flag;
+      break;
+
     case DW_AT_external:
       external = attr_data.u.flag;
       break;
@@ -1982,10 +2016,8 @@ lto_read_variable_formal_parameter_const
       declaration = attr_data.u.flag;
       break;
 
-    case DW_AT_specification:
     case DW_AT_variable_parameter:
     case DW_AT_is_optional:
-    case DW_AT_const_value:
       lto_unsupported_attr_error (abbrev, attr);
       break;
 
@@ -2029,6 +2061,8 @@ lto_read_variable_formal_parameter_const
       /* Build the tree node for this entity.  */
       decl = build_decl (code, name, type);
 
+      DECL_ARTIFICIAL (decl) = artificial;
+
       /* Parameter decls never have external linkage, never need merging,
 	 etc.  */
       if (code == VAR_DECL)
@@ -2317,6 +2351,7 @@ lto_read_subroutine_type_subprogram_DIE 
   tree asm_name = NULL_TREE;
   bool external;
   bool prototyped;
+  bool declaration;
   tree result;
   tree saved_scope;
   int inlined = DW_INL_not_inlined;
@@ -2362,6 +2397,10 @@ lto_read_subroutine_type_subprogram_DIE 
 	  /* Ignore.  */
 	  break;
 
+        case DW_AT_declaration:
+          declaration = attr_data.u.flag;
+          break;
+
 	case DW_AT_name:
 	  name = lto_get_identifier (&attr_data);
 	  /* Assume that the assembler name is the same as the source
@@ -2427,6 +2466,15 @@ lto_read_subroutine_type_subprogram_DIE 
 	*context->last_parm_type = void_list_node;
     }
 
+  /* We might have constructed the necessary type already while reading
+     attributes.  */
+  if (abbrev->tag == DW_TAG_subroutine_type)
+    {
+      tree result = lto_cache_lookup_DIE (fd, die, false);
+
+      if (result) return result;
+    }
+
   /* Build the function type.  */
   type = build_function_type (ret_type, arg_types);
   if (abbrev->tag == DW_TAG_subroutine_type)
@@ -2554,6 +2602,12 @@ lto_read_typedef_DIE (lto_info_fd *fd,
     }
   LTO_END_READ_ATTRS ();
 
+  {
+    tree type = lto_cache_lookup_DIE (fd, die, false);
+
+    if (type) return type;
+  }
+
   /* The DW_AT_name attribute is required.  */
   if (!name)
     lto_file_corrupt_error ((lto_fd *)fd);
@@ -2570,6 +2624,9 @@ lto_read_typedef_DIE (lto_info_fd *fd,
   TYPE_NAME (type) = decl;
   DECL_ORIGINAL_TYPE (decl) = base_type;
 
+  /* Store this future references in our children.  */
+  lto_cache_store_DIE (fd, die, type);
+
   lto_read_child_DIEs (fd, abbrev, context);
   return type;
 }
@@ -2880,6 +2937,9 @@ lto_read_const_volatile_restrict_type_DI
 						context, 
 						attr_data.u.reference);
       break;
+    case DW_AT_name:
+      /* Ignore.  FIXME: is this right?  */
+      break;
     }
   LTO_END_READ_ATTRS ();
 
@@ -3059,12 +3119,22 @@ lto_read_DIE (lto_info_fd *fd, lto_conte
 
       if (reader)
 	{
+          /* If we are reading some sort of formal parameter or
+             unspecified parameter, then we need to unset
+             context->skip_non_parameters to read the types for said
+             parameter.  */
+          bool saved_skip_non_parameters = context->skip_non_parameters;
+
+          context->skip_non_parameters = false;
+
 	  /* If there is a reader, use it.  */
 	  val = reader (fd, die, abbrev, context);
 	  /* If this DIE refers to a type, cache the value so that future
 	     references to the type can be processed quickly.  */
 	  if (val && TYPE_P (val))
 	    lto_cache_store_DIE (fd, die, val);
+
+          context->skip_non_parameters = saved_skip_non_parameters;
 	}
       else
 	{
@@ -3322,7 +3392,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 || TREE_CODE (fn) != FUNCTION_DECL)
-    lto_file_corrupt_error ((lto_fd *)info_fd); 
+    lto_file_corrupt_error ((lto_fd *)info_fd);
   /* Clean up.  */
   if (new_context != context)
     XDELETE (new_context);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]