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 .