This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[plugins][patch] Print plugin versions
- From: Rafael Espindola <espindola at google dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Diego Novillo <dnovillo at google dot com>
- Date: Tue, 7 Apr 2009 16:53:38 +0100
- Subject: [plugins][patch] Print plugin versions
The attached patch makes the compiler (cc1, cc1plus, ...) print the
version of the plugin it has loaded when given --version. I am not
sure if this is the best way to do it. In particular:
*) Should it be mandatory for the plugin to specify a version? If so,
it is probably better to change the plugin_init signature instead of
adding new plugin_event as the patch does.
*) I added a version field to plugin_name_args. Another option is to
add a new global hash function. It would store the version, help and
name of each plugin. If we keep that information in plugin_name_args,
maybe we should rename it to just plugin?
The patch is a bit big since it has to move thing a bit. The
plugin_name_args cannot be freed just after initializing the plugins
and the plugins have to be initialized even when we are not compiling
a file.
2009-04-07 Rafael Avila de Espindola <espindola@google.com>
* gcc-plugin.h (plugin_event): Add PLUGIN_INFO.
(plugin_info): New.
* opts.c (common_handle_option): Don't call print_version.
* plugin.c (plugin_name_args): Add version.
(register_plugin_info): New.
(register_callback): Handle PLUGIN_INFO.
(try_init_one_plugin): New.
(init_one_plugin): Use try_init_one_plugin. Only free plugin_name_args
if failed to init.
(finalize_one_plugin): New.
(finalize_plugins): New.
(print_one_plugin): New.
(print_plugins_versions): New.
* plugin.h (print_plugins_versions): New.
(finalize_plugins): New.
* toplev.c (compile_file): Don't call initialize_plugins.
(print_version): Call print_plugins_versions.
(toplev_main): Call initialize_plugins. Print version if needed.
Call finalize_plugins.
Cheers,
--
Rafael Avila de Espindola
Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047
diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h
index 46f7e11..b6afbff 100644
--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -27,6 +27,7 @@ enum plugin_event
PLUGIN_FINISH_UNIT, /* Useful for summary processing. */
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
PLUGIN_FINISH, /* Called before GCC exits. */
+ PLUGIN_INFO, /* Infomation about the plugin */
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
array. */
};
@@ -55,6 +56,11 @@ struct plugin_pass
enum pass_positioning_ops pos_op; /* how to insert the new pass. */
};
+struct plugin_info
+{
+ const char *version;
+};
+
/* Function type for the plugin initialization routine. Each plugin module
should define this as an externally-visible function with name
"plugin_init."
diff --git a/gcc/opts.c b/gcc/opts.c
index 8f3c0c7..b2bfbbf 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1580,7 +1580,6 @@ common_handle_option (size_t scode, const char *arg, int value,
case OPT_fversion:
case OPT__version:
- print_version (stderr, "");
exit_after_options = true;
break;
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 9551eb8..8672646 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -43,6 +43,7 @@ struct plugin_name_args
const char *full_name;
int argc;
struct plugin_argument *argv;
+ const char *version;
};
/* Hash table for the plugin_name_args objects created during command-line
@@ -427,6 +428,14 @@ register_pass (const char *plugin_name, struct plugin_pass *pass_info)
}
}
+static void
+register_plugin_info (const char* name, struct plugin_info *info)
+{
+ void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT);
+ struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+ plugin->version = info->version;
+}
+
/* Called from the plugin's initialization code. Register a single callback.
This function can be called multiple times.
@@ -446,6 +455,9 @@ register_callback (const char *plugin_name,
case PLUGIN_PASS_MANAGER_SETUP:
register_pass (plugin_name, (struct plugin_pass *) user_data);
break;
+ case PLUGIN_INFO:
+ register_plugin_info (plugin_name, (struct plugin_info *) user_data);
+ break;
case PLUGIN_FINISH_STRUCT:
case PLUGIN_FINISH_UNIT:
case PLUGIN_CXX_CP_PRE_GENERICIZE:
@@ -511,18 +523,9 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
#define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
#define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
-/* Routine to dlopen and initialize one plugin. This function is passed to
- (and called by) the hash table traverse routine. Return 1 for the
- htab_traverse to continue scan, 0 to stop.
-
- SLOT - slot of the hash table element
- INFO - auxiliary pointer handed to hash table traverse routine
- (unused in this function) */
-
-static int
-init_one_plugin (void **slot, void * ARG_UNUSED (info))
+static bool
+try_init_one_plugin (struct plugin_name_args *plugin)
{
- struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
void *dl_handle;
plugin_init_func plugin_init;
char *err;
@@ -532,7 +535,7 @@ init_one_plugin (void **slot, void * ARG_UNUSED (info))
if (!dl_handle)
{
error (G_("Cannot load plugin %s\n%s"), plugin->full_name, dlerror ());
- return 1;
+ return 0;
}
/* Clear any existing error. */
@@ -546,22 +549,37 @@ init_one_plugin (void **slot, void * ARG_UNUSED (info))
{
error (G_("Cannot find %s in plugin %s\n%s"), str_plugin_init_func_name,
plugin->full_name, err);
- return 1;
+ return 0;
}
/* Call the plugin-provided initialization routine with the arguments. */
if ((*plugin_init) (plugin->base_name, plugin->argc, plugin->argv))
{
error (G_("Fail to initialize plugin %s"), plugin->full_name);
- return 1;
+ return 0;
}
- /* We can now delete the plugin_name_args object as it will no longer
- be used. Note that base_name and argv fields (both of which were also
- dynamically allocated) are not freed as they could still be used by
- the plugin code. */
- XDELETE (plugin);
+ return 1;
+}
+/* Routine to dlopen and initialize one plugin. This function is passed to
+ (and called by) the hash table traverse routine. Return 1 for the
+ htab_traverse to continue scan, 0 to stop.
+
+ SLOT - slot of the hash table element
+ INFO - auxiliary pointer handed to hash table traverse routine
+ (unused in this function) */
+
+static int
+init_one_plugin (void **slot, void * ARG_UNUSED (info))
+{
+ struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+ bool ok = try_init_one_plugin (plugin);
+ if (!ok)
+ {
+ htab_remove_elt (plugin_name_args_tab, plugin->base_name);
+ XDELETE (plugin);
+ }
return 1;
}
@@ -577,8 +595,50 @@ initialize_plugins (void)
/* Traverse and initialize each plugin specified in the command-line. */
htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
+}
+
+static int
+finalize_one_plugin (void **slot, void * ARG_UNUSED (info))
+{
+ struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+ XDELETE (plugin);
+ return 1;
+}
+
+void
+finalize_plugins(void)
+{
+ if (!plugin_name_args_tab)
+ return;
+
+ /* We can now delete the plugin_name_args object as it will no longer
+ be used. Note that base_name and argv fields (both of which were also
+ dynamically allocated) are not freed as they could still be used by
+ the plugin code. */
+
+ htab_traverse_noresize (plugin_name_args_tab, finalize_one_plugin, NULL);
/* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it. */
htab_delete (plugin_name_args_tab);
plugin_name_args_tab = NULL;
}
+
+static int
+print_one_plugin (void **slot, void * ARG_UNUSED (info))
+{
+ struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
+ const char *version = plugin->version ? plugin->version : "Unknown version.";
+
+ printf("%s: %s\n", plugin->base_name, version);
+ return 1;
+}
+
+void
+print_plugins_versions (void)
+{
+ if (!plugin_name_args_tab || htab_elements (plugin_name_args_tab) == 0)
+ return;
+
+ printf("Versions of loaded plugins:\n");
+ htab_traverse_noresize (plugin_name_args_tab, print_one_plugin, NULL);
+}
diff --git a/gcc/plugin.h b/gcc/plugin.h
index 95f0802..8c6ea02 100644
--- a/gcc/plugin.h
+++ b/gcc/plugin.h
@@ -30,5 +30,10 @@ extern void parse_plugin_arg_opt (const char *arg);
extern void invoke_plugin_callbacks (enum plugin_event event, void *gcc_data);
/* Main plugin initialization function. */
extern void initialize_plugins (void);
+/* Print the version of each plugin. */
+extern void print_plugins_versions (void);
+/* Free memory allocated by the plugin system. */
+extern void finalize_plugins(void);
+
#endif /* PLUGIN_H */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 63a6ddc..342aeb3 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -968,7 +968,6 @@ compile_file (void)
init_final (main_input_filename);
coverage_init (aux_base_name);
statistics_init ();
- initialize_plugins ();
timevar_push (TV_PARSE);
@@ -1163,6 +1162,8 @@ print_version (FILE *file, const char *indent)
file == stderr ? _(fmt4) : fmt4,
indent, *indent != 0 ? " " : "",
PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
+
+ print_plugins_versions();
}
#ifdef ASM_COMMENT_START
@@ -2270,6 +2271,11 @@ toplev_main (unsigned int argc, const char **argv)
init_local_tick ();
+ initialize_plugins();
+
+ if (version_flag)
+ print_version (stderr, "");
+
/* Exit early if we can (e.g. -help). */
if (!exit_after_options)
do_compile ();
@@ -2280,6 +2286,7 @@ toplev_main (unsigned int argc, const char **argv)
/* Invoke registered plugin callbacks if any. */
invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
+ finalize_plugins();
if (errorcount || sorrycount)
return (FATAL_EXIT_CODE);