[llvm] [Opt] Enable statically-linked plugin support (PR #79227)
William Moses via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 24 18:06:36 PST 2024
https://github.com/wsmoses updated https://github.com/llvm/llvm-project/pull/79227
>From 4aaf28fc286d97df491f5f78f55d7f4811b1d821 Mon Sep 17 00:00:00 2001
From: "William S. Moses" <gh at wsmoses.com>
Date: Tue, 23 Jan 2024 18:33:53 -0500
Subject: [PATCH 1/2] [Opt] Enable support for statically linked plugins
---
llvm/lib/Passes/PassPlugin.cpp | 31 ++++++++---
llvm/test/Feature/load_staticextension.ll | 15 ++++++
llvm/tools/opt/CMakeLists.txt | 13 +++++
llvm/tools/opt/PrintPlugin.cpp | 63 +++++++++++++++++++++++
4 files changed, 115 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/Feature/load_staticextension.ll
create mode 100644 llvm/tools/opt/PrintPlugin.cpp
diff --git a/llvm/lib/Passes/PassPlugin.cpp b/llvm/lib/Passes/PassPlugin.cpp
index 6182cbbb1fddd3..9cdc27491a9bfb 100644
--- a/llvm/lib/Passes/PassPlugin.cpp
+++ b/llvm/lib/Passes/PassPlugin.cpp
@@ -14,20 +14,37 @@
using namespace llvm;
Expected<PassPlugin> PassPlugin::Load(const std::string &Filename) {
+ // First, see if the plugin is available in the current executable, with the
+ // suffix of the symbol being given by the `Filename` otherwise, try loading
+ // the plugin via the file
std::string Error;
- auto Library =
- sys::DynamicLibrary::getPermanentLibrary(Filename.c_str(), &Error);
+
+ auto Library = sys::DynamicLibrary::getPermanentLibrary(nullptr, &Error);
if (!Library.isValid())
- return make_error<StringError>(Twine("Could not load library '") +
- Filename + "': " + Error,
+ return make_error<StringError>("Could not load current executable",
inconvertibleErrorCode());
- PassPlugin P{Filename, Library};
-
// llvmGetPassPluginInfo should be resolved to the definition from the plugin
// we are currently loading.
+ std::string symbolName = "llvmGetPassPluginInfo" + Filename;
intptr_t getDetailsFn =
- (intptr_t)Library.getAddressOfSymbol("llvmGetPassPluginInfo");
+ (intptr_t)Library.getAddressOfSymbol(symbolName.c_str());
+
+ if (!getDetailsFn) {
+ Library = sys::DynamicLibrary::getPermanentLibrary(
+ (Filename == "") ? nullptr : Filename.c_str(), &Error);
+ if (!Library.isValid())
+ return make_error<StringError>(Twine("Could not load library '") +
+ Filename + "': " + Error,
+ inconvertibleErrorCode());
+
+ // llvmGetPassPluginInfo should be resolved to the definition from the
+ // plugin we are currently loading.
+ getDetailsFn =
+ (intptr_t)Library.getAddressOfSymbol("llvmGetPassPluginInfo");
+ }
+
+ PassPlugin P{Filename, Library};
if (!getDetailsFn)
// If the symbol isn't found, this is probably a legacy plugin, which is an
diff --git a/llvm/test/Feature/load_staticextension.ll b/llvm/test/Feature/load_staticextension.ll
new file mode 100644
index 00000000000000..6a17de86c0d18d
--- /dev/null
+++ b/llvm/test/Feature/load_staticextension.ll
@@ -0,0 +1,15 @@
+; REQUIRES: x86-registered-target
+; RUN: opt-printplugin %s -load-pass-plugin="PrintPlugin" -passes="printpass" -disable-output 2>&1 | FileCheck %s
+
+; REQUIRES: plugins
+
+; CHECK: [PrintPass] Found function: somefunk
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+ at junk = global i32 0
+
+define ptr @somefunk() {
+ ret ptr @junk
+}
+
diff --git a/llvm/tools/opt/CMakeLists.txt b/llvm/tools/opt/CMakeLists.txt
index 8d031b2cc57c78..2edb695eee03c9 100644
--- a/llvm/tools/opt/CMakeLists.txt
+++ b/llvm/tools/opt/CMakeLists.txt
@@ -50,3 +50,16 @@ add_llvm_tool(opt
target_link_libraries(opt PRIVATE LLVMOptDriver)
export_executable_symbols_for_plugins(opt)
+
+if (LLVM_ENABLE_PLUGINS)
+add_llvm_tool(opt-printplugin
+ NewPMDriver.cpp
+ opt.cpp
+ PrintPlugin.cpp
+
+ DEPENDS
+ intrinsics_gen
+ SUPPORT_PLUGINS
+ )
+target_link_options(opt-printplugin PUBLIC -Wl,--export-dynamic-symbol=llvmGetPassPluginInfoPrintPlugin)
+endif()
diff --git a/llvm/tools/opt/PrintPlugin.cpp b/llvm/tools/opt/PrintPlugin.cpp
new file mode 100644
index 00000000000000..b0bbca87b0a54a
--- /dev/null
+++ b/llvm/tools/opt/PrintPlugin.cpp
@@ -0,0 +1,63 @@
+//===- LLVMPrintFunctionNames.cpp
+//---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Example opt plugin which simply prints the names of all the functions
+// within the generated LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/PassManager.h"
+#include "llvm/Passes/OptimizationLevel.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassPlugin.h"
+#include "llvm/Support/Registry.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+
+class PrintPass final : public llvm::AnalysisInfoMixin<PrintPass> {
+ friend struct llvm::AnalysisInfoMixin<PrintPass>;
+
+private:
+ static llvm::AnalysisKey key;
+
+public:
+ using Result = llvm::PreservedAnalyses;
+
+ Result run(llvm::Module &M, llvm::ModuleAnalysisManager &MAM) {
+ for (auto &F : M)
+ llvm::outs() << "[PrintPass] Found function: " << F.getName() << "\n";
+ return llvm::PreservedAnalyses::all();
+ }
+ static bool isRequired() { return true; }
+};
+
+} // namespace
+
+llvm::PassPluginLibraryInfo getPrintPluginInfo() {
+ return {LLVM_PLUGIN_API_VERSION, "PrintPlugin", LLVM_VERSION_STRING,
+ [](PassBuilder &PB) {
+ PB.registerPipelineParsingCallback(
+ [](StringRef Name, llvm::ModulePassManager &PM,
+ ArrayRef<llvm::PassBuilder::PipelineElement>) {
+ if (Name == "printpass") {
+ PM.addPass(PrintPass());
+ return true;
+ }
+ return false;
+ });
+ }};
+}
+
+extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
+llvmGetPassPluginInfoPrintPlugin() {
+ return getPrintPluginInfo();
+}
>From 6ea94cb9ccae97266de585670b34bdecaea7c3a7 Mon Sep 17 00:00:00 2001
From: "William S. Moses" <gh at wsmoses.com>
Date: Wed, 24 Jan 2024 15:19:12 -0500
Subject: [PATCH 2/2] fix
---
llvm/lib/Passes/PassPlugin.cpp | 31 +++----------
llvm/test/CMakeLists.txt | 1 +
llvm/test/Feature/load_staticextension.ll | 2 +-
llvm/tools/opt/CMakeLists.txt | 37 ++--------------
llvm/tools/opt/driver/CMakeLists.txt | 8 ++++
llvm/tools/opt/{ => driver}/opt.cpp | 0
llvm/tools/opt/lib/CMakeLists.txt | 9 ++++
llvm/tools/opt/{ => lib}/NewPMDriver.cpp | 20 ++++-----
llvm/tools/opt/{ => lib}/NewPMDriver.h | 9 +---
llvm/tools/opt/{ => lib}/optdriver.cpp | 0
llvm/tools/opt/test/CMakeLists.txt | 8 ++++
.../opt-printplugin.cpp} | 44 ++++++++++---------
.../llvm-project-overlay/llvm/BUILD.bazel | 9 ++--
13 files changed, 78 insertions(+), 100 deletions(-)
create mode 100644 llvm/tools/opt/driver/CMakeLists.txt
rename llvm/tools/opt/{ => driver}/opt.cpp (100%)
create mode 100644 llvm/tools/opt/lib/CMakeLists.txt
rename llvm/tools/opt/{ => lib}/NewPMDriver.cpp (97%)
rename llvm/tools/opt/{ => lib}/NewPMDriver.h (97%)
rename llvm/tools/opt/{ => lib}/optdriver.cpp (100%)
create mode 100644 llvm/tools/opt/test/CMakeLists.txt
rename llvm/tools/opt/{PrintPlugin.cpp => test/opt-printplugin.cpp} (57%)
diff --git a/llvm/lib/Passes/PassPlugin.cpp b/llvm/lib/Passes/PassPlugin.cpp
index 9cdc27491a9bfb..6182cbbb1fddd3 100644
--- a/llvm/lib/Passes/PassPlugin.cpp
+++ b/llvm/lib/Passes/PassPlugin.cpp
@@ -14,37 +14,20 @@
using namespace llvm;
Expected<PassPlugin> PassPlugin::Load(const std::string &Filename) {
- // First, see if the plugin is available in the current executable, with the
- // suffix of the symbol being given by the `Filename` otherwise, try loading
- // the plugin via the file
std::string Error;
-
- auto Library = sys::DynamicLibrary::getPermanentLibrary(nullptr, &Error);
+ auto Library =
+ sys::DynamicLibrary::getPermanentLibrary(Filename.c_str(), &Error);
if (!Library.isValid())
- return make_error<StringError>("Could not load current executable",
+ return make_error<StringError>(Twine("Could not load library '") +
+ Filename + "': " + Error,
inconvertibleErrorCode());
+ PassPlugin P{Filename, Library};
+
// llvmGetPassPluginInfo should be resolved to the definition from the plugin
// we are currently loading.
- std::string symbolName = "llvmGetPassPluginInfo" + Filename;
intptr_t getDetailsFn =
- (intptr_t)Library.getAddressOfSymbol(symbolName.c_str());
-
- if (!getDetailsFn) {
- Library = sys::DynamicLibrary::getPermanentLibrary(
- (Filename == "") ? nullptr : Filename.c_str(), &Error);
- if (!Library.isValid())
- return make_error<StringError>(Twine("Could not load library '") +
- Filename + "': " + Error,
- inconvertibleErrorCode());
-
- // llvmGetPassPluginInfo should be resolved to the definition from the
- // plugin we are currently loading.
- getDetailsFn =
- (intptr_t)Library.getAddressOfSymbol("llvmGetPassPluginInfo");
- }
-
- PassPlugin P{Filename, Library};
+ (intptr_t)Library.getAddressOfSymbol("llvmGetPassPluginInfo");
if (!getDetailsFn)
// If the symbol isn't found, this is probably a legacy plugin, which is an
diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index 6127b76db06b7f..1a07e951811943 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -138,6 +138,7 @@ set(LLVM_TEST_DEPENDS
not
obj2yaml
opt
+ opt-printplugin
sancov
sanstats
split-file
diff --git a/llvm/test/Feature/load_staticextension.ll b/llvm/test/Feature/load_staticextension.ll
index 6a17de86c0d18d..11b754e1612562 100644
--- a/llvm/test/Feature/load_staticextension.ll
+++ b/llvm/test/Feature/load_staticextension.ll
@@ -1,5 +1,5 @@
; REQUIRES: x86-registered-target
-; RUN: opt-printplugin %s -load-pass-plugin="PrintPlugin" -passes="printpass" -disable-output 2>&1 | FileCheck %s
+; RUN: opt-printplugin %s -passes="printpass" -disable-output 2>&1 | FileCheck %s
; REQUIRES: plugins
diff --git a/llvm/tools/opt/CMakeLists.txt b/llvm/tools/opt/CMakeLists.txt
index 2edb695eee03c9..abbfa245350449 100644
--- a/llvm/tools/opt/CMakeLists.txt
+++ b/llvm/tools/opt/CMakeLists.txt
@@ -29,37 +29,6 @@ set(LLVM_LINK_COMPONENTS
Passes
)
-# We don't want to link this into libLLVM
-add_llvm_library(LLVMOptDriver
- STATIC
- NewPMDriver.cpp
- optdriver.cpp
- PARTIAL_SOURCES_INTENDED
- DEPENDS
- intrinsics_gen
-)
-
-add_llvm_tool(opt
- PARTIAL_SOURCES_INTENDED
- opt.cpp
- DEPENDS
- intrinsics_gen
- SUPPORT_PLUGINS
-
- )
-target_link_libraries(opt PRIVATE LLVMOptDriver)
-
-export_executable_symbols_for_plugins(opt)
-
-if (LLVM_ENABLE_PLUGINS)
-add_llvm_tool(opt-printplugin
- NewPMDriver.cpp
- opt.cpp
- PrintPlugin.cpp
-
- DEPENDS
- intrinsics_gen
- SUPPORT_PLUGINS
- )
-target_link_options(opt-printplugin PUBLIC -Wl,--export-dynamic-symbol=llvmGetPassPluginInfoPrintPlugin)
-endif()
+add_subdirectory(lib)
+add_subdirectory(driver)
+add_subdirectory(test)
diff --git a/llvm/tools/opt/driver/CMakeLists.txt b/llvm/tools/opt/driver/CMakeLists.txt
new file mode 100644
index 00000000000000..2b0d2722c00f51
--- /dev/null
+++ b/llvm/tools/opt/driver/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_llvm_tool(opt
+ opt.cpp
+ DEPENDS
+ intrinsics_gen
+ SUPPORT_PLUGINS
+ )
+target_link_libraries(opt PRIVATE LLVMOptDriver)
+export_executable_symbols_for_plugins(opt)
diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/driver/opt.cpp
similarity index 100%
rename from llvm/tools/opt/opt.cpp
rename to llvm/tools/opt/driver/opt.cpp
diff --git a/llvm/tools/opt/lib/CMakeLists.txt b/llvm/tools/opt/lib/CMakeLists.txt
new file mode 100644
index 00000000000000..bdcc6507c43c1a
--- /dev/null
+++ b/llvm/tools/opt/lib/CMakeLists.txt
@@ -0,0 +1,9 @@
+# We don't want to link this into libLLVM
+add_llvm_library(LLVMOptDriver
+ STATIC
+ NewPMDriver.cpp
+ optdriver.cpp
+ PARTIAL_SOURCES_INTENDED
+ DEPENDS
+ intrinsics_gen
+)
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/lib/NewPMDriver.cpp
similarity index 97%
rename from llvm/tools/opt/NewPMDriver.cpp
rename to llvm/tools/opt/lib/NewPMDriver.cpp
index fdfb4df53273fe..7c76e8a1e80b70 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/lib/NewPMDriver.cpp
@@ -57,12 +57,12 @@ cl::opt<bool> VerifyEachDebugInfoPreserve(
cl::desc("Start each pass with collecting and end it with checking of "
"debug info preservation."));
-cl::opt<std::string>
- VerifyDIPreserveExport("verify-di-preserve-export",
- cl::desc("Export debug info preservation failures into "
- "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(
+ "verify-di-preserve-export",
+ cl::desc("Export debug info preservation failures into "
+ "specified (JSON) file (should be abs path as we use"
+ " append mode to insert new JSON objects)"),
+ cl::value_desc("filename"), cl::init(""));
} // namespace llvm
@@ -163,7 +163,6 @@ static cl::opt<bool> DisablePipelineVerification(
"-print-pipeline-passes can be used to create a pipeline."),
cl::Hidden);
-
static cl::opt<PGOKind>
PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden,
cl::desc("The kind of profile guided optimization"),
@@ -174,8 +173,8 @@ static cl::opt<PGOKind>
"Use instrumented profile to guide PGO."),
clEnumValN(SampleUse, "pgo-sample-use-pipeline",
"Use sampled profile to guide PGO.")));
-static cl::opt<std::string> ProfileFile("profile-file",
- cl::desc("Path to the profile."), cl::Hidden);
+static cl::opt<std::string>
+ ProfileFile("profile-file", cl::desc("Path to the profile."), cl::Hidden);
static cl::opt<std::string>
MemoryProfileFile("memory-profile-file",
cl::desc("Path to the memory profile."), cl::Hidden);
@@ -411,8 +410,7 @@ bool llvm::runPassPipeline(
} else if (VerifyEachDebugInfoPreserve) {
Debugify.setDebugInfoBeforePass(DebugInfoBeforePass);
Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
- Debugify.setOrigDIVerifyBugsReportFilePath(
- VerifyDIPreserveExport);
+ Debugify.setOrigDIVerifyBugsReportFilePath(VerifyDIPreserveExport);
Debugify.registerCallbacks(PIC, MAM);
}
diff --git a/llvm/tools/opt/NewPMDriver.h b/llvm/tools/opt/lib/NewPMDriver.h
similarity index 97%
rename from llvm/tools/opt/NewPMDriver.h
rename to llvm/tools/opt/lib/NewPMDriver.h
index 19cabd15436ebe..c9d66855f39e9c 100644
--- a/llvm/tools/opt/NewPMDriver.h
+++ b/llvm/tools/opt/lib/NewPMDriver.h
@@ -45,14 +45,9 @@ enum OutputKind {
OK_OutputThinLTOBitcode,
};
enum VerifierKind { VK_NoVerifier, VK_VerifyOut, VK_VerifyEachPass };
-enum PGOKind {
- NoPGO,
- InstrGen,
- InstrUse,
- SampleUse
-};
+enum PGOKind { NoPGO, InstrGen, InstrUse, SampleUse };
enum CSPGOKind { NoCSPGO, CSInstrGen, CSInstrUse };
-}
+} // namespace opt_tool
void printPasses(raw_ostream &OS);
diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/lib/optdriver.cpp
similarity index 100%
rename from llvm/tools/opt/optdriver.cpp
rename to llvm/tools/opt/lib/optdriver.cpp
diff --git a/llvm/tools/opt/test/CMakeLists.txt b/llvm/tools/opt/test/CMakeLists.txt
new file mode 100644
index 00000000000000..6a2a369519257f
--- /dev/null
+++ b/llvm/tools/opt/test/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_llvm_tool(opt-printplugin
+ opt-printplugin.cpp
+ DEPENDS
+ intrinsics_gen
+ SUPPORT_PLUGINS
+ )
+target_link_libraries(opt-printplugin PRIVATE LLVMOptDriver)
+export_executable_symbols_for_plugins(opt-printplugin)
diff --git a/llvm/tools/opt/PrintPlugin.cpp b/llvm/tools/opt/test/opt-printplugin.cpp
similarity index 57%
rename from llvm/tools/opt/PrintPlugin.cpp
rename to llvm/tools/opt/test/opt-printplugin.cpp
index b0bbca87b0a54a..386a23e4f1d814 100644
--- a/llvm/tools/opt/PrintPlugin.cpp
+++ b/llvm/tools/opt/test/opt-printplugin.cpp
@@ -1,5 +1,5 @@
-//===- LLVMPrintFunctionNames.cpp
-//---------------------------------------------===//
+//===- opt-printplugin.cpp - The LLVM Modular Optimizer
+//-------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,11 +7,12 @@
//
//===----------------------------------------------------------------------===//
//
-// Example opt plugin which simply prints the names of all the functions
+// Example static opt plugin which simply prints the names of all the functions
// within the generated LLVM code.
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Passes/OptimizationLevel.h"
#include "llvm/Passes/PassBuilder.h"
@@ -19,6 +20,8 @@
#include "llvm/Support/Registry.h"
#include "llvm/Support/raw_ostream.h"
+#include <functional>
+
using namespace llvm;
namespace {
@@ -40,24 +43,25 @@ class PrintPass final : public llvm::AnalysisInfoMixin<PrintPass> {
static bool isRequired() { return true; }
};
+void registerPlugin(PassBuilder &PB) {
+ PB.registerPipelineParsingCallback(
+ [](StringRef Name, llvm::ModulePassManager &PM,
+ ArrayRef<llvm::PassBuilder::PipelineElement>) {
+ if (Name == "printpass") {
+ PM.addPass(PrintPass());
+ return true;
+ }
+ return false;
+ });
+}
+
} // namespace
-llvm::PassPluginLibraryInfo getPrintPluginInfo() {
- return {LLVM_PLUGIN_API_VERSION, "PrintPlugin", LLVM_VERSION_STRING,
- [](PassBuilder &PB) {
- PB.registerPipelineParsingCallback(
- [](StringRef Name, llvm::ModulePassManager &PM,
- ArrayRef<llvm::PassBuilder::PipelineElement>) {
- if (Name == "printpass") {
- PM.addPass(PrintPass());
- return true;
- }
- return false;
- });
- }};
-}
+extern "C" int optMain(int argc, char **argv,
+ llvm::ArrayRef<std::function<void(llvm::PassBuilder &)>>
+ PassBuilderCallbacks);
-extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
-llvmGetPassPluginInfoPrintPlugin() {
- return getPrintPluginInfo();
+int main(int argc, char **argv) {
+ std::function<void(llvm::PassBuilder &)> plugins[] = {registerPlugin};
+ return optMain(argc, argv, plugins);
}
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index c3efe178d6ed6d..d541fecf73b1ad 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -4817,8 +4817,8 @@ cc_binary(
cc_library(
name = "opt-driver",
srcs = glob([
- "tools/opt/*.cpp",
- "tools/opt/*.h",
+ "tools/opt/lib/*.cpp",
+ "tools/opt/lib/*.h",
]),
copts = llvm_copts,
linkopts = select({
@@ -4855,7 +4855,10 @@ cc_library(
cc_binary(
name = "opt",
stamp = 0,
- deps = [":opt-driver"]
+ deps = [":opt-driver"],
+ srcs = glob([
+ "tools/opt/driver/opt.cpp",
+ ]),
)
gentbl(
More information about the llvm-commits
mailing list