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 <dnovi...@google.com> Merge with mainline @146060. * configure.ac (ACX_PKGVERSION): Update. * configure: Regenerate. 2009-04-14 Diego Novillo <dnovi...@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 <dnovi...@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 }