| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /*! |
| * \file src/runtime/vm/module_utils.h |
| * \brief Internal helpers for declaring VM module vtables. |
| * |
| * Provides the TVM_MODULE_VTABLE_* macros and ModuleVTableEntryHelper |
| * template that VM module implementations use to expose member |
| * functions as ffi::Function entries via ffi::ModuleObj::GetFunction. |
| * |
| * This header is private to src/runtime/vm/. Module implementations |
| * outside this directory should not depend on these macros. |
| */ |
| #ifndef TVM_RUNTIME_VM_MODULE_UTILS_H_ |
| #define TVM_RUNTIME_VM_MODULE_UTILS_H_ |
| |
| #include <tvm/ffi/cast.h> |
| #include <tvm/ffi/extra/module.h> |
| #include <tvm/ffi/function.h> |
| |
| #include <utility> |
| |
| namespace tvm { |
| namespace runtime { |
| namespace vm { |
| namespace details { |
| |
| template <typename T> |
| struct ModuleVTableEntryHelper {}; |
| |
| template <typename T, typename R, typename... Args> |
| struct ModuleVTableEntryHelper<R (T::*)(Args...) const> { |
| using MemFnType = R (T::*)(Args...) const; |
| TVM_FFI_INLINE static void Call(ffi::Any* rv, T* self, MemFnType f, ffi::PackedArgs args) { |
| auto wrapped = [self, f](Args... args) -> R { return (self->*f)(std::forward<Args>(args)...); }; |
| ffi::details::unpack_call<R>(std::make_index_sequence<sizeof...(Args)>{}, nullptr, wrapped, |
| args.data(), args.size(), rv); |
| } |
| }; |
| |
| template <typename T, typename R, typename... Args> |
| struct ModuleVTableEntryHelper<R (T::*)(Args...)> { |
| using MemFnType = R (T::*)(Args...); |
| TVM_FFI_INLINE static void Call(ffi::Any* rv, T* self, MemFnType f, ffi::PackedArgs args) { |
| auto wrapped = [self, f](Args... args) -> R { return (self->*f)(std::forward<Args>(args)...); }; |
| ffi::details::unpack_call<R>(std::make_index_sequence<sizeof...(Args)>{}, nullptr, wrapped, |
| args.data(), args.size(), rv); |
| } |
| }; |
| |
| template <typename T, typename... Args> |
| struct ModuleVTableEntryHelper<void (T::*)(Args...) const> { |
| using MemFnType = void (T::*)(Args...) const; |
| TVM_FFI_INLINE static void Call(ffi::Any* rv, T* self, MemFnType f, ffi::PackedArgs args) { |
| auto wrapped = [self, f](Args... args) -> void { (self->*f)(std::forward<Args>(args)...); }; |
| ffi::details::unpack_call<void>(std::make_index_sequence<sizeof...(Args)>{}, nullptr, wrapped, |
| args.data(), args.size(), rv); |
| } |
| }; |
| |
| template <typename T, typename... Args> |
| struct ModuleVTableEntryHelper<void (T::*)(Args...)> { |
| using MemFnType = void (T::*)(Args...); |
| TVM_FFI_INLINE static void Call(ffi::Any* rv, T* self, MemFnType f, ffi::PackedArgs args) { |
| auto wrapped = [self, f](Args... args) -> void { (self->*f)(std::forward<Args>(args)...); }; |
| ffi::details::unpack_call<void>(std::make_index_sequence<sizeof...(Args)>{}, nullptr, wrapped, |
| args.data(), args.size(), rv); |
| } |
| }; |
| |
| } // namespace details |
| } // namespace vm |
| } // namespace runtime |
| } // namespace tvm |
| |
| #define TVM_MODULE_VTABLE_BEGIN(TypeKey) \ |
| const char* kind() const final { return TypeKey; } \ |
| ::tvm::ffi::Optional<::tvm::ffi::Function> GetFunction(const ffi::String& _name) override { \ |
| using SelfPtr = std::remove_cv_t<decltype(this)>; \ |
| ::tvm::ffi::ObjectPtr<::tvm::ffi::Object> _self = \ |
| ::tvm::ffi::GetObjectPtr<::tvm::ffi::Object>(this); |
| #define TVM_MODULE_VTABLE_END() \ |
| return std::nullopt; \ |
| } |
| #define TVM_MODULE_VTABLE_END_WITH_DEFAULT(MemFunc) \ |
| { \ |
| auto f = (MemFunc); \ |
| return (this->*f)(_name); \ |
| } \ |
| } // NOLINT(*) |
| #define TVM_MODULE_VTABLE_ENTRY(Name, MemFunc) \ |
| if (_name == Name) { \ |
| return ffi::Function::FromPacked([_self](ffi::PackedArgs args, ffi::Any* rv) -> void { \ |
| using Helper = ::tvm::runtime::vm::details::ModuleVTableEntryHelper<decltype(MemFunc)>; \ |
| SelfPtr self = static_cast<SelfPtr>(_self.get()); \ |
| Helper::Call(rv, self, MemFunc, args); \ |
| }); \ |
| } |
| #define TVM_MODULE_VTABLE_ENTRY_PACKED(Name, MemFunc) \ |
| if (_name == Name) { \ |
| return ffi::Function([_self](ffi::PackedArgs args, ffi::Any* rv) -> void { \ |
| (static_cast<SelfPtr>(_self.get())->*(MemFunc))(args, rv); \ |
| }); \ |
| } |
| |
| #endif // TVM_RUNTIME_VM_MODULE_UTILS_H_ |