[cfe-commits] [PATCH] Implement a better plugin API for clang

Tobias Grosser tobias at grosser.es
Thu Jun 21 05:17:56 PDT 2012


On 06/20/2012 11:58 PM, Joshua Cranmer wrote:
> diff --git a/docs/ClangPlugins.html b/docs/ClangPlugins.html
> --- a/docs/ClangPlugins.html
> +++ b/docs/ClangPlugins.html

Hi Joshua,

I am not a regular contributor to clang, but I am following the plugin 
infrastructure development and I must say I like the general direction. 
My use case are no frontend plugins, but a plugin to drive the Polly 
optimizer. What I would like clang to support is:

- Allow the insertion of linker flags such as '-lgmp' from a plugin
- Allow the insertion of '-mllvm -flag' style parameters to change the 
LLVM default behaviour.
- Shorter plugin parameters in the style of -<plugin-name>-<argument>. 
E.g. '-polly-vectorize'.

I know this is not the goal of this patch, but this gives the context 
from which I look at it. Now to the actual patch


> @@ -16,65 +16,79 @@
>   <p>Clang Plugins make it possible to run extra user defined actions during
>   a compilation. This document will provide a basic walkthrough of how to write
>   and run a Clang Plugin.</p>
>
>   <!-- ======================================================================= -->
>   <h2 id="intro">Introduction</h2>
>   <!-- ======================================================================= -->
>
> -<p>Clang Plugins run FrontendActions over code. See the
> -<a href="RAVFrontendAction.html">FrontendAction tutorial</a>  on how to write a
> -FrontendAction using the RecursiveASTVisitor. In this tutorial, we'll
> +<p>Clang Plugins run a set of callbacks over code. These callbacks are functions
> +that the plugin exports that the compiler uses over the course of compiling
> +code. These functions need not be implemented (except for clang_plugin_init). By
> +use of these hooks, compilers can affect or observer the course of compilation
> +by using several callbacks. The most important callback is the ASTConsumer
> +callback, which allows plugins to interact with the abstract syntax tree of
> +code. See the

This is still very frontend specific, but definitely an improvement.

>   <!-- ======================================================================= -->
> -<h2 id="pluginactions">Writing a PluginASTAction</h2>
> +<h2 id="init">Arguments and initialization</h2>
>   <!-- ======================================================================= -->
>
> -<p>The main difference from writing normal FrontendActions is that you can
> -handle plugin command line options. The
> -PluginASTAction base class declares a ParseArgs method which you have to
> -implement in your plugin.
> -</p>
> +<p>The first function called when a plugin is loaded is clang_plugin_init. This
> +function returns a boolean indicating whether or not the plugin can run on the
> +code. As arguments, this function is given the arguments of the plugin as well
> +as the version of clang being run. An example looks like this:</p>
>   <pre>
> -  bool ParseArgs(const CompilerInstance&CI,
> -                 const std::vector<std::string>& args) {
> -    for (unsigned i = 0, e = args.size(); i != e; ++i) {
> -      if (args[i] == "-some-arg") {
> -        // Handle the command line argument.
> +  bool clang_plugin_init(int argc, plugin::PluginArg *argv,
> +      plugin::Version *version) {
> +    // Check the version of clang
> +    if (version->major != CLANG_VERSION_MAJOR ||
> +        version->minor != CLANG_VERSION_MINOR)
> +      return false;
> +
> +    for (int i = 0; i< argc; ++i) {
> +      if (!strcmp(argv[i].name, "-some-arg")) {
> +        // Handle the command line argument
>         }

Like the runtime check for the plugin version. It is definitely a step 
forward. However, do you know what happens if some function names in 
clang changed and the plugin still references old function names? I 
suppose this will still give a linker error when loading the plugin. So 
even so this is going in the right direction, it may be nice to reason 
in future patches about a solution that gives a clear error message in 
that case.

>   <!-- ======================================================================= -->
> -<h2 id="registerplugin">Registering a plugin</h2>
> +<h2 id="callbacks">Setting callbacks</h2>
>   <!-- ======================================================================= -->
>
> -<p>A plugin is loaded from a dynamic library at runtime by the compiler. To register
> -a plugin in a library, use FrontendPluginRegistry::Add:</p>
> +<p>The most important plugin hook is the one that is called before each file is
> +compiled: clang_plugin_begin_file. This allows plugins to add their own custom
> +ASTConsumer (among other compiler hooks).</p>
>   <pre>
> -  static FrontendPluginRegistry::Add<MyPlugin>  X("my-plugin-name", "my plugin description");
> +  void clang_plugin_begin_file(llvm::StringRef fileName,
> +      const CompilerInstance&CI, plugin::PluginFileCallbacks *callbacks) {
> +    callbacks->astConsumer = new PrintFunctionsConsumer();
> +  }
>   </pre>

Sounds good. Do you think at it will be possible in later patches to add 
hooks to change the linker flags or the -mllvm flags?

>   <!-- ======================================================================= -->
>   <h2 id="running">Running the plugin</h2>
>   <!-- ======================================================================= -->
>
> -<p>To run a plugin, the dynamic library containing the plugin registry must be
> -loaded via the -load command line option. This will load all plugins that are
> -registered, and you can select the plugins to run by specifying the -plugin
> -option. Additional parameters for the plugins can be passed with -plugin-arg-<plugin-name>.</p>
> +<p>To run a plugin, you merely need to specify the plugin to be loaded using the
> +-fplugin command line options. Additional parameters for the plugins can be passed with -fplugin-arg-<plugin-name>-<arg>=<value>  or
> +-fplugin-arg<plugin-name>-<arg>. These options work the same when both run
> +with the normal driver and the cc1 process.</p>

Nice to see plugin arguments now also work with the normal driver!

That's it from me. Thanks Joshua for working on this!

Tobi




More information about the cfe-commits mailing list