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] Stream BLOCK nodes


This patch adds support for streaming BLOCK nodes.  This is the
first step towards supporting debug info in gimple files.

This is still work in progress.  In particular, I had to disable
the streaming of BLOCK_VARS because it's causing failures in 3
libstdc++ tests.  I am working on a fix, but the patch was
already growing too large.  I added a FIXME note that I will be
removing shortly.

Tested on x86_64.



	* lto-function-out.c (output_expr_operand): Move forward
	declaration earlier in the file.
	(output_tree_flags): Handle BLOCK nodes.
	(output_block_or_decl): New.
	(output_tree_block): New.
	(output_tree_with_context): Call it to handle BLOCK nodes.
	Handle BLOCK nodes when detecting nodes that have been
	written out already.
	(output_expr_operand): Handle every unhandled code with
	the default label.
	(output_local_var_decl): If DECL does not have a name,
	set DECL_NAME to D.<uid>.
	Write DECL_VALUE_EXPR, if it has one.
	(output_gimple_stmt): Write gimple_block (STMT).
	(lto_static_init): Remove BLOCK from set
	lto_types_needed_for.
	(output_function): Create a hash table for OB->MAIN_HASH_TABLE.
	Write DECL_INITIAL (FUNCTION).
	* lto-function-in.c (input_expr_operand): Forward declare.
	(input_local_var_decl): Read DECL_VALUE_EXPR, if needed.
	(input_gimple_stmt): Read gimple_block for STMT.
	(input_function): Read DECL_INITIAL for FN_DECL.
	(input_block_or_decl): New.
	(input_tree_block): New.
	(input_tree_operand): Call it.
	* lto-tags.h (enum LTO_tags): Add LTO_block.
	* lto-tree-tags.def: Call MAP_EXPR_TAG for LTO_block.
	Call SET_NAME for LTO_block.
	* lto-tree-flags.def: Remove asm_written_flag from BLOCK,
	QUAL_UNION_TYPE, RECORD_TYPE and UNION_TYPE.

Index: lto-function-out.c
===================================================================
--- lto-function-out.c	(revision 147598)
+++ lto-function-out.c	(working copy)
@@ -62,6 +62,7 @@ const char *LTO_tree_tag_names[LTO_tree_
 /* Forward declarations to break cyclical dependencies.  */
 static void output_record_start (struct output_block *, tree, tree,
 				 unsigned int);
+static void output_expr_operand (struct output_block *, tree);
 
 /* The index of the last eh_region seen for an instruction.  The
    eh_region for an instruction is only emitted if it different from
@@ -143,9 +144,6 @@ string_slot_free (void *p)
 }
 
 
-/* The output stream that contains the abbrev table for all of the
-   functions in this compilation unit.  */
-static void output_expr_operand (struct output_block *, tree);
 
 /* Clear the line info stored in DATA_IN.  */
 
@@ -580,6 +578,8 @@ output_tree_flags (struct output_block *
 		 inside a function.  */
 	      xloc = expand_location (DECL_SOURCE_LOCATION (expr));
 	    }
+	  else if (TREE_CODE (expr) == BLOCK)
+	    xloc = expand_location (BLOCK_SOURCE_LOCATION (expr));
 
 	  if (xloc.file)
 	    {
@@ -963,6 +963,88 @@ output_constructor (struct output_block 
     }
 }
 
+
+/* Helper for output_tree_block.  T is either a FUNCTION_DECL or a
+   BLOCK.  If T is a FUNCTION_DECL, write a reference to it (to avoid
+   duplicate definitions on the reader side).  Otherwise, write it as
+   a regular tree node.  OB is as in output_tree_block.
+
+   FIXME lto, this would not be needed if streaming of nodes in the
+   global context was unified with streaming of function bodies.  */
+
+static void
+output_block_or_decl (struct output_block *ob, tree t)
+{
+  if (t == NULL_TREE)
+    output_zero (ob);
+  else if (TREE_CODE (t) == FUNCTION_DECL)
+    output_expr_operand (ob, t);
+  else if (TREE_CODE (t) == BLOCK)
+    output_tree (ob, t);
+  else
+    gcc_unreachable ();
+}
+
+
+/* Write symbol binding block BLOCK to output block OB.  */
+
+static void
+output_tree_block (struct output_block *ob, tree block)
+{
+  unsigned HOST_WIDE_INT block_flags;
+  unsigned i;
+  tree t;
+  static struct function *last_cfun = NULL;
+  static struct pointer_set_t *local_syms = NULL;
+  static unsigned last_block_num = 0;
+
+  BLOCK_NUMBER (block) = last_block_num++;
+
+  block_flags = 0;
+  lto_set_flag (&block_flags, BLOCK_ABSTRACT (block));
+  lto_set_flags (&block_flags, BLOCK_NUMBER (block), 31);
+  output_sleb128 (ob, block_flags);
+
+  /* Note that we are only interested in emitting the symbols that are
+     actually referenced in CFUN.  Create a set of local symbols to
+     use as a filter for BLOCK_VARS.  */
+  if (last_cfun != cfun)
+    {
+      if (local_syms)
+	pointer_set_destroy (local_syms);
+      
+      local_syms = pointer_set_create ();
+      for (t = cfun->local_decls; t; t = TREE_CHAIN (t))
+	{
+	  tree v = TREE_VALUE (t);
+	  if (TREE_CODE (v) != TYPE_DECL)
+	    pointer_set_insert (local_syms, v);
+	}
+
+      last_cfun = cfun;
+    }
+
+  /* FIXME lto.  Disabled for now.  This is causing regressions in
+     libstdc++ testsuite
+     (testsuite/23_containers/list/check_construct_destroy.cc).  */
+  for (t = BLOCK_VARS (block); t && 0; t = TREE_CHAIN (t))
+    if (TREE_CODE (t) != TYPE_DECL && pointer_set_contains (local_syms, t))
+      output_expr_operand (ob, t);
+  output_zero (ob);
+
+  output_sleb128 (ob, VEC_length (tree, BLOCK_NONLOCALIZED_VARS (block)));
+  for (i = 0; VEC_iterate (tree, BLOCK_NONLOCALIZED_VARS (block), i, t); i++)
+    output_expr_operand (ob, t);
+
+  output_block_or_decl (ob, BLOCK_SUPERCONTEXT (block));
+  output_block_or_decl (ob, BLOCK_ABSTRACT_ORIGIN (block));
+  output_block_or_decl (ob, BLOCK_FRAGMENT_ORIGIN (block));
+  output_block_or_decl (ob, BLOCK_FRAGMENT_CHAIN (block));
+  output_tree (ob, BLOCK_CHAIN (block));
+  output_tree (ob, BLOCK_SUBBLOCKS (block));
+}
+
+
 /* Output EXPR to the main stream in OB.  */
 
 static void
@@ -1266,23 +1348,6 @@ output_expr_operand (struct output_block
 	break;
       }
 
-      /* This is the error case, these are type codes that will either
-	 never happen or that we have not gotten around to dealing
-	 with are here.  */
-    case BIND_EXPR:
-    case BLOCK:
-    case CATCH_EXPR:
-    case EH_FILTER_EXPR:
-    case OMP_CRITICAL:
-    case OMP_FOR:
-    case OMP_MASTER:
-    case OMP_ORDERED:
-    case OMP_PARALLEL:
-    case OMP_SECTIONS:
-    case OMP_SINGLE:
-    case TARGET_MEM_REF:
-    case TRY_CATCH_EXPR:
-    case TRY_FINALLY_EXPR:
     default:
       /* We cannot have forms that are not explicity handled.  So when
 	 this is triggered, there is some form that is not being
@@ -1677,6 +1751,9 @@ output_gimple_stmt (struct output_block 
   /* Emit location information for the statement.  */
   output_stmt_location (ob, stmt);
 
+  /* Emit the lexical block holding STMT.  */
+  output_tree (ob, gimple_block (stmt));
+
   /* Emit the tuple header.  FIXME lto.  This is emitting fields that are not
      necessary to emit (e.g., gimple_statement_base.bb,
      gimple_statement_base.block).  */
@@ -1940,6 +2017,7 @@ lto_static_init (void)
   /* These forms never need types.  */
   sbitmap_ones (lto_types_needed_for);
   RESET_BIT (lto_types_needed_for, ASM_EXPR);
+  RESET_BIT (lto_types_needed_for, BLOCK);
   RESET_BIT (lto_types_needed_for, CASE_LABEL_EXPR);
   RESET_BIT (lto_types_needed_for, FIELD_DECL);
   RESET_BIT (lto_types_needed_for, FUNCTION_DECL);
@@ -2031,7 +2109,8 @@ lto_static_init_local (void)
 static int function_num;
 #endif
 
-/* Output FN.  */
+
+/* Output the body of function NODE->DECL.  */
 
 static void
 output_function (struct cgraph_node *node)
@@ -2045,6 +2124,8 @@ output_function (struct cgraph_node *nod
   LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data);
   clear_line_info (ob);
   ob->cgraph_node = node;
+  ob->main_hash_table = htab_create (37, lto_hash_global_slot_node,
+				     lto_eq_global_slot_node, free);
 
   gcc_assert (!current_function_decl && !cfun);
 
@@ -2092,9 +2173,13 @@ output_function (struct cgraph_node *nod
   else
     output_zero (ob);
 
-  /* Output any exception-handling regions.  */
+  /* Output any exception handling regions.  */
   output_eh_regions (ob, fn);
 
+  /* Output DECL_INITIAL for the function, which contains the tree of
+     lexical scopes.  */
+  output_tree (ob, DECL_INITIAL (function));
+
   /* Output the head of the arguments list.  */
   LTO_DEBUG_INDENT_TOKEN ("decl_arguments");
   if (DECL_ARGUMENTS (function))
@@ -2714,8 +2799,6 @@ output_function_decl (struct output_bloc
   output_tree_with_context (ob, decl->decl_non_common.result, decl);
   output_tree (ob, decl->decl_non_common.vindex);
 
-  /* omit initial -- should be written with body */
-
   if (decl->function_decl.personality)
     {
       /* FIXME lto: We have to output the index since the symbol table
@@ -3189,7 +3272,10 @@ output_tree_with_context (struct output_
   fprintf (stderr, "\n");
 #endif
 
-  if (TYPE_P (expr) || DECL_P (expr) || TREE_CODE (expr) == TREE_BINFO)
+  if (TYPE_P (expr)
+      || DECL_P (expr)
+      || TREE_CODE (expr) == TREE_BINFO
+      || TREE_CODE (expr) == BLOCK)
     {
       unsigned int global_index;
       /* FIXME lto:  There are decls that pass the predicate above, but which
@@ -3213,7 +3299,6 @@ output_tree_with_context (struct output_
  	  case NAMESPACE_DECL:
  	  case TRANSLATION_UNIT_DECL:
 	  case LABEL_DECL:
- 	    break;
  	  case VOID_TYPE:
  	  case INTEGER_TYPE:
  	  case REAL_TYPE:
@@ -3231,8 +3316,8 @@ output_tree_with_context (struct output_
  	  case QUAL_UNION_TYPE:
  	  case FUNCTION_TYPE:
  	  case METHOD_TYPE:
- 	    break;
  	  case TREE_BINFO:
+	  case BLOCK:
  	    break;
  
  	  default:
@@ -3283,6 +3368,11 @@ output_tree_with_context (struct output_
 
   switch (code)
     {
+    case BLOCK:
+      output_global_record_start (ob, expr, NULL, LTO_block);
+      output_tree_block (ob, expr);
+      break;
+
     case COMPLEX_CST:
       if (TREE_CODE (TREE_REALPART (expr)) == REAL_CST)
 	{
@@ -3564,31 +3654,13 @@ output_tree_with_context (struct output_
 	break;
       }
 
-      /* This is the error case, these are type codes that will either
-	 never happen or that we have not gotten around to dealing
-	 with are here.  */
-    case BIND_EXPR:
-    case BLOCK:
-    case CATCH_EXPR:
-    case EH_FILTER_EXPR:
-    case OMP_CRITICAL:
-    case OMP_FOR:
-    case OMP_MASTER:
-    case OMP_ORDERED:
-    case OMP_PARALLEL:
-    case OMP_SECTIONS:
-    case OMP_SINGLE:
-    case TARGET_MEM_REF:
-    case TRY_CATCH_EXPR:
-    case TRY_FINALLY_EXPR:
     default:
       if (TREE_CODE (expr) >= NUM_TREE_CODES)
 	{
 	  /* EXPR is a language-specific tree node, which has no meaning
-	     outside of the front-end.  Something along the lines of
-	     http://gcc.gnu.org/ml/gcc-patches/2008-03/msg00349.html
-	     should be implemented.  */
-	  error ("Unimplemented code (FE-specific): %d", (int) code);
+	     outside of the front end.  These nodes should have been
+	     cleaned up by pass_ipa_free_lang_data.  */
+	  error ("Invalid FE-specific tree code: %d", (int) code);
 	  gcc_unreachable ();
 	}
       else
Index: lto-function-in.c
===================================================================
--- lto-function-in.c	(revision 147598)
+++ lto-function-in.c	(working copy)
@@ -59,6 +59,8 @@ static tree input_tree_operand (struct l
                                 tree, enum LTO_tags);
 static tree input_local_decl (struct lto_input_block *, struct data_in *,
 			      struct function *, unsigned int);
+static tree input_expr_operand (struct lto_input_block *, struct data_in *, 
+				struct function *, enum LTO_tags);
 
 /* Map between LTO tags and tree codes.  */
 static enum tree_code tag_to_expr[LTO_tree_last_tag];
@@ -1736,6 +1748,7 @@ input_gimple_stmt (struct lto_input_bloc
   size_t i, nbytes;
   char *buf;
   location_t location;
+  tree block;
 
   if (tag == LTO_gimple_asm)
     code = GIMPLE_ASM;
@@ -1768,6 +1781,9 @@ input_gimple_stmt (struct lto_input_bloc
   /* Read location information.  */
   location = input_stmt_location (ib, data_in);
 
+  /* Read lexical block reference.  */
+  block = input_tree (ib, data_in);
+
   /* Read the tuple header.  FIXME lto.  This seems unnecessarily slow
      and it is reading pointers in the tuple that need to be re-built
      locally (e.g, basic block, lexical block, operand vectors, etc).  */
@@ -1827,7 +1843,7 @@ input_gimple_stmt (struct lto_input_bloc
      should disappear after we fix the unnecessary fields that are
      written for every tuple.  */
   gimple_set_bb (stmt, NULL);
-  gimple_set_block (stmt, NULL);
+  gimple_set_block (stmt, block);
   if (gimple_has_ops (stmt))
     {
       gimple_set_def_ops (stmt, NULL);
@@ -1958,8 +1974,6 @@ input_function (tree fn_decl, struct dat
 
   fn = DECL_STRUCT_FUNCTION (fn_decl);
   tag = input_record_start (ib);
-  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);
 
   gimple_register_cfg_hooks ();
@@ -1994,8 +2008,18 @@ input_function (tree fn_decl, struct dat
   if (tag)
     fn->nonlocal_goto_save_area = input_expr_operand (ib, data_in, fn, tag);
 
+  /* Read the exception handling regions in the function.  */
   input_eh_regions (ib, data_in, fn);
 
+  /* Read the tree of lexical scopes for the function.  */
+  DECL_INITIAL (fn_decl) = input_tree (ib, data_in);
+  if (DECL_INITIAL (fn_decl) == NULL_TREE)
+    {
+      DECL_INITIAL (fn_decl) = make_node (BLOCK);
+      BLOCK_ABSTRACT_ORIGIN (DECL_SAVED_TREE (fn_decl)) = fn_decl;
+    }
+  DECL_SAVED_TREE (fn_decl) = DECL_INITIAL (fn_decl);
+
   LTO_DEBUG_INDENT_TOKEN ("decl_arguments");
   tag = input_record_start (ib);
   if (tag)
@@ -3283,6 +3307,87 @@ input_type_tree (struct lto_input_block 
 }
 
 
+/* Helper for input_tree_block.  Read a FUNCTION_DECL reference or a
+   BLOCK from IB using descriptors in DATA_IN.  */
+
+static tree
+input_block_or_decl (struct lto_input_block *ib, struct data_in *data_in)
+{
+  enum LTO_tags tag;
+
+  /* FIXME lto, this would not be needed if streaming of trees in
+     global context was unified with trees in function bodies.  */
+  tag = input_record_start (ib);
+
+  if (tag == LTO_null)
+    return NULL_TREE;
+  else if (tag == LTO_function_decl0)
+    return lto_file_decl_data_get_fn_decl (data_in->file_data,
+					   lto_input_uleb128 (ib));
+  else if (tag == LTO_block || tag == LTO_tree_pickle_reference)
+    return input_tree_operand (ib, data_in, NULL, tag);
+  else
+    gcc_unreachable ();
+}
+
+
+/* Read a BLOCK tree from input block IB using descriptors in DATA_IN.  */
+
+static tree
+input_tree_block (struct lto_input_block *ib, struct data_in *data_in)
+{
+  unsigned HOST_WIDE_INT block_flags;
+  tree block;
+  unsigned i, vlen;
+  enum LTO_tags tag;
+  tree first, curr, prev;
+
+  block = make_node (BLOCK);
+
+  global_vector_enter (data_in, block);
+
+  block_flags = lto_input_sleb128 (ib);
+  BLOCK_NUMBER (block) = lto_get_flags (&block_flags, 31);
+  BLOCK_ABSTRACT (block) = lto_get_flag (&block_flags);
+
+  first = prev = NULL_TREE;
+  tag = input_record_start (ib);
+  while (tag)
+    {
+      curr = input_expr_operand (ib, data_in, cfun, tag);
+      if (prev)
+	TREE_CHAIN (prev) = curr;
+      else
+	first = curr;
+
+      TREE_CHAIN (curr) = NULL_TREE;
+      prev = curr;
+      tag = input_record_start (ib);
+    }
+  BLOCK_VARS (block) = first;
+
+
+  vlen = lto_input_sleb128 (ib);
+  for (i = 0; i < vlen; i++)
+    {
+      tree var;
+
+      tag = input_record_start (ib);
+      var = input_expr_operand (ib, data_in, cfun, tag);
+      VEC_safe_push (tree, gc, BLOCK_NONLOCALIZED_VARS (block), var);
+    }
+
+  BLOCK_SUPERCONTEXT (block) = input_block_or_decl (ib, data_in);
+  BLOCK_ABSTRACT_ORIGIN (block) = input_block_or_decl (ib, data_in);
+  BLOCK_FRAGMENT_ORIGIN (block) = input_block_or_decl (ib, data_in);
+  BLOCK_FRAGMENT_CHAIN (block) = input_block_or_decl (ib, data_in);
+  BLOCK_CHAIN (block) = input_tree (ib, data_in);
+  BLOCK_SUBBLOCKS (block) = input_tree (ib, data_in);
+
+  return block;
+}
+
+
 /* Read a node in the body of function FN from input block IB using
    descriptors in DATA_IN.  TAG indicates the kind of tree that is
    expected to be read.  */
@@ -3359,6 +3464,10 @@ input_tree_operand (struct lto_input_blo
 
   switch (code)
     {
+    case BLOCK:
+      result = input_tree_block (ib, data_in);
+      break;
+
     case COMPLEX_CST:
       {
 	tree elt_type = input_type_tree (ib, data_in);
Index: lto-tree-tags.def
===================================================================
--- lto-tree-tags.def	(revision 147597)
+++ lto-tree-tags.def	(working copy)
@@ -65,6 +65,7 @@
   MAP_EXPR_TAG(ARRAY_RANGE_REF, LTO_array_range_ref)
   MAP_EXPR_TAG(ARRAY_REF, LTO_array_ref)
   MAP_EXPR_TAG(ARRAY_TYPE, LTO_array_type)
+  MAP_EXPR_TAG(BLOCK, LTO_block)
   MAP_EXPR_TAG(BOOLEAN_TYPE, LTO_boolean_type)
   MAP_EXPR_TAG(COMPLEX_TYPE, LTO_complex_type)
   MAP_EXPR_TAG(COMPONENT_REF, LTO_component_ref)
@@ -215,6 +216,7 @@
   SET_NAME (LTO_bit_field_ref1, "bit_field_ref1")
   SET_NAME (LTO_bit_not_expr, "bit_not_expr")
   SET_NAME (LTO_bit_xor_expr, "bit_xor_expr")
+  SET_NAME (LTO_block, "block")
   SET_NAME (LTO_case_label_expr0, "case_label_expr0")
   SET_NAME (LTO_case_label_expr1, "case_label_expr1")
   SET_NAME (LTO_case_label_expr2, "case_label_expr2")
Index: lto-tags.h
===================================================================
--- lto-tags.h	(revision 147597)
+++ lto-tags.h	(working copy)
@@ -307,6 +307,8 @@ enum LTO_tags 
   LTO_bit_not_expr,
   LTO_bit_xor_expr,
 
+  LTO_block,
+
   /* Call_exprs are terminated by a 0 to indicate the end of the
      parameter list.  Variant 1 indicates the presence of a call
      chain.  */
Index: lto-tree-flags.def
===================================================================
--- lto-tree-flags.def	(revision 147597)
+++ lto-tree-flags.def	(working copy)
@@ -193,7 +193,6 @@
     END_EXPR_CASE (BIT_XOR_EXPR)
       
     START_EXPR_CASE (BLOCK)
-      ADD_EXPR_FLAG (asm_written_flag)
     END_EXPR_CASE (BLOCK)
       
     START_EXPR_CASE (BOOLEAN_TYPE)
@@ -597,7 +596,6 @@
     END_EXPR_CASE (PREINCREMENT_EXPR)
       
     START_EXPR_CASE (QUAL_UNION_TYPE)
-      ADD_EXPR_FLAG (asm_written_flag)
       ADD_TYPE_FLAG (no_force_blk_flag)
     END_EXPR_CASE (QUAL_UNION_TYPE)
       
@@ -622,7 +620,6 @@
     END_EXPR_CASE (REAL_TYPE)
       
     START_EXPR_CASE (RECORD_TYPE)
-      ADD_EXPR_FLAG (asm_written_flag)
       ADD_TYPE_FLAG (no_force_blk_flag)
     END_EXPR_CASE (RECORD_TYPE)
       
@@ -775,7 +772,6 @@
     END_EXPR_CASE (UNGT_EXPR)
       
     START_EXPR_CASE (UNION_TYPE)
-      ADD_EXPR_FLAG (asm_written_flag)
       ADD_TYPE_FLAG (no_force_blk_flag)
       ADD_TYPE_FLAG (transparent_union_flag)
     END_EXPR_CASE (UNION_TYPE)


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