| // Copyright 2023 The IREE Authors | |
| // | |
| // Licensed under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| #ifndef IREE_HAL_LOCAL_EXECUTABLE_PLUGIN_H_ | |
| #define IREE_HAL_LOCAL_EXECUTABLE_PLUGIN_H_ | |
| //===----------------------------------------------------------------------===// | |
| // // | |
| // ██╗░░░██╗███╗░░██╗░██████╗████████╗░█████╗░██████╗░██╗░░░░░███████╗ // | |
| // ██║░░░██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██╔══██╗██║░░░░░██╔════╝ // | |
| // ██║░░░██║██╔██╗██║╚█████╗░░░░██║░░░███████║██████╦╝██║░░░░░█████╗░░ // | |
| // ██║░░░██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██╔══██╗██║░░░░░██╔══╝░░ // | |
| // ╚██████╔╝██║░╚███║██████╔╝░░░██║░░░██║░░██║██████╦╝███████╗███████╗ // | |
| // ░╚═════╝░╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝╚═════╝░╚══════╝╚══════╝ // | |
| // // | |
| //===----------------------------------------------------------------------===// | |
| //===----------------------------------------------------------------------===// | |
| // iree_hal_executable_plugin_*_t | |
| //===----------------------------------------------------------------------===// | |
| // An interface providing lifetime management and import resolution for | |
| // externally-defined executable library imports. Plugins can either be | |
| // statically or dynamically linked into the runtime consuming them. | |
| // | |
| // Plugins only need to be used when lifetime management is required and | |
| // otherwise users can register a much simpler import provider using | |
| // iree_hal_executable_plugin_manager_register_provider. For plugins loaded | |
| // from dynamic libraries, conditionally enabled, or needing lifetime management | |
| // using this plugin API and iree_hal_executable_plugin_manager_register_plugin | |
| // will ensure that import resolution is consistent and safe. | |
| // | |
| // Import resolution is intended to scale from function pointer lookup in .rdata | |
| // to ahead-of-time JITs that may compile functions during resolution or return | |
| // stubs that are JITed on-demand. See iree_hal_executable_plugin_v0_t::resolve | |
| // for more information about the resolution process and how multiple plugins | |
| // and import providers can resolve symbols. | |
| // NOTE: this file is designed to be a standalone header: it is intended to be | |
| // used by external projects that may build without the IREE source code. | |
| // Include nothing but headers always available on all platforms/toolchains. | |
| #include <stdbool.h> | |
| #include <stddef.h> | |
| #include <stdint.h> | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif // __cplusplus | |
| //===----------------------------------------------------------------------===// | |
| // Runtime feature support metadata | |
| //===----------------------------------------------------------------------===// | |
| // Defines a bitfield of features that the plugin requires or supports. | |
| enum iree_hal_executable_plugin_feature_bits_t { | |
| IREE_HAL_EXECUTABLE_PLUGIN_FEATURE_NONE = 0u, | |
| // Plugin is built standalone and does not require any system facilities | |
| // beyond those provided by the plugin API. | |
| // | |
| // Nearly all plugins should be of this form in order to allow for portable | |
| // deployment and robust loading/execution; if a plugin is just a list of | |
| // pure functions there's very few ways it can fail at runtime. | |
| IREE_HAL_EXECUTABLE_PLUGIN_FEATURE_STANDALONE = 1u << 0, | |
| // Plugin is built against the IREE runtime with IREE_STATUS_MODE > 0 and | |
| // iree_hal_executable_plugin_status_t will pass iree_status_t objects instead | |
| // of just status codes. The hosting runtime loading the plugin must also be | |
| // compiled with IREE_STATUS_MODE > 0. | |
| IREE_HAL_EXECUTABLE_PLUGIN_FEATURE_FULL_STATUS = 1u << 1, | |
| }; | |
| typedef uint32_t iree_hal_executable_plugin_features_t; | |
| // Defines a set of supported sanitizers that plugins may be compiled with. | |
| // The runtime uses this declaration to check as to whether the plugin is | |
| // compatible with the hosting environment for cases where the sanitizer | |
| // requires host support. | |
| typedef enum iree_hal_executable_plugin_sanitizer_kind_e { | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_NONE = 0, | |
| // Indicates the plugin is compiled to use AddressSanitizer: | |
| // https://clang.llvm.org/docs/AddressSanitizer.html | |
| // Equivalent compiler flag: -fsanitize=address | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_ADDRESS = 1, | |
| // Indicates the plugin is compiled to use MemorySanitizer: | |
| // https://clang.llvm.org/docs/MemorySanitizer.html | |
| // Equivalent compiler flag: -fsanitize=memory | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_MEMORY = 2, | |
| // Indicates the plugin is compiled to use ThreadSanitizer: | |
| // https://clang.llvm.org/docs/ThreadSanitizer.html | |
| // Equivalent compiler flag: -fsanitize=thread | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_THREAD = 3, | |
| // Indicates the plugin is compiled to use UndefinedBehaviorSanitizer: | |
| // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html | |
| // Equivalent compiler flag: -fsanitize=undefined | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_UNDEFINED = 4, | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_MAX_ENUM = INT32_MAX, | |
| } iree_hal_executable_plugin_sanitizer_kind_t; | |
| // The sanitizer kind currently enabled in the compilation unit. Can be used | |
| // in plugins to initialize the sanitizer header field. | |
| #if defined(__has_feature) | |
| #if __has_feature(address_sanitizer) | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_KIND \ | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_ADDRESS | |
| #endif // __has_feature(address_sanitizer) | |
| #if __has_feature(memory_sanitizer) | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_KIND \ | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_MEMORY | |
| #endif // __has_feature(memory_sanitizer) | |
| #if __has_feature(thread_sanitizer) | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_KIND \ | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_THREAD | |
| #endif // __has_feature(thread_sanitizer) | |
| #endif // defined(__has_feature) | |
| #if !defined(IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_KIND) | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_KIND \ | |
| IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_NONE | |
| #endif // !IREE_HAL_EXECUTABLE_PLUGIN_SANITIZER_KIND | |
| #if !defined(IREE_HOST_SIZE_T) | |
| #define IREE_HOST_SIZE_T size_t | |
| #endif // !IREE_HOST_SIZE_T | |
| // Size, in bytes, of a buffer on the local host. | |
| typedef IREE_HOST_SIZE_T iree_host_size_t; | |
| //===----------------------------------------------------------------------===// | |
| // Versioning and interface querying | |
| //===----------------------------------------------------------------------===// | |
| // Version code indicating the minimum required runtime structures. | |
| // Runtimes cannot load plugins with newer versions but may be able to load | |
| // older versions if backward compatibility is enabled. | |
| // | |
| // NOTE: until we hit v1 the versioning scheme here is not set in stone. | |
| // We may want to make this major release number, date codes (0x20220307), | |
| // or some semantic versioning we track in whatever spec we end up having. | |
| typedef uint32_t iree_hal_executable_plugin_version_t; | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_VERSION_0_1 0x00000001u | |
| // The latest version of the plugin API; can be used to populate the | |
| // iree_hal_executable_plugin_header_t::version when building plugins. | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_VERSION_LATEST \ | |
| IREE_HAL_EXECUTABLE_PLUGIN_VERSION_0_1 | |
| // A header present at the top of all versions of the plugin API used by the | |
| // runtime to ensure version compatibility. | |
| typedef struct iree_hal_executable_plugin_header_t { | |
| // Version of the API this plugin was built with, which was likely the value | |
| // of IREE_HAL_EXECUTABLE_PLUGIN_VERSION_LATEST. | |
| iree_hal_executable_plugin_version_t version; | |
| // Name used for logging/diagnostics - should be C literal-like. | |
| const char* name; | |
| // Human-readable description used for logging/diagnostics. | |
| // Could contain configuration information (debug/release, features, etc), | |
| // implementation version, git commit sha of the build, etc. | |
| const char* description; | |
| // Bitfield of features required/supported by this plugin. | |
| iree_hal_executable_plugin_features_t features; | |
| // Which sanitizer the plugin is compiled to use, if any. | |
| // Plugins meant for use with a particular sanitizer will are only usable | |
| // with hosting code that is using the same sanitizer. | |
| iree_hal_executable_plugin_sanitizer_kind_t sanitizer; | |
| // Reserved for future use. | |
| uint64_t reserved[8]; | |
| } iree_hal_executable_plugin_header_t; | |
| // Exported function from dynamic libraries for querying plugin information. | |
| // This should be implemented as pure as possible and may be called many times | |
| // while in process. This is only used to query for support, allow the plugin | |
| // to perform version switching, and return the vtables the runtime needs to | |
| // create and manage the plugin. | |
| // | |
| // The provided |max_version| is the maximum version the caller supports; | |
| // callees must return NULL if their lowest available version is greater | |
| // than the max version supported by the caller. | |
| typedef const iree_hal_executable_plugin_header_t** ( | |
| *iree_hal_executable_plugin_query_fn_t)( | |
| iree_hal_executable_plugin_version_t max_version, void* reserved); | |
| // Function name exported from dynamic libraries (pass to dlsym). | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_EXPORT_NAME \ | |
| "iree_hal_executable_plugin_query" | |
| #if defined(_WIN32) || defined(__CYGWIN__) | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_EXPORT __declspec(dllexport) | |
| #else | |
| #define IREE_HAL_EXECUTABLE_PLUGIN_EXPORT __attribute__((visibility("default"))) | |
| #endif | |
| //===----------------------------------------------------------------------===// | |
| // iree_hal_executable_plugin_status_t | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // A lightweight shim of the minimal iree/base/status.h interface. | |
| // This allows us to keep this header standalone for easy out-of-tree builds and | |
| // version things separately in the future. | |
| // | |
| // Most simple plugins will likely be fine with numeric status codes but more | |
| // complex ones may want the full status functionality in order to give back | |
| // file/line, error messages, and annotations. If the plugin links against the | |
| // IREE runtime it is allowed to return full iree_status_t objects across the | |
| // boundary so long as the hosting runtime was compiled with IREE_STATUS_MODE > | |
| // 0 (otherwise the runtime won't know how to deal with them). Plugins using | |
| // this functionality must declare the feature bit | |
| // IREE_HAL_EXECUTABLE_PLUGIN_FEATURE_FULL_STATUS so that the runtime can | |
| // verify it is compiled in a compatible mode. | |
| // Well-known status codes matching iree_status_code_t. | |
| // Note that any code within IREE_HAL_EXECUTABLE_PLUGIN_STATUS_CODE_MASK is | |
| // valid even if not enumerated here. Always check for unhandled errors/have | |
| // default conditions. | |
| typedef enum iree_hal_executable_plugin_status_code_e { | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_OK = 0, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_CANCELLED = 1, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_UNKNOWN = 2, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_INVALID_ARGUMENT = 3, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_DEADLINE_EXCEEDED = 4, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_NOT_FOUND = 5, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_ALREADY_EXISTS = 6, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_PERMISSION_DENIED = 7, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_RESOURCE_EXHAUSTED = 8, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_FAILED_PRECONDITION = 9, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_ABORTED = 10, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_OUT_OF_RANGE = 11, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_UNIMPLEMENTED = 12, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_INTERNAL = 13, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_UNAVAILABLE = 14, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_DATA_LOSS = 15, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_UNAUTHENTICATED = 16, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_DEFERRED = 17, | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_CODE_MASK = 0x1Fu, | |
| } iree_hal_executable_plugin_status_code_t; | |
| typedef struct iree_status_handle_t* iree_hal_executable_plugin_status_t; | |
| #define iree_hal_executable_plugin_status_from_code(code) \ | |
| ((iree_hal_executable_plugin_status_t)((uintptr_t)(( \ | |
| iree_hal_executable_plugin_status_code_t)(code)) & \ | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_CODE_MASK)) | |
| #define iree_hal_executable_plugin_status_code(value) \ | |
| ((iree_hal_executable_plugin_status_t)(((uintptr_t)(value)) & \ | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_CODE_MASK)) | |
| #define iree_hal_executable_plugin_ok_status() \ | |
| iree_hal_executable_plugin_status_from_code( \ | |
| IREE_HAL_EXECUTABLE_PLUGIN_STATUS_OK) | |
| #define iree_hal_executable_plugin_status_is_ok(value) \ | |
| ((uintptr_t)(value) == IREE_HAL_EXECUTABLE_PLUGIN_STATUS_OK) | |
| //===----------------------------------------------------------------------===// | |
| // iree_hal_executable_plugin_allocator_t | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // A lightweight shim of the iree/base/allocator.h interface. | |
| // This allows us to keep this header standalone for easy out-of-tree builds and | |
| // version things separately in the future. | |
| // | |
| // Plugins are expected to use the allocator for all requests such that the | |
| // hosting runtime can track the allocations. Plugins built in systems that | |
| // don't support custom allocators can do as they want but must not report | |
| // IREE_HAL_EXECUTABLE_PLUGIN_FEATURE_STANDALONE as the plugin would be making | |
| // syscalls in order to allocate/free memory from the underlying system. | |
| // | |
| // The iree_hal_executable_plugin_allocator_t struct is compatible with | |
| // iree_allocator_t and can be used interchangeably. | |
| typedef enum iree_hal_executable_plugin_allocator_command_e { | |
| IREE_HAL_EXECUTABLE_PLUGIN_ALLOCATOR_COMMAND_MALLOC = 0, | |
| IREE_HAL_EXECUTABLE_PLUGIN_ALLOCATOR_COMMAND_CALLOC = 1, | |
| IREE_HAL_EXECUTABLE_PLUGIN_ALLOCATOR_COMMAND_REALLOC = 2, | |
| IREE_HAL_EXECUTABLE_PLUGIN_ALLOCATOR_COMMAND_FREE = 3, | |
| } iree_hal_executable_plugin_allocator_command_t; | |
| typedef struct iree_hal_executable_plugin_allocator_alloc_params_t { | |
| iree_host_size_t byte_length; | |
| } iree_hal_executable_plugin_allocator_alloc_params_t; | |
| typedef iree_hal_executable_plugin_status_t ( | |
| *iree_hal_executable_plugin_allocator_ctl_fn_t)( | |
| void* self, iree_hal_executable_plugin_allocator_command_t command, | |
| const void* params, void** inout_ptr); | |
| typedef struct iree_hal_executable_plugin_allocator_t { | |
| void* self; | |
| iree_hal_executable_plugin_allocator_ctl_fn_t ctl; | |
| } iree_hal_executable_plugin_allocator_t; | |
| static inline iree_hal_executable_plugin_status_t | |
| iree_hal_executable_plugin_allocator_malloc( | |
| iree_hal_executable_plugin_allocator_t allocator, | |
| iree_host_size_t byte_length, void** inout_ptr) { | |
| iree_hal_executable_plugin_allocator_alloc_params_t params = {byte_length}; | |
| return allocator.ctl(allocator.self, | |
| IREE_HAL_EXECUTABLE_PLUGIN_ALLOCATOR_COMMAND_MALLOC, | |
| ¶ms, inout_ptr); | |
| } | |
| static inline iree_hal_executable_plugin_status_t | |
| iree_hal_executable_plugin_allocator_free( | |
| iree_hal_executable_plugin_allocator_t allocator, void* ptr) { | |
| return allocator.ctl(allocator.self, | |
| IREE_HAL_EXECUTABLE_PLUGIN_ALLOCATOR_COMMAND_FREE, | |
| /*params=*/NULL, &ptr); | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // iree_hal_executable_plugin_string_view_t | |
| //===----------------------------------------------------------------------===// | |
| // iree_string_view_t-compatible type. | |
| // The string data may not be NUL terminated and the provided size (in | |
| // characters) must be used. | |
| typedef struct iree_hal_executable_plugin_string_view_t { | |
| const char* data; | |
| iree_host_size_t size; | |
| } iree_hal_executable_plugin_string_view_t; | |
| // iree_string_pair_t-compatible type. | |
| typedef struct iree_hal_executable_plugin_string_pair_t { | |
| union { | |
| iree_hal_executable_plugin_string_view_t first; | |
| iree_hal_executable_plugin_string_view_t key; | |
| }; | |
| union { | |
| iree_hal_executable_plugin_string_view_t second; | |
| iree_hal_executable_plugin_string_view_t value; | |
| }; | |
| } iree_hal_executable_plugin_string_pair_t; | |
| //===----------------------------------------------------------------------===// | |
| // Common utilities | |
| //===----------------------------------------------------------------------===// | |
| // Matches iree_hal_executable_import_resolution_bits_e. | |
| // New bits may be added over time but the existing bits will not change. | |
| enum iree_hal_executable_plugin_resolution_bits_e { | |
| // One or more missing optional symbols. | |
| IREE_HAL_EXECUTABLE_PLUGIN_RESOLUTION_MISSING_OPTIONAL = 1u << 0, | |
| }; | |
| typedef uint32_t iree_hal_executable_plugin_resolution_t; | |
| // Returns true if the import |symbol_name| is optional. | |
| static inline bool iree_hal_executable_plugin_import_is_optional( | |
| const char* symbol_name) { | |
| // A `?` prefix indicates the symbol is optional and can be NULL. | |
| // Since the strings are NUL terminated we know there's always 1 char and | |
| // we can just test that for the prefix. | |
| return symbol_name ? (symbol_name[0] == '?') : false; | |
| } | |
| static inline int iree_hal_executable_plugin_strcmp(const char* lhs, | |
| const char* rhs) { | |
| unsigned char lhsc = 0; | |
| unsigned char rhsc = 0; | |
| do { | |
| lhsc = (unsigned char)*lhs++; | |
| rhsc = (unsigned char)*rhs++; | |
| if (lhsc == '\0') return lhsc - rhsc; | |
| } while (lhsc == rhsc); | |
| return lhsc - rhsc; | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // IREE_HAL_EXECUTABLE_PLUGIN_VERSION_0_* | |
| //===----------------------------------------------------------------------===// | |
| // Environment provided to the plugin on load. | |
| typedef struct iree_hal_executable_plugin_environment_v0_t { | |
| // Allocator to be used for all plugin allocations for the lifetime of the | |
| // plugin (such as those needed during resolution). The allocator will be | |
| // valid until the plugin is unloaded. | |
| iree_hal_executable_plugin_allocator_t host_allocator; | |
| } iree_hal_executable_plugin_environment_v0_t; | |
| typedef struct iree_hal_executable_plugin_resolve_params_v0_t { | |
| size_t count; | |
| const char* const* symbol_names; | |
| void** out_fn_ptrs; | |
| void** out_fn_contexts; | |
| } iree_hal_executable_plugin_resolve_params_v0_t; | |
| typedef iree_hal_executable_plugin_status_t ( | |
| *iree_hal_executable_plugin_resolve_fn_v0_t)( | |
| void* self, const iree_hal_executable_plugin_resolve_params_v0_t* params, | |
| iree_hal_executable_plugin_resolution_t* out_resolution); | |
| // Structure used for v0 plugin interfaces. | |
| // The entire structure is designed to be read-only and able to live embedded in | |
| // the binary .rdata section. | |
| // | |
| // Thread-safe: the plugin must be safe to load and resolve from multiple | |
| // threads simultaneously. No unloads will be performed with active resolves. | |
| typedef struct iree_hal_executable_plugin_v0_t { | |
| // Version/metadata header. | |
| // Will have a version of IREE_HAL_EXECUTABLE_PLUGIN_VERSION_*. | |
| const iree_hal_executable_plugin_header_t* header; | |
| // Loads a plugin by possibly allocating state, loading dependencies, and | |
| // preparing for resolution. | |
| // | |
| // The parameter strings are only available during the load and if the plugin | |
| // needs to retain any of them they must be cloned. | |
| // | |
| // The value specified in |out_self| will be passed to subsequent plugin | |
| // interface calls and may be NULL if the plugin has no state. As the same | |
| // plugin may be instantiated multiple times global state should be avoided | |
| // unless the | |
| iree_hal_executable_plugin_status_t (*load)( | |
| const iree_hal_executable_plugin_environment_v0_t* environment, | |
| size_t param_count, | |
| const iree_hal_executable_plugin_string_pair_t* params, void** out_self); | |
| // Unloads a plugin represented by |self|. | |
| // The plugin should free all resources as if in a shared library the hosting | |
| // runtime may immediately unload the library (dlclose/etc). | |
| void (*unload)(void* self); | |
| // Resolves |count| imports given |symbol_names| and stores pointers to their | |
| // implementation in |out_fn_ptrs| and optional contexts in |out_fn_contexts|. | |
| // The function contexts can be NULL, a pointer to shared state passed to each | |
| // import, unique state per function, or anything else. This allows JITs for | |
| // example to export a single function pointer and pack the information about | |
| // what to JIT in the context - or pass unique thunk functions for each import | |
| // and the shared JIT engine state for all contexts so that the thunk can | |
| // access it. | |
| // | |
| // A symbol name starting with `?` indicates that the symbol is optional and | |
| // is allowed to be resolved to NULL. Such cases will always return OK but set | |
| // the IREE_HAL_EXECUTABLE_PLUGIN_RESOLUTION_MISSING_OPTIONAL resolution bit. | |
| // | |
| // Any already resolved function pointers will be skipped and left unmodified. | |
| // When there's only partial availability of required imports any available | |
| // ones will still be populated and NOT_FOUND will is returned. This allows | |
| // for looping over multiple providers to populate what they can and only | |
| // fails out if all providers return NOT_FOUND for a required import. | |
| // | |
| // The returned function pointers are the direct storage in the runtime. | |
| // Implementations are allowed to update their own entries (and _only_ their | |
| // entries) at runtime so long as they observe the thread-safety guarantees. | |
| // For example, a JIT may default all exports to JIT thunk functions and then | |
| // atomically swap them out for the translated function pointers as they are | |
| // available. | |
| // | |
| // Symbol names must be sorted alphabetically so if we cared we could use this | |
| // information to more efficiently resolve the symbols from providers (O(n) | |
| // walk vs potential O(nlogn)/O(n^2)). For example if JITing many similar | |
| // ukernel variants (matmul_Ma_Na_Ka, matmul_Mb_Nb_Kb, etc) a resolver can | |
| // avoid big switch tables. | |
| iree_hal_executable_plugin_resolve_fn_v0_t resolve; | |
| } iree_hal_executable_plugin_v0_t; | |
| #ifdef __cplusplus | |
| } // extern "C" | |
| #endif // __cplusplus | |
| #endif // IREE_HAL_LOCAL_EXECUTABLE_PLUGIN_H_ |