History

Initial public commit for Dis VM

arr committed 10 years ago

Commit f95902eNo parent (first commit)40 files · +9358 −0Browse files

Showing the changes to src/vm/builtin_module.cpp (1 of 40 files). Show all

Unified · Split

src/vm/builtin_module.cpp+113−0
@@ -0,0 +1,113 @@
1+//
2+// Dis VM
3+// File: builtin_module.cpp
4+// Author: arr
5+//
6+
7+#include <cassert>
8+#include <atomic>
9+#include <mutex>
10+#include <forward_list>
11+#include <runtime.h>
12+#include <module_reader.h>
13+#include <builtin_module.h>
14+#include <debug.h>
15+#include <exceptions.h>
16+
17+using namespace disvm::runtime;
18+using namespace disvm::runtime::builtin;
19+
20+namespace
21+{
22+ std::atomic_bool builtin_modules_initialized;
23+
24+ std::mutex builtin_modules_lock;
25+ std::forward_list<std::shared_ptr<vm_module_t>> builtin_modules;
26+}
27+
28+// Declare initializers for built-in modules.
29+extern void Sysmodinit(void);
30+
31+void disvm::runtime::builtin::initialize_builtin_modules()
32+{
33+ auto is_false = bool{ false };
34+ if (!builtin_modules_initialized.compare_exchange_strong(is_false, true))
35+ return;
36+
37+ // Add built-in module initialization calls here.
38+ // e.g. Sysmodinit()
39+
40+ Sysmodinit();
41+}
42+
43+void disvm::runtime::builtin::register_module_exports(const char *name, word_t table_length, const vm_runtab_t *module_runtime_table)
44+{
45+ assert(name != nullptr && (module_runtime_table != nullptr || table_length == 0) && 0 <= table_length);
46+ assert(name[0] == BUILTIN_MODULE_PREFIX_CHAR && "Built-in modules should have the \"" BUILTIN_MODULE_PREFIX_STR "\" prefix");
47+
48+ auto new_builtin = std::make_shared<vm_module_t>();
49+
50+ // Define the module header
51+ auto &header = new_builtin->header;
52+ header.magic_number = format::magic_number_constants::xmagic;
53+ header.Signature.length = word_t{ 0 };
54+ header.runtime_flag = runtime_flags_t::builtin;
55+
56+ header.stack_extent = 0;
57+ header.code_size = table_length;
58+ header.data_size = 0;
59+ header.type_size = table_length; // 1 for each function frame type
60+ header.export_size = table_length;
61+ header.entry_pc = runtime_constants::invalid_program_counter;
62+ header.entry_type = -1;
63+
64+ new_builtin->module_name = std::make_unique<vm_string_t>(::strlen(name), reinterpret_cast<const uint8_t *>(name));
65+
66+ // Fill out code, type, and export sections
67+ for (auto i = word_t{ 0 }; i < table_length; ++i)
68+ {
69+ const auto &ex = module_runtime_table[i];
70+
71+ // Type
72+ auto frame_type = type_descriptor_t::create(ex.frame_size, ex.frame_pointer_count, ex.frame_pointer_map);
73+ new_builtin->type_section.push_back(std::move(frame_type));
74+
75+ // Export
76+ auto item = export_function_t{};
77+ item.pc = i;
78+ item.frame_type = i;
79+ item.sig = static_cast<word_t>(ex.sig);
80+ item.name = std::make_unique<vm_string_t>(std::strlen(ex.name), reinterpret_cast<const uint8_t *>(ex.name));
81+
82+ const auto sig = item.sig;
83+ new_builtin->export_section.emplace(sig, std::move(item));
84+
85+ // Instruction
86+ auto vm_instr = vm_instruction_t{};
87+ vm_instr.native = ex.fn;
88+ new_builtin->code_section.push_back(std::move(vm_instr));
89+ }
90+
91+ {
92+ std::lock_guard<std::mutex> lock{ builtin_modules_lock };
93+
94+#ifndef NDEBUG
95+ for (const auto &m : builtin_modules)
96+ assert(0 != std::strcmp(m->module_name->str(), name) && "Built-in module with matching name already exists");
97+#endif
98+
99+ builtin_modules.push_front(std::move(new_builtin));
100+ }
101+}
102+
103+std::shared_ptr<vm_module_t> disvm::runtime::builtin::get_builtin_module(const char *name)
104+{
105+ std::lock_guard<std::mutex> lock{ builtin_modules_lock };
106+ for (const auto &m : builtin_modules)
107+ {
108+ if (0 == std::strcmp(m->module_name->str(), name))
109+ return m;
110+ }
111+
112+ throw vm_module_exception{ "Unknown built-in module" };
113+}