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 committed to fix a lot of bugs.


This patch fixes a large number of issues with the lto function readers
and writers.  For the most part this is a large step forward, though
some other bugs have come to the surface because of the fixes made here.

This patch contains most of the code to get line numbers correct.  Old
style line numbers are completely done, mapped locations still need more
work.

This patch fixes a bug where the ssa form did not verify correctly
because some of the operands of the phi_functions were not being added
to the referenced vars list.

This patch properly connects the tree chain and the decl context for
local vars and parm decls.  This required a lot of plumbing from
nathan's last commits as well as a lot of plumbing here to get
type_decls pushed thru the system.  Getting this correct fixed several
odd ball failures that were not obviously related to the missing fields.

There were also bugs in reading the flags for local_vars and parm decls
that had to do with an improper partial implementation of line number
information. 

There was a latent bug that i stumbled over that would have messed up
the hash table that controls the string table on 32 bit machines.  Since
i work on 64 bit machines, i never saw this except while reading code.

There was a possible latent bug in reading unsigned leb128 numbers. 

this patch has been committed as revision 129762.

Kenny


2007-10-29  Kenneth Zadeck <zadeck@naturalbridge.com>

    * lto-tree-flags.def (VAR_DECL): Added seen_in_bind_expr flag.
    * lto-function-out.c (struct output_block): Added
    type_decl_hash_table, next_type_decl_index, type_decls,
    current_col. Changed last_file to current_file. Changed last_line
    to current_line.
    (clear_line_info): New function.
    (create_output_block): Added call to clear_line_info.  Added
    initialization of type_decl_hash_table.
    (destroy_output_block): Added destruction of type_decl_hash_table.
    (output_string): Fixed type snafu.
    (output_tree_flags): Added force_loc parameter and uses of it.
    Full rewrite of processing of line numbers.
    (output_expr_operand): Added TYPE_DECL case.
    (output_local_vars): Properly handle TREE_CHAIN and DECL_CONTEXT.
    (output_named_labels, output_constructor_or_init): Added call to
    clear_line_info.
    (output_ssa_names): Added parm to not process line numbers for ssa
    names.
    (produce_asm): Added code to output type_decls.
    (output_function): Added call to clear_line_info.  Moved
    production of labels to after local_vars to get processing of
    context correct.
    * lto-tree-tags.def (LTO_type_decl): New tag.
    * lto-tags.h (lto_header): Added num_type_decls.
    (LTO_type_decl): New tag.
    (LTO_SOURCE_FILE, LTO_SOURCE_LINE, LTO_SOURCE_LOC_BITS,
    LTO_SOURCE_COL): New macros.
    * tree-dfa.c (find_referenced_vars): Added code to walk phi
    operands.
    
2007-10-29  Kenneth Zadeck <zadeck@naturalbridge.com>

    * lto-read.c (data_in): Added type_decls and current_col fields.
    (string_slot): New type to hold canonized file name.
    (hash_string_slot_node, eq_string_slot_node, canon_file_name,
    input_line_info, set_line_info, clear_line_info): New functions.
    (file_name_hash_table): New hash table.
    (input_local_var, input_labels, input_local_vars_index,
    input_local_var, input_local_vars, input_ssa_names): Reorganized
parameters.
    (input_uleb128): Changed type of byte var.
    (input_expr_operand): Large number of changes to get line numbers
    correct.  Added TYPE_DECL case.
    (input_globals): Added code to get TYPE_DECLs processed.
    (input_local_var): Added code to process line numbers and
    TREE_CHAIN and DECL_CONTEXT.
    (input_function, input_constructor): Added call to
    clear_line_number.
    (lto_static_init_local): Added code to get line numbers correct.
    (lto_read_body): Added code to get TYPE_DECLS read and to change
    parameters to the calls above that had their parms reorganized.

   
Index: lto-tree-flags.def
===================================================================
--- lto-tree-flags.def	(revision 129732)
+++ lto-tree-flags.def	(working copy)
@@ -747,6 +747,7 @@
       ADD_VIS_FLAG (tls_model)
       ADD_VIS_FLAG (in_text_section)
       ADD_VIS_FLAG (common_flag)
+      ADD_VIS_FLAG (seen_in_bind_expr)
     END_EXPR_CASE (VAR_DECL)
       
     START_EXPR_CASE (VEC_COND_EXPR)
Index: lto-function-out.c
===================================================================
--- lto-function-out.c	(revision 129732)
+++ lto-function-out.c	(working copy)
@@ -281,6 +281,12 @@ struct output_block
   unsigned int next_var_decl_index;
   VEC(tree,heap) *var_decls;
 
+  /* The hash table that contains the set of type_decls we have
+     seen so far and the indexes assigned to them.  */
+  htab_t type_decl_hash_table;
+  unsigned int next_type_decl_index;
+  VEC(tree,heap) *type_decls;
+
   /* The hash table that contains the set of strings we have seen so
      far and the indexes assigned to them.  */
   htab_t string_hash_table;
@@ -295,8 +301,11 @@ struct output_block
   /* These are the last file and line that were seen in the stream.
      If the current node differs from these, it needs to insert
      something into the stream and fix these up.  */
-  const char *last_file;
-  int last_line;
+  const char *current_file;
+  int current_line;
+#ifdef USE_MAPPED_LOCATION  
+  int current_col;
+#endif
 };
 
 
@@ -321,6 +330,19 @@ do { \
 #endif
 
 
+/* Clear the line info stored in DATA_IN.  */
+
+static void
+clear_line_info (struct output_block *ob)
+{
+  ob->current_file = NULL;
+  ob->current_line = 0;
+#ifdef USE_MAPPED_LOCATION  
+  ob->current_col = 0;
+#endif
+}
+
+
 /* Create the output block and return it.  IS_FUNTION is true if this
    is for a function and false for a constructor.  */
 
@@ -344,8 +366,7 @@ create_output_block (bool is_function)
   lto_debug_context.indent = 0;
 #endif
 
-  ob->last_file = NULL;
-  ob->last_line = -1;
+  clear_line_info (ob);
 
   if (is_function)
     {
@@ -361,6 +382,8 @@ create_output_block (bool is_function)
     = htab_create (37, hash_decl_slot_node, eq_decl_slot_node, free);
   ob->var_decl_hash_table
     = htab_create (37, hash_decl_slot_node, eq_decl_slot_node, free);
+  ob->type_decl_hash_table
+    = htab_create (37, hash_decl_slot_node, eq_decl_slot_node, free);
   ob->string_hash_table
     = htab_create (37, hash_string_slot_node, eq_string_slot_node, free);
   ob->type_hash_table
@@ -386,6 +409,7 @@ destroy_output_block (struct output_bloc
   htab_delete (ob->field_decl_hash_table);
   htab_delete (ob->fn_decl_hash_table);
   htab_delete (ob->var_decl_hash_table);
+  htab_delete (ob->type_decl_hash_table);
   htab_delete (ob->string_hash_table);
   htab_delete (ob->type_hash_table);
 
@@ -612,7 +636,7 @@ output_string (struct output_block *ob, 
     }
   else
     {
-      struct decl_slot *old_slot = (struct decl_slot *)*slot;
+      struct string_slot *old_slot = (struct string_slot *)*slot;
       output_uleb128_stream (index_stream, old_slot->slot_num);
 
       /* From the debugging protocol's point of view, the entry needs
@@ -726,16 +750,19 @@ output_decl_index (struct output_stream 
 
 /* Build a densely packed word that contains only the flags that are
    used for this type of tree EXPR and write the word in uleb128 to
-   the OB.  */
+   the OB.  FORCE_LOC forces the line number to be serialized
+   reguardless of the type of tree.  */
 
 
 static void
-output_tree_flags (struct output_block *ob, enum tree_code code, tree expr)
+output_tree_flags (struct output_block *ob, 
+		   enum tree_code code, 
+		   tree expr, 
+		   bool force_loc)
 {
   unsigned HOST_WIDE_INT flags = 0;
   const char *file_to_write = NULL;
   int line_to_write = -1;
-  const char *current_file;
 
   if (code == 0 || TEST_BIT (lto_flags_needed_for, code))
     {
@@ -792,30 +819,64 @@ output_tree_flags (struct output_block *
 #undef END_EXPR_CASE
 #undef END_EXPR_SWITCH
 
-      /* Add two more bits onto the flag if this is a tree node that can
-	 have a line number.  The first bit is true if this node changes
-	 files and the second is set if this node changes lines.  */
-      if (expr && EXPR_P (expr))
-        {
-	  flags <<= 2;
-	  if (EXPR_HAS_LOCATION (expr))
+      flags <<= LTO_SOURCE_LOC_BITS;
+      if (expr)
+	{
+	  const char *current_file = NULL;
+	  int current_line = 0;
+#ifdef USE_MAPPED_LOCATION
+	  int current_col = 0;
+#endif
+	  if (EXPR_P (expr))
 	    {
-	      LOC current_loc = EXPR_LOC (expr);
-	      const int current_line = LOC_LINE (current_loc);
-	      current_file = LOC_FILE (current_loc);
-	      if (ob->last_file != current_file)
-		{
-		  file_to_write = current_file;
-		  ob->last_file = current_file;
-		  flags |= 0x2;
-		}
-	      if (ob->last_line != current_line)
+	      if (EXPR_HAS_LOCATION (expr))
 		{
-		  line_to_write = current_line;
-		  ob->last_line = current_line;
-		  flags |= 0x1;
+		  current_file = EXPR_FILENAME (expr);
+		  current_line = EXPR_LINENO (expr);
+#ifdef USE_MAPPED_LOCATION
+		/* This will blow up because i cannot find the function
+		   that i would have expected to have the name
+		   expr_col.  */ 
+		  current_col = ????
+#endif
 		}
 	    }
+	  else if (force_loc && DECL_P (expr))
+	    {
+	      expanded_location xloc 
+		= expand_location (DECL_SOURCE_LOCATION (expr));
+
+	      current_file = xloc.file;
+	      current_line = xloc.line;
+#ifdef USE_MAPPED_LOCATION
+	      current_col = xloc.column;
+#endif
+	    }
+
+	  if (current_file
+	      && (ob->current_file == NULL
+		  || strcmp (ob->current_file, current_file) != 0))
+	    {
+	      file_to_write = current_file;
+	      ob->current_file = current_file;
+	      flags |= LTO_SOURCE_FILE;
+	    }
+	  if (current_line != 0
+	      && ob->current_line != current_line)
+	    {
+	      line_to_write = current_line;
+	      ob->current_line = current_line;
+	      flags |= LTO_SOURCE_LINE;
+	    }
+#ifdef USE_MAPPED_LOCATION
+	  if (current_loc != 0
+	      && ob->current_col != current_col)
+	    {
+	      col_to_write = current_col;
+	      ob->current_clo = current_col;
+	      flags |= LTO_SOURCE_COL;
+	    }
+#endif
 	}
 
       LTO_DEBUG_TOKEN ("flags");
@@ -826,13 +887,20 @@ output_tree_flags (struct output_block *
 	{
 	  LTO_DEBUG_TOKEN ("file");
 	  output_string (ob, ob->main_stream, 
-			 file_to_write, strlen (file_to_write));
+			 file_to_write, strlen (file_to_write) + 1);
 	}
       if (line_to_write != -1)
 	{
 	  LTO_DEBUG_TOKEN ("line");
 	  output_uleb128 (ob, line_to_write);
 	}
+#ifdef USE_MAPPED_LOCATION
+      if (col_to_write != -1)
+	{
+	  LTO_DEBUG_TOKEN ("col");
+	  output_uleb128 (ob, col_to_write);
+	}
+#endif
     }
 }
 
@@ -924,7 +992,7 @@ output_record_start (struct output_block
       enum tree_code code = TREE_CODE (expr);
       if (value && TEST_BIT (lto_types_needed_for, code))
 	output_type_ref (ob, TREE_TYPE (value));
-      output_tree_flags (ob, code, expr);
+      output_tree_flags (ob, code, expr, false);
     }
 }
 
@@ -1308,6 +1376,18 @@ output_expr_operand (struct output_block
 	}
       break;
 
+    case TYPE_DECL:
+      {
+	bool new;
+	output_record_start (ob, NULL, NULL, tag);
+	
+	new = output_decl_index (ob->main_stream, ob->type_decl_hash_table,
+				 &ob->next_type_decl_index, expr);
+	if (new)
+	  VEC_safe_push (tree, heap, ob->type_decls, expr);
+      }
+      break;
+
     case PARM_DECL:
       gcc_assert (!DECL_RTL_SET_P (expr));
       output_record_start (ob, NULL, NULL, tag);
@@ -1589,16 +1669,23 @@ output_local_vars (struct output_block *
       output_type_ref (ob, TREE_TYPE (decl));
 
       if (!is_var)
-	{
-	  output_type_ref (ob, DECL_ARG_TYPE (decl));
-	  LTO_DEBUG_TOKEN ("chain");
-	  if (TREE_CHAIN (decl))
-	    output_expr_operand (ob, TREE_CHAIN (decl));
-	  else
-	    output_uleb128 (ob, 0);
-	}
+	output_type_ref (ob, DECL_ARG_TYPE (decl));
+
+      clear_line_info (ob);
+      output_tree_flags (ob, 0, decl, true);
+
+      LTO_DEBUG_TOKEN ("chain");
+      if (TREE_CHAIN (decl))
+	output_expr_operand (ob, TREE_CHAIN (decl));
+      else
+	output_uleb128 (ob, 0);
+
+      LTO_DEBUG_TOKEN ("context");
+      if (DECL_CONTEXT (decl))
+	output_expr_operand (ob, DECL_CONTEXT (decl));
+      else 
+	output_uleb128 (ob, 0);
 
-      output_tree_flags (ob, 0, decl);
       LTO_DEBUG_TOKEN ("align");
       output_uleb128 (ob, DECL_ALIGN (decl));
 
@@ -1653,6 +1740,7 @@ static void
 output_named_labels (struct output_block *ob)
 {
   unsigned int index = 0;
+  clear_line_info (ob);
 
   while (index < VEC_length (tree, ob->named_labels))
     {
@@ -1690,7 +1778,7 @@ output_ssa_names (struct output_block *o
       output_uleb128 (ob, i);
       output_expr_operand (ob, SSA_NAME_VAR (ptr));
       /* Lie about the type of object to get the flags out.  */
-      output_tree_flags (ob, 0, ptr);
+      output_tree_flags (ob, 0, ptr, false);
     }
 
   output_uleb128 (ob, 0);
@@ -1748,7 +1836,7 @@ output_phi (struct output_block *ob, tre
   
   output_record_start (ob, expr, expr, LTO_phi_node);
   output_uleb128 (ob, SSA_NAME_VERSION (PHI_RESULT (expr)));
-  
+
   for (i = 0; i < len; i++)
     {
       output_expr_operand (ob, PHI_ARG_DEF (expr, i));
@@ -1851,6 +1939,7 @@ produce_asm (struct output_block *ob, tr
   header.num_field_decls = VEC_length (tree, ob->field_decls);
   header.num_fn_decls = VEC_length (tree, ob->fn_decls);
   header.num_var_decls = VEC_length (tree, ob->var_decls);
+  header.num_type_decls = VEC_length (tree, ob->type_decls);
   header.num_types = VEC_length (tree, ob->types);
   if (is_function)
     {
@@ -1919,6 +2008,15 @@ produce_asm (struct output_block *ob, tr
 			    out_ref.base_label, " ");
     }
 
+  /* Write the global type_decl references.  */
+  for (index = 0; VEC_iterate(tree, ob->type_decls, index, decl); index++)
+    {
+      lto_typedecl_ref (decl, &out_ref);
+      dw2_asm_output_data (8, out_ref.section, " ");
+      dw2_asm_output_delta (8, out_ref.label,
+			    out_ref.base_label, " ");
+    }
+
   /* Write the global type references.  */
   for (index = 0; VEC_iterate(tree, ob->types, index, type); index++)
     {
@@ -2074,6 +2172,7 @@ output_function (tree function)
   struct output_block *ob = create_output_block (true);
 
   LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data);
+  clear_line_info (ob);
 
   gcc_assert (!current_function_decl && !cfun);
 
@@ -2109,9 +2208,6 @@ output_function (tree function)
   output_zero (ob);
   LTO_DEBUG_UNDENT();
 
-  LTO_SET_DEBUGGING_STREAM (debug_label_stream, label_data);
-  output_named_labels (ob);
-
   LTO_SET_DEBUGGING_STREAM (debug_ssa_names_stream, ssa_names_data);
   output_ssa_names (ob, fn);
 
@@ -2124,6 +2220,9 @@ output_function (tree function)
   LTO_SET_DEBUGGING_STREAM (debug_decl_index_stream, decl_index_data);
   output_local_vars_index (ob);
 
+  LTO_SET_DEBUGGING_STREAM (debug_label_stream, label_data);
+  output_named_labels (ob);
+
   /* Create a file to hold the pickled output of this function.  This
      is a temp standin until we start writing sections.  */
   produce_asm (ob, function, true);
@@ -2143,6 +2242,7 @@ output_constructor_or_init (tree var)
   struct output_block *ob = create_output_block (false);
 
   LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data);
+  clear_line_info (ob);
 
   /* Make string 0 be a NULL string.  */
   output_1_stream (ob->string_stream, 0);
Index: lto-tree-tags.def
===================================================================
--- lto-tree-tags.def	(revision 129732)
+++ lto-tree-tags.def	(working copy)
@@ -85,6 +85,7 @@
   MAP_EXPR_TAG(SSA_NAME, LTO_ssa_name)
   MAP_EXPR_TAG(STRING_CST, LTO_string_cst)
   MAP_EXPR_TAG(SWITCH_EXPR, LTO_switch_expr)
+  MAP_EXPR_TAG(TYPE_DECL, LTO_type_decl)
 #endif /* TREE_SINGLE_MECHANICAL_FALSE */
 
 #ifdef TREE_SINGLE_MECHANICAL_TRUE
@@ -275,6 +276,7 @@
   SET_NAME (LTO_truth_not_expr, "truth_not_expr")
   SET_NAME (LTO_truth_or_expr, "truth_or_expr")
   SET_NAME (LTO_truth_xor_expr, "truth_xor_expr")
+  SET_NAME (LTO_type_decl, "type_decl")
   SET_NAME (LTO_uneq_expr, "uneq_expr")
   SET_NAME (LTO_unge_expr, "unge_expr")
   SET_NAME (LTO_ungt_expr, "ungt_expr")
Index: lto-tags.h
===================================================================
--- lto-tags.h	(revision 129732)
+++ lto-tags.h	(working copy)
@@ -44,14 +44,15 @@
    2)    FIELD_DECLS.
    3)    FUNCTION_DECLS.
    4)    global VAR_DECLS.
-   5)    types.
-   6)    Names for the labels that have names
-   7)    The ssa names.
-   8)    The control flow graph.
-   9-10) Gimple for local decls.
-   11)   Gimple for the function.
-   12)   Strings.
-   13)   Redundant information to aid in debugging the stream.
+   5)    type_decls
+   6)    types.
+   7)    Names for the labels that have names
+   8)    The ssa names.
+   9)    The control flow graph.
+   10-11)Gimple for local decls.
+   12)   Gimple for the function.
+   13)   Strings.
+   14)   Redundant information to aid in debugging the stream.
          This is only present if the compiler is built with
          LTO_STREAM_DEBUGGING defined.
 
@@ -70,6 +71,7 @@ struct lto_header
   int32_t num_field_decls;        /* Number of FIELD_DECLS.  */
   int32_t num_fn_decls;           /* Number of FUNCTION_DECLS.  */
   int32_t num_var_decls;          /* Number of non local VAR_DECLS.  */
+  int32_t num_type_decls;         /* Number of TYPE_DECLs.  */
   int32_t num_types;              /* Number of types.  */
   int32_t num_local_decls;        /* Number of local VAR_DECLS and PARM_DECLS.  */
   int32_t num_named_labels;       /* Number of labels with names.  */
@@ -78,8 +80,8 @@ struct lto_header
   int32_t named_label_size;       /* Size of names for named labels.  */
   int32_t ssa_names_size;         /* Size of the SSA_NAMES table.  */
   int32_t cfg_size;               /* Size of the cfg.  */
-  int32_t local_decls_index_size; /* Size of local par and var decl index region. */
-  int32_t local_decls_size;       /* Size of local par and var decl region. */
+  int32_t local_decls_index_size; /* Size of local parm and var decl index region. */
+  int32_t local_decls_size;       /* Size of local parm and var decl region. */
   int32_t main_size;              /* Size of main gimple body of function.  */
   int32_t string_size;            /* Size of the string table.  */
   int32_t debug_decl_index_size;  /* Size of local decl index debugging information.  */
@@ -90,7 +92,7 @@ struct lto_header
   int32_t debug_main_size;        /* Size of main stream debugging information.  */
 };
 
-/* 2-5) THE GLOBAL DECLS AND TYPES.
+/* 2-6) THE GLOBAL DECLS AND TYPES.
 
       The global decls and types are encoded in the same way.  For each
       entry, there is a pair of words.  The first is the debugging
@@ -101,7 +103,7 @@ struct lto_header
       a label for the debugging section.  This will cause more work for
       the linker but will make ln -r work properly.
 
-   6) THE LABEL NAMES.  
+   7) THE LABEL NAMES.  
 
       Since most labels do not have names, this section my be of zero
       length.  It consists of an array of string table references, one
@@ -110,18 +112,18 @@ struct lto_header
       the negative ones do not.  The positive index can be used to
       find the name in this array.
 
-   7) THE ACTIVE SSA NAMES.  
+   8) THE ACTIVE SSA NAMES.  
 
       The SSA_NAME_VERSION in an SSA_NAME in used as an index into
       this table.
 
-   8) THE CFG. 
+   9) THE CFG. 
 
-   9) Index into the local decls.  Since local decls can have local
+   10) Index into the local decls.  Since local decls can have local
       decls inside them, they must be read in randomly in order to
       properly restore them.  
 
-   10-11) GIMPLE FOR THE LOCAL DECLS AND THE FUNCTION BODY.
+   11-12) GIMPLE FOR THE LOCAL DECLS AND THE FUNCTION BODY.
 
      The gimple consists of a set of records.
 
@@ -403,6 +405,7 @@ enum LTO_tags {
   LTO_truth_not_expr,
   LTO_truth_or_expr,
   LTO_truth_xor_expr,
+  LTO_type_decl,
   LTO_uneq_expr,
   LTO_unge_expr,
   LTO_ungt_expr,
@@ -525,6 +528,21 @@ struct lto_debug_context
   void * main_data;
 };
 
+
+/* Serialize out a file, line (and if USE_MAPPED_LOCATION was set) a
+   column.  */
+#define LTO_SOURCE_FILE 0x1
+#define LTO_SOURCE_LINE 0x2
+
+#ifdef USE_MAPPED_LOCATION
+#define LTO_SOURCE_LOC_BITS 3
+#define LTO_SOURCE_COL 0x4
+#else
+#define LTO_SOURCE_LOC_BITS 2
+#endif
+
+
+
 extern const char * LTO_tag_names[LTO_last_tag];
 
 extern void lto_debug_indent (struct lto_debug_context *, int);
Index: tree-dfa.c
===================================================================
--- tree-dfa.c	(revision 129732)
+++ tree-dfa.c	(working copy)
@@ -96,7 +96,18 @@ find_referenced_vars (void)
 	}
 
       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-	walk_tree (&phi, find_vars_r, NULL, NULL);
+	{
+	  int len = PHI_NUM_ARGS (phi);
+	  int i;
+
+	  walk_tree (&phi, find_vars_r, NULL, NULL);
+
+	  for (i = 0; i < len; i++)
+	    {
+	      tree arg = PHI_ARG_DEF (phi, i);
+	      walk_tree (&arg, find_vars_r, NULL, NULL);
+	    }
+	}
     }
 
   return 0;
Index: lto/lto-read.c
===================================================================
--- lto/lto-read.c	(revision 129732)
+++ lto/lto-read.c	(working copy)
@@ -52,6 +52,7 @@ Boston, MA 02110-1301, USA.  */
 #include "lto-tags.h"
 #include "lto.h"
 #include <ctype.h>
+#include "cpplib.h"
 
 static enum tree_code tag_to_expr[LTO_last_tag];
 
@@ -63,6 +64,7 @@ struct data_in
   tree *field_decls;        /* The field decls.  */
   tree *fn_decls;           /* The function decls.  */
   tree *var_decls;          /* The global or static var_decls.  */
+  tree *type_decls;         /* The type_decls.  */
   tree *types;              /* All of the types.  */
   int *local_decls_index;   /* The offsets to decode the local_decls.  */
 #ifdef LTO_STREAM_DEBUGGING
@@ -75,9 +77,52 @@ struct data_in
   /* Number of named labels.  Used to find the index of unnamed labels
      since they share space with the named labels.  */
   unsigned int num_named_labels;  
+  const char *current_file;
+  int current_line;
+#ifdef USE_MAPPED_LOCATION  
+  int current_col;
+#endif
+};
+
+
+
+/* This hash table is used to hash the file names in the
+   source_location field.  Unlike other structures here, this is a
+   persistent structure whose data lives for the entire
+   compilation.  */
+
+struct string_slot {
+  const char *s;
+  unsigned int slot_num;
 };
 
 
+/* Returns a hash code for P.  */
+
+static hashval_t
+hash_string_slot_node (const void *p)
+{
+  const struct string_slot *ds = (const struct string_slot *) p;
+  return (hashval_t) htab_hash_string (ds->s);
+}
+
+
+/* Returns nonzero if P1 and P2 are equal.  */
+
+static int
+eq_string_slot_node (const void *p1, const void *p2)
+{
+  const struct string_slot *ds1 =
+    (const struct string_slot *) p1;
+  const struct string_slot *ds2 =
+    (const struct string_slot *) p2;
+
+  return strcmp (ds1->s, ds2->s) == 0;
+}
+
+/* The table to hold the file_names.  */
+static htab_t file_name_hash_table;
+
 struct input_block 
 {
   const char *data;
@@ -96,7 +141,7 @@ static tree
 input_expr_operand (struct input_block *, struct data_in *, struct function *, 
                     enum LTO_tags);
 static tree
-input_local_var (struct data_in *, struct input_block *, struct function *, unsigned int i);
+input_local_var (struct input_block *, struct data_in *, struct function *, unsigned int i);
 
 
 /* Return the next character of input from IB.  Abort if you
@@ -117,7 +162,7 @@ input_uleb128 (struct input_block *ib)
 {
   unsigned HOST_WIDE_INT result = 0;
   int shift = 0;
-  unsigned int byte;
+  unsigned HOST_WIDE_INT byte;
 
   while (true)
     {
@@ -423,6 +468,129 @@ process_tree_flags (tree expr, unsigned 
 }
 
 
+/* Return the one true copy of STRING.  */
+
+static const char *
+canon_file_name (const char *string)
+{
+  void **slot;
+  struct string_slot s_slot;
+  s_slot.s = string;
+
+  slot = htab_find_slot (file_name_hash_table, &s_slot, INSERT);
+  if (*slot == NULL)
+    {
+      size_t len = strlen (string);
+      char * saved_string = xmalloc (len + 1);
+      strcpy (saved_string, string);
+
+      struct string_slot *new_slot
+	= xmalloc (sizeof (struct string_slot));
+
+      new_slot->s = saved_string;
+      *slot = new_slot;
+      return saved_string;
+    }
+  else
+    {
+      struct string_slot *old_slot = (struct string_slot *)*slot;
+      return old_slot->s;
+    }
+}
+
+
+/* Based on the FLAGS, read in a file, a line and a col into the
+   fields in DATA_IN.  */
+
+static void 
+input_line_info (struct input_block *ib, struct data_in *data_in, 
+		 unsigned HOST_WIDE_INT flags)
+{
+#ifdef USE_MAPPED_LOCATION  
+  if (flags & LTO_SOURCE_FILE)
+    {
+      unsigned int len;
+      if (data_in->current_file)
+	linemap_add (line_table, LC_LEAVE, false, data_in->current_file, 0);
+
+      LTO_DEBUG_TOKEN ("file");
+      data_in->current_file 
+	= canon_file_name (input_string_internal (data_in, input_uleb128 (ib), &len));
+    }
+  if (flags & LTO_SOURCE_LINE)
+    {
+      LTO_DEBUG_TOKEN ("line");
+      data_in->current_line = input_uleb128 (ib);
+
+      if (!(flags & LTO_SOURCE_FILE))
+	linemap_line_start (line_table, data_in->current_line, 80);
+    }
+  if (flags & LTO_SOURCE_FILE)
+    linemap_add (line_table, LC_ENTER, false, data_in->current_file, data_in->current_line);
+    
+  if (flags & LTO_SOURCE_COL)
+    {
+      LTO_DEBUG_TOKEN ("col");
+      data_in->current_col = input_uleb128 (ib);
+    }
+#else
+  if (flags & LTO_SOURCE_FILE)
+    {
+      unsigned int len;
+      LTO_DEBUG_TOKEN ("file");
+      data_in->current_file 
+	= input_string_internal (data_in, input_uleb128 (ib), &len);
+    }
+  if (flags & LTO_SOURCE_LINE)
+    {
+      LTO_DEBUG_TOKEN ("line");
+      data_in->current_line = input_uleb128 (ib);
+    }
+#endif
+}
+
+
+/* Set the line info stored in DATA_IN for NODE.  */
+
+static void
+set_line_info (struct data_in *data_in, tree node)
+{
+  if (data_in->current_file)
+    {
+#ifdef USE_MAPPED_LOCATION
+  
+
+
+#else
+      if (EXPR_P (node))
+	  annotate_with_file_line (node, 
+				   canon_file_name (data_in->current_file), 
+				   data_in->current_line);
+      else if (DECL_P (node))
+	{
+	  DECL_SOURCE_LOCATION (node).file = canon_file_name (data_in->current_file);
+	  DECL_SOURCE_LOCATION (node).line = data_in->current_line;
+	}
+#endif
+    }
+}
+
+
+/* Clear the line info stored in DATA_IN.  */
+
+static void
+clear_line_info (struct data_in *data_in)
+{
+#ifdef USE_MAPPED_LOCATION  
+  if (data_in->current_file)
+    linemap_add (line_table, LC_LEAVE, false, data_in->current_file, 0);
+  data_in->current_col = 0;
+#endif
+  data_in->current_file = NULL;
+  data_in->current_line = 0;
+}
+
+
 /* Read a node in the gimple tree from IB.  The TAG has already been
    read.  */
 
@@ -433,8 +601,6 @@ input_expr_operand (struct input_block *
   enum tree_code code = tag_to_expr[tag];
   tree type = NULL_TREE;
   unsigned HOST_WIDE_INT flags;
-  const char *new_file = NULL;
-  int new_line = -1;
   gcc_assert (code);
   tree result = NULL_TREE;
   
@@ -445,19 +611,7 @@ input_expr_operand (struct input_block *
 
   /* FIXME! need to figure out how to set the file and line number.  */
   if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
-    {
-      if (flags & 0x2)
-	{
-	  unsigned int len;
-	  LTO_DEBUG_TOKEN ("file");
-	  new_file = input_string_internal (data_in, input_uleb128 (ib), &len);
-	}
-      if (flags & 0x1)
-	{
-	  LTO_DEBUG_TOKEN ("line");
-	  new_line = input_uleb128 (ib);
-	}
-    }
+    input_line_info (ib, data_in, flags);
 
   switch (code)
     {
@@ -601,6 +755,11 @@ input_expr_operand (struct input_block *
       gcc_assert (result);
       break;
 
+    case TYPE_DECL:
+      result = data_in->type_decls [input_uleb128 (ib)];
+      gcc_assert (result);
+      break;
+
     case VAR_DECL:
     case PARM_DECL:
       if (tag == LTO_var_decl1)
@@ -632,7 +791,7 @@ input_expr_operand (struct input_block *
 	      lib.len = ib->len;
 	      lib.p = data_in->local_decls_index[lv_index];
 
-	      result = input_local_var (data_in, &lib, fn, lv_index); 
+	      result = input_local_var (&lib, data_in, fn, lv_index); 
 	      data_in->local_decls [lv_index] = result;
 
 #ifdef LTO_STREAM_DEBUGGING
@@ -918,6 +1077,9 @@ input_expr_operand (struct input_block *
   if (flags)
     process_tree_flags (result, flags);
 
+  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
+    set_line_info (data_in, result);
+
   /* It is not enought to just put the flags back as we serialized
      them.  There are side effects to the buildN functions which play
      with the flags to the point that we just have to call this here
@@ -939,12 +1101,14 @@ input_globals (struct lto_header * heade
 	      lto_ref in_field_decls[],
 	      lto_ref in_fn_decls[],
 	      lto_ref in_var_decls[],
+	      lto_ref in_type_decls[],
 	      lto_ref in_types[])
 {
   int i;
   data_in->field_decls = xcalloc (header->num_field_decls, sizeof (tree*));
   data_in->fn_decls    = xcalloc (header->num_fn_decls, sizeof (tree*));
   data_in->var_decls   = xcalloc (header->num_var_decls, sizeof (tree*));
+  data_in->type_decls  = xcalloc (header->num_type_decls, sizeof (tree*));
   data_in->types       = xcalloc (header->num_types, sizeof (tree*));
 
   for (i=0; i<header->num_field_decls; i++)
@@ -959,6 +1123,10 @@ input_globals (struct lto_header * heade
     data_in->var_decls[i] 
       = lto_resolve_var_ref (fd, context, &in_var_decls[i]);
 
+  for (i=0; i<header->num_type_decls; i++)
+    data_in->type_decls[i] 
+      = lto_resolve_typedecl_ref (fd, context, &in_type_decls[i]);
+
   for (i=0; i<header->num_types; i++)
     data_in->types[i] = lto_resolve_type_ref (fd, context, &in_types[i]);
 }
@@ -968,11 +1136,12 @@ input_globals (struct lto_header * heade
    labels from DATA segment SIZE bytes long using DATA_IN.  */
 
 static void 
-input_labels (struct data_in *data_in, struct input_block *ib, 
+input_labels (struct input_block *ib, struct data_in *data_in, 
 	      unsigned int named_count, unsigned int unnamed_count)
 {
   unsigned int i;
 
+  clear_line_info (data_in);
   /* The named and unnamed labels share the same array.  In the lto
      code, the unnamed labels have a negative index.  Their position
      in the array can be found by subtracting that index from the
@@ -997,7 +1166,7 @@ input_labels (struct data_in *data_in, s
 
 
 static void
-input_local_vars_index (struct data_in *data_in, struct input_block *ib, 
+input_local_vars_index (struct input_block *ib, struct data_in *data_in, 
 			unsigned int count)
 {
   unsigned int i;
@@ -1019,7 +1188,7 @@ input_local_vars_index (struct data_in *
 /* Input local var I from IB.  */
 
 static tree
-input_local_var (struct data_in *data_in, struct input_block *ib, 
+input_local_var (struct input_block *ib, struct data_in *data_in, 
 		 struct function *fn, unsigned int i)
 {
   enum LTO_tags tag;
@@ -1029,9 +1198,12 @@ input_local_var (struct data_in *data_in
   tree name;
   tree type;
   unsigned HOST_WIDE_INT flags;
-  const char *new_file = NULL;
-  int new_line = -1;
   tree result;
+  tree context;
+
+  /* The line number info needs to be reset for each local var since
+     they are read in random order.  */
+  clear_line_info (data_in);
 
   tag = input_record_start (ib);
   variant = tag & 0xF;
@@ -1058,37 +1230,31 @@ input_local_var (struct data_in *data_in
   data_in->local_decls[i] = result;
   
   if (!is_var)
-    {
-      DECL_ARG_TYPE (result) = get_type_ref (data_in, ib);
-      LTO_DEBUG_TOKEN ("chain");
-      tag = input_record_start (ib);
-      if (tag)
-	TREE_CHAIN (result) = input_expr_operand (ib, data_in, fn, tag);
-      else 
-	TREE_CHAIN (result) = NULL_TREE;
-    }
-  
+    DECL_ARG_TYPE (result) = get_type_ref (data_in, ib);
+
   flags = input_tree_flags (ib, LTO_flags_needed);
-  
-  /* FIXME: Need to figure out how to set the line number.  */
-  if (flags & 0x2)
-    {
-      unsigned int len;
-      LTO_DEBUG_TOKEN ("file");
-      new_file = input_string_internal (data_in, input_uleb128 (ib), &len);
-    }
-  if (flags & 0x1)
-    {
-      LTO_DEBUG_TOKEN ("line");
-      new_line = input_uleb128 (ib);
-    }
+  input_line_info (ib, data_in, flags);
+  set_line_info (data_in, result);
+
+  LTO_DEBUG_TOKEN ("chain");
+  tag = input_record_start (ib);
+  if (tag)
+    TREE_CHAIN (result) = input_expr_operand (ib, data_in, fn, tag);
+  else 
+    TREE_CHAIN (result) = NULL_TREE;
+
+  LTO_DEBUG_TOKEN ("context");
+  context = input_expr_operand (ib, data_in, fn, input_record_start (ib));
+  if (TYPE_P (context))
+    DECL_CONTEXT (result) = TYPE_NAME (context);
+  else
+    DECL_CONTEXT (result) = context;
   
   LTO_DEBUG_TOKEN ("align");
   DECL_ALIGN (result) = input_uleb128 (ib);
   LTO_DEBUG_TOKEN ("size");
-  DECL_SIZE (result) 
-    = input_expr_operand (ib, data_in, fn, input_record_start (ib));
-  
+  DECL_SIZE (result) = input_expr_operand (ib, data_in, fn, input_record_start (ib));
+
   if (variant & 0x1)
     {
       LTO_DEBUG_TOKEN ("attributes");
@@ -1121,7 +1287,7 @@ input_local_var (struct data_in *data_in
    bytes long using DATA_IN.  */
 
 static void 
-input_local_vars (struct data_in *data_in, struct input_block *ib, 
+input_local_vars (struct input_block *ib, struct data_in *data_in, 
 		  struct function *fn, unsigned int count)
 {
   unsigned int i;
@@ -1137,7 +1303,7 @@ input_local_vars (struct data_in *data_i
 	  = data_in->local_decls_index_d[i]; 
 #endif
 	ib->p = data_in->local_decls_index[i];
-	input_local_var (data_in, ib, fn, i);
+	input_local_var (ib, data_in, fn, i);
       }
 }
 
@@ -1307,7 +1473,7 @@ input_phi (struct input_block *ib, basic
 /* Read in the ssa_names array from IB.  */
 
 static void
-input_ssa_names (struct data_in *data_in, struct input_block *ib, struct function *fn)
+input_ssa_names (struct input_block *ib, struct data_in *data_in, struct function *fn)
 {
   unsigned int i;
   int size = input_uleb128 (ib);
@@ -1394,6 +1560,7 @@ input_function (tree fn_decl, struct dat
 
   DECL_INITIAL (fn_decl) = DECL_SAVED_TREE (fn_decl) = make_node (BLOCK);
   BLOCK_ABSTRACT_ORIGIN (DECL_SAVED_TREE (fn_decl)) = fn_decl;
+  clear_line_info (data_in);
 
   tree_register_cfg_hooks ();
   gcc_assert (tag == LTO_function);
@@ -1424,6 +1591,7 @@ input_constructor (tree var, struct data
 {
   enum LTO_tags tag;
 
+  clear_line_info (data_in);
   LTO_DEBUG_INDENT_TOKEN ("init");
   tag = input_record_start (ib);
   DECL_INITIAL (var) = input_expr_operand (ib, data_in, NULL, tag);
@@ -1432,7 +1600,8 @@ input_constructor (tree var, struct data
 
 static bool initialized_local = false;
 
-/* Static initialization for the lto writer.  */
+
+/* Static initialization for the lto reader.  */
 
 static void
 lto_static_init_local (void)
@@ -1470,11 +1639,8 @@ lto_static_init_local (void)
     int code;				      \
     for (code=0; code<NUM_TREE_CODES; code++) \
       {                                       \
-	/* The 2 leaves room for file and line number for exprs.  */ \
-	if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))  \
-          num_flags_for_code[code] = 2;	      \
-	else                                  \
-          num_flags_for_code[code] = 0;	      \
+	/* The LTO_SOURCE_LOC_BITS leaves room for file and line number for exprs.  */ \
+        num_flags_for_code[code] = LTO_SOURCE_LOC_BITS; \
                                               \
         switch (TREE_CODE_CLASS (code))       \
           {
@@ -1526,6 +1692,9 @@ lto_static_init_local (void)
 
   lto_static_init ();
   tree_register_cfg_hooks ();
+
+  file_name_hash_table
+    = htab_create (37, hash_string_slot_node, eq_string_slot_node, free);
 }
 
 
@@ -1549,8 +1718,10 @@ lto_read_body (lto_info_fd *fd,
     = fields_offset + (header->num_field_decls * sizeof (lto_ref));
   int32_t vars_offset 
     = fns_offset + (header->num_fn_decls * sizeof (lto_ref));
+  int32_t type_decls_offset 
+    = vars_offset + (header->num_type_decls * sizeof (lto_ref));
   int32_t types_offset 
-    = vars_offset + (header->num_var_decls * sizeof (lto_ref));
+    = type_decls_offset + (header->num_var_decls * sizeof (lto_ref));
   int32_t named_label_offset 
     = types_offset + (header->num_types * sizeof (lto_ref));
   int32_t ssa_names_offset 
@@ -1590,6 +1761,7 @@ lto_read_body (lto_info_fd *fd,
   lto_ref *in_field_decls = (lto_ref*)(data + fields_offset);
   lto_ref *in_fn_decls    = (lto_ref*)(data + fns_offset);
   lto_ref *in_var_decls   = (lto_ref*)(data + vars_offset);
+  lto_ref *in_type_decls  = (lto_ref*)(data + type_decls_offset);
   lto_ref *in_types       = (lto_ref*)(data + types_offset);
 
   struct input_block ib_named_labels 
@@ -1616,8 +1788,8 @@ lto_read_body (lto_info_fd *fd,
   gcc_assert (header->minor_version == LTO_minor_version);
 
   input_globals (header, fd, context, &data_in, 
-		in_field_decls, in_fn_decls, 
-		in_var_decls, in_types);
+		 in_field_decls, in_fn_decls, 
+		 in_var_decls, in_type_decls, in_types);
 
   if (in_function)
     {
@@ -1628,23 +1800,23 @@ lto_read_body (lto_info_fd *fd,
 #ifdef LTO_STREAM_DEBUGGING
       lto_debug_context.current_data = &debug_label;
 #endif
-      input_labels (&data_in, &ib_named_labels, 
+      input_labels (&ib_named_labels, &data_in, 
 		    header->num_named_labels, header->num_unnamed_labels);
       
 #ifdef LTO_STREAM_DEBUGGING
       lto_debug_context.current_data = &debug_decl_index;
 #endif
-      input_local_vars_index (&data_in, &ib_local_decls_index, header->num_local_decls);
+      input_local_vars_index (&ib_local_decls_index, &data_in, header->num_local_decls);
       
 #ifdef LTO_STREAM_DEBUGGING
       lto_debug_context.current_data = &debug_decl;
 #endif
-      input_local_vars (&data_in, &ib_local_decls, fn, header->num_local_decls);
+      input_local_vars (&ib_local_decls, &data_in, fn, header->num_local_decls);
       
 #ifdef LTO_STREAM_DEBUGGING
       lto_debug_context.current_data = &debug_ssa_names;
 #endif
-      input_ssa_names (&data_in, &ib_ssa_names, fn);
+      input_ssa_names (&ib_ssa_names, &data_in, fn);
       
 #ifdef LTO_STREAM_DEBUGGING
       lto_debug_context.current_data = &debug_cfg;
@@ -1668,6 +1840,7 @@ lto_read_body (lto_info_fd *fd,
   free (data_in.field_decls);
   free (data_in.fn_decls);
   free (data_in.var_decls);
+  free (data_in.type_decls);
   free (data_in.types);
   if (in_function)
     {

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