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]

Re: [cxx-conversion] Support garbage-collected C++ templates


On 12-08-09 09:05 , Richard Guenther wrote:

What I do not understand is why you need a GTY(()) annotation on
C++ types with user-defined gc routines.  gengtype should treat all
types not marked with GTY(()) as having user-defined gc routines, no?

Ideally, yes. But currently gengtype makes it hard to do because of the way it's designed. When it finds a struct with no GTY() hooks, it completely ignores it. If that struct is later reached from a ggc root, it is too late to say 'ah, it must be a user type'.


That's why if we add a keyword to indicate that this struct is user-handled, things start working (with some limitations).

In this patch, I implement this notion. As an example, I modified struct edge_def.

The good:

- No GTY markers are needed for the fields of the structure.
- The user provides gt_ggc_mx and gt_pch_nx (2 variants). These are implemented in terms of calls to gt_ggc_mx and gt_pch_nx (see tree-cfg.c).
- gengtype generates the generic glue that calls these functions.


The ugly:

- The structure needs to be marked 'GTY((user))' for the gty parser to put it in the list of interesting structures (most notably, it gives it a source location, which is the indicator used in the rest of gengtype to decide whether a structure is interesting).

- The user-provided markers need to declare the prototypes for the gt_ggc_mx and gt_pch_nx for the type fields. This is due to the lack of prototypes generated in gtype-desc.h (or some other header).

These two warts are the ones I was referring to. I need to fix these in trunk because they will require quite a bit of file reorganization.

The end point should be that the only thing we really need to tell gengtype about are the variable roots. Everything else would rely on user-provided markings. I suppose we could still keep the automatic option for really simple stuff, though.


Diego.



2012-08-10 Diego Novillo <dnovillo@google.com>


        * basic-block.h (struct edge_def): Mark GTY((user)).
        Remove all GTY markers from fields.
        (gt_ggc_mx): Declare.
        (gt_pch_nx): Declare.
        * tree-cfg.c (gt_ggc_mx): New.
        (gt_pch_nx): New.

        * gengtype-lex.l (USER_GTY): Add pattern for "user".
        * gengtype-parse.c (option): Handle USER_GTY.
        (opts_have): New.
        (type): Call it.
        If the keyword 'user' is used, do not walk the fields
        of the structure.
        * gengtype.h (USER_GTY): Add.

diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index bf18bae..23cec6b 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -33,19 +33,19 @@ along with GCC; see the file COPYING3.  If not see
 typedef HOST_WIDEST_INT gcov_type;

 /* Control flow edge information.  */
-struct GTY(()) edge_def {
+struct GTY((user)) edge_def {
   /* The two blocks at the ends of the edge.  */
   basic_block src;
   basic_block dest;

   /* Instructions queued on the edge.  */
   union edge_def_insns {
-    gimple_seq GTY ((tag ("true"))) g;
-    rtx GTY ((tag ("false"))) r;
-  } GTY ((desc ("current_ir_type () == IR_GIMPLE"))) insns;
+    gimple_seq g;
+    rtx r;
+  } insns;

   /* Auxiliary info specific to a pass.  */
-  PTR GTY ((skip (""))) aux;
+  PTR aux;

   /* Location of any goto implicit in the edge and associated BLOCK.  */
   tree goto_block;
@@ -65,6 +65,11 @@ DEF_VEC_P(edge);
 DEF_VEC_ALLOC_P(edge,gc);
 DEF_VEC_ALLOC_P(edge,heap);

+/* Garbage collection and PCH support for edge_def.  */
+extern void gt_ggc_mx (edge_def *e);
+extern void gt_pch_nx (edge_def *e);
+extern void gt_pch_nx (edge_def *e, gt_pointer_operator, void *);
+
 /* Masks for edge.flags.  */
 #define DEF_EDGE_FLAG(NAME,IDX) EDGE_##NAME = 1 << IDX ,
 enum cfg_edge_flags {
diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l
index 537acf6..5788a6a 100644
--- a/gcc/gengtype-lex.l
+++ b/gcc/gengtype-lex.l
@@ -108,6 +108,7 @@ EOID	[^[:alnum:]_]
 "enum"/{EOID}			{ return ENUM; }
 "ptr_alias"/{EOID}	  	{ return PTR_ALIAS; }
 "nested_ptr"/{EOID}		{ return NESTED_PTR; }
+"user"/{EOID}			{ return USER_GTY; }
 [0-9]+				{ return NUM; }
 "param"[0-9]*"_is"/{EOID}		{
   *yylval = XDUPVAR (const char, yytext, yyleng, yyleng+1);
diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c
index b213585..03ee781 100644
--- a/gcc/gengtype-parse.c
+++ b/gcc/gengtype-parse.c
@@ -499,6 +499,10 @@ option (options_p prev)
       advance ();
       return nestedptr_optvalue (prev);

+ case USER_GTY:
+ advance ();
+ return create_string_option (prev, "user", "");
+
default:
parse_error ("expected an option keyword, have %s", print_cur_token ());
advance ();
@@ -733,6 +737,18 @@ struct_field_seq (void)
return nreverse_pairs (f);
}


+/* Return true if OPTS contain the option named STR.  */
+
+static bool
+opts_have (options_p opts, const char *str)
+{
+  for (options_p opt = opts; opt; opt = opt->next)
+    if (strcmp (opt->name, str) == 0)
+      return true;
+  return false;
+}
+
+
 /* This is called type(), but what it parses (sort of) is what C calls
    declaration-specifiers and specifier-qualifier-list:

@@ -805,6 +821,7 @@ type (options_p *optsp, bool nested)

 	if (is_gty)
 	  {
+	    bool is_user_gty = opts_have (opts, "user");
 	    if (token () == '{')
 	      {
 		pair_p fields;
@@ -812,9 +829,20 @@ type (options_p *optsp, bool nested)
 		if (is_gty == GTY_AFTER_ID)
 		  parse_error ("GTY must be specified before identifier");

-		advance ();
-		fields = struct_field_seq ();
-		require ('}');
+		if (!is_user_gty)
+		  {
+		    advance ();
+		    fields = struct_field_seq ();
+		    require ('}');
+		  }
+		else
+		  {
+		    /* Do not look inside user defined structures.  */
+		    fields = NULL;
+		    kind = TYPE_USER_STRUCT;
+		    consume_balanced ('{', '}');
+		  }
+
 		return new_structure (s, kind, &lexer_line, fields, opts);
 	      }
 	  }
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index 2ca0e4e..4a178ec 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -463,6 +463,7 @@ enum
     ELLIPSIS,
     PTR_ALIAS,
     NESTED_PTR,
+    USER_GTY,
     PARAM_IS,
     NUM,
     SCALAR,
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index e4cf076..b734781 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -7836,3 +7836,54 @@ struct gimple_opt_pass pass_warn_unused_result =
     0,					/* todo_flags_finish */
   }
 };
+
+
+/* Garbage collection support for edge_def.  */
+
+extern void gt_ggc_mx (tree&);
+extern void gt_ggc_mx (gimple&);
+extern void gt_ggc_mx (rtx&);
+extern void gt_ggc_mx (basic_block&);
+
+void
+gt_ggc_mx (edge_def *e)
+{
+  gt_ggc_mx (e->src);
+  gt_ggc_mx (e->dest);
+  if (current_ir_type () == IR_GIMPLE)
+    gt_ggc_mx (e->insns.g);
+  else
+    gt_ggc_mx (e->insns.r);
+  gt_ggc_mx (e->goto_block);
+}
+
+/* PCH support for edge_def.  */
+
+extern void gt_pch_nx (tree&);
+extern void gt_pch_nx (gimple&);
+extern void gt_pch_nx (rtx&);
+extern void gt_pch_nx (basic_block&);
+
+void
+gt_pch_nx (edge_def *e)
+{
+  gt_pch_nx (e->src);
+  gt_pch_nx (e->dest);
+  if (current_ir_type () == IR_GIMPLE)
+    gt_pch_nx (e->insns.g);
+  else
+    gt_pch_nx (e->insns.r);
+  gt_pch_nx (e->goto_block);
+}
+
+void
+gt_pch_nx (edge_def *e, gt_pointer_operator op, void *cookie)
+{
+  op (&(e->src), cookie);
+  op (&(e->dest), cookie);
+  if (current_ir_type () == IR_GIMPLE)
+    op (&(e->insns.g), cookie);
+  else
+    op (&(e->insns.r), cookie);
+  op (&(e->goto_block), cookie);
+}


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