11std::vector<fs::path> get_plugin_name_variants(std::string_view name) {
12 std::vector<fs::path> names;
13 names.push_back(name);
23 search_paths_.emplace_front(fs::path{});
26 if (
auto env_path = std::getenv(
"THORIN_PLUGIN_PATH")) {
27 std::stringstream env_path_stream{env_path};
29 while (std::getline(env_path_stream, sub_path,
':'))
add_search_path(sub_path);
36 if (
auto install_path = fs::path{
THORIN_INSTALL_PREFIX} /
"lib" /
"thorin"; fs::exists(install_path)) {
42 insert_ = ++search_paths_.begin();
46 for (
const auto& [p, _] : imports_)
47 if (fs::equivalent(p, path))
return nullptr;
49 imports_.emplace_back(std::pair(std::move(path), sym));
50 return &imports_.back().first;
54 ILOG(
"loading plugin: '{}'", name);
57 WLOG(
"thorin/plugin '{}' already loaded", name);
62 if (
auto path = fs::path{name.view()}; path.is_absolute() && fs::is_regular_file(path))
66 for (
auto name_variants = get_plugin_name_variants(name);
const auto& name_variant : name_variants) {
67 auto full_path = path / name_variant;
68 std::error_code ignore;
69 if (
bool reg_file = fs::is_regular_file(full_path, ignore); reg_file && !ignore) {
70 auto path_str = full_path.string();
71 if (handle.reset(
dl::open(path_str.c_str())); handle)
break;
78 if (!handle)
error(
"cannot open plugin '{}'", name);
82 auto info = get_info();
83 if (
auto reg = info.register_passes) reg(passes_);
84 if (
auto reg = info.register_normalizers) reg(normalizers_);
85 if (
auto reg = info.register_backends) reg(backends_);
87 error(
"thorin/plugin has no 'thorin_get_plugin()'");
92 if (
auto handle =
lookup(plugins_, plugin))
return dl::get(handle->get(), name);
97 auto& annexes = plugin2annexes_[plugin];
98 if (annexes.size() > std::numeric_limits<tag_t>::max())
99 error(loc,
"exceeded maxinum number of axioms in current plugin");
101 auto [it, is_new] = annexes.emplace(sym,
Annex{plugin, tag, annexes.size()});
102 return {it->second, is_new};
std::pair< Annex &, bool > name2annex(Sym sym, Sym plugin, Sym tag, Loc loc)
void * get_fun_ptr(Sym plugin, const char *name)
const auto & search_paths() const
const fs::path * add_import(fs::path, Sym)
Yields a fs::path* if not already added that you can use in Location; returns nullptr otherwise.
bool is_loaded(Sym sym) const
void add_search_path(fs::path path)
#define THORIN_INSTALL_PREFIX
void * open(const char *filename)
static constexpr auto extension
void * get(void *handle, const char *symbol_name)
std::optional< fs::path > path_to_curr_exe()
Yields std::nullopt if an error occurred.
void error(const Def *def, const char *fmt, Args &&... args)
THORIN_EXPORT thorin::Plugin thorin_get_plugin()
To be implemented and exported by a plugin.
auto lookup(const C &container, const K &key)
Yields pointer to element (or the element itself if it is already a pointer), if found and nullptr ot...
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
std::string fmt(const char *s, Args &&... args)
Wraps thorin::print to output a formatted std:string.
Holds info about an entity defined within a Plugin (called Annex).
std::unique_ptr< void, void(*)(void *)> Handle