Geoffrey Martin-Noble | 552d3f8 | 2021-05-25 17:56:09 -0700 | [diff] [blame] | 1 | // Copyright 2019 The IREE Authors |
powderluv | 2e2fc9c | 2019-10-23 10:09:44 -0700 | [diff] [blame] | 2 | // |
Geoffrey Martin-Noble | 552d3f8 | 2021-05-25 17:56:09 -0700 | [diff] [blame] | 3 | // Licensed under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
powderluv | 2e2fc9c | 2019-10-23 10:09:44 -0700 | [diff] [blame] | 6 | |
Stella Laurenzo | 3b44a0a | 2022-04-18 19:57:57 -0700 | [diff] [blame] | 7 | #include "./vm.h" |
powderluv | 2e2fc9c | 2019-10-23 10:09:44 -0700 | [diff] [blame] | 8 | |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 9 | #include <ios> |
| 10 | #include <sstream> |
| 11 | #include <unordered_set> |
| 12 | |
| 13 | #include "./buffer_interop.h" |
Stella Laurenzo | 3b44a0a | 2022-04-18 19:57:57 -0700 | [diff] [blame] | 14 | #include "./status_utils.h" |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 15 | #include "iree/base/api.h" |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 16 | |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 17 | // TODO: We shouldn't need the HAL API but it is used for direct printing |
| 18 | // summaries of HAL objects in lists. We should have a better way of doing this |
| 19 | // dynamically vs hard depending on a type switch here. |
Ben Vanik | 6ada293 | 2021-06-21 09:09:32 -0700 | [diff] [blame] | 20 | #include "iree/modules/hal/module.h" |
Eugene Zhulenev | 6f81ceb | 2023-05-16 19:23:26 -0700 | [diff] [blame] | 21 | #include "iree/tooling/modules/resolver.h" |
Ben Vanik | c3a13e6 | 2020-11-16 01:54:22 -0800 | [diff] [blame] | 22 | #include "iree/vm/api.h" |
powderluv | 2e2fc9c | 2019-10-23 10:09:44 -0700 | [diff] [blame] | 23 | |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 24 | using namespace nanobind::literals; |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 25 | |
powderluv | 2e2fc9c | 2019-10-23 10:09:44 -0700 | [diff] [blame] | 26 | namespace iree { |
| 27 | namespace python { |
| 28 | |
Stella Laurenzo | edc8a98 | 2019-12-20 09:22:37 -0800 | [diff] [blame] | 29 | namespace { |
| 30 | |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 31 | static const char kFromBufferDocstring[] = |
| 32 | R"(Creates a Vmmodule from a Python buffer. |
| 33 | |
| 34 | This is intended as a quick and dirty way to instantiate a VmModule from |
| 35 | a binary blob. It will implicitly make a copy if alignment is not sufficient. |
| 36 | |
| 37 | It is recommended to use one of the other construction methods for maximum |
| 38 | determinism and efficiency: |
| 39 | |
| 40 | * `mmap` : To memory map from a file. |
| 41 | * `wrap_buffer` : To directly wrap a Python buffer that is known to be |
| 42 | aligned properly. |
| 43 | * `copy_buffer` : To always make a copy of a Python buffer such that it is |
| 44 | aligned properly. |
| 45 | |
| 46 | This was historically called `from_flatbuffer`. It is recommended that new |
| 47 | code use `flat_buffer`. |
| 48 | |
| 49 | Args: |
| 50 | instance: A VmInstance. |
| 51 | buffer: An object implementing the Python buffer protocol. Typically a |
| 52 | bytes, bytearray, memoryview, etc. |
| 53 | warn_if_copy: Raises a warning if alignment is not sufficient to use the |
| 54 | buffer directly, resulting in a copy. Defaults to True. |
| 55 | )"; |
| 56 | |
| 57 | static const char kCopyBufferDocstring[] = |
| 58 | R"(Creates a VmModule by making a copy of a Python buffer. |
| 59 | |
| 60 | Args: |
| 61 | instance: A VmInstance. |
| 62 | buffer: An object implementing the Python buffer protocol. Typically a |
| 63 | bytes, bytearray, memoryview, etc. |
| 64 | )"; |
| 65 | |
| 66 | static const char kWrapBufferDocstring[] = |
| 67 | R"(Creates a VmModule by directly using the backing memory of a Python buffer. |
| 68 | |
| 69 | Args: |
| 70 | instance: A VmInstance. |
| 71 | buffer: An object implementing the Python buffer protocol. Typically a |
| 72 | bytes, bytearray, memoryview, etc. |
| 73 | destroy_callback: A no-argument callback that is invoked when the backing |
| 74 | buffer is no longer in use. |
| 75 | close_buffer: Whether to call the `close` method on the `buffer` (prior to |
| 76 | invoking `destroy_callback`). Defaults to False. |
| 77 | |
| 78 | Raises: |
| 79 | ValueError if alignment is not satisfied. |
| 80 | )"; |
| 81 | |
| 82 | static const char kMMapDocstring[] = |
| 83 | R"(Create a VmModule by mmap'ing a file. |
| 84 | |
| 85 | When backed by a file, this is generally the most effective way to create a |
| 86 | VmModule. Especially for large modules, this will result in the fewest |
| 87 | copies and the most effective use of the system cache across invocations. |
| 88 | |
| 89 | Note that mmap behavior differs between Posix and Windows. Whereas the former |
| 90 | will allow the backing file to be open before an mmap call and deleted |
| 91 | immediately after, Windows generally allows neither. For compatibility, |
| 92 | make sure that the backing file is not open for writing before calling this |
| 93 | method and that if it needs to be deleted when done, that is done in a |
| 94 | `destroy_callback`. |
| 95 | |
| 96 | Args: |
| 97 | instance: A VmInstance. |
| 98 | filepath: Path to the file on the file system. |
| 99 | destroy_callback: A no-argument callback that is invoked when the backing |
| 100 | buffer is no longer in use. |
| 101 | )"; |
| 102 | |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 103 | // RAII wrapper for a Py_buffer which calls PyBuffer_Release when it goes |
| 104 | // out of scope. |
| 105 | class PyBufferReleaser { |
| 106 | public: |
| 107 | PyBufferReleaser(Py_buffer& b) : b_(b) {} |
| 108 | ~PyBufferReleaser() { PyBuffer_Release(&b_); } |
| 109 | |
| 110 | private: |
| 111 | Py_buffer& b_; |
| 112 | }; |
| 113 | |
| 114 | py::dict GetFunctionReflectionDict(iree_vm_function_t& f) { |
| 115 | py::dict attrs; |
Ben Vanik | 1d60c18 | 2022-06-28 12:37:40 -0700 | [diff] [blame] | 116 | for (iree_host_size_t i = 0;; ++i) { |
| 117 | iree_string_pair_t attr; |
| 118 | auto status = iree_vm_function_get_attr(f, i, &attr); |
| 119 | if (iree_status_is_out_of_range(status)) { |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 120 | iree_status_ignore(status); |
| 121 | break; |
| 122 | } |
| 123 | CheckApiStatus(status, "Error getting reflection attr"); |
Ben Vanik | 1d60c18 | 2022-06-28 12:37:40 -0700 | [diff] [blame] | 124 | py::str key_str(attr.key.data, attr.key.size); |
| 125 | py::str value_str(attr.value.data, attr.value.size); |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 126 | attrs[std::move(key_str)] = std::move(value_str); |
| 127 | } |
| 128 | return attrs; |
| 129 | } |
| 130 | |
Stella Laurenzo | edc8a98 | 2019-12-20 09:22:37 -0800 | [diff] [blame] | 131 | } // namespace |
| 132 | |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 133 | //------------------------------------------------------------------------------ |
Stella Laurenzo | 4f40080 | 2024-04-04 09:55:24 -0700 | [diff] [blame] | 134 | // VmBuffer |
| 135 | //------------------------------------------------------------------------------ |
| 136 | |
| 137 | int VmBuffer::HandleBufferProtocol(Py_buffer* view, int flags) { |
| 138 | view->buf = raw_ptr()->data.data; |
| 139 | view->len = raw_ptr()->data.data_length; |
| 140 | view->readonly = !(raw_ptr()->access & IREE_VM_BUFFER_ACCESS_MUTABLE); |
| 141 | view->itemsize = 1; |
| 142 | view->format = (char*)"B"; // Byte |
| 143 | view->ndim = 1; |
| 144 | view->shape = nullptr; |
| 145 | view->strides = nullptr; |
| 146 | view->suboffsets = nullptr; |
| 147 | view->internal = nullptr; |
| 148 | return 0; |
| 149 | } |
| 150 | |
| 151 | //------------------------------------------------------------------------------ |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 152 | // VmInstance |
| 153 | //------------------------------------------------------------------------------ |
| 154 | |
| 155 | VmInstance VmInstance::Create() { |
Ben Vanik | cc43680 | 2023-06-10 08:53:52 -0700 | [diff] [blame] | 156 | IREE_TRACE_SCOPE_NAMED("VmInstance::Create"); |
Ben Vanik | 9aa83ed | 2022-08-06 12:55:34 -0700 | [diff] [blame] | 157 | |
| 158 | iree_vm_instance_t* instance = NULL; |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 159 | auto status = iree_vm_instance_create(IREE_VM_TYPE_CAPACITY_DEFAULT, |
| 160 | iree_allocator_system(), &instance); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 161 | CheckApiStatus(status, "Error creating instance"); |
Ben Vanik | 9aa83ed | 2022-08-06 12:55:34 -0700 | [diff] [blame] | 162 | |
| 163 | // The python bindings assume the HAL is always available for use. |
| 164 | // We register the types here so modules can be loaded using the HAL types |
| 165 | // in any order. |
| 166 | CheckApiStatus(iree_hal_module_register_all_types(instance), |
| 167 | "registering HAL types"); |
| 168 | |
Stella Laurenzo | 65690a1 | 2022-01-31 12:43:00 -0800 | [diff] [blame] | 169 | return VmInstance::StealFromRawPtr(instance); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | //------------------------------------------------------------------------------ |
| 173 | // VmContext |
| 174 | //------------------------------------------------------------------------------ |
| 175 | |
| 176 | VmContext VmContext::Create(VmInstance* instance, |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 177 | std::optional<std::vector<VmModule*>>& modules) { |
Ben Vanik | cc43680 | 2023-06-10 08:53:52 -0700 | [diff] [blame] | 178 | IREE_TRACE_SCOPE_NAMED("VmContext::Create"); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 179 | iree_vm_context_t* context; |
| 180 | if (!modules) { |
| 181 | // Simple create with open allowed modules. |
Ben Vanik | 89e9530 | 2021-10-05 17:05:39 -0700 | [diff] [blame] | 182 | auto status = |
| 183 | iree_vm_context_create(instance->raw_ptr(), IREE_VM_CONTEXT_FLAG_NONE, |
| 184 | iree_allocator_system(), &context); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 185 | CheckApiStatus(status, "Error creating vm context"); |
| 186 | } else { |
| 187 | // Closed set of modules. |
Ben Vanik | b9b794b | 2021-06-19 20:11:08 -0700 | [diff] [blame] | 188 | std::vector<iree_vm_module_t*> module_handles; |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 189 | module_handles.resize(modules->size()); |
| 190 | for (size_t i = 0, e = module_handles.size(); i < e; ++i) { |
| 191 | module_handles[i] = (*modules)[i]->raw_ptr(); |
| 192 | } |
| 193 | auto status = iree_vm_context_create_with_modules( |
Ben Vanik | 70c2bb0 | 2022-06-09 12:42:54 -0700 | [diff] [blame] | 194 | instance->raw_ptr(), IREE_VM_CONTEXT_FLAG_NONE, module_handles.size(), |
| 195 | module_handles.data(), iree_allocator_system(), &context); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 196 | CheckApiStatus(status, "Error creating vm context with modules"); |
| 197 | } |
| 198 | |
Ben Vanik | 91c75fb | 2022-06-23 19:08:12 -0700 | [diff] [blame] | 199 | IREE_ASSERT(context); |
Stella Laurenzo | 65690a1 | 2022-01-31 12:43:00 -0800 | [diff] [blame] | 200 | return VmContext::StealFromRawPtr(context); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 201 | } |
| 202 | |
| 203 | void VmContext::RegisterModules(std::vector<VmModule*> modules) { |
Ben Vanik | b9b794b | 2021-06-19 20:11:08 -0700 | [diff] [blame] | 204 | std::vector<iree_vm_module_t*> module_handles; |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 205 | module_handles.resize(modules.size()); |
| 206 | for (size_t i = 0, e = module_handles.size(); i < e; ++i) { |
| 207 | module_handles[i] = modules[i]->raw_ptr(); |
| 208 | } |
Ben Vanik | 70c2bb0 | 2022-06-09 12:42:54 -0700 | [diff] [blame] | 209 | auto status = iree_vm_context_register_modules( |
| 210 | raw_ptr(), module_handles.size(), &module_handles[0]); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 211 | CheckApiStatus(status, "Error registering modules"); |
| 212 | } |
| 213 | |
Stella Laurenzo | d5efc48 | 2019-12-21 04:59:36 -0800 | [diff] [blame] | 214 | void VmContext::Invoke(iree_vm_function_t f, VmVariantList& inputs, |
| 215 | VmVariantList& outputs) { |
Stella Laurenzo | d2009dc | 2022-03-08 17:59:40 -0800 | [diff] [blame] | 216 | iree_status_t status; |
| 217 | { |
| 218 | py::gil_scoped_release release; |
| 219 | status = iree_vm_invoke(raw_ptr(), f, IREE_VM_INVOCATION_FLAG_NONE, nullptr, |
| 220 | inputs.raw_ptr(), outputs.raw_ptr(), |
| 221 | iree_allocator_system()); |
| 222 | } |
| 223 | CheckApiStatus(status, "Error invoking function"); |
Stella Laurenzo | d5efc48 | 2019-12-21 04:59:36 -0800 | [diff] [blame] | 224 | } |
| 225 | |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 226 | //------------------------------------------------------------------------------ |
| 227 | // VmModule |
| 228 | //------------------------------------------------------------------------------ |
| 229 | |
Eugene Zhulenev | 6f81ceb | 2023-05-16 19:23:26 -0700 | [diff] [blame] | 230 | VmModule VmModule::ResolveModuleDependency(VmInstance* instance, |
| 231 | const std::string& name, |
| 232 | uint32_t minimum_version) { |
Ben Vanik | cc43680 | 2023-06-10 08:53:52 -0700 | [diff] [blame] | 233 | IREE_TRACE_SCOPE_NAMED("VmModule::ResolveModuleDependency"); |
Eugene Zhulenev | 6f81ceb | 2023-05-16 19:23:26 -0700 | [diff] [blame] | 234 | iree_vm_module_t* module = nullptr; |
| 235 | |
| 236 | iree_vm_module_dependency_t dependency = { |
| 237 | iree_make_cstring_view(name.c_str()), minimum_version, |
| 238 | IREE_VM_MODULE_DEPENDENCY_FLAG_REQUIRED}; |
| 239 | |
| 240 | auto status = iree_tooling_resolve_module_dependency( |
| 241 | instance->raw_ptr(), &dependency, iree_allocator_system(), &module); |
| 242 | |
| 243 | assert(module != nullptr); |
| 244 | |
| 245 | CheckApiStatus(status, "Error resolving module dependency"); |
| 246 | auto py_module = VmModule::StealFromRawPtr(module); |
| 247 | return py_module; |
| 248 | } |
| 249 | |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 250 | VmModule VmModule::MMap(VmInstance* instance, std::string filepath, |
| 251 | py::object destroy_callback) { |
| 252 | IREE_TRACE_SCOPE_NAMED("VmModule::MMap"); |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 253 | auto mmap_module = py::module_::import_("mmap"); |
| 254 | auto open_func = py::module_::import_("io").attr("open"); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 255 | auto file_obj = open_func(filepath, "r+b"); |
| 256 | // The signature of mmap is different on Windows vs others. On others, |
| 257 | // we use explicit flags and protection attributes for better control, |
| 258 | // triggering off of the presence of the MAP_SHARED flag constant (which |
| 259 | // is not present on Windows). |
| 260 | py::object mapped_file; |
| 261 | if (py::hasattr(mmap_module, "MAP_SHARED")) { |
| 262 | // Posix mmap signature. |
| 263 | auto flags = py::cast<int64_t>(mmap_module.attr("MAP_SHARED")); |
| 264 | // MAP_POPULATE isn't available on all versions/platforms. |
| 265 | if (py::hasattr(mmap_module, "MAP_POPULATE")) { |
| 266 | flags |= py::cast<int64_t>(mmap_module.attr("MAP_POPULATE")); |
| 267 | } |
| 268 | auto prot = py::cast<int64_t>(mmap_module.attr("PROT_READ")); |
| 269 | mapped_file = mmap_module.attr("mmap")(file_obj.attr("fileno")(), 0, |
| 270 | "flags"_a = flags, "prot"_a = prot); |
| 271 | } else { |
| 272 | // Windows mmap signature. |
| 273 | mapped_file = |
| 274 | mmap_module.attr("mmap")(file_obj.attr("fileno")(), 0, |
| 275 | "access"_a = mmap_module.attr("ACCESS_READ")); |
| 276 | } |
| 277 | // Backing file can be closed after a successful mmap call. |
| 278 | file_obj.attr("close")(); |
| 279 | |
| 280 | // MADV_RANDOM is not available on Windows (and possibly others?). |
| 281 | if (py::hasattr(mmap_module, "MADV_RANDOM")) { |
| 282 | mapped_file.attr("madvise")(mmap_module.attr("MADV_RANDOM")); |
| 283 | } |
| 284 | return WrapBuffer(instance, std::move(mapped_file), |
| 285 | std::move(destroy_callback), |
| 286 | /*close_buffer=*/true); |
| 287 | } |
| 288 | |
| 289 | VmModule VmModule::WrapBuffer(VmInstance* instance, py::object buffer_obj, |
| 290 | py::object destroy_callback, bool close_buffer) { |
| 291 | IREE_TRACE_SCOPE_NAMED("VmModule::FromAlignedMemory"); |
Stella Laurenzo | 92df2b4 | 2023-12-19 17:32:30 -0800 | [diff] [blame] | 292 | // State object that is retained for the life of the module. |
| 293 | // It is responsible for keeping the backing resources alive and |
| 294 | // holding the user-level destroy callback. |
| 295 | // Note that the original buffer_obj is not captured explicitly but |
| 296 | // is available as part of the Py_buffer underlying the PyBufferRequest. |
| 297 | // Aside from being more efficient, avoiding redundant capture removes |
| 298 | // destruction race potential. |
| 299 | struct BufferState { |
| 300 | BufferState(py::object buffer_obj, py::object destroy_callback, |
| 301 | bool close_buffer) |
| 302 | : buffer_info(buffer_obj, PyBUF_SIMPLE), |
| 303 | destroy_callback(std::move(destroy_callback)), |
| 304 | close_buffer(close_buffer) {} |
| 305 | PyBufferRequest buffer_info; |
| 306 | py::object destroy_callback; |
| 307 | bool close_buffer; |
| 308 | |
| 309 | py::handle get_buffer() { return py::handle(buffer_info.view().obj); } |
| 310 | }; |
| 311 | BufferState* state = |
| 312 | new BufferState(buffer_obj, destroy_callback, close_buffer); |
| 313 | PyBufferRequest& buffer_info = state->buffer_info; |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 314 | if (!iree_host_size_has_alignment((uintptr_t)buffer_info.view().buf, |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 315 | IREE_HAL_HEAP_BUFFER_ALIGNMENT)) { |
| 316 | std::stringstream err; |
| 317 | err << "VmModule.from_aligned_memory received an unaligned buffer. "; |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 318 | err << "Got 0x" << (void*)buffer_info.view().buf << ", expected alignment "; |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 319 | err << IREE_HAL_HEAP_BUFFER_ALIGNMENT; |
| 320 | throw std::invalid_argument(err.str()); |
| 321 | } |
| 322 | |
Ben Vanik | 9aa83ed | 2022-08-06 12:55:34 -0700 | [diff] [blame] | 323 | iree_vm_module_t* module = nullptr; |
Ben Vanik | 5ca3e18 | 2021-07-12 07:46:23 -0700 | [diff] [blame] | 324 | auto ctl_fn = +([](void* self, iree_allocator_command_t command, |
| 325 | const void* params, void** inout_ptr) { |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 326 | py::gil_scoped_acquire gil; |
Ben Vanik | 5ca3e18 | 2021-07-12 07:46:23 -0700 | [diff] [blame] | 327 | assert(command == IREE_ALLOCATOR_COMMAND_FREE); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 328 | try { |
Stella Laurenzo | 92df2b4 | 2023-12-19 17:32:30 -0800 | [diff] [blame] | 329 | // Destruction sequencing is tricky. We must have released the |
| 330 | // PyBufferRequest before calling close, so we first get what we |
| 331 | // need out of the state into local variables, then delete the state |
| 332 | // (releasing the PyBufferRequest), then closing and issuing the |
| 333 | // destroy callback. Getting the order wrong will result in an |
| 334 | // unrecoverable exception indicating the the buffer cannot be closed |
| 335 | // with outstanding mappings. |
| 336 | BufferState* state = static_cast<BufferState*>(self); |
| 337 | py::object destroy_callback = std::move(state->destroy_callback); |
| 338 | py::object buffer_to_close; |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 339 | if (state->close_buffer) { |
Stella Laurenzo | 92df2b4 | 2023-12-19 17:32:30 -0800 | [diff] [blame] | 340 | buffer_to_close = py::borrow(state->get_buffer()); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 341 | } |
| 342 | delete state; |
Stella Laurenzo | 92df2b4 | 2023-12-19 17:32:30 -0800 | [diff] [blame] | 343 | |
| 344 | if (buffer_to_close) { |
| 345 | buffer_to_close.attr("close")(); |
| 346 | } |
| 347 | |
| 348 | if (!destroy_callback.is_none()) { |
| 349 | destroy_callback(); |
| 350 | } |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 351 | } catch (std::exception& e) { |
| 352 | // There are many situations where deallocation exceptions can be |
| 353 | // swallowed, so carp loudly. This is almost always a critical issue |
| 354 | // that needs to be visible. |
| 355 | fprintf( |
| 356 | stderr, |
| 357 | "error: exception raised while deallocating storage for an " |
| 358 | "iree.runtime.VmModule. This is unrecoverable and likely indicates a " |
| 359 | "serious problem, minimally resulting in memory leaks: %s", |
| 360 | e.what()); |
| 361 | return iree_make_status( |
| 362 | IREE_STATUS_UNKNOWN, |
| 363 | "exception raised while deallocating storage for an " |
| 364 | "iree.runtime.VmModule. This is unrecoverable and likely indicates a " |
| 365 | "serious problem, minimally resulting in memory leaks: %s", |
| 366 | e.what()); |
| 367 | } |
Ben Vanik | 5ca3e18 | 2021-07-12 07:46:23 -0700 | [diff] [blame] | 368 | return iree_ok_status(); |
Stella Laurenzo | e2b0d7f | 2020-01-06 13:14:40 -0800 | [diff] [blame] | 369 | }); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 370 | iree_allocator_t deallocator{/*self=*/state, /*ctl=*/ctl_fn}; |
Stella Laurenzo | e2b0d7f | 2020-01-06 13:14:40 -0800 | [diff] [blame] | 371 | |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 372 | auto status = iree_vm_bytecode_module_create( |
Ben Vanik | 9aa83ed | 2022-08-06 12:55:34 -0700 | [diff] [blame] | 373 | instance->raw_ptr(), |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 374 | {static_cast<const uint8_t*>(buffer_info.view().buf), |
| 375 | static_cast<iree_host_size_t>(buffer_info.view().len)}, |
Ben Vanik | f5bd6fd | 2020-08-05 21:14:57 -0700 | [diff] [blame] | 376 | deallocator, iree_allocator_system(), &module); |
Ben Vanik | af5401f | 2020-08-06 21:31:15 -0700 | [diff] [blame] | 377 | if (!iree_status_is_ok(status)) { |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 378 | delete state; |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 379 | } |
| 380 | |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 381 | CheckApiStatus(status, "Error creating vm module from aligned memory"); |
Stella Laurenzo | 65690a1 | 2022-01-31 12:43:00 -0800 | [diff] [blame] | 382 | auto py_module = VmModule::StealFromRawPtr(module); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 383 | // Stash a reference to the flatbuffer at the Python instance level. This |
| 384 | // is exposed to the tracing API, allowing it to get at the backing contents. |
| 385 | py_module.stashed_flatbuffer_blob = buffer_obj; |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 386 | return py_module; |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 387 | } |
| 388 | |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 389 | VmModule VmModule::CopyBuffer(VmInstance* instance, py::object buffer_obj) { |
| 390 | IREE_TRACE_SCOPE_NAMED("VmModule::CopyBuffer"); |
| 391 | auto alignment = |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 392 | py::cast<uintptr_t>(py::module_::import_("mmap").attr("PAGESIZE")); |
| 393 | auto bytearray_ctor = py::module_::import_("builtins").attr("bytearray"); |
| 394 | PyBufferRequest src_buffer_info(buffer_obj, PyBUF_SIMPLE); |
| 395 | auto src_buffer_size = src_buffer_info.view().len; |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 396 | |
| 397 | // Need to allocate an extra page because there is no control at the Python |
| 398 | // level for the alignment it may have. |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 399 | auto dst_buffer = bytearray_ctor(src_buffer_size + alignment); |
| 400 | PyBufferRequest dst_buffer_info(dst_buffer, PyBUF_SIMPLE); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 401 | void* dst_aligned = |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 402 | (void*)iree_host_align((uintptr_t)dst_buffer_info.view().buf, alignment); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 403 | uintptr_t dst_offset = |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 404 | (uintptr_t)dst_aligned - (uintptr_t)dst_buffer_info.view().buf; |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 405 | |
| 406 | // Now create a memoryview over the unaligned bytearray and slice into that |
| 407 | // to get the aligned Python buffer. |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 408 | auto dst_slice = |
| 409 | py::slice(py::cast(dst_offset), py::cast(dst_offset + src_buffer_size), |
| 410 | py::cast(1)); |
| 411 | |
| 412 | py::object dst_view = py::steal<py::object>( |
| 413 | PyMemoryView_GetContiguous(dst_buffer.ptr(), PyBUF_READ, 'C')); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 414 | py::object dst_view_aligned = dst_view[dst_slice]; |
| 415 | |
| 416 | // If any of the indexing math was wrong, Python exceptions will be raised |
| 417 | // above, so this is implicitly guarding the memcpy if it is done last. |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 418 | std::memcpy(dst_aligned, src_buffer_info.view().buf, src_buffer_size); |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 419 | return WrapBuffer(instance, std::move(dst_view_aligned), |
| 420 | /*destroy_callback=*/py::none(), |
| 421 | /*close_buffer=*/false); |
| 422 | } |
| 423 | |
| 424 | VmModule VmModule::FromBuffer(VmInstance* instance, py::object buffer_obj, |
| 425 | bool warn_if_copy) { |
| 426 | IREE_TRACE_SCOPE_NAMED("VmModule::FromBuffer"); |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 427 | PyBufferRequest buffer_info(buffer_obj, PyBUF_SIMPLE); |
| 428 | |
| 429 | if (iree_host_size_has_alignment((uintptr_t)buffer_info.view().buf, |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 430 | IREE_HAL_HEAP_BUFFER_ALIGNMENT)) { |
| 431 | return WrapBuffer(instance, std::move(buffer_obj), |
| 432 | /*destroy_callback=*/py::none(), /*close_buffer=*/false); |
| 433 | } else { |
| 434 | if (warn_if_copy) { |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 435 | py::module_::import_("warnings") |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 436 | .attr("warn")( |
| 437 | "Making copy of unaligned VmModule buffer. It is recommended to " |
| 438 | "make this deterministic by calling `copy_buffer` to always make " |
| 439 | "a copy or `mmap` to efficiently load from a file. This warning " |
| 440 | "can be silenced by adding `warn_if_copy=False` to " |
| 441 | "`from_buffer`"); |
| 442 | } |
| 443 | return CopyBuffer(instance, std::move(buffer_obj)); |
| 444 | } |
| 445 | } |
| 446 | |
Ben Vanik | df89eb0 | 2021-06-20 18:01:16 -0700 | [diff] [blame] | 447 | std::optional<iree_vm_function_t> VmModule::LookupFunction( |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 448 | const std::string& name, iree_vm_function_linkage_t linkage) { |
| 449 | iree_vm_function_t f; |
Ben Vanik | fcd368b | 2019-12-20 10:55:37 -0800 | [diff] [blame] | 450 | auto status = iree_vm_module_lookup_function_by_name( |
Scott Todd | 60b0764 | 2023-06-15 09:41:01 -0700 | [diff] [blame] | 451 | raw_ptr(), linkage, |
| 452 | {name.data(), static_cast<iree_host_size_t>(name.size())}, &f); |
Ben Vanik | af5401f | 2020-08-06 21:31:15 -0700 | [diff] [blame] | 453 | if (iree_status_is_not_found(status)) { |
| 454 | iree_status_ignore(status); |
Ben Vanik | df89eb0 | 2021-06-20 18:01:16 -0700 | [diff] [blame] | 455 | return std::nullopt; |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 456 | } |
| 457 | CheckApiStatus(status, "Error looking up function"); |
| 458 | return f; |
| 459 | } |
| 460 | |
Stella Laurenzo | 480e6ef | 2019-12-23 10:07:52 -0800 | [diff] [blame] | 461 | //------------------------------------------------------------------------------ |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 462 | // VmRef |
| 463 | //------------------------------------------------------------------------------ |
| 464 | |
| 465 | const char* const VmRef::kRefAttr = "__iree_vm_ref__"; |
| 466 | const char* const VmRef::kCastAttr = "__iree_vm_cast__"; |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 467 | const char* const VmRef::kTypeAttr = "__iree_vm_type__"; |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 468 | |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 469 | py::object VmRef::Deref(py::object ref_object_class, bool optional) { |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 470 | py::object casted = ref_object_class.attr(kCastAttr)(this); |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 471 | if (!optional && casted.is_none()) { |
| 472 | throw py::type_error("Cannot dereference to specific type"); |
| 473 | } |
| 474 | return casted; |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 475 | } |
| 476 | |
| 477 | bool VmRef::IsInstance(py::object ref_object_class) { |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 478 | auto type = py::cast<iree_vm_ref_type_t>(ref_object_class.attr(kTypeAttr)()); |
| 479 | return type == ref_.type; |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 480 | } |
| 481 | |
| 482 | std::string VmRef::ToString() { |
| 483 | if (!ref_.ptr) { |
| 484 | return "<VmRef NULL>"; |
| 485 | } |
| 486 | iree_string_view_t type_name = iree_vm_ref_type_name(ref_.type); |
| 487 | std::stringstream ss; |
| 488 | ss << "<VmRef "; |
| 489 | ss.write(type_name.data, type_name.size); |
| 490 | ss << " at " << std::hex << "0x" << reinterpret_cast<uintptr_t>(ref_.ptr) |
| 491 | << ">"; |
| 492 | return ss.str(); |
| 493 | } |
| 494 | |
| 495 | //------------------------------------------------------------------------------ |
Stella Laurenzo | 480e6ef | 2019-12-23 10:07:52 -0800 | [diff] [blame] | 496 | // VmVariantList |
| 497 | //------------------------------------------------------------------------------ |
| 498 | |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 499 | void VmVariantList::PushFloat(double fvalue) { |
| 500 | // Note that Python floats are f64. |
| 501 | iree_vm_value_t value = iree_vm_value_make_f64(fvalue); |
| 502 | CheckApiStatus(iree_vm_list_push_value(raw_ptr(), &value), |
| 503 | "Could not push float"); |
| 504 | } |
| 505 | |
| 506 | void VmVariantList::PushInt(int64_t ivalue) { |
| 507 | // Note that Python ints are unbounded, so just use the largest type we |
| 508 | // have. |
| 509 | iree_vm_value_t value = iree_vm_value_make_i64(ivalue); |
| 510 | CheckApiStatus(iree_vm_list_push_value(raw_ptr(), &value), |
| 511 | "Could not push int"); |
| 512 | } |
| 513 | |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 514 | void VmVariantList::PushList(VmVariantList& other) { |
| 515 | iree_vm_ref_t retained = iree_vm_list_retain_ref(other.raw_ptr()); |
| 516 | iree_vm_list_push_ref_move(raw_ptr(), &retained); |
| 517 | } |
| 518 | |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 519 | void VmVariantList::PushRef(py::handle ref_or_object) { |
| 520 | py::object py_ref = ref_or_object.attr(VmRef::kRefAttr); |
| 521 | VmRef& ref = py::cast<VmRef&>(py_ref); |
| 522 | CheckApiStatus(iree_vm_list_push_ref_retain(raw_ptr(), &ref.ref()), |
| 523 | "Failed to push ref"); |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 524 | } |
| 525 | |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 526 | py::object VmVariantList::GetAsList(int index) { |
Stella Laurenzo | 5ba8a7a | 2021-05-11 21:29:23 -0700 | [diff] [blame] | 527 | iree_vm_ref_t ref = {0}; |
| 528 | CheckApiStatus(iree_vm_list_get_ref_assign(raw_ptr(), index, &ref), |
| 529 | "Could not access list element"); |
| 530 | iree_vm_list_t* sub_list = NULL; |
| 531 | CheckApiStatus(iree_vm_list_check_deref(ref, &sub_list), |
| 532 | "Could not deref list (wrong type?)"); |
| 533 | iree_vm_list_retain(sub_list); |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 534 | return py::cast(VmVariantList::StealFromRawPtr(sub_list)); |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 535 | } |
| 536 | |
| 537 | py::object VmVariantList::GetVariant(int index) { |
| 538 | iree_vm_variant_t v = iree_vm_variant_empty(); |
Ben Vanik | 78fc0e3 | 2023-03-06 16:20:08 -0800 | [diff] [blame] | 539 | CheckApiStatus(iree_vm_list_get_variant_assign(raw_ptr(), index, &v), |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 540 | "Could not access list element"); |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 541 | if (iree_vm_variant_is_empty(v)) { |
| 542 | return py::none(); |
| 543 | } else if (iree_vm_variant_is_value(v)) { |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 544 | // Convert a value type. |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 545 | switch (iree_vm_type_def_as_value(v.type)) { |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 546 | case IREE_VM_VALUE_TYPE_I8: |
| 547 | return py::cast(v.i8); |
| 548 | case IREE_VM_VALUE_TYPE_I16: |
| 549 | return py::cast(v.i16); |
| 550 | case IREE_VM_VALUE_TYPE_I32: |
| 551 | return py::cast(v.i32); |
| 552 | case IREE_VM_VALUE_TYPE_I64: |
| 553 | return py::cast(v.i64); |
| 554 | case IREE_VM_VALUE_TYPE_F32: |
| 555 | return py::cast(v.f32); |
| 556 | case IREE_VM_VALUE_TYPE_F64: |
| 557 | return py::cast(v.f64); |
| 558 | default: |
| 559 | throw RaiseValueError("Unsupported VM value type conversion"); |
| 560 | } |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 561 | } else if (iree_vm_variant_is_ref(v)) { |
| 562 | VmRef ref; |
| 563 | iree_vm_ref_retain(&v.ref, &ref.ref()); |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 564 | return py::cast(ref, py::rv_policy::move); |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 565 | } |
| 566 | |
| 567 | throw RaiseValueError("Unsupported VM to Python Type Conversion"); |
Stella Laurenzo | 5ba8a7a | 2021-05-11 21:29:23 -0700 | [diff] [blame] | 568 | } |
| 569 | |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 570 | py::object VmVariantList::GetAsSerializedTraceValue(int index) { |
| 571 | iree_vm_variant_t v = iree_vm_variant_empty(); |
Ben Vanik | 78fc0e3 | 2023-03-06 16:20:08 -0800 | [diff] [blame] | 572 | CheckApiStatus(iree_vm_list_get_variant_assign(raw_ptr(), index, &v), |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 573 | "Could not access list element"); |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 574 | if (iree_vm_variant_is_empty(v)) { |
| 575 | py::dict record; |
| 576 | record["type"] = "null"; |
| 577 | return std::move(record); |
| 578 | } else if (iree_vm_variant_is_value(v)) { |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 579 | // Convert a value type. |
| 580 | py::dict record; |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 581 | switch (iree_vm_type_def_as_value(v.type)) { |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 582 | case IREE_VM_VALUE_TYPE_I8: |
| 583 | record["i8"] = py::cast(v.i8); |
| 584 | break; |
| 585 | case IREE_VM_VALUE_TYPE_I16: |
| 586 | record["i16"] = py::cast(v.i16); |
| 587 | break; |
| 588 | case IREE_VM_VALUE_TYPE_I32: |
| 589 | record["i32"] = py::cast(v.i32); |
| 590 | break; |
| 591 | case IREE_VM_VALUE_TYPE_I64: |
| 592 | record["i64"] = py::cast(v.i64); |
| 593 | break; |
| 594 | case IREE_VM_VALUE_TYPE_F32: |
| 595 | record["f32"] = py::cast(v.f32); |
| 596 | break; |
| 597 | case IREE_VM_VALUE_TYPE_F64: |
| 598 | record["f64"] = py::cast(v.f64); |
| 599 | break; |
| 600 | default: |
| 601 | throw RaiseValueError("Unsupported VM value type conversion"); |
| 602 | } |
| 603 | record["type"] = py::cast("value"); |
| 604 | return std::move(record); |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 605 | } else if (iree_vm_variant_is_ref(v)) { |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 606 | // Convert reference type. |
| 607 | if (iree_vm_list_isa(v.ref)) { |
| 608 | py::dict record; |
Ben Vanik | abe6c76 | 2021-06-27 21:57:07 -0700 | [diff] [blame] | 609 | record["type"] = "vm.list"; |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 610 | py::list items; |
| 611 | iree_vm_list_t* sub_list = NULL; |
| 612 | CheckApiStatus(iree_vm_list_check_deref(v.ref, &sub_list), |
| 613 | "Could not deref list (wrong type?)"); |
| 614 | iree_vm_list_retain(sub_list); |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 615 | VmVariantList sub_list_object = VmVariantList::StealFromRawPtr(sub_list); |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 616 | for (int i = 0, e = sub_list_object.size(); i < e; ++i) { |
| 617 | items.append(sub_list_object.GetAsSerializedTraceValue(i)); |
| 618 | } |
| 619 | record["items"] = std::move(items); |
| 620 | return std::move(record); |
| 621 | } else if (iree_hal_buffer_view_isa(v.ref)) { |
| 622 | py::dict record; |
Ben Vanik | abe6c76 | 2021-06-27 21:57:07 -0700 | [diff] [blame] | 623 | record["type"] = "hal.buffer_view"; |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 624 | iree_hal_buffer_view_t* buffer_view = iree_hal_buffer_view_deref(v.ref); |
| 625 | if (!buffer_view) { |
| 626 | throw RaiseValueError( |
| 627 | "Could not deref result buffer view (wrong type?)"); |
| 628 | } |
| 629 | iree_hal_buffer_t* raw_buffer = iree_hal_buffer_view_buffer(buffer_view); |
| 630 | if (!raw_buffer) { |
| 631 | throw RaiseValueError("Could not deref result buffer (wrong type?)"); |
| 632 | } |
| 633 | |
| 634 | // Extract dims from the buffer view. |
Scott Todd | 60b0764 | 2023-06-15 09:41:01 -0700 | [diff] [blame] | 635 | iree_host_size_t rank = 0; |
Ben Vanik | 49fee30 | 2022-05-16 21:18:59 -0700 | [diff] [blame] | 636 | std::vector<iree_hal_dim_t> dims(6); |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 637 | iree_status_t status = iree_hal_buffer_view_shape( |
| 638 | buffer_view, dims.capacity(), dims.data(), &rank); |
| 639 | if (iree_status_is_out_of_range(status)) { |
| 640 | dims.resize(rank); |
| 641 | status = iree_hal_buffer_view_shape(buffer_view, dims.capacity(), |
| 642 | dims.data(), &rank); |
| 643 | } |
| 644 | CheckApiStatus(status, "Error extracting shape"); |
| 645 | dims.resize(rank); |
| 646 | record["shape"] = py::cast(std::move(dims)); |
| 647 | |
| 648 | // Element type. |
| 649 | iree_hal_element_type_t element_type = |
| 650 | iree_hal_buffer_view_element_type(buffer_view); |
Ben Vanik | 40876b9 | 2023-03-06 11:26:53 -0800 | [diff] [blame] | 651 | char element_type_str[64] = {0}; |
| 652 | iree_host_size_t element_type_length = 0; |
| 653 | CheckApiStatus( |
| 654 | iree_hal_format_element_type(element_type, sizeof(element_type_str), |
| 655 | element_type_str, &element_type_length), |
| 656 | "Formatting element type"); |
| 657 | record["element_type"] = |
| 658 | std::string(element_type_str, element_type_length); |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 659 | |
| 660 | // Map memory. |
| 661 | iree_device_size_t byte_length = iree_hal_buffer_byte_length(raw_buffer); |
Ben Vanik | eff1bb5 | 2021-12-16 11:04:21 -0800 | [diff] [blame] | 662 | iree_hal_buffer_mapping_t mapped_memory = {{0}}; |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 663 | CheckApiStatus(iree_hal_buffer_map_range( |
Ben Vanik | b036c63 | 2021-12-14 14:21:16 -0800 | [diff] [blame] | 664 | raw_buffer, IREE_HAL_MAPPING_MODE_SCOPED, |
| 665 | IREE_HAL_MEMORY_ACCESS_READ, 0 /* element_offset */, |
| 666 | byte_length, &mapped_memory), |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 667 | "Could not map memory"); |
| 668 | record["contents"] = |
| 669 | py::bytes(reinterpret_cast<const char*>(mapped_memory.contents.data), |
| 670 | mapped_memory.contents.data_length); |
| 671 | iree_hal_buffer_unmap_range(&mapped_memory); |
| 672 | |
| 673 | return std::move(record); |
| 674 | } |
| 675 | } |
| 676 | |
| 677 | throw RaiseValueError("Unsupported VM to Python Type Conversion"); |
| 678 | } |
| 679 | |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 680 | py::object VmVariantList::GetAsRef(int index) { |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 681 | iree_vm_variant_t v = iree_vm_variant_empty(); |
Ben Vanik | 78fc0e3 | 2023-03-06 16:20:08 -0800 | [diff] [blame] | 682 | CheckApiStatus(iree_vm_list_get_variant_assign(raw_ptr(), index, &v), |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 683 | "Could not access list element"); |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 684 | if (!iree_vm_variant_is_ref(v)) { |
| 685 | throw std::invalid_argument("list element is not a ref"); |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 686 | } |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 687 | VmRef ref; |
| 688 | iree_vm_ref_retain(&v.ref, &ref.ref()); |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 689 | return py::cast(ref, py::rv_policy::move); |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 690 | } |
| 691 | |
| 692 | py::object VmVariantList::GetAsObject(int index, py::object clazz) { |
| 693 | return clazz.attr(VmRef::kCastAttr)(GetAsRef(index)); |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 694 | } |
| 695 | |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 696 | namespace { |
| 697 | |
Ben Vanik | b9b794b | 2021-06-19 20:11:08 -0700 | [diff] [blame] | 698 | static std::string ToHexString(const uint8_t* data, size_t length) { |
| 699 | static constexpr char kHexChars[] = {'0', '1', '2', '3', '4', '5', '6', '7', |
| 700 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
| 701 | std::string s(length * 2, ' '); |
| 702 | for (size_t i = 0; i < length; ++i) { |
| 703 | s[2 * i + 0] = kHexChars[(data[i] & 0xF0) >> 4]; |
| 704 | s[2 * i + 1] = kHexChars[(data[i] & 0x0F) >> 0]; |
| 705 | } |
| 706 | return s; |
| 707 | } |
| 708 | static std::string ToHexString(uint32_t value) { |
| 709 | return ToHexString((const uint8_t*)&value, sizeof(value)); |
| 710 | } |
| 711 | |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 712 | void AppendListContents(std::string& out, iree_vm_list_t* list, |
| 713 | std::unordered_set<iree_vm_list_t*>& visited) { |
| 714 | for (iree_host_size_t i = 0, e = iree_vm_list_size(list); i < e; ++i) { |
| 715 | iree_vm_variant_t variant = iree_vm_variant_empty(); |
Ben Vanik | 78fc0e3 | 2023-03-06 16:20:08 -0800 | [diff] [blame] | 716 | iree_status_t status = iree_vm_list_get_variant_assign(list, i, &variant); |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 717 | if (!iree_status_is_ok(status)) { |
| 718 | iree_status_ignore(status); |
| 719 | out.append("Error"); |
| 720 | continue; |
| 721 | } |
| 722 | if (i > 0) out.append(", "); |
| 723 | |
| 724 | if (iree_vm_variant_is_value(variant)) { |
Sean Silva | bef60b4 | 2021-09-09 20:51:05 -0700 | [diff] [blame] | 725 | // Convert a value type to a string. |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 726 | switch (iree_vm_type_def_as_value(variant.type)) { |
Sean Silva | bef60b4 | 2021-09-09 20:51:05 -0700 | [diff] [blame] | 727 | case IREE_VM_VALUE_TYPE_I8: { |
| 728 | out += std::to_string(variant.i8); |
| 729 | break; |
| 730 | } |
| 731 | case IREE_VM_VALUE_TYPE_I16: { |
| 732 | out += std::to_string(variant.i16); |
| 733 | break; |
| 734 | } |
| 735 | case IREE_VM_VALUE_TYPE_I32: { |
| 736 | out += std::to_string(variant.i32); |
| 737 | break; |
| 738 | } |
| 739 | case IREE_VM_VALUE_TYPE_I64: { |
| 740 | out += std::to_string(variant.i64); |
| 741 | break; |
| 742 | } |
| 743 | case IREE_VM_VALUE_TYPE_F32: { |
| 744 | out += std::to_string(variant.f32); |
| 745 | break; |
| 746 | } |
| 747 | case IREE_VM_VALUE_TYPE_F64: { |
| 748 | out += std::to_string(variant.f64); |
| 749 | break; |
| 750 | } |
| 751 | default: |
| 752 | throw RaiseValueError("Unsupported VM value type to string"); |
| 753 | } |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 754 | } else if (iree_vm_variant_is_ref(variant)) { |
| 755 | // Pretty print a subset of ABI impacting known types. |
| 756 | if (iree_hal_buffer_isa(variant.ref)) { |
| 757 | auto* hal_buffer = iree_hal_buffer_deref(variant.ref); |
| 758 | assert(hal_buffer); |
Ben Vanik | b9b794b | 2021-06-19 20:11:08 -0700 | [diff] [blame] | 759 | out += std::string("HalBuffer(") + |
| 760 | std::to_string(iree_hal_buffer_byte_length(hal_buffer)) + ")"; |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 761 | } else if (iree_hal_buffer_view_isa(variant.ref)) { |
| 762 | auto hal_bv = iree_hal_buffer_view_deref(variant.ref); |
Ben Vanik | b9b794b | 2021-06-19 20:11:08 -0700 | [diff] [blame] | 763 | out += "HalBufferView("; |
Ben Vanik | 49fee30 | 2022-05-16 21:18:59 -0700 | [diff] [blame] | 764 | std::vector<iree_hal_dim_t> shape( |
| 765 | iree_hal_buffer_view_shape_rank(hal_bv)); |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 766 | iree_hal_buffer_view_shape(hal_bv, shape.size(), shape.data(), nullptr); |
Ben Vanik | b9b794b | 2021-06-19 20:11:08 -0700 | [diff] [blame] | 767 | for (size_t i = 0; i < shape.size(); ++i) { |
| 768 | if (i > 0) out += 'x'; |
| 769 | out += std::to_string(shape[i]); |
| 770 | } |
| 771 | out += ":0x" + |
| 772 | ToHexString(static_cast<uint32_t>( |
| 773 | iree_hal_buffer_view_element_type(hal_bv))) + |
| 774 | ")"; |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 775 | } else if (iree_vm_list_isa(variant.ref)) { |
| 776 | out.append("List["); |
| 777 | iree_vm_list_t* sub_list = iree_vm_list_deref(variant.ref); |
| 778 | if (visited.insert(sub_list).second) { |
| 779 | AppendListContents(out, sub_list, visited); |
| 780 | } else { |
| 781 | out.append("...circular..."); |
| 782 | } |
| 783 | out.append("]"); |
Stanley Winata | 094d9ba | 2023-10-23 22:37:55 -0700 | [diff] [blame] | 784 | } else if (iree_hal_fence_isa(variant.ref)) { |
| 785 | out.append("fence("); |
| 786 | auto* hal_fence = iree_hal_fence_deref(variant.ref); |
| 787 | iree_host_size_t timepoint_count = |
| 788 | iree_hal_fence_timepoint_count(hal_fence); |
| 789 | out.append(std::to_string(timepoint_count) + ")"); |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 790 | } else { |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 791 | out += "Unknown(" + |
| 792 | std::to_string(iree_vm_type_def_as_ref(variant.type)) + ")"; |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 793 | } |
| 794 | } else { |
| 795 | out.append("None"); |
| 796 | } |
| 797 | } |
| 798 | } |
| 799 | |
| 800 | } // namespace |
| 801 | |
Stella Laurenzo | 480e6ef | 2019-12-23 10:07:52 -0800 | [diff] [blame] | 802 | std::string VmVariantList::DebugString() const { |
| 803 | // The variant list API requires mutability, so we const cast to it internally |
| 804 | // so we can maintain a const DebugString() for callers. |
| 805 | auto mutable_this = const_cast<VmVariantList*>(this); |
Ben Vanik | b9b794b | 2021-06-19 20:11:08 -0700 | [diff] [blame] | 806 | std::string s = |
| 807 | std::string("<VmVariantList(") + std::to_string(size()) + "): ["; |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 808 | iree_vm_list_t* list = mutable_this->raw_ptr(); |
| 809 | std::unordered_set<iree_vm_list_t*> visited; |
| 810 | visited.insert(list); |
| 811 | AppendListContents(s, list, visited); |
| 812 | s.append("]>"); |
Stella Laurenzo | 480e6ef | 2019-12-23 10:07:52 -0800 | [diff] [blame] | 813 | return s; |
| 814 | } |
| 815 | |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 816 | void SetupVmBindings(nanobind::module_ m) { |
Ben Vanik | 4c0a53e | 2020-06-16 10:33:19 -0700 | [diff] [blame] | 817 | py::enum_<enum iree_vm_function_linkage_e>(m, "Linkage") |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 818 | .value("INTERNAL", IREE_VM_FUNCTION_LINKAGE_INTERNAL) |
| 819 | .value("IMPORT", IREE_VM_FUNCTION_LINKAGE_IMPORT) |
Ben Vanik | 79495f4 | 2022-04-18 10:49:21 -0700 | [diff] [blame] | 820 | .value("IMPORT_OPTIONAL", IREE_VM_FUNCTION_LINKAGE_IMPORT_OPTIONAL) |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 821 | .value("EXPORT", IREE_VM_FUNCTION_LINKAGE_EXPORT) |
Ben Vanik | 96c9bfb | 2024-07-08 15:44:51 -0700 | [diff] [blame] | 822 | .value("EXPORT_OPTIONAL", IREE_VM_FUNCTION_LINKAGE_EXPORT_OPTIONAL) |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 823 | .export_values(); |
| 824 | |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 825 | auto vm_buffer = py::class_<VmBuffer>(m, "VmBuffer"); |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 826 | VmRef::BindRefProtocol(vm_buffer, iree_vm_buffer_type, |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 827 | iree_vm_buffer_retain_ref, iree_vm_buffer_deref, |
| 828 | iree_vm_buffer_isa); |
Stella Laurenzo | 4f40080 | 2024-04-04 09:55:24 -0700 | [diff] [blame] | 829 | BindBufferProtocol<VmBuffer>(vm_buffer); |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 830 | vm_buffer |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 831 | .def( |
| 832 | "__init__", |
| 833 | [](VmBuffer* self, iree_host_size_t length, |
| 834 | iree_host_size_t alignment, bool is_mutable) { |
| 835 | iree_vm_buffer_access_t access = 0; |
| 836 | if (is_mutable) { |
| 837 | access |= IREE_VM_BUFFER_ACCESS_MUTABLE; |
| 838 | } |
| 839 | iree_vm_buffer_t* raw_buffer; |
| 840 | CheckApiStatus( |
| 841 | iree_vm_buffer_create(access, length, alignment, |
| 842 | iree_allocator_system(), &raw_buffer), |
| 843 | "Error creating buffer"); |
| 844 | |
| 845 | new (self) VmBuffer(); |
| 846 | *self = VmBuffer::StealFromRawPtr(raw_buffer); |
| 847 | }, |
| 848 | py::arg("length"), py::arg("alignment") = 0, |
| 849 | py::arg("mutable") = true) |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 850 | .def("__repr__", [](VmBuffer& self) { |
| 851 | std::stringstream ss; |
| 852 | ss << "<VmBuffer size " << self.raw_ptr()->data.data_length << " at 0x" |
| 853 | << std::hex << reinterpret_cast<uintptr_t>(self.raw_ptr()->data.data) |
| 854 | << ">"; |
| 855 | return ss.str(); |
| 856 | }); |
| 857 | |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 858 | // Mutation and inspection of the variant list is mostly opaque to python. |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 859 | auto vm_list = py::class_<VmVariantList>(m, "VmVariantList"); |
Ben Vanik | 09630d6 | 2023-04-13 14:21:40 -0700 | [diff] [blame] | 860 | VmRef::BindRefProtocol(vm_list, iree_vm_list_type, iree_vm_list_retain_ref, |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 861 | iree_vm_list_deref, iree_vm_list_isa); |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 862 | vm_list |
| 863 | // User Methods. |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 864 | .def( |
| 865 | "__init__", |
| 866 | [](VmVariantList* self, iree_host_size_t capacity) { |
| 867 | new (self) VmVariantList(); |
| 868 | *self = VmVariantList::Create(capacity); |
| 869 | }, |
| 870 | py::arg("capacity")) |
| 871 | .def_prop_ro("size", &VmVariantList::size) |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 872 | .def("__len__", &VmVariantList::size) |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 873 | .def("get_as_ref", &VmVariantList::GetAsRef) |
| 874 | .def("get_as_object", &VmVariantList::GetAsObject) |
Stella Laurenzo | 5ba8a7a | 2021-05-11 21:29:23 -0700 | [diff] [blame] | 875 | .def("get_as_list", &VmVariantList::GetAsList) |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 876 | .def("get_variant", &VmVariantList::GetVariant) |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 877 | .def("get_serialized_trace_value", |
| 878 | &VmVariantList::GetAsSerializedTraceValue) |
Stella Laurenzo | 9995604 | 2021-05-14 10:32:38 -0700 | [diff] [blame] | 879 | .def("push_float", &VmVariantList::PushFloat) |
| 880 | .def("push_int", &VmVariantList::PushInt) |
Stella Laurenzo | 397c4fc | 2021-05-08 00:19:22 -0700 | [diff] [blame] | 881 | .def("push_list", &VmVariantList::PushList) |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 882 | .def("push_ref", &VmVariantList::PushRef) |
Stella Laurenzo | 480e6ef | 2019-12-23 10:07:52 -0800 | [diff] [blame] | 883 | .def("__repr__", &VmVariantList::DebugString); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 884 | |
| 885 | py::class_<iree_vm_function_t>(m, "VmFunction") |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 886 | .def_ro("linkage", &iree_vm_function_t::linkage) |
| 887 | .def_ro("ordinal", &iree_vm_function_t::ordinal) |
| 888 | .def_prop_ro("name", |
| 889 | [](iree_vm_function_t& self) { |
| 890 | iree_string_view_t name = iree_vm_function_name(&self); |
| 891 | return py::str(name.data, name.size); |
| 892 | }) |
| 893 | .def_prop_ro("module_name", |
| 894 | [](iree_vm_function_t& self) { |
| 895 | iree_string_view_t name = iree_vm_module_name(self.module); |
| 896 | return py::str(name.data, name.size); |
| 897 | }) |
| 898 | .def_prop_ro("reflection", |
| 899 | [](iree_vm_function_t& self) { |
| 900 | return GetFunctionReflectionDict(self); |
| 901 | }) |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 902 | .def("__repr__", [](iree_vm_function_t& self) { |
| 903 | iree_string_view_t name = iree_vm_function_name(&self); |
| 904 | std::string repr("<VmFunction "); |
| 905 | repr.append(name.data, name.size); |
| 906 | |
| 907 | iree_vm_function_signature_t sig = iree_vm_function_signature(&self); |
| 908 | repr.append("("); |
| 909 | repr.append(sig.calling_convention.data, sig.calling_convention.size); |
| 910 | repr.append("), reflection = "); |
| 911 | py::dict reflection = GetFunctionReflectionDict(self); |
| 912 | repr.append(py::cast<std::string>(py::repr(reflection))); |
| 913 | repr.append(">"); |
| 914 | return repr; |
| 915 | }); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 916 | |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 917 | py::class_<VmInstance>(m, "VmInstance").def("__init__", [](VmInstance* self) { |
| 918 | new (self) VmInstance(); |
| 919 | *self = VmInstance::Create(); |
| 920 | }); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 921 | py::class_<VmContext>(m, "VmContext") |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 922 | .def( |
| 923 | "__init__", |
| 924 | [](VmContext* self, VmInstance* instance, |
| 925 | std::optional<std::vector<VmModule*>> modules) { |
| 926 | new (self) VmContext(); |
| 927 | *self = VmContext::Create(instance, modules); |
| 928 | }, |
| 929 | py::arg("instance"), |
| 930 | py::arg("modules") = std::optional<std::vector<VmModule*>>()) |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 931 | .def("register_modules", &VmContext::RegisterModules) |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 932 | .def_prop_ro("context_id", &VmContext::context_id) |
Stella Laurenzo | d5efc48 | 2019-12-21 04:59:36 -0800 | [diff] [blame] | 933 | .def("invoke", &VmContext::Invoke); |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 934 | |
| 935 | py::class_<VmModule>(m, "VmModule") |
Eugene Zhulenev | 6f81ceb | 2023-05-16 19:23:26 -0700 | [diff] [blame] | 936 | .def_static("resolve_module_dependency", |
| 937 | &VmModule::ResolveModuleDependency) |
Stella Laurenzo | 89a41d9 | 2023-06-19 19:17:42 -0700 | [diff] [blame] | 938 | .def_static("from_flatbuffer", &VmModule::FromBuffer, py::arg("instance"), |
| 939 | py::arg("buffer"), py::arg("warn_if_copy") = true, |
| 940 | kFromBufferDocstring) |
| 941 | .def_static("from_buffer", &VmModule::FromBuffer, py::arg("instance"), |
| 942 | py::arg("buffer"), py::arg("warn_if_copy") = true, |
| 943 | kFromBufferDocstring) |
| 944 | .def_static("copy_buffer", &VmModule::CopyBuffer, py::arg("instance"), |
| 945 | py::arg("buffer"), kCopyBufferDocstring) |
| 946 | .def_static("wrap_buffer", &VmModule::WrapBuffer, py::arg("instance"), |
| 947 | py::arg("buffer"), py::arg("destroy_callback") = py::none(), |
| 948 | py::arg("close_buffer") = false, kWrapBufferDocstring) |
| 949 | .def_static("mmap", &VmModule::MMap, py::arg("instance"), |
| 950 | py::arg("filepath"), py::arg("destroy_callback") = py::none(), |
| 951 | kMMapDocstring) |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 952 | .def_prop_ro("name", &VmModule::name) |
| 953 | .def_prop_ro("version", |
| 954 | [](VmModule& self) { |
| 955 | iree_vm_module_signature_t sig = |
| 956 | iree_vm_module_signature(self.raw_ptr()); |
| 957 | return sig.version; |
| 958 | }) |
Stella Laurenzo | dc513de | 2019-12-19 10:19:57 -0800 | [diff] [blame] | 959 | .def("lookup_function", &VmModule::LookupFunction, py::arg("name"), |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 960 | py::arg("linkage") = IREE_VM_FUNCTION_LINKAGE_EXPORT) |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 961 | .def_prop_ro( |
Stella Laurenzo | 7304521 | 2021-06-25 16:18:57 -0700 | [diff] [blame] | 962 | "stashed_flatbuffer_blob", |
| 963 | [](VmModule& self) { return self.get_stashed_flatbuffer_blob(); }) |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 964 | .def_prop_ro("function_names", |
| 965 | [](VmModule& self) { |
| 966 | py::list names; |
| 967 | iree_vm_module_signature_t sig = |
| 968 | iree_vm_module_signature(self.raw_ptr()); |
| 969 | for (size_t ordinal = 0; |
| 970 | ordinal < sig.export_function_count; ++ordinal) { |
| 971 | iree_vm_function_t f; |
| 972 | auto status = iree_vm_module_lookup_function_by_ordinal( |
| 973 | self.raw_ptr(), IREE_VM_FUNCTION_LINKAGE_EXPORT, |
| 974 | ordinal, &f); |
| 975 | if (iree_status_is_not_found(status)) { |
| 976 | iree_status_ignore(status); |
| 977 | break; |
| 978 | } |
| 979 | CheckApiStatus(status, "Error enumerating module"); |
| 980 | iree_string_view_t fname = iree_vm_function_name(&f); |
| 981 | py::str name(fname.data, fname.size); |
| 982 | names.append(name); |
| 983 | } |
| 984 | return names; |
| 985 | }) |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 986 | .def("__repr__", [](VmModule& self) { |
| 987 | std::string repr("<VmModule "); |
| 988 | iree_string_view_t name = iree_vm_module_name(self.raw_ptr()); |
| 989 | repr.append(name.data, name.size); |
| 990 | |
| 991 | iree_vm_module_signature_t sig = |
| 992 | iree_vm_module_signature(self.raw_ptr()); |
| 993 | repr.append(" : ["); |
| 994 | for (size_t ordinal = 0; ordinal < sig.export_function_count; |
| 995 | ++ordinal) { |
| 996 | iree_vm_function_t f; |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 997 | auto status = iree_vm_module_lookup_function_by_ordinal( |
Ben Vanik | 6c4dd5b | 2021-10-05 15:29:23 -0700 | [diff] [blame] | 998 | self.raw_ptr(), IREE_VM_FUNCTION_LINKAGE_EXPORT, ordinal, &f); |
Stella Laurenzo | aeaaad6 | 2021-05-03 13:44:52 -0700 | [diff] [blame] | 999 | if (iree_status_is_not_found(status)) { |
| 1000 | iree_status_ignore(status); |
| 1001 | break; |
| 1002 | } |
| 1003 | CheckApiStatus(status, "Error enumerating module"); |
| 1004 | iree_string_view_t fname = iree_vm_function_name(&f); |
| 1005 | if (ordinal > 0) { |
| 1006 | repr.append(", "); |
| 1007 | } |
| 1008 | repr.append(fname.data, fname.size); |
| 1009 | } |
| 1010 | repr.append("]"); |
| 1011 | repr.append(">"); |
| 1012 | return repr; |
| 1013 | }); |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 1014 | |
| 1015 | py::class_<VmRef>(m, "VmRef") |
| 1016 | .def("isinstance", &VmRef::IsInstance) |
Stella Laurenzo | 7b06657 | 2022-07-31 18:38:15 -0700 | [diff] [blame] | 1017 | .def("deref", &VmRef::Deref, py::arg("value"), |
| 1018 | py::arg("optional") = false) |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 1019 | .def("__repr__", &VmRef::ToString) |
Stella Laurenzo | abe91fa | 2023-06-26 16:57:30 -0700 | [diff] [blame] | 1020 | .def_prop_ro(VmRef::kRefAttr, [](py::object self) { return self; }) |
Stella Laurenzo | 95dff50 | 2022-07-31 14:16:12 -0700 | [diff] [blame] | 1021 | .def("__eq__", |
| 1022 | [](VmRef& self, VmRef& other) { |
| 1023 | return self.ref().ptr == other.ref().ptr; |
| 1024 | }) |
| 1025 | .def("__eq__", [](VmRef& self, py::object& other) { return false; }); |
powderluv | 2e2fc9c | 2019-10-23 10:09:44 -0700 | [diff] [blame] | 1026 | } |
| 1027 | |
| 1028 | } // namespace python |
| 1029 | } // namespace iree |