Showing the changes to src/vm/module_ref.cpp (1 of 40 files). Show all
Unified · Split
| @@ -0,0 +1,128 @@ | |||
| 1 | // | ||
| 2 | // Dis VM | ||
| 3 | // File: module_ref.cpp | ||
| 4 | // Author: arr | ||
| 5 | // | ||
| 6 | |||
| 7 | #include <runtime.h> | ||
| 8 | #include <exceptions.h> | ||
| 9 | #include <vm_memory.h> | ||
| 10 | #include <utils.h> | ||
| 11 | #include <debug.h> | ||
| 12 | |||
| 13 | using namespace disvm; | ||
| 14 | using namespace disvm::runtime; | ||
| 15 | |||
| 16 | namespace | ||
| 17 | { | ||
| 18 | std::unique_ptr<vm_array_t> resolve_imports(const export_section_t &exports, const import_vm_module_t &imports) | ||
| 19 | { | ||
| 20 | static auto function_ref_type_desc = type_descriptor_t::create(sizeof(vm_module_function_ref_t), std::vector<byte_t>{}); | ||
| 21 | auto refs = std::make_unique<vm_array_t>(function_ref_type_desc, imports.functions.size()); | ||
| 22 | |||
| 23 | for (auto index = std::size_t{ 0 }; index < imports.functions.size(); ++index) | ||
| 24 | { | ||
| 25 | const auto &import = imports.functions[index]; | ||
| 26 | |||
| 27 | const auto exports_with_sig = exports.equal_range(import.sig); | ||
| 28 | if (exports_with_sig.first == exports.cend() && exports_with_sig.second == exports.cend()) | ||
| 29 | throw vm_user_exception{ "Module does not export a function with expected signature" }; | ||
| 30 | |||
| 31 | auto export_match = exports_with_sig.first; | ||
| 32 | while (export_match != exports_with_sig.second) | ||
| 33 | { | ||
| 34 | // Look for the matching function name in those with matching signature | ||
| 35 | if (0 == vm_string_t::compare(export_match->second.name.get(), import.name.get())) | ||
| 36 | break; | ||
| 37 | |||
| 38 | ++export_match; | ||
| 39 | } | ||
| 40 | |||
| 41 | if (export_match == exports_with_sig.second) | ||
| 42 | throw vm_user_exception{ "Type check failure for exported function" }; | ||
| 43 | |||
| 44 | const auto &export_entry = export_match->second; | ||
| 45 | |||
| 46 | auto &ref = refs->at<vm_module_function_ref_t>(index); | ||
| 47 | ref.entry_pc = export_entry.pc; | ||
| 48 | ref.frame_type = export_entry.frame_type; | ||
| 49 | |||
| 50 | if (debug::is_component_tracing_enabled<debug::component_trace_t::module>()) | ||
| 51 | { | ||
| 52 | debug::log_msg( | ||
| 53 | debug::component_trace_t::module, | ||
| 54 | debug::log_level_t::debug, | ||
| 55 | "export: %d %#08x >>%s<<\n", | ||
| 56 | index, | ||
| 57 | export_entry.sig, | ||
| 58 | export_entry.name->str()); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | return refs; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | std::shared_ptr<const type_descriptor_t> vm_module_ref_t::type_desc() | ||
| 67 | { | ||
| 68 | return intrinsic_type_desc::type<vm_module_ref_t>(); | ||
| 69 | } | ||
| 70 | |||
| 71 | vm_module_ref_t::vm_module_ref_t(std::shared_ptr<const vm_module_t> module) | ||
| 72 | : vm_alloc_t(vm_module_ref_t::type_desc()) | ||
| 73 | , code_section{ module->code_section } | ||
| 74 | , module{ module } | ||
| 75 | , mp_base{ nullptr } | ||
| 76 | , type_section{ module->type_section } | ||
| 77 | , _builtin_module{ util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin) } | ||
| 78 | { | ||
| 79 | if (module->original_mp != nullptr) | ||
| 80 | mp_base = vm_alloc_t::copy(*module->original_mp); | ||
| 81 | |||
| 82 | if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>()) | ||
| 83 | debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "init: vm module ref\n"); | ||
| 84 | } | ||
| 85 | |||
| 86 | vm_module_ref_t::vm_module_ref_t(std::shared_ptr<const vm_module_t> module, const import_vm_module_t &imports) | ||
| 87 | : vm_alloc_t(vm_module_ref_t::type_desc()) | ||
| 88 | , code_section{ module->code_section } | ||
| 89 | , module{ module } | ||
| 90 | , type_section{ module->type_section } | ||
| 91 | , _function_refs{ resolve_imports(module->export_section, imports) } | ||
| 92 | , _builtin_module{ util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin) } | ||
| 93 | { | ||
| 94 | assert(module->header.data_size == 0 || module->original_mp != nullptr); | ||
| 95 | |||
| 96 | if (module->original_mp != nullptr) | ||
| 97 | mp_base = vm_alloc_t::copy(*module->original_mp); | ||
| 98 | |||
| 99 | if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>()) | ||
| 100 | debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "init: vm module ref: exported %d\n", _function_refs->get_length()); | ||
| 101 | } | ||
| 102 | |||
| 103 | vm_module_ref_t::~vm_module_ref_t() | ||
| 104 | { | ||
| 105 | dec_ref_count_and_free(mp_base); | ||
| 106 | |||
| 107 | if (_function_refs != nullptr) | ||
| 108 | _function_refs->release(); | ||
| 109 | |||
| 110 | if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>()) | ||
| 111 | debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "destroy: vm module ref\n"); | ||
| 112 | } | ||
| 113 | |||
| 114 | bool vm_module_ref_t::is_builtin_module() const | ||
| 115 | { | ||
| 116 | return _builtin_module; | ||
| 117 | } | ||
| 118 | |||
| 119 | const vm_module_function_ref_t& vm_module_ref_t::get_function_ref(word_t index) const | ||
| 120 | { | ||
| 121 | assert(_function_refs != nullptr); | ||
| 122 | |||
| 123 | if (index < 0 || _function_refs->get_length() <= index) | ||
| 124 | throw vm_system_exception{ "Invalid function reference index into module reference functions" }; | ||
| 125 | |||
| 126 | return _function_refs->at<vm_module_function_ref_t>(index); | ||
| 127 | } | ||
| 128 | |||