This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[plugins] Merge with post-plugins trunk @146060
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc at gcc dot gnu dot org, Rafael Espindola <espindola at google dot com>, Le-Chun Wu <lcwu at google dot com>
- Date: Tue, 14 Apr 2009 23:21:32 -0400
- Subject: [plugins] Merge with post-plugins trunk @146060
This merge brings over all the changes I made when I committed
the plugin patches to mainline.
There are a few patches that still need to be moved from plugins, but
they are not too big. I will get to those later this week.
Tested on x86_64.
2009-04-14 Diego Novillo <dnovillo@google.com>
Merge with mainline @146060.
* configure.ac (ACX_PKGVERSION): Update.
* configure: Regenerate.
2009-04-14 Diego Novillo <dnovillo@google.com>
* gcc-plugin.h (enum plugin_event)<PLUGIN_FINISH_TYPE>: Rename
from PLUGIN_FINISH_STRUCT.
(plugin_event_name): Declare.
* plugin.c: Only include dlfcn.h if ENABLE_PLUGIN is set.
Do not include errors.h.
Include timevar.h.
Do not prefix strings in calls to error() with G_.
(plugin_event_name): Define.
(str_plugin_init_func_name): Only declare if ENABLE_PLUGIN is
set.
(invoke_plugin_callbacks): Call timevar_push/timevar_pop.
(try_init_one_plugin, init_one_plugin): Protect with
ENABLE_PLUGIN macro.
(initialize_plugins): Call timevar_push/timevar_pop.
(plugins_active_p): New.
(dump_active_plugins): New.
(debug_active_plugins): New.
* plugin.h: Tidy declarations.
(plugins_active_p): Declare.
(dump_active_plugins): Declare.
(debug_active_plugins): Declare.
testsuite/ChangeLog.plugins:
2009-04-14 Diego Novillo <dnovillo@google.com>
* gcc.dg/plugin/plugin.exp: Check for ENABLE_PLUGIN.
* g++.dg/plugin/plugin.exp: Likewise.
* g++.dg/plugin/dumb_plugin.c: Register PLUGIN_FINISH_TYPE.
Index: gcc-plugin.h
===================================================================
--- gcc-plugin.h (revision 146060)
+++ gcc-plugin.h (working copy)
@@ -20,10 +20,11 @@ along with GCC; see the file COPYING3.
#ifndef GCC_PLUGIN_H
#define GCC_PLUGIN_H
+/* Event names. Keep in sync with plugin_event_name[]. */
enum plugin_event
{
PLUGIN_PASS_MANAGER_SETUP, /* To hook into pass manager. */
- PLUGIN_FINISH_STRUCT, /* After finishing parsing a struct/class. */
+ PLUGIN_FINISH_TYPE, /* After finishing parsing a type. */
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. */
@@ -32,6 +33,8 @@ enum plugin_event
array. */
};
+extern const char *plugin_event_name[];
+
struct plugin_argument
{
char *key; /* key of the argument. */
Index: plugin.c
===================================================================
--- plugin.c (revision 146060)
+++ plugin.c (working copy)
@@ -18,21 +18,38 @@ along with GCC; see the file COPYING3.
<http://www.gnu.org/licenses/>. */
/* This file contains the support for GCC plugin mechanism based on the
- APIs described in the following wiki page:
-
- http://gcc.gnu.org/wiki/GCC_PluginAPI */
+ APIs described in doc/plugin.texi. */
-#include <dlfcn.h>
-#include <string.h>
#include "config.h"
#include "system.h"
+
+/* If plugin support is not enabled, do not try to execute any code
+ that may reference libdl. The generic code is still compiled in to
+ avoid including to many conditional compilation paths in the rest
+ of the compiler. */
+#ifdef ENABLE_PLUGIN
+#include <dlfcn.h>
+#endif
+
#include "coretypes.h"
-#include "errors.h"
#include "toplev.h"
#include "tree.h"
#include "tree-pass.h"
#include "intl.h"
#include "plugin.h"
+#include "timevar.h"
+
+/* Event names as strings. Keep in sync with enum plugin_event. */
+const char *plugin_event_name[] =
+{
+ "PLUGIN_PASS_MANAGER_SETUP",
+ "PLUGIN_FINISH_TYPE",
+ "PLUGIN_FINISH_UNIT",
+ "PLUGIN_CXX_CP_PRE_GENERICIZE",
+ "PLUGIN_FINISH",
+ "PLUGIN_INFO",
+ "PLUGIN_EVENT_LAST"
+};
/* Object that keeps track of the plugin name and its arguments
when parsing the command-line options -fplugin=/path/to/NAME.so and
@@ -78,10 +95,11 @@ struct pass_list_node
static struct pass_list_node *added_pass_nodes = NULL;
static struct pass_list_node *prev_added_pass_node;
+#ifdef ENABLE_PLUGIN
/* Each plugin should define an initialization function with exactly
this name. */
static const char *str_plugin_init_func_name = "plugin_init";
-
+#endif
/* Helper function for the hash table that compares the base_name of the
existing entry (S1) with the given string (S2). */
@@ -93,6 +111,7 @@ htab_str_eq (const void *s1, const void
return !strcmp (plugin->base_name, (const char *) s2);
}
+
/* Given a plugin's full-path name FULL_NAME, e.g. /pass/to/NAME.so,
return NAME. */
@@ -108,6 +127,7 @@ get_plugin_base_name (const char *full_n
return base_name;
}
+
/* Create a plugin_name_args object for the give plugin and insert it to
the hash table. This function is called when -fplugin=/path/to/NAME.so
option is processed. */
@@ -134,7 +154,7 @@ add_new_plugin (const char* plugin_name)
{
plugin = (struct plugin_name_args *) *slot;
if (strcmp (plugin->full_name, plugin_name))
- error (G_("Plugin %s was specified with different paths:\n%s\n%s"),
+ error ("Plugin %s was specified with different paths:\n%s\n%s",
plugin->base_name, plugin->full_name, plugin_name);
return;
}
@@ -146,6 +166,7 @@ add_new_plugin (const char* plugin_name)
*slot = plugin;
}
+
/* Parse the -fplugin-arg-<name>-<key>[=<value>] option and create a
'plugin_argument' object for the parsed key-value pair. ARG is
the <name>-<key>[=<value>] part of the option. */
@@ -179,8 +200,8 @@ parse_plugin_arg_opt (const char *arg)
{
if (key_parsed)
{
- error (G_("Malformed option -fplugin-arg-%s"
- " (multiple '=' signs)"), arg);
+ error ("Malformed option -fplugin-arg-%s (multiple '=' signs)",
+ arg);
return;
}
key_len = len;
@@ -195,7 +216,7 @@ parse_plugin_arg_opt (const char *arg)
if (!key_start)
{
- error (G_("Malformed option -fplugin-arg-%s (missing -<key>[=<value>])"),
+ error ("Malformed option -fplugin-arg-%s (missing -<key>[=<value>])",
arg);
return;
}
@@ -257,13 +278,14 @@ parse_plugin_arg_opt (const char *arg)
plugin->argv[plugin->argc - 1].value = value;
}
else
- error (G_("Plugin %s should be specified before -fplugin-arg-%s"
- " in the command line"), name, arg);
+ error ("Plugin %s should be specified before -fplugin-arg-%s "
+ "in the command line", name, arg);
/* We don't need the plugin's name anymore. Just release it. */
XDELETEVEC (name);
}
+
/* Insert the plugin pass at the proper position. Return true if the pass
is successfully added.
@@ -337,7 +359,7 @@ position_pass (struct plugin_pass *plugi
pass = new_pass;
break;
default:
- error (G_("Invalid pass positioning operation"));
+ error ("Invalid pass positioning operation");
return false;
}
@@ -364,6 +386,7 @@ position_pass (struct plugin_pass *plugi
return success;
}
+
/* Hook into the pass lists (trees) a new pass registered by a plugin.
PLUGIN_NAME - display name for the plugin
@@ -376,15 +399,15 @@ register_pass (const char *plugin_name,
{
if (!pass_info->pass)
{
- error (G_("No pass specified when registering a new pass in plugin %s"),
+ error ("No pass specified when registering a new pass in plugin %s",
plugin_name);
return;
}
if (!pass_info->reference_pass_name)
{
- error (G_("No reference pass specified for positioning the pass"
- " from plugin %s"), plugin_name);
+ error ("No reference pass specified for positioning the pass "
+ " from plugin %s", plugin_name);
return;
}
@@ -393,8 +416,8 @@ register_pass (const char *plugin_name,
if (!position_pass (pass_info, &all_lowering_passes)
&& !position_pass (pass_info, &all_ipa_passes)
&& !position_pass (pass_info, &all_passes))
- error (G_("Failed to position pass %s registered by plugin %s."
- " Cannot find the (specified instance of) reference pass %s"),
+ error ("Failed to position pass %s registered by plugin %s. "
+ "Cannot find the (specified instance of) reference pass %s",
pass_info->pass->name, plugin_name, pass_info->reference_pass_name);
else
{
@@ -429,6 +452,7 @@ register_pass (const char *plugin_name,
}
}
+
/* Register additional plugin information. */
static void
@@ -462,7 +486,7 @@ register_callback (const char *plugin_na
case PLUGIN_INFO:
register_plugin_info (plugin_name, (struct plugin_info *) user_data);
break;
- case PLUGIN_FINISH_STRUCT:
+ case PLUGIN_FINISH_TYPE:
case PLUGIN_FINISH_UNIT:
case PLUGIN_CXX_CP_PRE_GENERICIZE:
case PLUGIN_FINISH:
@@ -470,8 +494,8 @@ register_callback (const char *plugin_na
struct callback_info *new_callback;
if (!callback)
{
- error (G_("Plugin %s registered a null callback function"),
- plugin_name);
+ error ("Plugin %s registered a null callback function "
+ "for event %s", plugin_name, plugin_event_name[event]);
return;
}
new_callback = XNEW (struct callback_info);
@@ -484,11 +508,12 @@ register_callback (const char *plugin_na
break;
case PLUGIN_EVENT_LAST:
default:
- error (G_("Unkown callback event registered by plugin %s"),
+ error ("Unkown callback event registered by plugin %s",
plugin_name);
}
}
+
/* Called from inside GCC. Invoke all plug-in callbacks registered with
the specified event.
@@ -498,9 +523,11 @@ register_callback (const char *plugin_na
void
invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
{
+ timevar_push (TV_PLUGIN_RUN);
+
switch (event)
{
- case PLUGIN_FINISH_STRUCT:
+ case PLUGIN_FINISH_TYPE:
case PLUGIN_FINISH_UNIT:
case PLUGIN_CXX_CP_PRE_GENERICIZE:
case PLUGIN_FINISH:
@@ -512,13 +539,17 @@ invoke_plugin_callbacks (enum plugin_eve
(*callback->func) (gcc_data, callback->user_data);
}
break;
+
case PLUGIN_PASS_MANAGER_SETUP:
case PLUGIN_EVENT_LAST:
default:
gcc_assert (false);
}
+
+ timevar_pop (TV_PLUGIN_RUN);
}
+#ifdef ENABLE_PLUGIN
/* We need a union to cast dlsym return value to a function pointer
as ISO C forbids assignment between function pointer and 'void *'.
Use explicit union instead of __extension__(<union_cast>) for
@@ -538,8 +569,8 @@ try_init_one_plugin (struct plugin_name_
dl_handle = dlopen (plugin->full_name, RTLD_NOW);
if (!dl_handle)
{
- error (G_("Cannot load plugin %s\n%s"), plugin->full_name, dlerror ());
- return 0;
+ error ("Cannot load plugin %s\n%s", plugin->full_name, dlerror ());
+ return false;
}
/* Clear any existing error. */
@@ -551,21 +582,22 @@ try_init_one_plugin (struct plugin_name_
if ((err = dlerror ()) != NULL)
{
- error (G_("Cannot find %s in plugin %s\n%s"), str_plugin_init_func_name,
+ error ("Cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
plugin->full_name, err);
- return 0;
+ return false;
}
/* 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 0;
+ error ("Fail to initialize plugin %s", plugin->full_name);
+ return false;
}
- return 1;
+ return true;
}
+
/* 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.
@@ -587,7 +619,9 @@ init_one_plugin (void **slot, void * ARG
return 1;
}
-/* Main plugin initialization function. Called from compiler_file() in
+#endif /* ENABLE_PLUGIN */
+
+/* Main plugin initialization function. Called from compile_file() in
toplev.c. */
void
@@ -596,9 +630,15 @@ initialize_plugins (void)
/* If no plugin was specified in the command-line, simply return. */
if (!plugin_name_args_tab)
return;
+
+ timevar_push (TV_PLUGIN_INIT);
+#ifdef ENABLE_PLUGIN
/* Traverse and initialize each plugin specified in the command-line. */
htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
+#endif
+
+ timevar_pop (TV_PLUGIN_INIT);
}
/* Release memory used by one plugin. */
@@ -709,3 +749,54 @@ print_plugins_help (FILE *file, const ch
fprintf (file, "%sHelp for the loaded plugins:\n", indent);
htab_traverse_noresize (plugin_name_args_tab, print_help_one_plugin, &opt);
}
+
+
+/* Return true if plugins have been loaded. */
+
+bool
+plugins_active_p (void)
+{
+ enum plugin_event event;
+
+ for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+ if (plugin_callbacks[event])
+ return true;
+
+ return false;
+}
+
+
+/* Dump to FILE the names and associated events for all the active
+ plugins. */
+
+void
+dump_active_plugins (FILE *file)
+{
+ enum plugin_event event;
+
+ if (!plugins_active_p ())
+ return;
+
+ fprintf (stderr, "Event\t\tPlugins\n");
+ for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
+ if (plugin_callbacks[event])
+ {
+ struct callback_info *ci;
+
+ fprintf (file, "%s\t", plugin_event_name[event]);
+
+ for (ci = plugin_callbacks[event]; ci; ci = ci->next)
+ fprintf (file, "%s ", ci->plugin_name);
+
+ fprintf (file, "\n");
+ }
+}
+
+
+/* Dump active plugins to stderr. */
+
+void
+debug_active_plugins (void)
+{
+ dump_active_plugins (stderr);
+}
Index: plugin.h
===================================================================
--- plugin.h (revision 146060)
+++ plugin.h (working copy)
@@ -22,20 +22,15 @@ along with GCC; see the file COPYING3.
#include "gcc-plugin.h"
-/* Called when -fplugin=/path/to/NAME.so option is parsed. */
-extern void add_new_plugin (const char* plugin_name);
-/* Parse the -fplugin-arg-<name>-<key>[=<value>] option. */
-extern void parse_plugin_arg_opt (const char *arg);
-/* Invoke all plug-in callbacks registered with the specified event. */
-extern void invoke_plugin_callbacks (enum plugin_event event, void *gcc_data);
-/* Main plugin initialization function. */
+extern void add_new_plugin (const char *);
+extern void parse_plugin_arg_opt (const char *);
+extern void invoke_plugin_callbacks (enum plugin_event, void *);
extern void initialize_plugins (void);
-/* Print the version of each plugin. */
+extern bool plugins_active_p (void);
+extern void dump_active_plugins (FILE *);
+extern void debug_active_plugins (void);
extern void print_plugins_versions (FILE *file, const char *indent);
-/* Print help for each plugin. */
extern void print_plugins_help (FILE *file, const char *indent);
-/* Free memory allocated by the plugin system. */
extern void finalize_plugins (void);
-
#endif /* PLUGIN_H */
Index: testsuite/gcc.dg/plugin/plugin.exp
===================================================================
--- testsuite/gcc.dg/plugin/plugin.exp (revision 146060)
+++ testsuite/gcc.dg/plugin/plugin.exp (working copy)
@@ -20,10 +20,11 @@ load_lib target-supports.exp
load_lib gcc-dg.exp
global TESTING_IN_BUILD_TREE
+global ENABLE_PLUGIN
# The plugin testcases currently only work when the build tree is available.
# Also check whether the host supports plugins.
-if { ![info exists TESTING_IN_BUILD_TREE] || ![check_plugin_available] } {
+if { ![info exists TESTING_IN_BUILD_TREE] || ![info exists ENABLE_PLUGIN] } {
return
}
Index: testsuite/g++.dg/plugin/dumb_plugin.c
===================================================================
--- testsuite/g++.dg/plugin/dumb_plugin.c (revision 146060)
+++ testsuite/g++.dg/plugin/dumb_plugin.c (working copy)
@@ -123,7 +123,7 @@ plugin_init (const char *plugin_name, in
register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
- register_callback (plugin_name, PLUGIN_FINISH_STRUCT, handle_struct, NULL);
+ register_callback (plugin_name, PLUGIN_FINISH_TYPE, handle_struct, NULL);
register_callback (plugin_name, PLUGIN_CXX_CP_PRE_GENERICIZE,
handle_pre_generic, NULL);
Index: testsuite/g++.dg/plugin/plugin.exp
===================================================================
--- testsuite/g++.dg/plugin/plugin.exp (revision 146060)
+++ testsuite/g++.dg/plugin/plugin.exp (working copy)
@@ -20,10 +20,11 @@ load_lib target-supports.exp
load_lib g++-dg.exp
global TESTING_IN_BUILD_TREE
+global ENABLE_PLUGIN
# The plugin testcases currently only work when the build tree is available.
# Also check whether the host supports plugins.
-if { ![info exists TESTING_IN_BUILD_TREE] || ![check_plugin_available] } {
+if { ![info exists TESTING_IN_BUILD_TREE] || ![info exists ENABLE_PLUGIN] } {
return
}
Index: testsuite/lib/plugin-support.exp
===================================================================
--- testsuite/lib/plugin-support.exp (revision 146060)
+++ testsuite/lib/plugin-support.exp (working copy)
@@ -62,7 +62,7 @@ proc plugin-get-options { src } {
proc plugin-test-execute { plugin_src plugin_tests } {
global srcdir objdir
global verbose
- global HOSTCC HOSTCFLAGS
+ global GMPINC
set basename [file tail $plugin_src]
set base [file rootname $basename]
@@ -70,10 +70,7 @@ proc plugin-test-execute { plugin_src pl
verbose "Test the plugin $basename" 1
- #
# Build the plugin itself
- #
-
set extra_flags [plugin-get-options $plugin_src]
# Note that the plugin test support currently only works when the GCC
@@ -85,30 +82,21 @@ proc plugin-test-execute { plugin_src pl
set gcc_objdir "$objdir/../../.."
set includes "-I. -I${srcdir} -I${gcc_srcdir}/gcc -I${gcc_objdir}/gcc \
-I${gcc_srcdir}/include -I${gcc_srcdir}/libcpp/include \
- -I${gcc_objdir}/gmp"
-
- set optstr "$includes $extra_flags -DIN_GCC -shared -fPIC"
- set compline "$optstr $plugin_src -o $plugin_lib"
+ -I$GMPINC"
- set status [remote_exec build "$HOSTCC $HOSTCFLAGS $compline"]
- set status [lindex $status 0]
+ set optstr "$includes $extra_flags -DIN_GCC -fPIC -shared"
- if { $status != 0 } {
+ set status [target_compile "$optstr $plugin_src" "$plugin_lib"
executable ""]
+ if { "$status" != "" } {
unresolved "$basename compilation, $optstr"
return
}
- #
# Compile the input source files with the plugin
- #
-
global default_flags
set plugin_enabling_flags "-fplugin=./$plugin_lib"
dg-runtest $plugin_tests $plugin_enabling_flags $default_flags
- #
# Clean up
- #
-
remote_file build delete $plugin_lib
}