On 3/16/2013 12:14 AM, Sean Silva wrote:
On Sat, Mar 16, 2013 at 12:32 AM, Joshua Cranmer <[email protected]
<mailto:[email protected]>> wrote:
On 3/15/2013 11:01 PM, Sean Silva wrote:
The clang driver already forks at least one process per compiler
invocation. Your comments apply equally to that and I don't see
anybody running to fix them (or even complaining), so I'm not
convinced that this is really as significant of an issue as you
make it out to be.
If I were to add a command in my Makefiles to spawn a $(shell),
the reviewers would throw a hissy fit. I'll also point out that
Clang is not a widely-used compilers on Windows systems, where
this kind of stuff matters more.
I'm not sure how I got derailed, but for the plugins there is no
"wrapper script", just `clang-plugin-config myPlugin.so arg1 arg2`
once at configure time. (the wrapper script would be for harvesting
the compile commands, but that's a separate discussion and I'm not
sure how it got brought into this one).
Also, you have to find more binaries to run it: if I specify
CXX via a path, how should a build system know where to run
clang-plugin-config from? You could guess by looking up the
dirname of CXX and hoping it's there,
I'm not sure I follow your point here. I image
clang-plugin-config and the wrapper to be installed next to clang
and be looked up/executed as usual.
but you are also advocating using shell scripts to represent
CXX in another email, which renders this approach impossible.
I also don't see the connection with my suggestion in the other
email. In fact, the wrapper script for plugins and the
compile_commands.json harvester could probably be the same
script, and at configure time clang-plugin-config (or, perhaps
better just `clang-config` now that it is going beyond plugins)
would arrange for the wrapper script to perform the requested
actions.
The logic I currently use to look up llvm-config for building the
plugin is as follows:
if test -z "$CXX"; then
CXX=`which clang++`
fi
if test -z "$LLVMCONFIG"; then
LLVMCONFIG=`which llvm-config`
fi
if test -z "$LLVMCONFIG"; then
LLVMCONFIG=`dirname $CXX`/llvm-config
fi
The ideas is to try to make this "just work" if the compiler to be
used is clang. However, if CXX is a shell script and clang is not
specifically in PATH (the latter case is not an esoteric
situation--it's how our own builders get to clang), then the value
returned is wrong. It's also wrong if people start using clang
with versioning numbers: consider clang symlinked to a clang-3.2,
but you're building with clang-3.3. Looking up llvm-config in the
path would find the llvm-config for 3.2 here instead of 3.3, which
would be wrong. IMHO, gcc's -print-file-name=plugin is much better
(you don't need to guess at the locations of other tools!).
Sorry I was confusing myself earlier. As I said before the
"clang-plugin-config" runs once at configure time. Let's keep the
discussion of the pros/cons of the wrapper script in the other thread.
If you really want to immediately push plugins forward in a
big way, it would be monumental to set up a buildbot that
runs a clang plugin that does extra checking that isn't
really appropriate for being integrated as a diagnostic into
the compiler proper. For example, a plugin that warns on
incorrect uses of dyn_cast<>. For maximum effect this should
be developed in-tree (probably in clang-tools-extra. Even
though it has "tools" in the name, I don't think anybody
would be opposed to developing plugins in there). It should
also have an easy way for people in our community to come up
with and implement good extra checks and get them integrated
into that buildbot.
I am working on adding a compiler static checker plugin to
Mozilla that would check the guarantees our old dehydra
plugin used to check: a "must override" annotation (all
subclasses must provide their own implementation of this
method), a "stack class" annotation (this class cannot be
allocated from the heap), and a warning that gets emitted
every time you emit a static initializer.
Awesome. Please keep us up to date with this work. Some of these
checks seem like they could be relevant to llvm/clang too.
The biggest stumbling block to implementing useful checkers is the
inability to add custom annotations... annotate(string) is
currently being used as a hack, but what is really needed is the
ability to specify custom C++11 attributes. Actually committing
the static checker can be found in
<https://bugzilla.mozilla.org/show_bug.cgi?id=767563>
<https://bugzilla.mozilla.org/show_bug.cgi?id=767563>, but there
is a long list of desired analyses here
<https://bugzilla.mozilla.org/buglist.cgi?list_id=6034150&resolution=---&query_format=advanced&component=Rewriting%20and%20Analysis&product=Core>
<https://bugzilla.mozilla.org/buglist.cgi?list_id=6034150&resolution=---&query_format=advanced&component=Rewriting%20and%20Analysis&product=Core>.
The changes in this patch retain almost all of the same
functionality as the original plugin approach (including
the ability to do things like add custom compile passes
via the RegisterPass statics) while wrapping it in a
much saner wrapper.
My opposition to the current patch is that it does not
provide enough value to our users to compensate for the
inconvenience that it will cause them (by breaking their
code). My opposition is not technical; I don't doubt that
your approach here is an improvement from a purely technical
standpoint.
The current plugin approach presumes that it is a pure
consumer of the AST, which isn't a viable option in my
opinion. One thing I would like to do in the future is be
able to map Decls in the AST to functions emitted in the LLVM
IR, which is completely impossible under the current
architecture. Note also that I'm not removing the current
(more or less broken) plugin architecture, so I'm not
compelling people to switch.
You did delete the only code (PrintFunctionNames) in tree that
AFAIK tests the previous functionality, which I interpreted as
meaning that it was dead to you.
The old API I consider deprecated, but deprecated does not mean
imminent removal. Also, the examples directory isn't built by
default, so I doubt it's actually really being tested.
Rather, this is about enabling future changes that permit
plugins to not take the view that they happen independently
of code generation.
This did not get through to me from the OP. Could you explain how
the design you implement in this patch achieves that? It should
be the emphasis of the review (and IMHO warrants a "does this
direction and implementation approach sound good to everyone"
cfe-dev discussion before proposing code to be committed).
If you pay careful attention, you'd notice that the plugins are
kept around in the CompilerInstance object, which is passed around
to all the AST actions, including the CodeGen AST action; the old
plugin API stores everything as separate AST actions and instead
multiplexes all the AST actions together, so the CodeGen AST
action is unaware of the existence of plugins, short of creating
Yet Another Static Initializer attachment point.
Is there any way we could fuse the old functionality into the new
functionality?
The present entry point is a fundamentally different registration
functionality from the new one, both in terms of how a plugin specifies
the entry point and in terms of how clang is invoked to load the
plugins--it's not possible to run them the same way and keep the same
semantics. It is possible to make #if-guarded wrappers to switch between
the two APIs for the plugin code in the common case however, but it's
not something that can automatically be done.
Also, the command line parsing stuff should be in a separate
patch, and IMO the -fplugin should be just a driver arg: that
way, the previous commandline args for plugins (directly via cc1)
remains in a live code path.
That isn't feasible here, as the two plugin loading paths are
actually doing rather different things, and I don't think it is
desirable to attempt to merge what are conceptually different
models of plugins.
As I said earlier, the compatibilty stuff also deserves a rehash,
since I'm still not convinced that it is really useful.
The primary purpose of compatibility checking is to detect a
situation that would almost certainly lead to crash instead of
crashing. Users deserve to get useful error messages instead of
panicking crash dumps.
It does nothing against subtle memory corruption, which is the real
issue. A crash is a *best-case scenario* and is not a priority to
protect against IMO. Blatant crashes are easy to catch and remedy.
Regardless, it is deceptive to have something like
DECLARE_PLUGIN_COMPATIBILITY() which still permits silent corruption
to happen, even though the user thinks they are "protected".
The only satisfactory solution that I can think of is to have a
special configure option that generates and embeds a unique ID
(sha1sum of all the headers?) for a specific build which guarantees
compatibility (it could be called ENABLE_PLUGINS, with the option
ENABLE_UNSAFE_PLUGINS available to imitate the current plugin
situation). ENABLE_PLUGINS not be on by default (presumably it would
have some impact on build time), but we could document that when
preparing binary packages of clang that clang should be built with
this flag.
That isn't a perfect solution: it does nothing against guaranteeing,
e.g., that clang and the plugin are using ABI-compatible standard
libraries. But if we hold new APIs hostage to perfect solutions, then
nothing will get added. What I want to protect against is what I believe
would be the most common mistake: someone will use a heuristic to figure
out which version of clang to compile against, and that heuristic will
be wrong. In such a scenario, the only case the current compatibility
would fail is if someone has a revision of clang installed to their path
but is using a different revision of clang (not in the path) from the
same branch to build--at which point I am happy to say "you're on the
bleeding edge, so you should expect to bleed every now and then".
--
Joshua Cranmer
News submodule owner
DXR coauthor
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits