1 /* 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * All rights reserved. 4 * 5 * This source code is licensed under the BSD-style license found in the 6 * LICENSE file in the root directory of this source tree. 7 */ 8 9 #pragma once 10 11 #include <cstring> 12 13 #include <executorch/runtime/backend/backend_execution_context.h> 14 #include <executorch/runtime/backend/backend_init_context.h> 15 #include <executorch/runtime/core/array_ref.h> 16 #include <executorch/runtime/core/error.h> 17 #include <executorch/runtime/core/evalue.h> 18 #include <executorch/runtime/core/freeable_buffer.h> 19 #include <executorch/runtime/core/memory_allocator.h> 20 #include <executorch/runtime/core/result.h> 21 #include <executorch/runtime/platform/compiler.h> 22 23 namespace executorch { 24 namespace runtime { 25 26 struct SizedBuffer { 27 void* buffer; 28 size_t nbytes; // number of bytes of buffer 29 }; 30 31 struct CompileSpec { 32 const char* key; // spec key 33 SizedBuffer value; // spec value 34 }; 35 36 /** 37 * An opaque handle managed by a backend. Typically points to a backend-private 38 * class/struct. 39 */ 40 using DelegateHandle = void; 41 42 class BackendInterface { 43 public: 44 virtual ~BackendInterface() = 0; 45 46 /** 47 * Returns true if the backend is available to process delegation calls. 48 */ 49 ET_NODISCARD virtual bool is_available() const = 0; 50 51 /** 52 * Responsible to further process (compile/transform/optimize) the compiled 53 * unit that was produced, ahead-of-time, as well as perform any backend 54 * initialization to ready it for execution. This method is called every time 55 * the ExecuTorch program is initialized. Consequently, this is the place to 56 * perform any backend initialization as well as transformations, 57 * optimizations, and even compilation that depend on the target device. As 58 * such, it is strongly encouraged to push as much processing as possible to 59 * the ahead-of-time processing. 60 * 61 * @param[in] processed An opaque (to ExecuTorch) backend-specific compiled 62 * unit from the preprocessor. Can contain anything the backend needs to 63 * execute the equivalent semantics of the passed-in Module and its 64 * method. Often passed unmodified to `execute()` as a `DelegateHandle`, 65 * unless it needs further processing at init time to be fully executable. 66 * If the data is not needed after init(), calling processed->Free() can 67 * reclaim its memory. 68 * @param[in] compile_specs The exact same compiler specification that 69 * was used ahead-of-time to produce `processed`. 70 * 71 * @returns On success, an opaque handle representing the the method 72 * implemented by the delegate. This handle is passed to `execute()` and 73 * `destroy()`, and the memory it points to is owned by the backend. 74 * Typically points to a backend-private class/struct. 75 * @returns On error, returns an error code other than Error::Ok. If the 76 * compiled unit (the preprocessed result from ahead of time) is not 77 * compatible with the current backend runtime, return the error code 78 * Error::DelegateInvalidCompatibility. Other backend delegate 79 * specific error codes can be found in error.h. 80 */ 81 ET_NODISCARD virtual Result<DelegateHandle*> init( 82 BackendInitContext& context, 83 FreeableBuffer* processed, 84 ArrayRef<CompileSpec> compile_specs) const = 0; 85 86 /** 87 * Responsible for executing the given method’s handle, as it was produced 88 * by compile. 89 * 90 * @param[in] handle An opaque handle returned by `init()`. Usually a backend 91 * executable unit. This executable unit should be ready to execute the 92 * delegate blobs. 93 * @param[in] args The method’s inputs and outputs. 94 * @retval Error::Ok if successful. 95 */ 96 ET_NODISCARD virtual Error execute( 97 BackendExecutionContext& context, 98 DelegateHandle* handle, 99 EValue** args) const = 0; 100 101 /** 102 * Responsible for destroying a handle, if it's required for some backend. 103 * It may be needed for some backends. For example, resources associated with 104 * this handle needs to be released. This method is called when the execution 105 * plan is destroyed (i.e., the program is out of its lifespan). 106 * 107 * @param[in] handle The handle to be destroyed. An opaque handle returned by 108 * `init()`. 109 */ destroy(ET_UNUSED DelegateHandle * handle)110 virtual void destroy(ET_UNUSED DelegateHandle* handle) const {} 111 }; 112 113 /** 114 * Returns the corresponding object pointer for a given string name. 115 * The mapping is populated using register_backend method. 116 * 117 * @param[in] name Name of the user-defined backend delegate. 118 * @retval Pointer to the appropriate object that implements BackendInterface. 119 * Nullptr if it can't find anything with the given name. 120 */ 121 BackendInterface* get_backend_class(const char* name); 122 123 /** 124 * A named instance of a backend. 125 */ 126 struct Backend { 127 /// The name of the backend. Must match the string used in the PTE file. 128 const char* name; 129 /// The instance of the backend to use when loading and executing programs. 130 BackendInterface* backend; 131 }; 132 133 /** 134 * Registers the Backend object (i.e. string name and BackendInterface pair) so 135 * that it could be called via the name during the runtime. 136 * 137 * @param[in] backend Backend object 138 * @retval Error code representing whether registration was successful. 139 */ 140 ET_NODISCARD Error register_backend(const Backend& backend); 141 142 } // namespace runtime 143 } // namespace executorch 144 145 namespace torch { 146 namespace executor { 147 // TODO(T197294990): Remove these deprecated aliases once all users have moved 148 // to the new `::executorch` namespaces. 149 using ::executorch::runtime::Backend; 150 using ::executorch::runtime::CompileSpec; 151 using ::executorch::runtime::DelegateHandle; 152 using ::executorch::runtime::get_backend_class; 153 using ::executorch::runtime::register_backend; 154 using ::executorch::runtime::SizedBuffer; 155 using PyTorchBackendInterface = ::executorch::runtime::BackendInterface; 156 } // namespace executor 157 } // namespace torch 158