| // 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_ |