[incremental] Patch: FYI: fix -g

Tom Tromey tromey@redhat.com
Tue Sep 25 02:27:00 GMT 2007


I'm checking this in on the incremental-compiler branch.

This patch makes '-g' work with the compile server.  It has a few
parts:

* Call rest_of_decl_compilation or rest_of_type_compilation when
  re-binding an already-parsed object.

* Change dwarf2out not to use TREE_ASM_WRITTEN or TYPE_SYMTAB_DIE.
  Instead it uses module-local per-compilation hashes.  In general,
  with the server, mutable flags on trees are problematic.

  Another approach here would be to push all debuginfo generation
  until after the server forks for code generation.  If the hashes
  cost too much, or if this is desirable for other reasons, I'll look
  at that more deeply.

* Re-bind built-in types.  This ensures that they are seen by the
  debug info generator.

  This re-initialization stuff needs a scrubbing.

Next is make '-g -O2' work.

Tom

ChangeLog:
2007-09-24  Tom Tromey  <tromey@redhat.com>

	* c-decl.c (all_c_built_ins): New global.
	(c_decl_re_bind): Pass re-bound decls to rest_of_decl_compilation
	or rest_of_type_compilation.
	(re_bind_built_in): New function.
	(pushdecl): Note built-ins in all_c_built_ins.
	(c_init_decl_processing): Initialize all_c_built_ins.  Call
	re_bind_built_in when re-run.
	* dwarf2out.c (mark_decl): New function.
	(seen_decl_p): Likewise.
	(struct type_die_entry): New struct.
	(type_die_table): New global.
	(seen_decls): Likewise.
	(hash_type_die_entry): New function.
	(eq_type_die_entry): Likewise.
	(lookup_type_die): Use type_die_table.
	(equate_type_number_to_die): Likewise.
	(reference_to_unused): Use seen_decl_p.
	(add_name_and_src_coords_attributes): Likewise.
	(scope_die_for): Likewise.
	(gen_variable_die): Likewise.
	(gen_typedef_die): Likewise.
	(gen_type_die_with_usage): Likewise.
	(gen_block_die): Likewise.
	(dwarf2out_init): Initialize seen_decls, type_die_table.
	(gen_enumeration_type_die): Use mark_decl.
	(gen_struct_or_union_type_die): Likewise.
	(gen_typedef_die): Likewise.
	(gen_type_die_with_usage): Likewise.
	* dwarf2asm.h (dw2_initialize): Declare.
	* dwarf2asm.c (dw2_initialize): New function.
	* toplev.c (lang_dependent_init): Call dw2_initialize.

Index: dwarf2asm.c
===================================================================
--- dwarf2asm.c	(revision 127650)
+++ dwarf2asm.c	(working copy)
@@ -695,6 +695,13 @@
 
 static GTY(()) int dw2_const_labelno;
 
+void
+dw2_initialize (void)
+{
+  indirect_pool = NULL;
+  dw2_const_labelno = 0;
+}
+
 #if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
 # define USE_LINKONCE_INDIRECT 1
 #else
Index: dwarf2asm.h
===================================================================
--- dwarf2asm.h	(revision 127650)
+++ dwarf2asm.h	(working copy)
@@ -64,6 +64,7 @@
 extern const char *eh_data_format_name (int);
 
 extern void dw2_output_indirect_constants (void);
+extern void dw2_initialize (void);
 
 /* These are currently unused.  */
 
Index: toplev.c
===================================================================
--- toplev.c	(revision 128628)
+++ toplev.c	(working copy)
@@ -2088,6 +2088,7 @@
   /* Now we have the correct original filename, we can initialize
      debug output.  */
   (*debug_hooks->init) (name);
+  dw2_initialize ();
 
   timevar_pop (TV_SYMOUT);
 
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 128257)
+++ dwarf2out.c	(working copy)
@@ -362,6 +362,9 @@
 static bool clobbers_queued_reg_save (rtx);
 static void dwarf2out_frame_debug_expr (rtx, const char *);
 
+static void mark_decl (tree);
+static bool seen_decl_p (tree);
+
 /* Support for complex CFA locations.  */
 static void output_cfa_loc (dw_cfi_ref);
 static void get_cfa_from_loc_descr (dw_cfa_location *,
@@ -3913,6 +3916,18 @@
    The key is a DECL_UID() which is a unique number identifying each decl.  */
 static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
 
+/* Map a type to a DIE.  */
+struct type_die_entry GTY (())
+{
+  /* The type.  */
+  tree type;
+  /* The corresponding DIE.  */
+  dw_die_ref die;
+};
+
+/* This hash maps types onto DIEs.  */
+static GTY ((param_is (struct type_die_entry))) htab_t type_die_table;
+
 /* Node of the variable location list.  */
 struct var_loc_node GTY ((chain_next ("%h.next")))
 {
@@ -3949,7 +3964,7 @@
 /* Number of elements currently allocated for abbrev_die_table.  */
 static GTY(()) unsigned abbrev_die_table_allocated;
 
-/* Number of elements in type_die_table currently in use.  */
+/* Number of elements in abbrev_die_table currently in use.  */
 static GTY(()) unsigned abbrev_die_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
@@ -4061,6 +4076,8 @@
 /* The default cold text section.  */
 static GTY(()) section *cold_text_section;
 
+static GTY ((param_is (union tree_node))) htab_t seen_decls;
+
 #ifdef DWARF2_DEBUGGING_INFO
 
 /* Offset from the "steady-state frame pointer" to the frame base,
@@ -5674,12 +5691,35 @@
   return die;
 }
 
+/* Compute the hash code of a struct type_die_entry.  */
+
+static hashval_t
+hash_type_die_entry (const void *ep)
+{
+  const struct type_die_entry *entry = (const struct type_die_entry *) ep;
+  return htab_hash_pointer (entry->type);
+}
+
+/* Compare two struct type_die_entry's for equality.  */
+
+static int
+eq_type_die_entry (const void *a, const void *b)
+{
+  const struct type_die_entry *left = (const struct type_die_entry *) a;
+  const struct type_die_entry *right = (const struct type_die_entry *) b;
+  return left->type == right->type;
+}
+
 /* Return the DIE associated with the given type specifier.  */
 
 static inline dw_die_ref
 lookup_type_die (tree type)
 {
-  return TYPE_SYMTAB_DIE (type);
+  struct type_die_entry temp, *result;
+
+  temp.type = type;
+  result = (struct type_die_entry *) htab_find (type_die_table, &temp);
+  return result ? result->die : NULL;
 }
 
 /* Equate a DIE to a given type specifier.  */
@@ -5687,7 +5727,11 @@
 static inline void
 equate_type_number_to_die (tree type, dw_die_ref type_die)
 {
-  TYPE_SYMTAB_DIE (type) = type_die;
+  struct type_die_entry *entry = GGC_NEW (struct type_die_entry);
+  entry->type = type;
+  entry->die = type_die;
+  void **slot = htab_find_slot (type_die_table, entry, INSERT);
+  *slot = entry;
 }
 
 /* Returns a hash value for X (which really is a die_struct).  */
@@ -10339,7 +10383,7 @@
     *walk_subtrees = 0;
 
   if (DECL_P (*tp) && ! TREE_PUBLIC (*tp) && ! TREE_USED (*tp)
-      && ! TREE_ASM_WRITTEN (*tp))
+      && ! seen_decl_p (*tp))
     return *tp;
   else if (!flag_unit_at_a_time)
     return NULL_TREE;
@@ -11322,7 +11366,7 @@
 #ifdef VMS_DEBUGGING_INFO
   /* Get the function's name, as described by its RTL.  This may be different
      from the DECL_NAME name used in the source file.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
+  if (TREE_CODE (decl) == FUNCTION_DECL && seen_decl_p (decl))
     {
       add_AT_addr (die, DW_AT_VMS_rtnbeg_pd_address,
 		   XEXP (DECL_RTL (decl), 0));
@@ -11394,7 +11438,7 @@
       if (i < 0)
 	{
 	  gcc_assert (debug_info_level <= DINFO_LEVEL_TERSE
-		      || TREE_ASM_WRITTEN (containing_scope));
+		      || seen_decl_p (containing_scope));
 
 	  /* If none of the current dies are suitable, we get file scope.  */
 	  scope_die = comp_unit_die;
@@ -11723,7 +11767,7 @@
     {
       tree link;
 
-      TREE_ASM_WRITTEN (type) = 1;
+      mark_decl (type);
       add_byte_size_attribute (type_die, type);
       if (TYPE_STUB_DECL (type) != NULL_TREE)
 	add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
@@ -12355,7 +12399,7 @@
 			definition is required, so the compiler will
 			not emit a definition.  */
 		     || (TREE_CODE (decl) == VAR_DECL
-			 && DECL_COMDAT (decl) && !TREE_ASM_WRITTEN (decl))
+			 && DECL_COMDAT (decl) && !seen_decl_p (decl))
 		     || class_or_namespace_scope_p (context_die));
 
   if (origin != NULL)
@@ -12882,7 +12926,7 @@
     {
       /* Prevent infinite recursion in cases where the type of some member of
 	 this type is expressed in terms of this type itself.  */
-      TREE_ASM_WRITTEN (type) = 1;
+      mark_decl (type);
       add_byte_size_attribute (type_die, type);
       if (TYPE_STUB_DECL (type) != NULL_TREE)
 	add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
@@ -12947,10 +12991,10 @@
   dw_die_ref type_die;
   tree origin;
 
-  if (TREE_ASM_WRITTEN (decl))
+  if (seen_decl_p (decl))
     return;
 
-  TREE_ASM_WRITTEN (decl) = 1;
+  mark_decl (decl);
   type_die = new_die (DW_TAG_typedef, context_die, decl);
   origin = decl_ultimate_origin (decl);
   if (origin != NULL)
@@ -12995,13 +13039,13 @@
   if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
       && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
     {
-      if (TREE_ASM_WRITTEN (type))
+      if (seen_decl_p (type))
 	return;
 
       /* Prevent broken recursion; we can't hand off to the same type.  */
       gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
 
-      TREE_ASM_WRITTEN (type) = 1;
+      mark_decl (type);
       gen_decl_die (TYPE_NAME (type), context_die);
       return;
     }
@@ -13014,7 +13058,7 @@
   if (TREE_CODE (type) != VECTOR_TYPE)
     type = type_main_variant (type);
 
-  if (TREE_ASM_WRITTEN (type))
+  if (seen_decl_p (type))
     return;
 
   switch (TREE_CODE (type))
@@ -13024,12 +13068,12 @@
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
-      /* We must set TREE_ASM_WRITTEN in case this is a recursive type.  This
+      /* We must set seen_decl_p in case this is a recursive type.  This
 	 ensures that the gen_type_die recursion will terminate even if the
 	 type is recursive.  Recursive types are possible in Ada.  */
       /* ??? We could perhaps do this for all types before the switch
 	 statement.  */
-      TREE_ASM_WRITTEN (type) = 1;
+      mark_decl (type);
 
       /* For these types, all that is required is that we output a DIE (or a
 	 set of DIEs) to represent the "basis" type.  */
@@ -13086,11 +13130,11 @@
 	 what set of template instantiations we'll get.  */
       if (TYPE_CONTEXT (type)
 	  && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
-	  && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
+	  && ! seen_decl_p (TYPE_CONTEXT (type)))
 	{
 	  gen_type_die_with_usage (TYPE_CONTEXT (type), context_die, usage);
 
-	  if (TREE_ASM_WRITTEN (type))
+	  if (seen_decl_p (type))
 	    return;
 
 	  /* If that failed, attach ourselves to the stub.  */
@@ -13108,7 +13152,7 @@
 	{
 	  /* This might have been written out by the call to
 	     declare_in_namespace.  */
-	  if (!TREE_ASM_WRITTEN (type))
+	  if (!seen_decl_p (type))
 	    gen_enumeration_type_die (type, context_die);
 	}
       else
@@ -13117,7 +13161,7 @@
       if (need_pop)
 	pop_decl_scope ();
 
-      /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix
+      /* Don't set seen_decl_p on an incomplete struct; we want to fix
 	 it up if it is ever completed.  gen_*_type_die will set it for us
 	 when appropriate.  */
       return;
@@ -13139,7 +13183,7 @@
       gcc_unreachable ();
     }
 
-  TREE_ASM_WRITTEN (type) = 1;
+  mark_decl (type);
 }
 
 static void
@@ -13162,7 +13206,7 @@
      type now.  */
   gcc_assert (type == type_main_variant (type));
 
-  /* Do not check TREE_ASM_WRITTEN (type) as it may not be set if this is
+  /* Do not check seen_decl_p (type) as it may not be set if this is
      an instance of an unresolved type.  */
 
   switch (TREE_CODE (type))
@@ -13248,7 +13292,7 @@
 	       as being a "significant" one.  */
 	    must_output_die = (BLOCK_VARS (stmt) != NULL
 			       && (TREE_USED (stmt)
-				   || TREE_ASM_WRITTEN (stmt)
+				   || seen_decl_p (stmt)
 				   || BLOCK_ABSTRACT (stmt)));
 	  else
 	    /* We are in terse mode, so only local (nested) function
@@ -14282,7 +14326,6 @@
   next_die_offset = 0;
   current_function_has_inlines = false;
 #endif
-  comp_unit_die = NULL;
   limbo_die_list = NULL;
   line_info_table_in_use = 0;
   have_multiple_function_sections = false;
@@ -14315,6 +14358,9 @@
   decl_die_table = htab_create_ggc (10, decl_die_table_hash,
 				    decl_die_table_eq, NULL);
 
+  type_die_table = htab_create_ggc (50, hash_type_die_entry,
+				    eq_type_die_entry, NULL);
+
   /* Allocate the decl_loc_table.  */
   decl_loc_table = htab_create_ggc (10, decl_loc_table_hash,
 				    decl_loc_table_eq, NULL);
@@ -14415,8 +14461,26 @@
       switch_to_section (cold_text_section);
       ASM_OUTPUT_LABEL (asm_out_file, cold_text_section_label);
     }
+
+  /* Initialize the set of seen decls.  */
+  seen_decls = htab_create_ggc (20, htab_hash_pointer, htab_eq_pointer, NULL);
 }
 
+/* Mark DECL as having been written.   */
+static void
+mark_decl (tree decl)
+{
+  void **slot = htab_find_slot (seen_decls, decl, INSERT);
+  *slot = decl;
+}
+
+/* Return true if DECL was written, false otherwise.  */
+static bool
+seen_decl_p (tree decl)
+{
+  return htab_find (seen_decls, decl) != NULL;
+}
+
 /* A helper function for dwarf2out_finish called through
    ht_forall.  Emit one queued .debug_str string.  */
 
Index: c-decl.c
===================================================================
--- c-decl.c	(revision 128604)
+++ c-decl.c	(working copy)
@@ -160,6 +160,10 @@
    says we are in file scope.  */
 bool c_override_global_bindings_to_false;
 
+/* This holds all the built-ins defined at startup.  When
+   re-initializing the front end (in server mode), these are
+   re-bound.  */
+static GTY ((param_is (union tree_node))) htab_t all_c_built_ins;
 
 /* Each c_binding structure describes one binding of an identifier to
    a decl.  All the decls in a scope - irrespective of namespace - are
@@ -523,17 +527,47 @@
 {
   /* FIXME: perhaps should be using pushdecl, etc, here -- do we want
      to re-smash in this thread?  */
-  bind (name, decl, file_scope, /*invisible=*/false, /*nested=*/false,
-	/*notify_ok=*/false);
+  if (!DECL_P (decl) || !DECL_IS_BUILTIN (decl))
+    bind (name, decl, file_scope, /*invisible=*/false, /*nested=*/false,
+	  /*notify_ok=*/false);
   /* FIXME: more problems related to the above.  We need to re-declare
      in the external scope sometimes.  But what about smashing?  And
      other semantics of pushdecl?  Does this work for builtins which
      are put into the external scope?  */
-  if (TREE_PUBLIC (decl))
-    bind (name, decl, external_scope, /*invisible=*/false, /*nested=*/true,
+  if (TREE_PUBLIC (decl) || (DECL_P (decl) && DECL_IS_BUILTIN (decl)))
+    bind (name, decl, external_scope, /*invisible=*/false,
+	  /*nested=*/ !(DECL_P (decl) && DECL_IS_BUILTIN (decl)),
 	  /*notify_ok=*/false);
+
+  TREE_ASM_WRITTEN (decl) = 0;
+  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      /* FIXME: moral equivalent of decl smashing here.  */
+      if (DECL_INITIAL (decl) == NULL_TREE
+	  || DECL_INITIAL (decl) == error_mark_node)
+	/* Don't output anything
+	   when a tentative file-scope definition is seen.
+	   But at end of compilation, do output code for them.  */
+	DECL_DEFER_OUTPUT (decl) = 1;
+      rest_of_decl_compilation (decl, true, 0);
+    }
+  else if (TREE_CODE (decl) == TYPE_DECL)
+    rest_of_decl_compilation (decl, true, 0);
+  else if (TREE_CODE (decl) == RECORD_TYPE
+	   || TREE_CODE (decl) == UNION_TYPE
+	   || TREE_CODE (decl) == ENUMERAL_TYPE)
+    rest_of_type_compilation (decl, true);
 }
 
+static int
+re_bind_built_in (void **slot, void *ignore ATTRIBUTE_UNUSED)
+{
+  tree decl = (tree) *slot;
+  gcc_assert (DECL_P (decl) && DECL_IS_BUILTIN (decl));
+  c_decl_re_bind (DECL_NAME (decl), decl);
+  return 1;
+}
+
 /* Clear the binding structure B, stick it on the binding_freelist,
    and return the former value of b->prev.  This is used by pop_scope
    and get_parm_info to iterate destructively over all the bindings
@@ -2416,6 +2450,13 @@
   if (TREE_CODE (x) == TYPE_DECL)
     clone_underlying_type (x);
 
+  if (B_IN_EXTERNAL_SCOPE (scope) && DECL_IS_BUILTIN (x))
+    {
+      void **slot = htab_find_slot (all_c_built_ins, x, INSERT);
+      gcc_assert (!*slot);
+      *slot = x;
+    }
+
   bind (name, x, scope, /*invisible=*/false, nested, /*notify_ok=*/true);
 
   /* If x's type is incomplete because it's based on a
@@ -2925,6 +2966,9 @@
 
   if (!did_it)
     {
+      all_c_built_ins = htab_create_ggc (50, htab_hash_pointer,
+					 htab_eq_pointer, NULL);
+
       build_common_tree_nodes (flag_signed_char, false);
 
       c_common_nodes_and_builtins ();
@@ -2938,6 +2982,12 @@
       pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
 			    boolean_type_node));
     }
+  else
+    {
+      /* Re-bind all the builtins.  */
+      htab_traverse_noresize (all_c_built_ins, re_bind_built_in, NULL);
+    }
+
   did_it = true;
 
   input_location = save_loc;



More information about the Gcc-patches mailing list