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
17using namespace disvm::runtime;
18using namespace disvm::runtime::builtin;
19
20namespace
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.
29extern void Sysmodinit(void);
30
31void 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
43void 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
103std::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}