Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
driver.cpp
Go to the documentation of this file.
1#include "thorin/driver.h"
2
3#include "thorin/plugin.h"
4
5#include "thorin/util/dl.h"
6#include "thorin/util/sys.h"
7
8namespace thorin {
9
10namespace {
11std::vector<fs::path> get_plugin_name_variants(std::string_view name) {
12 std::vector<fs::path> names;
13 names.push_back(name); // if the user gives "libthorin_foo.so"
14 names.push_back(fmt("libthorin_{}.{}", name, dl::extension));
15 return names;
16}
17} // namespace
18
20 : log_(flags_)
21 , world_(this) {
22 // prepend empty path
23 search_paths_.emplace_front(fs::path{});
24
25 // paths from env
26 if (auto env_path = std::getenv("THORIN_PLUGIN_PATH")) {
27 std::stringstream env_path_stream{env_path};
28 std::string sub_path;
29 while (std::getline(env_path_stream, sub_path, ':')) add_search_path(sub_path);
30 }
31
32 // add path/to/thorin.exe/../../lib/thorin
33 if (auto path = sys::path_to_curr_exe()) add_search_path(path->parent_path().parent_path() / "lib" / "thorin");
34
35 // add install path if different from above
36 if (auto install_path = fs::path{THORIN_INSTALL_PREFIX} / "lib" / "thorin"; fs::exists(install_path)) {
37 if (search_paths().empty() || !fs::equivalent(install_path, search_paths().back()))
38 add_search_path(std::move(install_path));
39 }
40
41 // all other user paths are placed just behind the first path (the empty path)
42 insert_ = ++search_paths_.begin();
43}
44
45const fs::path* Driver::add_import(fs::path path, Sym sym) {
46 for (const auto& [p, _] : imports_)
47 if (fs::equivalent(p, path)) return nullptr;
48
49 imports_.emplace_back(std::pair(std::move(path), sym));
50 return &imports_.back().first;
51}
52
53void Driver::load(Sym name) {
54 ILOG("loading plugin: '{}'", name);
55
56 if (is_loaded(name)) {
57 WLOG("thorin/plugin '{}' already loaded", name);
58 return;
59 }
60
61 auto handle = Plugin::Handle{nullptr, dl::close};
62 if (auto path = fs::path{name.view()}; path.is_absolute() && fs::is_regular_file(path))
63 handle.reset(dl::open(name));
64 if (!handle) {
65 for (const auto& path : search_paths()) {
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;
72 }
73 }
74 if (handle) break;
75 }
76 }
77
78 if (!handle) error("cannot open plugin '{}'", name);
79
80 if (auto get_info = reinterpret_cast<decltype(&thorin_get_plugin)>(dl::get(handle.get(), "thorin_get_plugin"))) {
81 assert_emplace(plugins_, name, std::move(handle));
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_);
86 } else {
87 error("thorin/plugin has no 'thorin_get_plugin()'");
88 }
89}
90
91void* Driver::get_fun_ptr(Sym plugin, const char* name) {
92 if (auto handle = lookup(plugins_, plugin)) return dl::get(handle->get(), name);
93 return nullptr;
94}
95
96std::pair<Annex&, bool> Driver::name2annex(Sym sym, Sym plugin, Sym tag, Loc loc) {
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");
100
101 auto [it, is_new] = annexes.emplace(sym, Annex{plugin, tag, annexes.size()});
102 return {it->second, is_new};
103}
104
105} // namespace thorin
std::pair< Annex &, bool > name2annex(Sym sym, Sym plugin, Sym tag, Loc loc)
Definition driver.cpp:96
void * get_fun_ptr(Sym plugin, const char *name)
Definition driver.cpp:91
void load(Sym name)
Definition driver.cpp:53
const auto & search_paths() const
Definition driver.h:36
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.
Definition driver.cpp:45
bool is_loaded(Sym sym) const
Definition driver.h:60
void add_search_path(fs::path path)
Definition driver.h:37
#define THORIN_INSTALL_PREFIX
Definition config.h:10
#define ILOG(...)
Definition log.h:86
#define WLOG(...)
Definition log.h:85
void * open(const char *filename)
Definition dl.cpp:17
static constexpr auto extension
Definition dl.h:8
void close(void *handle)
Definition dl.cpp:55
void * get(void *handle, const char *symbol_name)
Definition dl.cpp:36
std::optional< fs::path > path_to_curr_exe()
Yields std::nullopt if an error occurred.
Definition sys.cpp:27
Definition cfg.h:11
void error(const Def *def, const char *fmt, Args &&... args)
Definition def.h:622
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...
Definition util.h:93
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
Definition util.h:102
std::string fmt(const char *s, Args &&... args)
Wraps thorin::print to output a formatted std:string.
Definition print.h:144
Holds info about an entity defined within a Plugin (called Annex).
Definition plugin.h:53
std::unique_ptr< void, void(*)(void *)> Handle
Definition plugin.h:30