MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
driver.cpp
Go to the documentation of this file.
1#include "mim/driver.h"
2
3#include "mim/plugin.h"
4
5#include "mim/util/dl.h"
6#include "mim/util/sys.h"
7
8namespace mim {
9
10std::pair<const fs::path*, bool> Driver::Imports::add(fs::path path, Sym sym, ast::Tok::Tag tag) {
11 if (!fs::exists(path)) {
12 driver_.WLOG("import path '{}' does not exist", path.string());
13 return {nullptr, false};
14 }
15
16 const fs::path* imported_path = nullptr;
17 bool fresh = true;
18 for (const auto& parsed_path : parsed_paths_) {
19 if (fs::equivalent(parsed_path, path)) {
20 imported_path = &parsed_path;
21 fresh = false;
22 break;
23 }
24 }
25
26 if (!imported_path) {
27 parsed_paths_.emplace_back(std::move(path));
28 imported_path = &parsed_paths_.back();
29 }
30
31 bool seen_entry = false;
32 for (const auto& entry : entries_) {
33 if (entry.sym == sym && entry.tag == tag && fs::equivalent(entry.path, *imported_path)) {
34 seen_entry = true;
35 break;
36 }
37 }
38
39 if (!seen_entry) entries_.emplace_back(Entry{*imported_path, sym, tag});
40 return {imported_path, fresh};
41}
42
44 : log_(flags_)
45 , world_(this)
46 , imports_(*this) {
47 // prepend empty path
48 search_paths_.emplace_front(fs::path{});
49
50 // paths from env
51 if (auto env_path = std::getenv("MIM_PLUGIN_PATH")) {
52 std::stringstream env_path_stream{env_path};
53 std::string sub_path;
54 while (std::getline(env_path_stream, sub_path, ':'))
55 add_search_path(sub_path);
56 }
57
58 // add path/to/mim.exe/../../lib/mim
59 if (auto path = sys::path_to_curr_exe()) add_search_path(path->parent_path().parent_path() / MIM_LIBDIR / "mim");
60
61 // add install path if different from above
62 if (auto install_path = fs::path{MIM_INSTALL_PREFIX} / MIM_LIBDIR / "mim"; fs::exists(install_path)) {
63 if (search_paths().size() < 2 || !fs::equivalent(install_path, search_paths().back()))
64 add_search_path(std::move(install_path));
65 }
66
67 // all other user paths are placed just behind the first path (the empty path)
68 insert_ = ++search_paths_.begin();
69}
70
71void Driver::load(Sym name) {
72 ILOG("💾 loading plugin: '{}'", name);
73
74 if (is_loaded(name)) {
75 WLOG("mim/plugin '{}' already loaded", name);
76 return;
77 }
78
79 auto handle = Plugin::Handle{nullptr, dl::close};
80 if (auto path = fs::path{name.view()}; path.is_absolute() && fs::is_regular_file(path))
81 handle.reset(dl::open(name.c_str()));
82 if (!handle) {
83 for (const auto& path : search_paths()) {
84 auto full_path = path / fmt("libmim_{}.{}", name, dl::extension);
85 std::error_code ignore;
86 if (bool reg_file = fs::is_regular_file(full_path, ignore); reg_file && !ignore) {
87 auto path_str = full_path.string();
88 if (handle.reset(dl::open(path_str.c_str())); handle) break;
89 }
90 if (handle) break;
91 }
92 }
93
94 if (!handle) error("cannot open plugin '{}'", name);
95
96 if (auto get_info = reinterpret_cast<decltype(&mim_get_plugin)>(dl::get(handle.get(), "mim_get_plugin"))) {
97 assert_emplace(plugins_, name, std::move(handle));
98 auto info = get_info();
99 // clang-format off
100 if (auto reg = info.register_normalizers) reg(normalizers_);
101 if (auto reg = info.register_stages) reg(stages_);
102 if (auto reg = info.register_backends) reg(backends_);
103 // clang-format on
104 } else {
105 error("mim/plugin has no 'mim_get_plugin()'");
106 }
107}
108
109void* Driver::get_fun_ptr(Sym plugin, const char* name) {
110 if (auto handle = lookup(plugins_, plugin)) return dl::get(handle->get(), name);
111 return nullptr;
112}
113
114} // namespace mim
std::pair< const fs::path *, bool > add(fs::path, Sym, ast::Tok::Tag)
Remembers an import or plugin directive and reports whether the resolved file is new.
Definition driver.cpp:10
void load(Sym name)
Definition driver.cpp:71
void add_search_path(fs::path path)
Definition driver.h:40
bool is_loaded(Sym sym) const
Definition driver.h:93
void * get_fun_ptr(Sym plugin, const char *name)
Definition driver.cpp:109
const auto & search_paths() const
Definition driver.h:39
#define MIM_LIBDIR
Definition config.h:11
#define MIM_INSTALL_PREFIX
Definition config.h:10
#define ILOG(...)
Definition log.h:91
#define WLOG(...)
Definition log.h:90
void * get(void *handle, const char *symbol_name)
Definition dl.cpp:36
void close(void *handle)
Definition dl.cpp:55
void * open(const char *filename)
Definition dl.cpp:17
static constexpr auto extension
Definition dl.h:8
std::optional< fs::path > path_to_curr_exe()
Yields std::nullopt if an error occurred.
Definition sys.cpp:28
Definition ast.h:14
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
Definition util.h:118
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:100
std::string fmt(const char *s, Args &&... args)
Wraps mim::print to output a formatted std:string.
Definition print.h:178
void error(Loc loc, const char *f, Args &&... args)
Definition dbg.h:125
mim::Plugin mim_get_plugin()
std::unique_ptr< void, void(*)(void *)> Handle
Definition plugin.h:31