2016-03-29 12:07 GMT-03:00 Andres Tiraboschi
<andres.tirabos...@tallertechnologies.com>:
> 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.tirabos...@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
>  {


Hi,
please see the updated patch at
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70201 .

Reply via email to