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] PATCH: Make global function/variable references work


This patch wires up bits to write out and read in references to global
variables and global functions from the bodies of functions.

I was hoping this small program:

  extern int i;

  void f(int j) {
    f(i);
  }

could be round-tripped with this patch, but it causes the
function-body reader to crash.  

Kenny, will you have time to work on that?  

Also, you've got some debugging output printing from
lto-function-out.c; that needs to be turned off before we can do
automated testing.  Would you please conditionalize this on some macro
that you can turn on/off in lto-function-out.c in your own tree for
debugging?

Committed to LTO branch.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

2006-11-10  Mark Mitchell  <mark@codesourcery.com>

	* gcc/lto-function-out.c (produce_asm): Uncomment variable and
	function emission.
	* gcc/dwarf2out.c (lto_init_ref): Generate DIE symbols here.
	Ensure DIEs are emitted.
	(lto_type_ref): Adjust according.
	(lto_var_ref): Implement.
	(lto_fn_ref): Likewise.
	* gcc/lto/lto.c (lto_die_ptr): New type.  Use it throughout.
	(lto_read_compile_unit): Add DIE paramter to this and all other
	DIE readers.
	(lto_read_variable_formal_parameter_constant_DIE): Remember
	variables.
	(lto_read_subroutine_type_subprogram_DIE): Remember functions too.
	(lto_read_DIE): Pass DIE to readers.
	(lto_resolve_type_ref): Tweak.
	(lto_resolve_var_ref): Implement.
	(lto_resolve_fn_ref): Likewise.

Index: gcc/lto-function-out.c
===================================================================
--- gcc/lto-function-out.c	(revision 118626)
+++ gcc/lto-function-out.c	(working copy)
@@ -1607,13 +1607,7 @@ produce_asm (struct output_block *ob, tr
   /* Write the global type references.  */
   for (index = 0; VEC_iterate(tree, ob->fn_decls, index, decl); index++)
     {
-#ifdef GIMPLE_SYMBOL_TABLE_WORKS
-      lto_fn_ref (delc, &out_ref);
-#else
-      out_ref.section = 0;
-      out_ref.base_label = "0";
-      out_ref.label = "0";
-#endif
+      lto_fn_ref (decl, &out_ref);
       dw2_asm_output_data (8, out_ref.section, " ");
       dw2_asm_output_delta (8, out_ref.label,
 			    out_ref.base_label, " ");
@@ -1622,13 +1616,7 @@ produce_asm (struct output_block *ob, tr
   /* Write the global type references.  */
   for (index = 0; VEC_iterate(tree, ob->var_decls, index, decl); index++)
     {
-#ifdef GIMPLE_SYMBOL_TABLE_WORKS
       lto_var_ref (decl, &out_ref);
-#else
-      out_ref.section = 0;
-      out_ref.base_label = "0";
-      out_ref.label = "0";
-#endif
       dw2_asm_output_data (8, out_ref.section, " ");
       dw2_asm_output_delta (8, out_ref.label,
 			    out_ref.base_label, " ");
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 118626)
+++ gcc/dwarf2out.c	(working copy)
@@ -14345,18 +14345,26 @@ dwarf2out_finish (const char *filename)
     htab_traverse (debug_str_hash, output_indirect_string, NULL);
 }
 
-/* Initialize REF.  SCOPE indicates the lexical scope containing the
-   entity being referenced.  */
+/* Initialize REF as a reference to DIE.  SCOPE is the lexical scope
+   containing the entity being referenced.  */
 static void
-lto_init_ref (tree scope ATTRIBUTE_UNUSED, 
-	      lto_out_ref *ref)
+lto_init_ref (lto_out_ref *ref,
+	      dw_die_ref die,
+	      tree scope ATTRIBUTE_UNUSED)
 {
+  /* We must be able to refer to DIE by name.  */
+  gcc_assert (die);
+  /* Make sure the DIE has a label.  */
+  assign_symbol_name (die);
+  gcc_assert (die->die_symbol);
+  /* Make sure the DIE is actually emitted.  */
+  die->die_perennial_p = 1;
   /* At present, we use only one DWARF section.  When we begin using
      multiple sections, SCOPE will be used to figure out the section
      and corresponding BASE_LABEL.  */
   ref->section = 0;
   ref->base_label = debug_info_section_label;
-  ref->label = NULL;
+  ref->label = die->die_symbol;
 }
 
 void 
@@ -14401,31 +14409,34 @@ lto_type_ref (tree type, lto_out_ref *re
  			     scope_die);
   gcc_assert (die);
   
-  /* Make sure the DIE has a label.  */
-  assign_symbol_name (die);
   /* Construct the reference.  */
-  lto_init_ref (scope, ref);
-  ref->label = die->die_symbol;
-
-  return;
+  lto_init_ref (ref, die, scope);
 }
 
 void 
-lto_var_ref (tree var ATTRIBUTE_UNUSED, 
-	     lto_out_ref *ref ATTRIBUTE_UNUSED)
+lto_var_ref (tree var,
+	     lto_out_ref *ref)
 {
+  dw_die_ref die;
+
   gcc_assert (TREE_CODE (var) == VAR_DECL);
-  /* Not yet implemented.  */
-  abort ();
+  /* Generate the DIE for VAR.  */
+  die = force_decl_die (var);
+  /* Construct the reference.  */
+  lto_init_ref (ref, die, DECL_CONTEXT (var));
 }
 
 void 
-lto_fn_ref (tree fn ATTRIBUTE_UNUSED, 
-	    lto_out_ref *ref ATTRIBUTE_UNUSED)
+lto_fn_ref (tree fn,
+	    lto_out_ref *ref)
 {
+  dw_die_ref die;
+
   gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
-  /* Not yet implemented.  */
-  abort ();
+  /* Generate the DIE for FN.  */
+  die = force_decl_die (fn);
+  /* Construct the reference.  */
+  lto_init_ref (ref, die, DECL_CONTEXT (fn));
 }
 
 #else
Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 118626)
+++ gcc/lto/lto.c	(working copy)
@@ -85,6 +85,12 @@ typedef enum DWARF2_class
    forms are allowed, so define a shorthand.  */
 #define DW_cl_constant (DW_cl_uconstant | DW_cl_sconstant)
 
+/* A pointer to a DWARF2 DIE, as mapped into memory.  
+
+   The "lto_die" type is intentionally never defined.  This typedef
+   exists purely for type safety.  */
+typedef struct lto_die *lto_die_ptr;
+
 /* The data corresponding to a single attribute form in a DIE.  */
 typedef struct DWARF2_form_data
 {
@@ -112,7 +118,7 @@ typedef struct DWARF2_form_data
     const char *string;
     /* Used when CL is DW_cl_reference.  The value is a pointer into
        the .debug_info section indicating the DIE referenced.  */
-    const char *reference;
+    lto_die_ptr reference;
   } u;
 } DWARF2_form_data;
 
@@ -649,14 +655,14 @@ find_cu_for_offset (const lto_info_fd *f
    or to a newly allocated context corresponding to the DIE referred
    to by OFFSET.  If *NEW_CONTEXT != CONTEXT upon return, the caller
    must free *NEW_CONTEXT when it is no longer needed.  */
-static const char *
+static lto_die_ptr
 lto_resolve_reference (lto_info_fd *info_fd,
 		       uint64_t offset,
 		       const lto_context *context,
 		       lto_context **new_context)
 {
   DWARF2_CompUnit *cu;
-  const char *reference;
+  lto_die_ptr reference;
 
   /* Swap context if necessary.  */
   cu = find_cu_for_offset (info_fd, offset);
@@ -668,9 +674,10 @@ lto_resolve_reference (lto_info_fd *info
       context = *new_context;
     }
   /* Resolve reference.  */
-  reference = (context->cu_start
-	       + lto_check_size_t_val (offset, "offset too large"));
-  if (reference >= context->cu_end)
+  reference = (lto_die_ptr) ((context->cu_start
+			      + lto_check_size_t_val (offset,
+						      "offset too large")));
+  if (reference >= (lto_die_ptr) context->cu_end)
     lto_file_corrupt_error ((lto_fd *)info_fd);
 
   return reference;
@@ -993,9 +1000,10 @@ lto_read_form (lto_info_fd *info_fd, 
 	  }
 	out->cl = DW_cl_reference;
 	out->u.reference 
-	  = (context->cu_start 
-	     + lto_check_size_t_val (offset, "offset too large"));
-	if (out->u.reference >= context->cu_end)
+	  = (lto_die_ptr) ((context->cu_start 
+			    + lto_check_size_t_val (offset, 
+						    "offset too large")));
+	if (out->u.reference >= (lto_die_ptr) context->cu_end)
 	  lto_file_corrupt_error (fd);
       }
       break;
@@ -1142,7 +1150,7 @@ attribute_value_as_constant (DWARF2_form
 
 typedef struct lto_die_cache_entry {
   /* The DIE address.  */
-  const char *die;
+  lto_die_ptr die;
   /* The tree corresponding to this DIE.  */
   tree val;
   /* The address of the next sibling after the DIE.  */
@@ -1168,7 +1176,7 @@ lto_cache_eq (const void *data, const vo
 /* Record the fact that DIE refers to VAL.  */
 static void
 lto_cache_store_DIE (lto_info_fd *fd,
-		     const char *die,
+		     lto_die_ptr die,
 		     tree val)
 {
   void **slot;
@@ -1194,7 +1202,7 @@ lto_cache_store_DIE (lto_info_fd *fd,
    adjust FD to skip over the DIE and its children and point to its next
    sibling.  */
 static tree
-lto_cache_lookup_DIE (lto_info_fd *fd, const char *die, bool skip)
+lto_cache_lookup_DIE (lto_info_fd *fd, lto_die_ptr die, bool skip)
 {
   lto_die_cache_entry *entry;
 
@@ -1268,6 +1276,7 @@ lto_find_integral_type (tree base_type, 
 
       static tree
       lto_read_tag_DIE (lto_info_fd *fd, 
+                        lto_die_ptr die,
                         const DWARF2_abbrev *abbrev,
 		        lto_context *context)
       {
@@ -1400,15 +1409,15 @@ lto_get_identifier (const DWARF2_form_da
 static tree
 lto_read_referenced_type_DIE (lto_info_fd *fd,
 			      lto_context *context,
-			      const char *reference)
+			      lto_die_ptr reference)
 {
   tree type;
 
   /* Check that the reference is in range.  We use an assert, rather
      than calling lto_file_corrupt_error, because REFERENCE should be
      checked for validity when it is read from the file.  */
-  gcc_assert (reference >= context->cu_start
-	      && reference < context->cu_end);
+  gcc_assert (reference >= (lto_die_ptr) context->cu_start
+	      && reference < (lto_die_ptr) context->cu_end);
   type = lto_cache_lookup_DIE (fd, reference, false);
   if (!type)
     {
@@ -1416,7 +1425,7 @@ lto_read_referenced_type_DIE (lto_info_f
       tree parentdata = context->parentdata; 
 
       /* Move the file pointer to the referenced location.  */
-      fd->base.cur = reference;
+      fd->base.cur = (const char *) reference;
       /* Reset parent data in context.  */
       context->parentdata = NULL_TREE;
       /* Read the DIE, which we insist must be a type.  */
@@ -1434,6 +1443,7 @@ lto_read_referenced_type_DIE (lto_info_f
 
 static tree
 lto_read_compile_unit_DIE (lto_info_fd *fd, 
+			   lto_die_ptr die ATTRIBUTE_UNUSED,
 			   const DWARF2_abbrev *abbrev,
 			   lto_context *context)
 {
@@ -1485,6 +1495,7 @@ lto_read_compile_unit_DIE (lto_info_fd *
 
 static tree
 lto_read_array_type_DIE (lto_info_fd *fd,
+			 lto_die_ptr die ATTRIBUTE_UNUSED,
 			 const DWARF2_abbrev *abbrev,
 			 lto_context *context)
 {
@@ -1570,6 +1581,7 @@ lto_read_array_type_DIE (lto_info_fd *fd
 
 static tree
 lto_read_structure_union_class_type_DIE (lto_info_fd *fd,
+					 lto_die_ptr die ATTRIBUTE_UNUSED,
 					 const DWARF2_abbrev *abbrev,
 					 lto_context *context)
 {
@@ -1766,6 +1778,7 @@ lto_read_structure_union_class_type_DIE 
 
 static tree
 lto_read_enumeration_type_DIE (lto_info_fd *fd,
+			      lto_die_ptr die ATTRIBUTE_UNUSED,
 			       const DWARF2_abbrev *abbrev,
 			       lto_context *context)
 {
@@ -1855,6 +1868,7 @@ lto_read_enumeration_type_DIE (lto_info_
 
 static tree
 lto_read_enumerator_DIE (lto_info_fd *fd,
+			 lto_die_ptr die ATTRIBUTE_UNUSED,
 			 const DWARF2_abbrev *abbrev,
 			 lto_context *context)
 {
@@ -1895,6 +1909,7 @@ lto_read_enumerator_DIE (lto_info_fd *fd
 
 static tree
 lto_read_variable_formal_parameter_constant_DIE (lto_info_fd *fd,
+						 lto_die_ptr die ATTRIBUTE_UNUSED,
 						 const DWARF2_abbrev *abbrev,
 						 lto_context *context)
 {
@@ -1993,11 +2008,16 @@ lto_read_variable_formal_parameter_const
   /* If this variable has already been declared, merge the
      declarations.  */
   decl = lto_symtab_merge_var (decl);
-  /* Let the middle end know about the new entity.  */
   if (decl != error_mark_node)
-    rest_of_decl_compilation (decl,
-			      /*top_level=*/1,
-			      /*at_end=*/0);
+    {
+      /* Record this variable in the DIE cache so that it can be
+	 resolved from the bodies of functions.  */
+      lto_cache_store_DIE (fd, die, decl);
+      /* Let the middle end know about the new entity.  */
+      rest_of_decl_compilation (decl,
+				/*top_level=*/1,
+				/*at_end=*/0);
+    }
 
   lto_read_child_DIEs (fd, abbrev, context);
   return decl;
@@ -2006,6 +2026,7 @@ lto_read_variable_formal_parameter_const
 
 static tree
 lto_read_member_DIE (lto_info_fd *fd,
+		     lto_die_ptr die ATTRIBUTE_UNUSED,
 		     const DWARF2_abbrev *abbrev,
 		     lto_context *context)
 {
@@ -2207,6 +2228,7 @@ lto_read_member_DIE (lto_info_fd *fd,
 
 static tree
 lto_read_subroutine_type_subprogram_DIE (lto_info_fd *fd,
+					 lto_die_ptr die ATTRIBUTE_UNUSED,
 					 const DWARF2_abbrev *abbrev,
 					 lto_context *context)
 {
@@ -2369,6 +2391,10 @@ lto_read_subroutine_type_subprogram_DIE 
       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)
@@ -2378,6 +2404,7 @@ lto_read_subroutine_type_subprogram_DIE 
 	      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);
@@ -2391,6 +2418,7 @@ lto_read_subroutine_type_subprogram_DIE 
 
 static tree
 lto_read_unspecified_parameters_DIE (lto_info_fd *fd,
+				     lto_die_ptr die ATTRIBUTE_UNUSED,
 				     const DWARF2_abbrev *abbrev,
 				     lto_context *context)
 {
@@ -2405,6 +2433,7 @@ lto_read_unspecified_parameters_DIE (lto
 
 static tree
 lto_read_typedef_DIE (lto_info_fd *fd,
+		      lto_die_ptr die ATTRIBUTE_UNUSED,
 		      const DWARF2_abbrev *abbrev,
 		      lto_context *context)
 {
@@ -2457,6 +2486,7 @@ lto_read_typedef_DIE (lto_info_fd *fd,
 
 static tree
 lto_read_pointer_reference_type_DIE (lto_info_fd *fd,
+				     lto_die_ptr die ATTRIBUTE_UNUSED,
 				     const DWARF2_abbrev *abbrev,
 				     lto_context *context)
 {
@@ -2504,6 +2534,7 @@ lto_read_pointer_reference_type_DIE (lto
 
 static tree
 lto_read_subrange_type_DIE (lto_info_fd *fd,
+			    lto_die_ptr die ATTRIBUTE_UNUSED,
 			    const DWARF2_abbrev *abbrev,
 			    lto_context *context)
 {
@@ -2602,6 +2633,7 @@ lto_read_subrange_type_DIE (lto_info_fd 
 
 static tree
 lto_read_base_type_DIE (lto_info_fd *fd, 
+			lto_die_ptr die ATTRIBUTE_UNUSED,
 			const DWARF2_abbrev *abbrev,
 			lto_context *context)
 {
@@ -2743,6 +2775,7 @@ lto_read_base_type_DIE (lto_info_fd *fd,
 
 static tree
 lto_read_const_volatile_restrict_type_DIE (lto_info_fd *fd,
+					   lto_die_ptr die ATTRIBUTE_UNUSED,
 					   const DWARF2_abbrev *abbrev,
 					   lto_context *context)
 {
@@ -2788,6 +2821,7 @@ lto_read_const_volatile_restrict_type_DI
 
 static tree
 lto_read_unspecified_type_DIE (lto_info_fd *fd,
+			       lto_die_ptr die ATTRIBUTE_UNUSED,
 			       const DWARF2_abbrev *abbrev,
 			       lto_context *context)
 {
@@ -2818,6 +2852,7 @@ static tree
 lto_read_DIE (lto_info_fd *fd, lto_context *context, bool *more)
 {
   typedef tree (*DIE_reader_fnptr)(lto_info_fd * fd,
+				   lto_die_ptr die,
 				   const DWARF2_abbrev *abbrev,
 				   lto_context *context);
   /* Reader functions for the tags defined by DWARF 3.  */
@@ -2893,12 +2928,12 @@ lto_read_DIE (lto_info_fd *fd, lto_conte
   uint64_t index;
   const DWARF2_abbrev *abbrev;
   DIE_reader_fnptr reader;
-  const char *die;
+  lto_die_ptr die;
   tree val;
 
   /* Record the location of the current DIE -- before we change the
      file pointer.  */
-  die = ((lto_fd *)fd)->cur;
+  die = (lto_die_ptr) ((lto_fd *)fd)->cur;
   /* Read the abbreviation index.  */
   index = lto_read_uleb128 ((lto_fd *)fd);
   /* Zero indicates a null entry.  */
@@ -2912,7 +2947,7 @@ lto_read_DIE (lto_info_fd *fd, lto_conte
   abbrev = lto_abbrev_lookup (&fd->base.file->debug_abbrev, index);
   /* Check to see if this DIE has already been processed.  If so, skip
      over it and its children.  */
-  val = lto_cache_lookup_DIE (fd, die, true);
+  val = lto_cache_lookup_DIE (fd, die, /*skip=*/true);
   if (!val)
     {
       /* Determine the DIE reader function.  */
@@ -2922,7 +2957,7 @@ lto_read_DIE (lto_info_fd *fd, lto_conte
       if (reader)
 	{
 	  /* If there is a reader, use it.  */
-	  val = reader (fd, abbrev, context);
+	  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))
@@ -3114,17 +3149,19 @@ lto_resolve_type_ref (lto_info_fd *info_
 		      lto_context *context,
 		      const lto_ref *ref)
 {
-  const char *reference;
+  lto_die_ptr die;
   lto_context *new_context = context;
   tree type;
 
   /* At present, we only support a single DWARF section.  */
   if (ref->section != 0)
     lto_abi_mismatch_error ();
-  reference = lto_resolve_reference (info_fd, ref->offset, context,
-				     &new_context);
-  /* Resolve the reference.  */
-  type = lto_read_referenced_type_DIE (info_fd, context, reference);
+  /* Map REF to a DIE.  */
+  die = lto_resolve_reference (info_fd, ref->offset, context, &new_context);
+  /* Map DIE to a type.  */
+  type = lto_read_referenced_type_DIE (info_fd, context, die);
+  if (!type || !TYPE_P (type))
+    lto_file_corrupt_error ((lto_fd *)info_fd);
   /* Clean up.  */
   if (new_context != context)
     XDELETE (new_context);
@@ -3133,19 +3170,53 @@ lto_resolve_type_ref (lto_info_fd *info_
 }
 
 tree 
-lto_resolve_var_ref (lto_info_fd *info_fd ATTRIBUTE_UNUSED,
-		     lto_context *context ATTRIBUTE_UNUSED,
-		     const lto_ref *ref ATTRIBUTE_UNUSED)
+lto_resolve_var_ref (lto_info_fd *info_fd,
+		     lto_context *context,
+		     const lto_ref *ref)
 {
-  abort ();
+  lto_die_ptr die;
+  lto_context *new_context = context;
+  tree var;
+
+  /* At present, we only support a single DWARF section.  */
+  if (ref->section != 0)
+    lto_abi_mismatch_error ();
+  /* Map REF to a DIE.  */
+  die = lto_resolve_reference (info_fd, ref->offset, context, &new_context);
+  /* Map DIE to a variable.  */
+  var = lto_cache_lookup_DIE (info_fd, die, /*skip=*/false);
+  if (!var || TREE_CODE (var) != VAR_DECL)
+    lto_file_corrupt_error ((lto_fd *)info_fd); 
+  /* Clean up.  */
+  if (new_context != context)
+    XDELETE (new_context);
+
+  return var;
 }
 
 tree 
-lto_resolve_fn_ref (lto_info_fd *info_fd ATTRIBUTE_UNUSED,
-		    lto_context *context ATTRIBUTE_UNUSED,
-		    const lto_ref *ref ATTRIBUTE_UNUSED)
+lto_resolve_fn_ref (lto_info_fd *info_fd,
+		    lto_context *context,
+		    const lto_ref *ref)
 {
-  abort ();
+  lto_die_ptr die;
+  lto_context *new_context = context;
+  tree fn;
+
+  /* At present, we only support a single DWARF section.  */
+  if (ref->section != 0)
+    lto_abi_mismatch_error ();
+  /* Map REF to a DIE.  */
+  die = lto_resolve_reference (info_fd, ref->offset, context, &new_context);
+  /* 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); 
+  /* Clean up.  */
+  if (new_context != context)
+    XDELETE (new_context);
+
+  return fn;
 }
 
 void


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