Skip to content

Commit

Permalink
[Opt] Enable support for statically linked plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
wsmoses committed Jan 23, 2024
1 parent 1c9d5c6 commit 801e49c
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 7 deletions.
31 changes: 24 additions & 7 deletions llvm/lib/Passes/PassPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions llvm/test/Feature/load_staticextension.ll
Original file line number Diff line number Diff line change
@@ -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"
@junk = global i32 0

define ptr @somefunk() {
ret ptr @junk
}

14 changes: 14 additions & 0 deletions llvm/tools/opt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ set(LLVM_LINK_COMPONENTS
)

add_llvm_tool(opt
PARTIAL_SOURCES_INTENDED
NewPMDriver.cpp
opt.cpp

Expand All @@ -38,3 +39,16 @@ add_llvm_tool(opt
SUPPORT_PLUGINS
)
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()
63 changes: 63 additions & 0 deletions llvm/tools/opt/PrintPlugin.cpp
Original file line number Diff line number Diff line change
@@ -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();
}

0 comments on commit 801e49c

Please sign in to comment.