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:

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:

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:

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

Features to Avoid

None: GCC_PluginAPI (last edited 2009-07-16 14:13:41 by dslb-092-077-219-033)