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 {