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]

[PATCH] New flag in order to dump information about template instantiations.


Hi,
the attached patch adds a new compilation flag
'ftemplate-instantiations' in order
to allow dumping debug information for template instantiations.
This flag has 2 possible values: none(by default) and hreadable, that
prints witch
templates instantiations had been made in a human readable way.
This patch was also made in order to add options easily and to interact with
plugins.
  For example in a plugin can be defined a derived class for
template_instantiations_callbacks
implementing _function_instantiation, _class_instantiation, _using_instantiation
and then using add_template_instantiations_callbacks in order to
access information
about witch template instantiations had been made.

Changelog
2016-03-29  Andres Tiraboschi  <andres.tiraboschi@tallertechnologies.com>

    * gcc/c-family/c.opt (ftemplate-instantiations): New flag.
    * gcc/flag-types.h (ti_dump_options): New type.
    * gcc/cp/decl2.c (cp_write_global_declarations): Added code to
dump information.
    * gcc/cp/cp-tree.h (template_instantiations_callbacks): New type.
    (call_template_instantiation_callbacks): Declare.
    (add_template_instantiations_callbacks): Likewise.
    (clean_up_callbacks): Likewise.
    * gcc/cp/pt.c (human_readable_template_instantiations): New type.
    (instantiation_callbacks): Declare.
    (call_template_instantiation_callback): New function.
    (call_template_instantiation_callbacks): Likewise.
    (add_template_instantiations_callbacks): Likewise.
    (initialize_instantiations_callbacks): Likewise.
    (clean_up_callbacks): Likewise.
    (init_template_processing): Added code to initialize instatiation_callbacks.
    (register_specialization): Added code to dump information.
    * gcc/doc/invoke.texi (ftemplate-instantiations): Added documentation.


diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 7c5f6c7..a0ebcdc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1487,6 +1487,19 @@ fstats
 C++ ObjC++ Var(flag_detailed_statistics)
 Display statistics accumulated during compilation.

+ftemplate-instantiations=
+C++ Joined RejectNegative Enum(ti_dump_options) Var(ti_dump_option)
Init(TI_NONE)
+Dump information about wich templates have been instantiated
+
+Enum
+Name(ti_dump_options) Type(enum ti_dump_options)
UnknownError(unrecognized template instantiation dumping option %qs)
+
+EnumValue
+Enum(ti_dump_options) String(none) Value(TI_NONE)
+
+EnumValue
+Enum(ti_dump_options) String(hreadable) Value(TI_HREADABLE)
+
 fstrict-enums
 C++ ObjC++ Optimization Var(flag_strict_enums)
 Assume that values of enumeration type are always within the minimum
range of that type.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 15b004d..f682b4a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4816,6 +4816,61 @@ struct local_specialization_stack
   hash_map<tree, tree> *saved;
 };

+class template_instantiations_callbacks
+{
+public:
+  template_instantiations_callbacks () : next(NULL){}
+
+  void function_instantiation (tree tmpl, tree args, tree spec)
+  {
+    _function_instantiation (tmpl, args, spec);
+    if (next != NULL)
+      next->function_instantiation (tmpl, args, spec);
+  }
+
+  void class_instantiation (tree tmpl, tree args, tree spec)
+  {
+    _class_instantiation (tmpl, args, spec);
+    if (next != NULL)
+      next->class_instantiation (tmpl, args, spec);
+  }
+
+  void using_instantiation (tree tmpl, tree args, tree spec)
+  {
+    _using_instantiation (tmpl, args, spec);
+    if (next != NULL)
+      next->using_instantiation (tmpl, args, spec);
+  }
+
+  void add_callbacks (template_instantiations_callbacks* new_next)
+  {
+    if (next)
+      next->add_callbacks (new_next);
+    else
+      next = new_next;
+  }
+
+  virtual ~template_instantiations_callbacks ()
+  {
+    delete next;
+  }
+
+private:
+  template_instantiations_callbacks* next;
+
+  virtual void _function_instantiation (tree, tree, tree)
+  {
+  }
+
+  virtual void _class_instantiation (tree, tree, tree)
+  {
+  }
+
+  virtual void _using_instantiation (tree, tree, tree)
+  {
+  }
+};
+
 /* in class.c */

 extern int current_class_depth;
@@ -6199,6 +6254,9 @@ extern void register_local_specialization
(tree, tree);
 extern tree retrieve_local_specialization       (tree);
 extern tree extract_fnparm_pack                 (tree, tree *);
 extern tree template_parm_to_arg                (tree);
+extern void call_template_instantiation_callbacks (void);
+extern void add_template_instantiations_callbacks
(template_instantiations_callbacks* new_callback);
+extern void clean_up_callbacks (void);

 /* in repo.c */
 extern void init_repo                (void);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 73b0d28..097e3564 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4914,6 +4914,9 @@ c_parse_final_cleanups (void)
       dump_time_statistics ();
     }

+  call_template_instantiation_callbacks ();
+  clean_up_callbacks ();
+
   timevar_stop (TV_PHASE_DEFERRED);
   timevar_start (TV_PHASE_PARSING);

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e8cfb66..9f5877d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -98,12 +98,39 @@ struct GTY((for_user)) spec_entry
   tree spec;
 };

+class human_readable_template_instantiations
+    : public template_instantiations_callbacks
+{
+  void _function_instantiation(tree /*tmpl*/, tree /*args*/, tree spec)
+  {
+    int flags = TFF_DECL_SPECIFIERS|TFF_RETURN_TYPE
+        | TFF_FUNCTION_DEFAULT_ARGUMENTS
+        | TFF_EXCEPTION_SPECIFICATION ;
+    fprintf (stderr, "Function inst: %s\n", decl_as_string (spec, flags));
+  }
+
+  void _class_instantiation(tree /*tmpl*/, tree /*args*/, tree spec)
+  {
+    fprintf (stderr, "Type inst: %s\n", type_as_string (TREE_TYPE
(spec), TFF_TEMPLATE_NAME));
+  }
+
+  void _using_instantiation(tree /*tmpl*/, tree /*args*/, tree spec)
+  {
+    fprintf (stderr, "Alias inst: %s = %s\n",
+              type_as_string (TREE_TYPE (spec), 0),
+              type_as_string (DECL_ORIGINAL_TYPE (spec), 0)
+    );
+  }
+};
+
 struct spec_hasher : ggc_ptr_hash<spec_entry>
 {
   static hashval_t hash (spec_entry *);
   static bool equal (spec_entry *, spec_entry *);
 };

+static template_instantiations_callbacks *instantiation_callbacks = NULL;
+
 static GTY (()) hash_table<spec_hasher> *decl_specializations;

 static GTY (()) hash_table<spec_hasher> *type_specializations;
@@ -216,6 +243,40 @@ static tree tsubst_template_parm (tree, tree,
tsubst_flags_t);
 static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
 static bool complex_alias_template_p (const_tree tmpl);
 static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);
+static void call_template_instantiation_callback (tree tmpl, tree
args, tree spec);
+static void initialize_instantiations_callbacks (void);
+
+static void
+initialize_instantiations_callbacks (void)
+{
+  if (instantiation_callbacks == NULL)
+    {
+      switch (ti_dump_option)
+    {
+      case TI_HREADABLE:
+        instantiation_callbacks = new human_readable_template_instantiations;
+        break;
+      default:
+        instantiation_callbacks = new template_instantiations_callbacks;
+    }
+    }
+  /*Otherwise is already initialized*/
+}
+
+void
+add_template_instantiations_callbacks
(template_instantiations_callbacks* new_callback)
+{
+  if (instantiation_callbacks == NULL)
+    /*If instantiation_callbacks is not already initialized at this
moment, do it.*/
+    initialize_instantiations_callbacks ();
+  instantiation_callbacks->add_callbacks (new_callback);
+}
+
+void
+clean_up_callbacks (void)
+{
+  delete instantiation_callbacks;
+}

 /* Make the current scope suitable for access checking when we are
    processing T.  T can be FUNCTION_DECL for instantiated function
@@ -1507,9 +1568,12 @@ register_specialization (tree spec, tree tmpl,
tree args, bool is_friend,
     return spec;

   if (optimize_specialization_lookup_p (tmpl))
+    {
     /* We don't put these specializations in the hash table, but we might
        want to give an error about a mismatch.  */
-    fn = retrieve_specialization (tmpl, args, 0);
+      call_template_instantiation_callback (tmpl, args, spec);
+      fn = retrieve_specialization (tmpl, args, 0);
+    }
   else
     {
       elt.tmpl = tmpl;
@@ -24413,6 +24477,7 @@ init_constraint_processing (void)
 void
 init_template_processing (void)
 {
+  initialize_instantiations_callbacks ();
   decl_specializations = hash_table<spec_hasher>::create_ggc (37);
   type_specializations = hash_table<spec_hasher>::create_ggc (37);
 }
@@ -24432,4 +24497,34 @@ print_template_statistics (void)
        type_specializations->collisions ());
 }

+static void
+call_template_instantiation_callback (tree tmpl, tree args, tree spec)
+{
+  if (!instantiation_callbacks)
+    /*Do nothing*/;
+  else if (TREE_CODE (spec) == TYPE_DECL)
+    {
+      if (TYPE_DECL_ALIAS_P (spec))
+    instantiation_callbacks->using_instantiation (tmpl, args, spec);
+      else
+    instantiation_callbacks->class_instantiation (tmpl, args, spec);
+    }
+  else if (TREE_CODE (spec) == FUNCTION_DECL)
+    instantiation_callbacks->function_instantiation (tmpl, args, spec);
+}
+
+void
+call_template_instantiation_callbacks (void)
+{
+  hash_table<spec_hasher>::iterator it = decl_specializations->begin();
+  for (; it != decl_specializations->end(); ++it)
+    {
+      spec_entry *entry = *it;
+      tree tmpl = entry->tmpl;
+      tree args = entry->args;
+      tree spec = entry->spec;
+      call_template_instantiation_callback (tmpl, args, spec);
+    }
+}
+
 #include "gt-cp-pt.h"
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 99ac11b..3d72685 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -549,6 +549,7 @@ Objective-C and Objective-C++ Dialects}.
 -frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
 -fsel-sched-verbose -fsel-sched-dump-cfg -fsel-sched-pipelining-verbose @gol
 -fstats  -fstack-usage  -ftime-report @gol
+-ftemplate-instantiations @gol
 -fvar-tracking-assignments-toggle -gtoggle @gol
 -print-file-name=@var{library}  -print-libgcc-file-name @gol
 -print-multi-directory  -print-multi-lib  -print-multi-os-directory @gol
@@ -12610,6 +12611,10 @@ Emit statistics about front-end processing at
the end of the compilation.
 This option is supported only by the C++ front end, and
 the information is generally only useful to the G++ development team.

+@item -ftemplate-instantiations
+@opindex ftemplate-instantiations
+Dump information about wich templates have been instantiated.
+
 @item -fdbg-cnt-list
 @opindex fdbg-cnt-list
 Print the name and the counter upper bound for all debug counters.
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 8201676..95a5fbd 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -116,6 +116,13 @@ enum ivar_visibility
   IVAR_VISIBILITY_PACKAGE
 };

+/* Enumerate the template instantiations dump options */
+enum ti_dump_options
+{
+  TI_NONE,
+  TI_HREADABLE
+};
+
 /* The stack reuse level.  */
 enum stack_reuse_level
 {


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