[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