mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-30 07:00:46 +03:00
131 lines
3.9 KiB
C++
131 lines
3.9 KiB
C++
//===-- driver/plugins.cpp -------------------------------------*- C++ -*-===//
|
||
//
|
||
// LDC – the LLVM D compiler
|
||
//
|
||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||
// file for details.
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
//
|
||
// Implements functionality related to plugins (`-plugin=...`).
|
||
//
|
||
// Note: plugins can be LLVM-plugins (to be registered with the pass manager)
|
||
// or dlang-plugins for semantic analysis.
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
#include "driver/plugins.h"
|
||
|
||
#if LDC_ENABLE_PLUGINS
|
||
|
||
#include "dmd/errors.h"
|
||
#include "dmd/globals.h"
|
||
#include "dmd/module.h"
|
||
#include "llvm/Passes/PassBuilder.h"
|
||
#include "llvm/Support/CommandLine.h"
|
||
#include "llvm/Support/DynamicLibrary.h"
|
||
#include "llvm/ADT/SmallVector.h"
|
||
#include "llvm/Passes/PassPlugin.h"
|
||
#include "llvm/Support/Error.h"
|
||
|
||
#include "driver/cl_options.h"
|
||
|
||
namespace {
|
||
namespace cl = llvm::cl;
|
||
|
||
cl::list<std::string> pluginFiles("plugin", cl::CommaSeparated,
|
||
cl::desc("Pass plugins to load."),
|
||
cl::value_desc("dynamic_library.so,lib2.so"));
|
||
|
||
struct SemaPlugin {
|
||
llvm::sys::DynamicLibrary library;
|
||
void (*runSemanticAnalysis)(Module *);
|
||
|
||
SemaPlugin(const llvm::sys::DynamicLibrary &library,
|
||
void (*runSemanticAnalysis)(Module *))
|
||
: library(library), runSemanticAnalysis(runSemanticAnalysis) {}
|
||
};
|
||
|
||
llvm::SmallVector<SemaPlugin, 1> sema_plugins;
|
||
|
||
} // anonymous namespace
|
||
|
||
// Tries to load plugin as SemanticAnalysis. Returns true on 'success', i.e. no
|
||
// further attempts needed.
|
||
bool loadSemanticAnalysisPlugin(const std::string &filename) {
|
||
std::string errorString;
|
||
auto library = llvm::sys::DynamicLibrary::getPermanentLibrary(
|
||
filename.c_str(), &errorString);
|
||
if (!library.isValid()) {
|
||
error(Loc(), "Error loading plugin '%s': %s", filename.c_str(),
|
||
errorString.c_str());
|
||
return true; // No success, but no need to try loading again as LLVM plugin.
|
||
}
|
||
|
||
// SemanticAnalysis plugins need to export the `runSemanticAnalysis` function.
|
||
void *runSemanticAnalysisFnPtr =
|
||
library.getAddressOfSymbol("runSemanticAnalysis");
|
||
|
||
// If the symbol isn't found, this is probably an LLVM plugin.
|
||
if (!runSemanticAnalysisFnPtr)
|
||
return false;
|
||
|
||
sema_plugins.emplace_back(
|
||
library, reinterpret_cast<void (*)(Module *)>(runSemanticAnalysisFnPtr));
|
||
return true;
|
||
}
|
||
|
||
namespace {
|
||
llvm::SmallVector<llvm::PassPlugin, 1> llvm_plugins;
|
||
|
||
/// Loads plugin for the new pass manager. The plugin will need to be
|
||
/// added explicitly when building the optimization pipeline.
|
||
void loadLLVMPluginNewPM(const std::string &filename) {
|
||
|
||
auto plugin = llvm::PassPlugin::Load(filename);
|
||
if (!plugin) {
|
||
error(Loc(), "Error loading plugin '%s': %s", filename.c_str(),
|
||
llvm::toString(plugin.takeError()).c_str());
|
||
return;
|
||
}
|
||
llvm_plugins.emplace_back(plugin.get());
|
||
}
|
||
|
||
} // anonymous namespace
|
||
|
||
void loadLLVMPlugin(const std::string &filename) {
|
||
loadLLVMPluginNewPM(filename);
|
||
}
|
||
|
||
void loadAllPlugins() {
|
||
for (auto &filename : pluginFiles) {
|
||
// First attempt to load plugin as SemanticAnalysis plugin. If unsuccesfull,
|
||
// load as LLVM plugin.
|
||
auto success = loadSemanticAnalysisPlugin(filename);
|
||
if (!success)
|
||
loadLLVMPlugin(filename);
|
||
}
|
||
}
|
||
|
||
void registerAllPluginsWithPassBuilder(llvm::PassBuilder &PB) {
|
||
for (auto &plugin : llvm_plugins) {
|
||
plugin.registerPassBuilderCallbacks(PB);
|
||
}
|
||
}
|
||
|
||
void runAllSemanticAnalysisPlugins(Module *m) {
|
||
for (auto &plugin : sema_plugins) {
|
||
assert(plugin.runSemanticAnalysis);
|
||
plugin.runSemanticAnalysis(m);
|
||
}
|
||
}
|
||
|
||
#else // #if LDC_ENABLE_PLUGINS
|
||
|
||
class Module;
|
||
|
||
void loadAllPlugins() {}
|
||
void registerAllPluginsWithPassBuilder(llvm::PassBuilder &) {}
|
||
void runAllSemanticAnalysisPlugins(Module *m) {}
|
||
|
||
#endif // LDC_ENABLE_PLUGINS
|