-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Opt] Enable statically-linked plugin support #79227
base: main
Are you sure you want to change the base?
Conversation
Let me see if I understand your constraints correctly:
If making the "opt" tool a library is actually helpful, I guess I'm not really against it... but please add a proper entry-point instead of abusing dlsym(). |
What would you propose in the alternate? I can only otherwise think of adding a global variable, like in the earliest revisions of #70171 . |
Rename main() to OptDriverMain(), add a new file opt-executable.cpp that's a wrapper around it. Add whatever parameters you need to OptDriverMain(). Alternatively, adding a global variable to opt.cpp isn't that terrible. We want to avoid global variables in core libraries so we don't have issues with shared state, but I wouldn't expect opt-driver to be used in that sort of context. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
@efriedma-quic this now does the new file with wrapper, with tests, as discussed. Mind reviewing? |
if this is just to be used in non-core tools, I'd prefer a that seems much simpler than this PR + #79205 |
I'm not sure I understand what you're getting at with the reference to #79205 . Most of the decisions there were constrained by producing something that actually builds correctly in all configurations. The goal is to allow users to build an "opt-with-a-plugin" without rebuilding LLVM. So we put the logic of opt into a library. We have to be able to build that library as a shared library for -DBUILD_SHARED_LIBS builds, so that library can't contain the definition of main(). So in sum, we need to have a library that contains all the logic, and exposes optMain() to call that logic. We could remove the parameter from optMain, and use a global variable instead, but that doesn't really simplify anything. |
I vaguely remember the end result of the clang patch being that internally we cloned the build target for clang but with an extra dependency on a file that registered a clang plugin via a static constructor. If we did the same thing here, we wouldn't need these patches. I may be misremembering though. @wsmoses am I misunderstanding? |
The clang version of this only supported Bazel builds, not CMake builds, so it didn't have to worry about -DBUILD_SHARED_LIBS. (I didn't realize this at the time because the patch didn't actually touch those bits.) |
So the way the clang one worked, was as follows: Bazel's build for clang already separated all of the clang driver libraries into a separate
For our custom clang, we simply linked the clang-driver against whatever plugin we wanted. Doing the same for opt has two issues:
Originally the first Bazel PR (#79205) was a 2-line bazel patch which added a similar opt-driver library target in Bazel, like there exists already for clang. Code review requested that if this was going to happen, one should also make a library for the opt driver in CMake as well. Unfortunately making such a library in CMake is a non-trivial task, if one wants to permit all build targets (e.g. shared libs, etc), which obviously we need to support. Specifically, it required creating a separate opt.cpp file which just contains main, as distinct from the actual opt functionality. This was required to make shared library linkage work (among other minor things, like not linking the new lib into libLLVM, etc). Since the goal was to support additional plugins, we went ahead and just added the vector of callbacks to the optMain function in the new library. We could also support a registry, and remove the vector of callbacks to optMain. However, the need for the separate opt.cpp with just main for each executable variant [e.g. actual opt, this test plugin opt], is required for CMake + build variants. In light of that I'd say the two most reasonable design decisions are to either:
--
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the explanation
I took a look at the llvm driver code and it seems pretty similar to this, so I'm ok with this now
perhaps this might conflict with the llvm driver stuff if we ever decide to add opt
to it, but we can cross that bridge when we get there (e.g. expose a global variable in opt-driver)
; REQUIRES: x86-registered-target | ||
; RUN: opt-printplugin %s -passes="printpass" -disable-output 2>&1 | FileCheck %s | ||
|
||
; REQUIRES: plugins |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this actually requires plugins, that's only necessary for shared library plugins IIUC
@@ -0,0 +1,8 @@ | |||
add_llvm_tool(opt-printplugin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make this add_llvm_example
? then test will need REQUIRES: examples
STATIC | ||
NewPMDriver.cpp | ||
optdriver.cpp | ||
PARTIAL_SOURCES_INTENDED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't need PARTIAL_SOURCES_INTENDED
anymore
SUPPORT_PLUGINS | ||
) | ||
target_link_libraries(opt-printplugin PRIVATE LLVMOptDriver) | ||
export_executable_symbols_for_plugins(opt-printplugin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this for an example/test binary?
@@ -0,0 +1,67 @@ | |||
//===- opt-printplugin.cpp - The LLVM Modular Optimizer | |||
//-------------------------------===// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatting
|
||
} // namespace | ||
|
||
extern "C" int optMain(int argc, char **argv, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optMain()
shouldn't be extern "C"
since it uses C++ classes. this mirrors the llvm driver support, e.g. llvm/cmake/modules/llvm-driver-template.cpp.in
@@ -0,0 +1,9 @@ | |||
# We don't want to link this into libLLVM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for my understanding, how do we tell the build system not to link this into libLLVM?
target_link_libraries(opt PRIVATE LLVMOptDriver) | ||
|
||
export_executable_symbols_for_plugins(opt) | ||
add_subdirectory(lib) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(can't comment above due to github limitations) should LLVM_LINK_COMPONENTS
go down to llvm/tools/opt/lib/CMakeLists.txt
?
"specified (JSON) file (should be abs path as we use" | ||
" append mode to insert new JSON objects)"), | ||
cl::value_desc("filename"), cl::init("")); | ||
cl::opt<std::string> VerifyDIPreserveExport( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you commit the formatting changes ahead of time
Companion PR to #70171 except now for opt rather than clang.
This PR enables using custom passes in plugins, when statically linked against opt.
See #79205 for a standalone bazel PR needed for this to be used in a different build system.