Update plugins

pull/5/head
A. R. Shajii 2021-10-16 20:10:06 -04:00
parent 3914b44a7d
commit 24df3dce6c
3 changed files with 56 additions and 58 deletions

View File

@ -114,7 +114,7 @@ ProcessResult processSource(const std::vector<const char *> &args) {
std::vector<std::string> disabledOptsVec(disabledOpts);
auto pm =
std::make_unique<codon::ir::transform::PassManager>(isDebug, disabledOptsVec);
auto plm = std::make_unique<codon::PluginManager>(pm.get(), isDebug);
auto plm = std::make_unique<codon::PluginManager>();
LOG_TIME("[T] ir-setup = {:.1f}",
std::chrono::duration_cast<std::chrono::milliseconds>(
@ -124,22 +124,13 @@ ProcessResult processSource(const std::vector<const char *> &args) {
// load other plugins
for (const auto &dsl : dsls) {
auto result = plm->load(dsl);
switch (result) {
case codon::PluginManager::NONE:
break;
case codon::PluginManager::NOT_FOUND:
codon::compilationError("DSL '" + dsl + "' not found");
break;
case codon::PluginManager::NO_ENTRYPOINT:
codon::compilationError("DSL '" + dsl + "' has no entry point");
break;
case codon::PluginManager::UNSUPPORTED_VERSION:
codon::compilationError("DSL '" + dsl + "' version incompatible");
break;
default:
break;
}
std::string errMsg;
if (!plm->load(dsl, &errMsg))
codon::compilationError(errMsg);
}
// add all IR passes
for (const auto *plugin : *plm) {
plugin->dsl->addIRPasses(pm.get(), isDebug);
}
t = std::chrono::high_resolution_clock::now();

View File

@ -9,28 +9,33 @@
namespace codon {
namespace {
bool isVersionSupported(const std::string &versionRange, int major, int minor,
int patch) {
try {
return semver::range::satisfies(semver::version(major, minor, patch), versionRange);
} catch (const std::invalid_argument &) {
return false;
}
bool error(const std::string &msg, std::string *errMsg) {
if (!msg.empty() && errMsg)
*errMsg = msg;
return false;
}
} // namespace
typedef std::unique_ptr<DSL> LoadFunc();
} // namespace
namespace fs = std::filesystem;
PluginManager::Error PluginManager::load(const std::string &path) {
bool PluginManager::load(const std::string &path, std::string *errMsg) {
#if __APPLE__
const std::string libExt = "dylib";
#else
const std::string libExt = "so";
#endif
fs::path tomlPath = path;
auto tml = toml::parse_file(path);
fs::path tomlPath = fs::path(path) / "plugin.toml";
toml::parse_result tml;
try {
tml = toml::parse_file(tomlPath.string());
} catch (const toml::parse_error &e) {
return error(
fmt::format("[toml::parse_file(\"{}\")] {}", tomlPath.string(), e.what()),
errMsg);
}
auto about = tml["about"];
auto library = tml["library"];
@ -51,34 +56,45 @@ PluginManager::Error PluginManager::load(const std::string &path) {
about["version"].value_or(""), about["url"].value_or(""),
about["supported"].value_or(""), stdlibPath};
if (!isVersionSupported(info.supported, CODON_VERSION_MAJOR, CODON_VERSION_MINOR,
CODON_VERSION_PATCH))
return Error::UNSUPPORTED_VERSION;
bool versionOk = false;
try {
versionOk = semver::range::satisfies(
semver::version(CODON_VERSION_MAJOR, CODON_VERSION_MINOR, CODON_VERSION_PATCH),
info.supported);
} catch (const std::invalid_argument &e) {
return error(fmt::format("[semver::range::satisfies(..., \"{}\")] {}",
info.supported, e.what()),
errMsg);
}
if (!versionOk)
return error(fmt::format("unsupported version {} (supported: {})", CODON_VERSION,
info.supported),
errMsg);
if (!dylibPath.empty()) {
std::string errMsg;
auto handle =
llvm::sys::DynamicLibrary::getPermanentLibrary(dylibPath.c_str(), &errMsg);
std::string libLoadErrorMsg;
auto handle = llvm::sys::DynamicLibrary::getPermanentLibrary(dylibPath.c_str(),
&libLoadErrorMsg);
if (!handle.isValid())
return Error::NOT_FOUND;
return error(
fmt::format(
"[llvm::sys::DynamicLibrary::getPermanentLibrary(\"{}\", ...)] {}",
dylibPath, libLoadErrorMsg),
errMsg);
auto *entry = (LoadFunc *)handle.getAddressOfSymbol("load");
if (!entry)
return Error::NO_ENTRYPOINT;
return error(
fmt::format("could not find 'load' in plugin shared library: {}", dylibPath),
errMsg);
auto dsl = (*entry)();
plugins.push_back(std::make_unique<Plugin>(std::move(dsl), info, handle));
return load(plugins.back()->dsl.get());
} else {
plugins.push_back(std::make_unique<Plugin>(std::make_unique<DSL>(), info,
llvm::sys::DynamicLibrary()));
return Error::NONE;
}
}
PluginManager::Error PluginManager::load(DSL *dsl) {
dsl->addIRPasses(pm, debug);
return Error::NONE;
return true;
}
} // namespace codon

View File

@ -27,22 +27,12 @@ struct Plugin {
/// Manager for loading, applying and unloading plugins.
class PluginManager {
private:
/// pass manager with which to register plugin IR passes
ir::transform::PassManager *pm;
/// vector of loaded plugins
std::vector<std::unique_ptr<Plugin>> plugins;
/// true if compiling in debug mode
bool debug;
public:
/// Error codes when loading plugins
enum Error { NONE = 0, NOT_FOUND, NO_ENTRYPOINT, UNSUPPORTED_VERSION };
/// Constructs a plugin manager from a given IR pass manager
/// @param pm the IR pass manager to register IR passes with
/// @param debug true if compining in debug mode
explicit PluginManager(ir::transform::PassManager *pm, bool debug = false)
: pm(pm), plugins(), debug(debug) {}
/// Constructs a plugin manager
PluginManager() : plugins() {}
/// @return iterator to the first plugin
auto begin() { return ir::util::raw_ptr_adaptor(plugins.begin()); }
@ -54,9 +44,10 @@ public:
auto end() const { return ir::util::const_raw_ptr_adaptor(plugins.end()); }
/// Loads the plugin at the given load path.
Error load(const std::string &path);
/// Loads the given DSL
Error load(DSL *dsl);
/// @param path path to plugin directory containing "plugin.toml" file
/// @param errMsg where to store potential error messages, if non-null
/// @return true if the plugin was loaded successfully, false otherwise
bool load(const std::string &path, std::string *errMsg = nullptr);
};
} // namespace codon