tvm
Loading...
Searching...
No Matches
node_functor.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
23#ifndef TVM_IR_NODE_FUNCTOR_H_
24#define TVM_IR_NODE_FUNCTOR_H_
25
26#include <tvm/ffi/error.h>
27
28#include <cstring>
29#include <type_traits>
30#include <utility>
31#include <vector>
32
33namespace tvm {
34
61template <typename FType>
63
64template <typename R, typename... Args>
65class NodeFunctor<R(const ffi::ObjectRef& n, Args...)> {
66 private:
68 typedef R (*FPointer)(const ffi::ObjectRef& n, Args...);
70 using TSelf = NodeFunctor<R(const ffi::ObjectRef& n, Args...)>;
72 std::vector<FPointer> func_;
74 uint32_t begin_type_index_{0};
75
76 public:
78 using result_type = R;
84 bool can_dispatch(const ffi::ObjectRef& n) const {
85 uint32_t type_index = n->type_index();
86 if (type_index < begin_type_index_) return false;
87 type_index -= begin_type_index_;
88 return type_index < func_.size() && func_[type_index] != nullptr;
89 }
96 R operator()(const ffi::ObjectRef& n, Args... args) const {
97 uint32_t type_index = n->type_index();
98 if (type_index >= begin_type_index_) {
99 uint32_t index = type_index - begin_type_index_;
100 if (index < func_.size() && func_[index] != nullptr) {
101 return (*func_[index])(n, std::forward<Args>(args)...);
102 }
103 }
104
105 const TVMFFITypeInfo* type_info = TVMFFIGetTypeInfo(type_index);
106 for (int32_t i = type_info->type_depth - 1; i >= 0; --i) {
107 type_index = type_info->type_ancestors[i]->type_index;
108 if (type_index >= begin_type_index_) {
109 uint32_t index = type_index - begin_type_index_;
110 if (index < func_.size() && func_[index] != nullptr) {
111 return (*func_[index])(n, std::forward<Args>(args)...);
112 }
113 }
114 }
115 TVM_FFI_THROW(InternalError) << "NodeFunctor calls un-registered function on type "
116 << n->GetTypeKey();
117 throw;
118 }
125 template <typename TNode>
126 TSelf& set_dispatch(FPointer f) { // NOLINT(*)
127 uint32_t tindex = TNode::RuntimeTypeIndex();
128 if (func_.size() <= tindex) {
129 func_.resize(tindex + 1, nullptr);
130 }
131 TVM_FFI_ICHECK(func_[tindex] == nullptr)
132 << "Dispatch for " << TNode::_type_key << " is already set";
133 TVM_FFI_ICHECK_EQ(begin_type_index_, 0) << " Cannot call set_dispatch after calling Finalize";
134 func_[tindex] = f;
135 return *this;
136 }
143 template <typename TNode>
144 TSelf& clear_dispatch() { // NOLINT(*)
145 uint32_t tindex = TNode::RuntimeTypeIndex();
146 TVM_FFI_ICHECK_LT(tindex, func_.size()) << "clear_dispatch: index out of range";
147 TVM_FFI_ICHECK_EQ(begin_type_index_, 0) << " Cannot call clear_dispatch after calling Finalize";
148 func_[tindex] = nullptr;
149 return *this;
150 }
156 void Finalize() {
157 TVM_FFI_ICHECK_EQ(begin_type_index_, 0) << "Can only call Finalize once";
158 while (begin_type_index_ < func_.size() && func_[begin_type_index_] == nullptr) {
159 ++begin_type_index_;
160 }
161 // shift up the function value
162 size_t new_ftable_size = func_.size() - begin_type_index_;
163 if (begin_type_index_ != 0) {
164 std::memmove(func_.data(), func_.data() + begin_type_index_,
165 new_ftable_size * sizeof(FPointer));
166 }
167 func_.resize(new_ftable_size);
168 func_.shrink_to_fit();
169 }
170};
171
172#define TVM_REG_FUNC_VAR_DEF(ClsName) [[maybe_unused]] static auto& __make_functor##_##ClsName
173
209#define TVM_STATIC_IR_FUNCTOR(ClsName, FField) \
210 TVM_FFI_STR_CONCAT(TVM_REG_FUNC_VAR_DEF(ClsName), __COUNTER__) = ClsName::FField()
211} // namespace tvm
212#endif // TVM_IR_NODE_FUNCTOR_H_
TSelf & set_dispatch(FPointer f)
set the dispatcher for type TNode
Definition node_functor.h:126
bool can_dispatch(const ffi::ObjectRef &n) const
Whether the functor can dispatch the corresponding Node.
Definition node_functor.h:84
void Finalize()
Finalize the functor after calling sequence of set_dispatch This function will attempt to find the mi...
Definition node_functor.h:156
R operator()(const ffi::ObjectRef &n, Args... args) const
invoke the functor, dispatch on type of n
Definition node_functor.h:96
TSelf & clear_dispatch()
unset the dispatcher for type TNode
Definition node_functor.h:144
A dynamically dispatched functor on the type of the first argument.
Definition node_functor.h:62
RAII wrapper function to enter and exit a context object similar to python's with syntax.
Definition with_context.h:59
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition analyzer.h:40