[llvm] r329293 - Re-land r329273: [Plugins] Add a slim plugin API to work together with the new PM
Philip Pfaffe via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 5 08:04:13 PDT 2018
Author: pfaffe
Date: Thu Apr 5 08:04:13 2018
New Revision: 329293
URL: http://llvm.org/viewvc/llvm-project?rev=329293&view=rev
Log:
Re-land r329273: [Plugins] Add a slim plugin API to work together with the new PM
Fix unittest: Do not link LLVM into the test plugin.
Additionally, remove an unrelated change that slipped in in r329273.
Added:
llvm/trunk/include/llvm/Passes/PassPlugin.h
llvm/trunk/lib/Passes/PassPlugin.cpp
llvm/trunk/unittests/Passes/CMakeLists.txt
llvm/trunk/unittests/Passes/PluginsTest.cpp
llvm/trunk/unittests/Passes/TestPlugin.cxx
llvm/trunk/unittests/Passes/TestPlugin.h
Modified:
llvm/trunk/include/llvm/Demangle/Compiler.h
llvm/trunk/lib/Passes/CMakeLists.txt
llvm/trunk/tools/opt/NewPMDriver.cpp
llvm/trunk/unittests/CMakeLists.txt
Modified: llvm/trunk/include/llvm/Demangle/Compiler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Demangle/Compiler.h?rev=329293&r1=329292&r2=329293&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Demangle/Compiler.h (original)
+++ llvm/trunk/include/llvm/Demangle/Compiler.h Thu Apr 5 08:04:13 2018
@@ -503,4 +503,22 @@ void AnnotateIgnoreWritesEnd(const char
#define LLVM_ENABLE_EXCEPTIONS 1
#endif
+/// \macro LLVM_PLUGIN_IMPORT
+/// \brief Used to import the well-known entry point for registering loaded pass
+/// plugins
+#ifdef WIN32
+#define LLVM_PLUGIN_IMPORT __declspec(dllimport)
+#else
+#define LLVM_PLUGIN_IMPORT
+#endif
+
+/// \macro LLVM_PLUGIN_EXPORT
+/// \brief Used to export the well-known entry point for registering loaded pass
+/// plugins
+#ifdef WIN32
+#define LLVM_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define LLVM_PLUGIN_EXPORT
+#endif
+
#endif
Added: llvm/trunk/include/llvm/Passes/PassPlugin.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Passes/PassPlugin.h?rev=329293&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Passes/PassPlugin.h (added)
+++ llvm/trunk/include/llvm/Passes/PassPlugin.h Thu Apr 5 08:04:13 2018
@@ -0,0 +1,114 @@
+//===- llvm/Passes/PassPlugin.h - Public Plugin API -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines the public entry point for new-PM pass plugins.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PASSES_PASSPLUGIN_H
+#define LLVM_PASSES_PASSPLUGIN_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <string>
+
+namespace llvm {
+class PassBuilder;
+
+/// \macro LLVM_PLUGIN_API_VERSION
+/// Identifies the API version understood by this plugin.
+///
+/// When a plugin is loaded, the driver will check it's supported plugin version
+/// against that of the plugin. A mismatch is an error. The supported version
+/// will be incremented for ABI-breaking changes to the \c PassPluginLibraryInfo
+/// struct, i.e. when callbacks are added, removed, or reordered.
+#define LLVM_PLUGIN_API_VERSION 1
+
+extern "C" {
+/// Information about the plugin required to load its passes
+///
+/// This struct defines the core interface for pass plugins and is supposed to
+/// be filled out by plugin implementors. LLVM-side users of a plugin are
+/// expected to use the \c PassPlugin class below to interface with it.
+struct PassPluginLibraryInfo {
+ /// The API version understood by this plugin, usually \c
+ /// LLVM_PLUGIN_API_VERSION
+ uint32_t APIVersion;
+ /// A meaningful name of the plugin.
+ const char *PluginName;
+ /// The version of the plugin.
+ const char *PluginVersion;
+
+ /// The callback for registering plugin passes with a \c PassBuilder
+ /// instance
+ void (*RegisterPassBuilderCallbacks)(PassBuilder &);
+};
+}
+
+/// A loaded pass plugin.
+///
+/// An instance of this class wraps a loaded pass plugin and gives access to
+/// its interface defined by the \c PassPluginLibraryInfo it exposes.
+class PassPlugin {
+public:
+ /// Attempts to load a pass plugin from a given file.
+ ///
+ /// \returns Returns an error if either the library cannot be found or loaded,
+ /// there is no public entry point, or the plugin implements the wrong API
+ /// version.
+ static Expected<PassPlugin> Load(const std::string &Filename);
+
+ /// Get the filename of the loaded plugin.
+ StringRef getFilename() const { return Filename; }
+
+ /// Get the plugin name
+ StringRef getPluginName() const { return Info.PluginName; }
+
+ /// Get the plugin version
+ StringRef getPluginVersion() const { return Info.PluginVersion; }
+
+ /// Get the plugin API version
+ uint32_t getAPIVersion() const { return Info.APIVersion; }
+
+ /// Invoke the PassBuilder callback registration
+ void registerPassBuilderCallbacks(PassBuilder &PB) const {
+ Info.RegisterPassBuilderCallbacks(PB);
+ }
+
+private:
+ PassPlugin(const std::string &Filename, const sys::DynamicLibrary &Library)
+ : Filename(Filename), Library(Library), Info() {}
+
+ std::string Filename;
+ sys::DynamicLibrary Library;
+ PassPluginLibraryInfo Info;
+};
+}
+
+/// The public entry point for a pass plugin.
+///
+/// When a plugin is loaded by the driver, it will call this entry point to
+/// obtain information about this plugin and about how to register its passes.
+/// This function needs to be implemented by the plugin, see the example below:
+///
+/// ```
+/// extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
+/// LLVM_PLUGIN_EXPORT llvmGetPassPluginInfo() {
+/// return {
+/// LLVM_PLUGIN_API_VERSION, "MyPlugin", "v0.1", [](PassBuilder &PB) { ... }
+/// };
+/// }
+/// ```
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK LLVM_PLUGIN_IMPORT
+llvmGetPassPluginInfo();
+
+#endif /* LLVM_PASSES_PASSPLUGIN_H */
Modified: llvm/trunk/lib/Passes/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/CMakeLists.txt?rev=329293&r1=329292&r2=329293&view=diff
==============================================================================
--- llvm/trunk/lib/Passes/CMakeLists.txt (original)
+++ llvm/trunk/lib/Passes/CMakeLists.txt Thu Apr 5 08:04:13 2018
@@ -1,5 +1,6 @@
add_llvm_library(LLVMPasses
PassBuilder.cpp
+ PassPlugin.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Passes
Added: llvm/trunk/lib/Passes/PassPlugin.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassPlugin.cpp?rev=329293&view=auto
==============================================================================
--- llvm/trunk/lib/Passes/PassPlugin.cpp (added)
+++ llvm/trunk/lib/Passes/PassPlugin.cpp Thu Apr 5 08:04:13 2018
@@ -0,0 +1,50 @@
+//===- lib/Passes/PassPluginLoader.cpp - Load Plugins for New PM Passes ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+Expected<PassPlugin> PassPlugin::Load(const std::string &Filename) {
+ std::string Error;
+ auto Library =
+ sys::DynamicLibrary::getPermanentLibrary(Filename.c_str(), &Error);
+ if (!Library.isValid())
+ return make_error<StringError>(Twine("Could not load library '") +
+ Filename + "': " + Error,
+ inconvertibleErrorCode());
+
+ PassPlugin P{Filename, Library};
+ auto *getDetailsFn =
+ Library.SearchForAddressOfSymbol("llvmGetPassPluginInfo");
+
+ if (!getDetailsFn)
+ // If the symbol isn't found, this is probably a legacy plugin, which is an
+ // error
+ return make_error<StringError>(Twine("Plugin entry point not found in '") +
+ Filename + "'. Is this a legacy plugin?",
+ inconvertibleErrorCode());
+
+ P.Info = reinterpret_cast<decltype(llvmGetPassPluginInfo) *>(getDetailsFn)();
+
+ if (P.Info.APIVersion != LLVM_PLUGIN_API_VERSION)
+ return make_error<StringError>(
+ Twine("Wrong API version on plugin '") + Filename + "'. Got version " +
+ Twine(P.Info.APIVersion) + ", supported version is " +
+ Twine(LLVM_PLUGIN_API_VERSION) + ".",
+ inconvertibleErrorCode());
+
+ if (!P.Info.RegisterPassBuilderCallbacks)
+ return make_error<StringError>(Twine("Empty entry callback in plugin '") +
+ Filename + "'.'",
+ inconvertibleErrorCode());
+
+ return P;
+}
Modified: llvm/trunk/tools/opt/NewPMDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/NewPMDriver.cpp?rev=329293&r1=329292&r2=329293&view=diff
==============================================================================
--- llvm/trunk/tools/opt/NewPMDriver.cpp (original)
+++ llvm/trunk/tools/opt/NewPMDriver.cpp Thu Apr 5 08:04:13 2018
@@ -27,6 +27,7 @@
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ToolOutputFile.h"
@@ -41,6 +42,10 @@ static cl::opt<bool>
DebugPM("debug-pass-manager", cl::Hidden,
cl::desc("Print pass management debugging information"));
+static cl::list<std::string>
+ PassPlugins("load-pass-plugin",
+ cl::desc("Load passes from plugin library"));
+
// This flag specifies a textual description of the alias analysis pipeline to
// use when querying for aliasing information. It only works in concert with
// the "passes" flag above.
@@ -210,6 +215,18 @@ bool llvm::runPassPipeline(StringRef Arg
PassBuilder PB(TM, P);
registerEPCallbacks(PB, VerifyEachPass, DebugPM);
+ // Load requested pass plugins and let them register pass builder callbacks
+ for (auto &PluginFN : PassPlugins) {
+ auto PassPlugin = PassPlugin::Load(PluginFN);
+ if (!PassPlugin) {
+ errs() << "Failed to load passes from '" << PluginFN
+ << "'. Request ignored.\n";
+ continue;
+ }
+
+ PassPlugin->registerPassBuilderCallbacks(PB);
+ }
+
// Register a callback that creates the debugify passes as needed.
PB.registerPipelineParsingCallback(
[](StringRef Name, ModulePassManager &MPM,
Modified: llvm/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CMakeLists.txt?rev=329293&r1=329292&r2=329293&view=diff
==============================================================================
--- llvm/trunk/unittests/CMakeLists.txt (original)
+++ llvm/trunk/unittests/CMakeLists.txt Thu Apr 5 08:04:13 2018
@@ -22,6 +22,7 @@ add_subdirectory(Object)
add_subdirectory(BinaryFormat)
add_subdirectory(ObjectYAML)
add_subdirectory(Option)
+add_subdirectory(Passes)
add_subdirectory(ProfileData)
add_subdirectory(Support)
add_subdirectory(Target)
Added: llvm/trunk/unittests/Passes/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Passes/CMakeLists.txt?rev=329293&view=auto
==============================================================================
--- llvm/trunk/unittests/Passes/CMakeLists.txt (added)
+++ llvm/trunk/unittests/Passes/CMakeLists.txt Thu Apr 5 08:04:13 2018
@@ -0,0 +1,18 @@
+set(LLVM_LINK_COMPONENTS Support Passes Core)
+
+add_llvm_unittest(PluginsTests PluginsTest.cpp)
+export_executable_symbols(PluginsTests)
+
+add_library(TestPlugin MODULE TestPlugin.cxx)
+
+set_output_directory(TestPlugin
+ BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
+ LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
+ )
+
+set_target_properties(TestPlugin
+ PROPERTIES PREFIX ""
+ SUFFIX ".so"
+ )
+
+add_dependencies(PluginsTests TestPlugin)
Added: llvm/trunk/unittests/Passes/PluginsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Passes/PluginsTest.cpp?rev=329293&view=auto
==============================================================================
--- llvm/trunk/unittests/Passes/PluginsTest.cpp (added)
+++ llvm/trunk/unittests/Passes/PluginsTest.cpp Thu Apr 5 08:04:13 2018
@@ -0,0 +1,53 @@
+//===- unittests/Passes/Plugins/PluginsTest.cpp ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Transforms/Scalar/LoopPassManager.h"
+#include "gtest/gtest.h"
+
+#include "TestPlugin.h"
+
+using namespace llvm;
+
+void anchor() {}
+
+static std::string LibPath(const std::string Name = "TestPlugin") {
+ const std::vector<testing::internal::string> &Argvs =
+ testing::internal::GetArgvs();
+ const char *Argv0 = Argvs.size() > 0 ? Argvs[0].c_str() : "PluginsTests";
+ void *Ptr = (void *)anchor;
+ std::string Path = sys::fs::getMainExecutable(Argv0, Ptr);
+ llvm::SmallString<256> Buf{sys::path::parent_path(Path)};
+ sys::path::append(Buf, (Name + ".so").c_str());
+ return Buf.str();
+}
+
+TEST(PluginsTests, LoadPlugin) {
+ auto PluginPath = LibPath();
+ ASSERT_NE("", PluginPath);
+
+ Expected<PassPlugin> Plugin = PassPlugin::Load(PluginPath);
+ ASSERT_TRUE(!!Plugin) << "Plugin path: " << PluginPath;
+
+ ASSERT_EQ(TEST_PLUGIN_NAME, Plugin->getPluginName());
+ ASSERT_EQ(TEST_PLUGIN_VERSION, Plugin->getPluginVersion());
+
+ PassBuilder PB;
+ ModulePassManager PM;
+ ASSERT_FALSE(PB.parsePassPipeline(PM, "plugin-pass"));
+
+ Plugin->registerPassBuilderCallbacks(PB);
+ ASSERT_TRUE(PB.parsePassPipeline(PM, "plugin-pass"));
+}
Added: llvm/trunk/unittests/Passes/TestPlugin.cxx
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Passes/TestPlugin.cxx?rev=329293&view=auto
==============================================================================
--- llvm/trunk/unittests/Passes/TestPlugin.cxx (added)
+++ llvm/trunk/unittests/Passes/TestPlugin.cxx Thu Apr 5 08:04:13 2018
@@ -0,0 +1,39 @@
+//===- unittests/Passes/Plugins/Plugin.cxx --------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
+
+#include "TestPlugin.h"
+
+using namespace llvm;
+
+struct TestModulePass : public PassInfoMixin<TestModulePass> {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM) {
+ return PreservedAnalyses::all();
+ }
+};
+
+void registerCallbacks(PassBuilder &PB) {
+ PB.registerPipelineParsingCallback(
+ [](StringRef Name, ModulePassManager &PM,
+ ArrayRef<PassBuilder::PipelineElement> InnerPipeline) {
+ if (Name == "plugin-pass") {
+ PM.addPass(TestModulePass());
+ return true;
+ }
+ return false;
+ });
+}
+
+extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK LLVM_PLUGIN_EXPORT
+llvmGetPassPluginInfo() {
+ return {LLVM_PLUGIN_API_VERSION, TEST_PLUGIN_NAME, TEST_PLUGIN_VERSION,
+ registerCallbacks};
+}
Added: llvm/trunk/unittests/Passes/TestPlugin.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Passes/TestPlugin.h?rev=329293&view=auto
==============================================================================
--- llvm/trunk/unittests/Passes/TestPlugin.h (added)
+++ llvm/trunk/unittests/Passes/TestPlugin.h Thu Apr 5 08:04:13 2018
@@ -0,0 +1,2 @@
+#define TEST_PLUGIN_NAME "TestPlugin"
+#define TEST_PLUGIN_VERSION "0.1-unit"
More information about the llvm-commits
mailing list