[PATCH] Implement a sane plugin API for clang

Joshua Cranmer pidgeot18 at gmail.com
Sun May 5 22:19:18 PDT 2013


On 5/3/2013 6:18 PM, Jordan Rose wrote:
>>> We really ought to have a preliminary discussion on cfe-dev to map 
>>> out the directions we want to take the plugin API, and what 
>>> *compelling*, *enabling* changes we can make to it.
>
> While I mostly like what you've come up with, Sean has a point that 
> the community hasn't really picked it up. I have your e-mail from a 
> year ago still flagged ("[cfe-dev] Thinking about clang plugins"). No 
> one responded to it then, but I think it was a good summary of the 
> problems you were/are trying to solve. I would say to bring that up 
> again...except most likely nothing will happen until after the 3.3 
> release (and for us Apple folks, after WWDC).

I had originally wanted to get this patch into the 3.1 release. That 
nothing can come before 3.3 is... disheartening, to say the least.
>> +Clang Plugins run a set of callbacks over code. These callbacks are 
>> set up by
>> +the plugin when the compiler calls a function exported by the 
>> plugin. The main
>> +function exported by the plugin is clang_plugin_begin_tu, which is 
>> called before
>> +any file is compiled.
>
> s/any/each/, I think. Is there a separate callback that is guaranteed 
> to only be called once, or at least once per CompilerInstance?

If you call clang a.cpp b.cpp, the last time I checked, this spawns two 
clang -cc1 processes. Since the plugin is loaded in the clang -cc1 
process, it gets loaded twice, so call-per-invocation is effectively 
equivalent to call-per-translation unit. My original implementation had 
a call-per-invocation callback, but I removed it after discovering this 
fact since its effect were misleading.

>> +/// A struct containing sufficient information to express ABI 
>> compatibility for
>> +/// plugins. It is sufficient for plugins to use the
>> +/// DECLARE_PLUGIN_COMPATIBILITY macro to find compatibility.
>> +struct Version {
>> +  /// The major version of clang (corresponds to CLANG_VERSION_MAJOR)
>> +  unsigned Major;
>> +  /// The minor version of clang (corresponds to CLANG_VERSION_MINOR)
>> +  unsigned Minor;
>> +};
>
> VersionTuple is a bit overkill here, but do we really need another 
> version struct?

My main rationale for making a new version struct was that this would be 
effectively ABI-frozen. Since the version code is used to decide whether 
or not to attempt to use the plugin, an ABI-mismatch is particularly 
deadly for the compiler in this code.

>> All non-null callbacks will be deleted by the compiler internally.
>
> "On return, the compiler takes ownership of any non-null callbacks."
>
> ...although I'm not sure this is a good idea. Why not reuse the same 
> callbacks over multiple TUs?

As mentioned earlier, in practice, a single invocation gets called for a 
single TU.
>> +    /// Arguments to the plugin
>> +    SmallVector<std::pair<std::string, std::string>, 4> Args;
>
> Should this just be a std::vector? I think the most common case will 
> be 0 args, in which case SmallVector doesn't do much good.

I originally had this as a std::vector, and was told to make it a 
SmallVector instead.

> ...any reason not to do this with a map, to avoid N iterations over 
> the arguments?

There is likely to be very few arguments and plugins in use for a given 
invocation; with such small numbers, the extra overhead of a map isn't 
worth it.

-- 
Joshua Cranmer
News submodule owner
DXR coauthor

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130506/5b900b63/attachment.html>


More information about the cfe-commits mailing list