GCC Plugin API
Goal
Provide a unified API based on practical needs of existing plugin efforts:
as discussed at the GCC Summit '08, and the GCC plug-in interface published at GCC Summit '07.
Some more recent mailing discussions include:
libiberty should be a shared library when cc1 has plugin enabled. (07/2009)
plugins & PCH (07/2009)
preprocessors & GCC plugins (07/2009)
Questions on exported plugin headers: minimal or full? (06/2009)
plugins directory (06/2009)
gengtype and plugins (06/2009) It may be possible to have a plugin using gengtype without the source tree.
GSoC (plugins) (ici) function cloning + fine-grain optimizations/program instrumentation
plugin callbacks after compiler errors (06/2009)
New Interactive Compilation Interface (ICI) v2.0 has been released (06/2009)
LLVM as a gcc plugin? (06/2009)
"plugin"-ifying the MELT branch. (06/2009)
plugins callbacks and data (05/2009)
Finding gcc plugin headers (05/2009)
Related wiki pages are:
More info on the development branch can be found here, you can view the branch using a browser here.
Related patches that were posted to the gcc mailing lists include:
enhancing gengtype for plugins? (06/2009)
[plugins] [patch] allows to see AST in C (03/2009)
Loading Plug-ins
Linking GCC with -ld -rdynamic on supported platforms. Plugins are to be loaded by specifying with
-fplugin=/path/to/NAME.so -fplugin-arg-NAME-<key1>[=<value1>] -fplugin-arg-NAME-<key2>[=<value2>]
The plugin arguments are parsed by GCC and passed to respective plugins as key-value pairs. Multiple plugins can be invoked by specifying multiple -fplugin arguments.
All of GCC functions should be exposed to plugins, it does not make sense to export a subset of the API. Additionally, plugins should not require freezing any GCC APIs.
Event Callbacks
Typically GCC mutates data structures in place and frees them as soon as possible. In order to allow plugins to access short-lived data, a callback system should be used. This way the plugin can make note of important data for later use.
The callback system should satisfy the following requirements:
- It is useful to be able to invoke plugins at certain key points during GCC execution, for example: before gimplification, within pass manager, after compilation.
- There should be a simple way of identifying hooks.
- There should be a simple way to register functions in the plugin as hooks.
- Some plugins are not aware of which hooks they require at compile-time, so it should be possible to register different functions at run-time.
The current C API is as follows:
1 enum plugin_event {
2 PLUGIN_PASS_MANAGER_SETUP, // to hook into pass manager
3 PLUGIN_FINISH_STRUCT,
4 PLUGIN_FINISH_UNIT, // useful for summary processing
5 PLUGIN_CXX_CP_PRE_GENERICIZE, // allows to see low level AST in C++ FE
6 PLUGIN_FINISH, // called before GCC exits
7 ...
8 };
9
10 // The prototype for a plugin callback function.
11 // gcc_data - event-specific data provided by GCC
12 // user_data - plugin-specific data provided by the plug-in
13 typedef void (*plugin_callback_func)(void *gcc_data,
14 void *user_data);
15
16 struct callback_registration {
17 char* name; // display name for this plug-in
18 enum plugin_event event; // which event the callback is for
19 plugin_callback_func callback; // the callback to be called at the event
20 void* user_data; // user-specified data passed in user_data
21 };
22
23 // Called from inside GCC. Invokes all plug-in callbacks compatible with an event.
24 // id - the event identifier. There should be exactly one for each call.
25 // gcc_data - event-specific data provided by the compiler
26 void invoke_plugin_callbacks(enum plugin_event id,
27 void *gcc_data);
28
29 // Called from the plugin's initialization code. Registers a number of callbacks.
30 // This function can be called multiple times.
31 // nregistrations - the size of the registrations array
32 // registrations - an array of registrations
33 void register_callbacks(int nregistrations,
34 struct callback_registration *registrations);
35
36 // A wrapper for the above that registers one callback.
37 // All parameters are as described for struct plugin_registration.
38 void register_callback(char* name,
39 enum plugin_event event,
40 plugin_callback_func callback,
41 void* user_data);
42
43 struct plugin_argument {
44 char *key;
45 char *value;
46 };
47
48 // The prototype for a module initialization function. Each module should define this
49 // as an externally-visible function with name "plugin_init."
50 // plugin_name - name of the plugin (useful for error reporting)
51 // argc - the size of the argv array
52 // argv - an array of key-value pairs
53 // Returns 0 if initialization finishes successfully.
54 typedef int (*plugin_init_func)(const char *plugin_name, int argc, struct plugin_argument *argv);
Pass Manager
There needs to be a way to add/reorder/remove passes dynamically. This is useful for both analysis plugins (plugging in after a certain pass such as CFG or an IPA pass) and optimization plugins such as MELT or MILEPOST/ICI.
So far Mozilla's, MELT's and ICI plugin efforts have relied on passes having unique names such that one can insert custom passes before or after a certain pass, etc. Currently this isn't enforced in GCC.
In the initial implementation of the plugin mechanism (see the branch status here), basic support for inserting new passes or replacing existing passes is provided. A plugin registers a new pass with GCC by calling register_callback() (mentioned above) with the PLUGIN_PASS_MANAGER_SETUP event and a pointer to a struct plugin_pass object as defined below:
1 enum pass_positioning_ops
2 {
3 PASS_POS_INSERT_AFTER, // Insert after the reference pass.
4 PASS_POS_INSERT_BEFORE, // Insert before the reference pass.
5 PASS_POS_REPLACE // Replace the reference pass.
6 };
7
8 struct plugin_pass
9 {
10 struct opt_pass *pass; // New pass provided by the plugin.
11 const char *reference_pass_name; // Name of the reference pass for hooking
12 // up the new pass.
13 int ref_pass_instance_number; // Insert the pass at the specified
14 // instance number of the reference pass.
15 // Do it for every instance if it is 0.
16 enum pass_positioning_ops pos_op; // how to insert the new pass.
17 };
18
19
20 // Sample plugin code that registers a new pass
21 int
22 plugin_init (const char *plugin_name, int argc, struct plugin_argument *argv)
23 {
24 struct plugin_pass pass_info;
25
26 ...
27
28 // Code to fill in the pass_info object with new pass information
29
30 ...
31
32 // Register the new pass
33 register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
34
35 ...
36 }
Nice to Have
GTY as attribute support is useful for reflecting GCC data structures
The *_as_string functions in C++ FE are very useful. It would be great to have those improved and extended to support more pretty printing.
API for verifying compatibility (exporting the required GCC version, target triplet and anything else likely to affect compatibility) and for --version and --help information so people can use those options together with -fplugin to get the plugin's version number and bug-reporting information
user() GCC attribute
- [Basile Starynkevitch] thinks that plugins could add specific attributes and pragmas.
- an API for storing trees across multiple functions, such as an alternate GC root for plugins.
- an API for extracting major, minor, etc. numbers from version_string so that plug-ins can quickly check for compatibility.
- GCC should include names of the loaded plugins in --version string
ability to force running cc1 or cc1plus even without any input source files. Perhaps a -force-cc1 or -force-cc1plus (or spell it -fforce-cc1 with two f) option?
Features to Avoid
- Loading plugins using environment variables instead of GCC command-line switches. Same effect can be accomplished with shell script wrappers for the compiler that modify the command-line.
- Mutual plugin dependencies (?)