tvm
packed_func.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  */
19 
24 #ifndef TVM_RUNTIME_PACKED_FUNC_H_
25 #define TVM_RUNTIME_PACKED_FUNC_H_
26 
31 #include <tvm/runtime/data_type.h>
32 #include <tvm/runtime/logging.h>
33 #include <tvm/runtime/module.h>
34 #include <tvm/runtime/ndarray.h>
35 #include <tvm/runtime/object.h>
36 
37 #include <functional>
38 #include <limits>
39 #include <memory>
40 #include <string>
41 #include <tuple>
42 #include <type_traits>
43 #include <utility>
44 #include <vector>
45 
46 // Whether use TVM runtime in header only mode.
47 #ifndef TVM_RUNTIME_HEADER_ONLY
48 #define TVM_RUNTIME_HEADER_ONLY 0
49 #endif
50 
51 namespace tvm {
52 namespace runtime {
53 
54 // forward declarations
55 class TVMArgs;
56 class TVMArgValue;
57 class TVMMovableArgValueWithContext_;
58 class TVMRetValue;
59 class TVMArgsSetter;
60 template <typename FType>
62 template <typename TSignature>
64 
69 class PackedFuncObj : public Object {
70  public:
76  TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue* rv) const;
77 
78  static constexpr const uint32_t _type_index = TypeIndex::kRuntimePackedFunc;
79  static constexpr const char* _type_key = "runtime.PackedFunc";
81 
82  protected:
86  template <class TPackedFuncSubObj>
87  struct Extractor {
94  static void Call(const PackedFuncObj* obj, TVMArgs args, TVMRetValue* rv);
95  };
96 
98  using FCallPacked = void(const PackedFuncObj*, TVMArgs, TVMRetValue*);
99 
104  explicit PackedFuncObj(FCallPacked* f_call_pack) : f_call_packed_(f_call_pack) {}
105 
107  PackedFuncObj() = delete;
108 
111 };
112 
114 template <class TCallable>
116  using TStorage = typename std::remove_cv<typename std::remove_reference<TCallable>::type>::type;
117 
118  public:
125  explicit PackedFuncSubObj(TCallable callable)
126  : PackedFuncObj(Extractor<TSelf>::Call), callable_(callable) {}
128  mutable TStorage callable_;
129 };
130 
139 class PackedFunc : public ObjectRef {
140  public:
142  PackedFunc(std::nullptr_t null) : ObjectRef(nullptr) {} // NOLINT(*)
148  template <typename TCallable,
149  typename = std::enable_if_t<
150  std::is_convertible<TCallable, std::function<void(TVMArgs, TVMRetValue*)>>::value &&
151  !std::is_base_of<TCallable, PackedFunc>::value>>
152  explicit PackedFunc(TCallable data) {
153  using ObjType = PackedFuncSubObj<TCallable>;
154  data_ = make_object<ObjType>(std::forward<TCallable>(data));
155  }
170  template <typename... Args>
171  inline TVMRetValue operator()(Args&&... args) const;
177  TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue* rv) const;
179  bool operator==(std::nullptr_t null) const { return data_ == nullptr; }
181  bool operator!=(std::nullptr_t null) const { return data_ != nullptr; }
182 
184 };
185 
187 using FSig = std::string();
188 
192 template <typename FType>
193 class TypedPackedFunc;
194 
227 template <typename R, typename... Args>
228 class TypedPackedFunc<R(Args...)> {
229  public:
231  using TSelf = TypedPackedFunc<R(Args...)>;
235  TypedPackedFunc(std::nullptr_t null) {} // NOLINT(*)
253  inline TypedPackedFunc(PackedFunc packed); // NOLINT(*)
258  inline TypedPackedFunc(const TVMRetValue& value); // NOLINT(*)
263  inline TypedPackedFunc(const TVMArgValue& value); // NOLINT(*)
268  inline TypedPackedFunc(TVMMovableArgValueWithContext_&& value); // NOLINT(*)
285  template <typename FLambda, typename = typename std::enable_if<std::is_convertible<
286  FLambda, std::function<R(Args...)>>::value>::type>
287  TypedPackedFunc(const FLambda& typed_lambda, std::string name) { // NOLINT(*)
288  this->AssignTypedLambda(typed_lambda, name);
289  }
308  template <typename FLambda, typename = typename std::enable_if<std::is_convertible<
309  FLambda, std::function<R(Args...)>>::value>::type>
310  TypedPackedFunc(const FLambda& typed_lambda) { // NOLINT(*)
311  this->AssignTypedLambda(typed_lambda);
312  }
329  template <typename FLambda, typename = typename std::enable_if<
330  std::is_convertible<FLambda,
331  std::function<R(Args...)>>::value>::type>
332  TSelf& operator=(FLambda typed_lambda) { // NOLINT(*)
333  this->AssignTypedLambda(typed_lambda);
334  return *this;
335  }
342  packed_ = packed;
343  return *this;
344  }
350  TVM_ALWAYS_INLINE R operator()(Args... args) const;
355  operator PackedFunc() const { return packed(); }
359  const PackedFunc& packed() const { return packed_; }
361  bool operator==(std::nullptr_t null) const { return packed_ == nullptr; }
363  bool operator!=(std::nullptr_t null) const { return packed_ != nullptr; }
364 
365  private:
366  friend class TVMRetValue;
368  PackedFunc packed_;
377  template <typename FLambda>
378  inline void AssignTypedLambda(FLambda flambda, std::string name);
387  template <typename FLambda>
388  inline void AssignTypedLambda(FLambda flambda);
389 };
390 
392 class TVMArgs {
393  public:
394  const TVMValue* values;
395  const int* type_codes;
396  int num_args;
403  TVMArgs(const TVMValue* values, const int* type_codes, int num_args)
406  inline int size() const;
412  inline TVMArgValue operator[](int i) const;
419  template <typename T>
420  inline T At(int i) const;
421 };
422 
428 inline const char* ArgTypeCode2Str(int type_code);
429 
430 inline std::ostream& operator<<(std::ostream& os, DLDevice dev); // NOLINT(*)
431 
432 // macro to check type code.
433 #define TVM_CHECK_TYPE_CODE(CODE, T) \
434  ICHECK_EQ(CODE, T) << "expected " << ArgTypeCode2Str(T) << " but got " << ArgTypeCode2Str(CODE)
435 
440 template <typename T>
450  using ContainerType = typename T::ContainerType;
451  if (ptr == nullptr) {
452  if (T::_type_is_nullable) {
453  return NullOpt;
454  } else {
455  return String("nullptr");
456  }
457  }
458  if (ptr->IsInstance<ContainerType>()) {
459  return NullOpt;
460  } else {
461  return String(ptr->GetTypeKey());
462  }
463  }
469  static bool Check(const Object* ptr) {
470  using ContainerType = typename T::ContainerType;
471  if (ptr == nullptr) return T::_type_is_nullable;
472  return ptr->IsInstance<ContainerType>();
473  }
474  static std::string TypeName() {
475  using ContainerType = typename T::ContainerType;
476  return ContainerType::_type_key;
477  }
478 };
479 
480 // Additional overloads for PackedFunc checking.
481 template <typename T>
484  if (ptr == nullptr) {
485  return NullOpt;
486  }
487  if (!ptr->IsInstance<ArrayNode>()) {
488  return String(ptr->GetTypeKey());
489  }
490  const ArrayNode* n = static_cast<const ArrayNode*>(ptr);
491  for (size_t i = 0; i < n->size(); i++) {
492  const ObjectRef& p = (*n)[i];
494  if (check_subtype.defined()) {
495  return String("Array[index " + std::to_string(i) + ": " + check_subtype.value() + "]");
496  }
497  }
498  return NullOpt;
499  }
500  static bool Check(const Object* ptr) {
501  if (ptr == nullptr) return true;
502  if (!ptr->IsInstance<ArrayNode>()) return false;
503  const ArrayNode* n = static_cast<const ArrayNode*>(ptr);
504  for (const ObjectRef& p : *n) {
505  if (!ObjectTypeChecker<T>::Check(p.get())) {
506  return false;
507  }
508  }
509  return true;
510  }
511  static std::string TypeName() { return "Array[" + ObjectTypeChecker<T>::TypeName() + "]"; }
512 };
513 template <typename K, typename V>
514 struct ObjectTypeChecker<Map<K, V>> {
516  if (ptr == nullptr) return NullOpt;
517  if (!ptr->IsInstance<MapNode>()) return String(ptr->GetTypeKey());
518  const MapNode* n = static_cast<const MapNode*>(ptr);
519  for (const auto& kv : *n) {
521  Optional<String> value_type = ObjectTypeChecker<K>::CheckAndGetMismatch(kv.first.get());
522  if (key_type.defined() || value_type.defined()) {
523  std::string key_name =
524  key_type.defined() ? std::string(key_type.value()) : ObjectTypeChecker<K>::TypeName();
525  std::string value_name = value_type.defined() ? std::string(value_type.value())
527  return String("Map[" + key_name + ", " + value_name + "]");
528  }
529  }
530  return NullOpt;
531  }
532  static bool Check(const Object* ptr) {
533  if (ptr == nullptr) return true;
534  if (!ptr->IsInstance<MapNode>()) return false;
535  const MapNode* n = static_cast<const MapNode*>(ptr);
536  for (const auto& kv : *n) {
537  if (!ObjectTypeChecker<K>::Check(kv.first.get())) return false;
538  if (!ObjectTypeChecker<V>::Check(kv.second.get())) return false;
539  }
540  return true;
541  }
542  static std::string TypeName() {
544  ']';
545  }
546 };
547 
553  public:
554  operator double() const {
555  // Allow automatic conversion from int to float
556  // This avoids errors when user pass in int from
557  // the frontend while the API expects a float.
558  if (type_code_ == kDLInt) {
559  return static_cast<double>(value_.v_int64);
560  }
561  TVM_CHECK_TYPE_CODE(type_code_, kDLFloat);
562  return value_.v_float64;
563  }
564  operator int64_t() const {
566  return value_.v_int64;
567  }
568  operator uint64_t() const {
570  return value_.v_int64;
571  }
572  operator int() const {
576  return static_cast<int>(value_.v_int64);
577  }
578  operator bool() const {
580  return value_.v_int64 != 0;
581  }
582  operator void*() const {
583  if (type_code_ == kTVMNullptr) return nullptr;
586  return value_.v_handle;
587  }
588  operator DLTensor*() const {
590  return static_cast<DLTensor*>(value_.v_handle);
591  } else {
592  if (type_code_ == kTVMNullptr) return nullptr;
593  LOG(FATAL) << "Expected "
594  << "DLTensor* or NDArray but got " << ArgTypeCode2Str(type_code_);
595  return nullptr;
596  }
597  }
598  operator NDArray() const {
599  if (type_code_ == kTVMNullptr) return NDArray(ObjectPtr<Object>(nullptr));
602  }
603  operator Module() const {
604  if (type_code_ == kTVMNullptr) {
605  return Module(ObjectPtr<Object>(nullptr));
606  }
608  return Module(ObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
609  }
610  operator PackedFunc() const {
611  if (type_code_ == kTVMNullptr) {
612  return PackedFunc(ObjectPtr<Object>(nullptr));
613  }
615  return PackedFunc(ObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
616  }
617  operator Device() const {
619  return value_.v_device;
620  }
621  int type_code() const { return type_code_; }
627  template <typename T>
628  T* ptr() const {
629  return static_cast<T*>(value_.v_handle);
630  }
631  // ObjectRef handling
632  template <typename TObjectRef,
633  typename = typename std::enable_if<std::is_base_of<ObjectRef, TObjectRef>::value>::type>
634  inline bool IsObjectRef() const;
635  template <typename TObjectRef>
636  inline TObjectRef AsObjectRef() const;
637 
638  protected:
639  friend class TVMArgsSetter;
640  friend class TVMRetValue;
641  friend class TVMMovableArgValue_;
644 
649 };
650 
657 class TVMArgValue : public TVMPODValue_ {
658  public:
667  // reuse converter from parent
668  using TVMPODValue_::operator double;
669  using TVMPODValue_::operator int64_t;
670  using TVMPODValue_::operator uint64_t;
671  using TVMPODValue_::operator int;
672  using TVMPODValue_::operator bool;
673  using TVMPODValue_::operator void*;
674  using TVMPODValue_::operator DLTensor*;
675  using TVMPODValue_::operator NDArray;
676  using TVMPODValue_::operator Device;
677  using TVMPODValue_::operator Module;
678  using TVMPODValue_::operator PackedFunc;
681 
682  // conversion operator.
683  operator std::string() const {
684  if (type_code_ == kTVMDataType) {
685  return DLDataType2String(operator DLDataType());
686  } else if (type_code_ == kTVMBytes) {
687  TVMByteArray* arr = static_cast<TVMByteArray*>(value_.v_handle);
688  return std::string(arr->data, arr->size);
689  } else if (type_code_ == kTVMStr) {
690  return std::string(value_.v_str);
691  } else {
692  return AsObjectRef<tvm::runtime::String>().operator std::string();
693  }
694  }
695  template <typename FType>
696  operator TypedPackedFunc<FType>() const {
697  return TypedPackedFunc<FType>(operator PackedFunc());
698  }
699  const TVMValue& value() const { return value_; }
700 
701  template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
702  inline operator T() const;
703  inline operator DLDataType() const;
704  inline operator DataType() const;
705 };
706 
718  public:
720  // reuse converter from parent
721  using TVMPODValue_::operator double;
722  using TVMPODValue_::operator int64_t;
723  using TVMPODValue_::operator uint64_t;
724  using TVMPODValue_::operator int;
725  using TVMPODValue_::operator bool;
726  using TVMPODValue_::operator void*;
727  using TVMPODValue_::operator DLTensor*;
728  using TVMPODValue_::operator NDArray;
729  using TVMPODValue_::operator Device;
730  using TVMPODValue_::operator Module;
731  using TVMPODValue_::operator PackedFunc;
732  // reuse conversion rule from ArgValue.
733  operator std::string() const { return AsArgValue().operator std::string(); }
734  template <typename FType>
735  operator TypedPackedFunc<FType>() const {
736  return TypedPackedFunc<FType>(operator PackedFunc());
737  }
738  operator DLDataType() const { return AsArgValue().operator DLDataType(); }
739  operator DataType() const { return AsArgValue().operator DataType(); }
740  operator TVMArgValue() const { return AsArgValue(); }
746  template <typename T,
747  typename = typename std::enable_if<std::is_base_of<ObjectRef, T>::value>::type>
748  inline operator T() const;
749 
750  private:
752  TVMArgValue AsArgValue() const { return TVMArgValue(value_, type_code_); }
753 };
754 
763  public:
773  TVMMovableArgValueWithContext_(TVMValue value, int type_code, int arg_index,
774  const std::string* optional_name, FSig* f_sig)
775  : value_(value, type_code),
776  arg_index_(arg_index),
777  optional_name_(optional_name),
778  f_sig_(f_sig) {}
779 
780  template <typename T>
781  operator T() const {
782  try {
783  return value_; // implicit conversion happens here
784  } catch (dmlc::Error& e) {
785  LOG(FATAL) << "In function " << (optional_name_ == nullptr ? "<anonymous>" : *optional_name_)
786  << (f_sig_ == nullptr ? "" : (*f_sig_)()) << ": error while converting argument "
787  << arg_index_ << ": " << e.what();
788  throw; // never reached, LOG(FATAL) throws, but this silences a warning.
789  }
790  }
791 
792  private:
793  TVMMovableArgValue_ value_;
794  int arg_index_;
795  const std::string* optional_name_;
796  FSig* f_sig_;
797 };
798 
807 class TVMRetValue : public TVMPODValue_ {
808  public:
816  other.value_.v_handle = nullptr;
817  other.type_code_ = kTVMNullptr;
818  }
820  ~TVMRetValue() { this->Clear(); }
821  // reuse converter from parent
822  using TVMPODValue_::operator double;
823  using TVMPODValue_::operator int64_t;
824  using TVMPODValue_::operator uint64_t;
825  using TVMPODValue_::operator int;
826  using TVMPODValue_::operator bool;
827  using TVMPODValue_::operator void*;
828  using TVMPODValue_::operator DLTensor*;
829  using TVMPODValue_::operator Device;
830  using TVMPODValue_::operator NDArray;
831  using TVMPODValue_::operator Module;
832  using TVMPODValue_::operator PackedFunc;
835 
836  TVMRetValue(const TVMRetValue& other) : TVMPODValue_() { this->Assign(other); }
837  // conversion operators
838  operator std::string() const {
839  if (type_code_ == kTVMDataType) {
840  return DLDataType2String(operator DLDataType());
841  } else if (type_code_ == kTVMBytes) {
842  return *ptr<std::string>();
843  }
845  return *ptr<std::string>();
846  }
847  operator DLDataType() const {
848  if (type_code_ == kTVMStr) {
849  return String2DLDataType(operator std::string());
850  }
852  return value_.v_type;
853  }
854  operator DataType() const { return DataType(operator DLDataType()); }
855  template <typename FType>
856  operator TypedPackedFunc<FType>() const {
857  return TypedPackedFunc<FType>(operator PackedFunc());
858  }
859  // Assign operators
861  this->Clear();
862  value_ = other.value_;
863  type_code_ = other.type_code_;
864  other.type_code_ = kTVMNullptr;
865  return *this;
866  }
868  this->SwitchToPOD(kDLFloat);
870  return *this;
871  }
872  TVMRetValue& operator=(std::nullptr_t value) {
873  this->SwitchToPOD(kTVMNullptr);
875  return *this;
876  }
878  this->SwitchToPOD(kTVMOpaqueHandle);
880  return *this;
881  }
883  this->SwitchToPOD(kDLInt);
884  value_.v_int64 = value;
885  return *this;
886  }
888  this->SwitchToPOD(kDLInt);
889  value_.v_int64 = value;
890  return *this;
891  }
893  this->SwitchToPOD(kDLDevice);
895  return *this;
896  }
897  TVMRetValue& operator=(DLDataType t) {
898  this->SwitchToPOD(kTVMDataType);
899  value_.v_type = t;
900  return *this;
901  }
902  TVMRetValue& operator=(const DataType& other) { return operator=(other.operator DLDataType()); }
904  this->SwitchToPOD(kDLInt);
905  value_.v_int64 = value;
906  return *this;
907  }
908  TVMRetValue& operator=(std::string value) {
909  this->SwitchToClass(kTVMStr, value);
910  return *this;
911  }
913  this->SwitchToClass(kTVMBytes, std::string(value.data, value.size));
914  return *this;
915  }
917  if (other.data_ != nullptr) {
918  this->Clear();
922  } else {
923  SwitchToPOD(kTVMNullptr);
924  value_.v_handle = nullptr;
925  }
926  return *this;
927  }
929  SwitchToObject(kTVMModuleHandle, std::move(m.data_));
930  return *this;
931  }
933  this->SwitchToObject(kTVMPackedFuncHandle, std::move(f.data_));
934  return *this;
935  }
936  template <typename FType>
938  return operator=(f.packed());
939  }
940  TVMRetValue& operator=(const TVMRetValue& other) { // NOLINT(*0
941  this->Assign(other);
942  return *this;
943  }
945  this->Assign(other);
946  return *this;
947  }
949  this->Assign(other);
950  return *this;
951  }
961  void MoveToCHost(TVMValue* ret_value, int* ret_type_code) {
962  // cannot move str; need specially handle.
963  ICHECK(type_code_ != kTVMStr && type_code_ != kTVMBytes);
964  *ret_value = value_;
965  *ret_type_code = type_code_;
967  }
976  // Can move POD and everything under the object system.
979  ret.value_ = value;
980  ret.type_code_ = type_code;
981  return ret;
982  }
984  const TVMValue& value() const {
987  << "TVMRetValue.value can only be used for POD data";
988  return value_;
989  }
990  // ObjectRef handling
991  template <typename TObjectRef,
992  typename = typename std::enable_if<std::is_base_of<ObjectRef, TObjectRef>::value>::type>
993  inline TVMRetValue& operator=(TObjectRef other);
994  template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
995  inline operator T() const;
996 
997  private:
998  template <typename T>
999  void Assign(const T& other) {
1000  switch (other.type_code()) {
1001  case kTVMStr: {
1002  SwitchToClass<std::string>(kTVMStr, other);
1003  break;
1004  }
1005  case kTVMBytes: {
1006  SwitchToClass<std::string>(kTVMBytes, other);
1007  break;
1008  }
1009  case kTVMPackedFuncHandle: {
1010  *this = other.operator PackedFunc();
1011  break;
1012  }
1013  case kTVMModuleHandle: {
1014  *this = other.operator Module();
1015  break;
1016  }
1017  case kTVMNDArrayHandle: {
1018  *this = other.operator NDArray();
1019  break;
1020  }
1021  case kTVMObjectHandle: {
1022  // Avoid operator ObjectRef as we already know it is not NDArray/Module
1023  SwitchToObject(kTVMObjectHandle,
1024  GetObjectPtr<Object>(static_cast<Object*>(other.value_.v_handle)));
1025  break;
1026  }
1027  case kTVMObjectRValueRefArg: {
1028  operator=(other.operator ObjectRef());
1029  break;
1030  }
1031  default: {
1032  SwitchToPOD(other.type_code());
1033  value_ = other.value_;
1034  break;
1035  }
1036  }
1037  }
1038  // get the internal container.
1039  void SwitchToPOD(int type_code) {
1040  if (type_code_ != type_code) {
1041  this->Clear();
1043  }
1044  }
1045  template <typename T>
1046  void SwitchToClass(int type_code, T v) {
1047  if (type_code_ != type_code) {
1048  this->Clear();
1050  value_.v_handle = new T(v);
1051  } else {
1052  *static_cast<T*>(value_.v_handle) = v;
1053  }
1054  }
1055  void SwitchToObject(int type_code, ObjectPtr<Object> other) {
1056  if (other.data_ != nullptr) {
1057  this->Clear();
1059  // move the handle out
1060  value_.v_handle = other.data_;
1061  other.data_ = nullptr;
1062  } else {
1063  SwitchToPOD(kTVMNullptr);
1064  value_.v_handle = nullptr;
1065  }
1066  }
1067  void Clear() {
1068  if (type_code_ == kTVMNullptr) return;
1069  switch (type_code_) {
1070  case kTVMStr:
1071  case kTVMBytes:
1072  delete ptr<std::string>();
1073  break;
1074  case kTVMPackedFuncHandle:
1075  static_cast<Object*>(value_.v_handle)->DecRef();
1076  break;
1077  case kTVMNDArrayHandle: {
1079  break;
1080  }
1081  case kTVMModuleHandle: {
1082  static_cast<Object*>(value_.v_handle)->DecRef();
1083  break;
1084  }
1085  case kTVMObjectHandle: {
1086  static_cast<Object*>(value_.v_handle)->DecRef();
1087  break;
1088  }
1089  }
1091  }
1092 };
1093 
1103 template <typename TObjectRef>
1110  static TObjectRef From(const TVMArgValue& val) { return val.AsObjectRef<TObjectRef>(); }
1116  static TObjectRef From(const TVMRetValue& val) { return val.AsObjectRef<TObjectRef>(); }
1117 };
1118 
1138 #define TVM_DLL_EXPORT_PACKED_FUNC(ExportName, Function) \
1139  extern "C" { \
1140  TVM_DLL int ExportName(TVMValue* args, int* type_code, int num_args, TVMValue* out_value, \
1141  int* out_type_code, void* resource_handle); \
1142  int ExportName(TVMValue* args, int* type_code, int num_args, TVMValue* out_value, \
1143  int* out_type_code, void* resource_handle) { \
1144  try { \
1145  ::tvm::runtime::TVMRetValue rv; \
1146  Function(::tvm::runtime::TVMArgs(args, type_code, num_args), &rv); \
1147  rv.MoveToCHost(out_value, out_type_code); \
1148  return 0; \
1149  } catch (const ::std::exception& _except_) { \
1150  TVMAPISetLastError(_except_.what()); \
1151  return -1; \
1152  } \
1153  } \
1154  }
1155 
1156 #define TVM_MODULE_VTABLE_BEGIN(TypeKey) \
1157  const char* type_key() const final { return TypeKey; } \
1158  PackedFunc GetFunction(const String& _name, const ObjectPtr<Object>& _self) override { \
1159  using SelfPtr = std::remove_cv_t<decltype(this)>;
1160 #define TVM_MODULE_VTABLE_END() \
1161  return PackedFunc(nullptr); \
1162  }
1163 #define TVM_MODULE_VTABLE_END_WITH_DEFAULT(MemFunc) \
1164  { \
1165  auto f = (MemFunc); \
1166  return (this->*f)(_name); \
1167  } \
1168  } // NOLINT(*)
1169 #define TVM_MODULE_VTABLE_ENTRY(Name, MemFunc) \
1170  if (_name == Name) { \
1171  return PackedFunc([_self](TVMArgs args, TVMRetValue* rv) -> void { \
1172  using Helper = ::tvm::runtime::detail::ModuleVTableEntryHelper<decltype(MemFunc)>; \
1173  SelfPtr self = static_cast<SelfPtr>(_self.get()); \
1174  CHECK_EQ(args.size(), Helper::LenArgs) \
1175  << "Function `" << self->type_key() << "::" << Name << "` requires " << Helper::LenArgs \
1176  << " arguments, but got " << args.size(); \
1177  Helper::Call(rv, self, MemFunc, args, Helper::IndexSeq{}); \
1178  }); \
1179  }
1180 #define TVM_MODULE_VTABLE_ENTRY_PACKED(Name, MemFunc) \
1181  if (_name == Name) { \
1182  return PackedFunc([_self](TVMArgs args, TVMRetValue* rv) -> void { \
1183  (static_cast<SelfPtr>(_self.get())->*(MemFunc))(args, rv); \
1184  }); \
1185  }
1186 
1222 #define TVM_DLL_EXPORT_TYPED_FUNC(ExportName, Function) \
1223  extern "C" { \
1224  TVM_DLL int ExportName(TVMValue* args, int* type_code, int num_args, TVMValue* out_value, \
1225  int* out_type_code, void* resource_handle) { \
1226  try { \
1227  auto f = Function; \
1228  using FType = ::tvm::runtime::detail::function_signature<decltype(f)>::FType; \
1229  ::tvm::runtime::TVMRetValue rv; \
1230  ::tvm::runtime::detail::unpack_call_by_signature<FType>::run( \
1231  f, ::tvm::runtime::TVMArgs(args, type_code, num_args), &rv); \
1232  rv.MoveToCHost(out_value, out_type_code); \
1233  return 0; \
1234  } catch (const ::std::exception& _except_) { \
1235  TVMAPISetLastError(_except_.what()); \
1236  return -1; \
1237  } \
1238  } \
1239  }
1240 
1241 inline TVMArgValue TVMArgs::operator[](int i) const {
1242  ICHECK_LT(i, num_args) << "not enough argument passed, " << num_args << " passed"
1243  << " but request arg[" << i << "].";
1244  return TVMArgValue(values[i], type_codes[i]);
1245 }
1246 
1247 inline int TVMArgs::size() const { return num_args; }
1248 
1249 template <class TPackedFuncSubObj>
1251  TVMRetValue* rv) {
1252  (static_cast<const TPackedFuncSubObj*>(obj))->callable_(args, rv);
1253 }
1254 
1255 TVM_ALWAYS_INLINE void PackedFuncObj::CallPacked(TVMArgs args, TVMRetValue* rv) const {
1256  (*f_call_packed_)(this, args, rv);
1257 }
1258 
1259 TVM_ALWAYS_INLINE void PackedFunc::CallPacked(TVMArgs args, TVMRetValue* rv) const {
1260  (static_cast<PackedFuncObj*>(data_.get()))->CallPacked(args, rv);
1261 }
1262 
1263 // internal namespace
1264 inline const char* ArgTypeCode2Str(int type_code) {
1265  switch (type_code) {
1266  case kDLInt:
1267  return "int";
1268  case kDLUInt:
1269  return "uint";
1270  case kDLFloat:
1271  return "float";
1272  case kTVMStr:
1273  return "str";
1274  case kTVMBytes:
1275  return "bytes";
1276  case kTVMOpaqueHandle:
1277  return "handle";
1278  case kTVMNullptr:
1279  return "NULL";
1280  case kTVMDLTensorHandle:
1281  return "ArrayHandle";
1282  case kTVMDataType:
1283  return "DLDataType";
1284  case kDLDevice:
1285  return "DLDevice";
1286  case kTVMPackedFuncHandle:
1287  return "FunctionHandle";
1288  case kTVMModuleHandle:
1289  return "ModuleHandle";
1290  case kTVMNDArrayHandle:
1291  return "NDArrayContainer";
1292  case kTVMObjectHandle:
1293  return "Object";
1295  return "ObjectRValueRefArg";
1296  default:
1297  LOG(FATAL) << "unknown type_code=" << static_cast<int>(type_code);
1298  }
1299  throw;
1300 }
1301 
1307 inline const char* DLDeviceType2Str(int type) {
1308  switch (type) {
1309  case kDLCPU:
1310  return "cpu";
1311  case kDLCUDA:
1312  return "cuda";
1313  case kDLCUDAHost:
1314  return "cuda_host";
1315  case kDLCUDAManaged:
1316  return "cuda_managed";
1317  case kDLOpenCL:
1318  return "opencl";
1319  case kDLSDAccel:
1320  return "sdaccel";
1321  case kDLAOCL:
1322  return "aocl";
1323  case kDLVulkan:
1324  return "vulkan";
1325  case kDLMetal:
1326  return "metal";
1327  case kDLVPI:
1328  return "vpi";
1329  case kDLROCM:
1330  return "rocm";
1331  case kDLROCMHost:
1332  return "rocm_host";
1333  case kDLExtDev:
1334  return "ext_dev";
1335  case kDLOneAPI:
1336  return "oneapi";
1337  case kDLWebGPU:
1338  return "webgpu";
1339  case kDLHexagon:
1340  return "hexagon";
1341  case kOpenGL:
1342  return "opengl";
1343  case kDLMicroDev:
1344  return "microdev";
1345  default:
1346  LOG(FATAL) << "unknown type = " << type;
1347  }
1348  throw;
1349 }
1350 
1351 namespace detail {
1352 
1353 template <bool stop, std::size_t I, typename F>
1354 struct for_each_dispatcher {
1355  template <typename T, typename... Args>
1356  static void run(const F& f, T&& value, Args&&... args) { // NOLINT(*)
1357  f(I, std::forward<T>(value));
1358  for_each_dispatcher<sizeof...(Args) == 0, (I + 1), F>::run(f, std::forward<Args>(args)...);
1359  }
1360 };
1361 
1362 template <std::size_t I, typename F>
1363 struct for_each_dispatcher<true, I, F> {
1364  static void run(const F& f) {} // NOLINT(*)
1365 };
1366 
1367 template <typename F, typename... Args>
1368 inline void for_each(const F& f, Args&&... args) { // NOLINT(*)
1369  for_each_dispatcher<sizeof...(Args) == 0, 0, F>::run(f, std::forward<Args>(args)...);
1370 }
1371 
1372 template <typename T>
1373 struct ModuleVTableEntryHelper {};
1374 
1375 template <typename T, typename R, typename... Args>
1376 struct ModuleVTableEntryHelper<R (T::*)(Args...) const> {
1377  using MemFnType = R (T::*)(Args...) const;
1378  using IndexSeq = std::index_sequence_for<Args...>;
1379  static constexpr const std::size_t LenArgs = sizeof...(Args);
1380 
1381  template <std::size_t... Is>
1382  static TVM_ALWAYS_INLINE void Call(TVMRetValue* rv, T* self, MemFnType f, TVMArgs args,
1383  std::index_sequence<Is...>) {
1384  *rv = (self->*f)(args[Is]...);
1385  }
1386 };
1387 
1388 template <typename T, typename R, typename... Args>
1389 struct ModuleVTableEntryHelper<R (T::*)(Args...)> {
1390  using MemFnType = R (T::*)(Args...);
1391  using IndexSeq = std::index_sequence_for<Args...>;
1392  static constexpr const std::size_t LenArgs = sizeof...(Args);
1393 
1394  template <std::size_t... Is>
1395  static TVM_ALWAYS_INLINE void Call(TVMRetValue* rv, T* self, MemFnType f, TVMArgs args,
1396  std::index_sequence<Is...>) {
1397  *rv = (self->*f)(args[Is]...);
1398  }
1399 };
1400 
1401 template <typename T, typename... Args>
1402 struct ModuleVTableEntryHelper<void (T::*)(Args...) const> {
1403  using MemFnType = void (T::*)(Args...) const;
1404  using IndexSeq = std::index_sequence_for<Args...>;
1405  static constexpr const std::size_t LenArgs = sizeof...(Args);
1406 
1407  template <std::size_t... Is>
1408  static TVM_ALWAYS_INLINE void Call(TVMRetValue* rv, T* self, MemFnType f, TVMArgs args,
1409  std::index_sequence<Is...>) {
1410  (self->*f)(args[Is]...);
1411  }
1412 };
1413 
1414 template <typename T, typename... Args>
1415 struct ModuleVTableEntryHelper<void (T::*)(Args...)> {
1416  using MemFnType = void (T::*)(Args...);
1417  using IndexSeq = std::index_sequence_for<Args...>;
1418  static constexpr const std::size_t LenArgs = sizeof...(Args);
1419 
1420  template <std::size_t... Is>
1421  static TVM_ALWAYS_INLINE void Call(TVMRetValue* rv, T* self, MemFnType f, TVMArgs args,
1422  std::index_sequence<Is...>) {
1423  (self->*f)(args[Is]...);
1424  }
1425 };
1426 
1427 namespace parameter_pack {
1428 
1429 template <typename... EnumArgs>
1430 struct EnumeratedParamPack {
1431  struct InvokeWithoutArg {
1432  template <template <size_t i, typename TArgument> class Functor, typename ExtraParams>
1433  static void F(ExtraParams&& extra_params) {
1434  using TExpander = int[];
1435  (void)TExpander{
1436  0,
1437  (Functor<EnumArgs::i, typename EnumArgs::T>::F(std::forward<ExtraParams>(extra_params)),
1438  0)...,
1439  };
1440  }
1441  };
1442  struct InvokeWithArg {
1443  template <template <size_t i, typename TArgument> class Functor, typename ExtraParams,
1444  typename... Params>
1445  static void F(ExtraParams&& extra_params, Params&&... params) {
1446  using TExpander = int[];
1447  (void)TExpander{
1448  0,
1449  (Functor<EnumArgs::i, typename EnumArgs::T>::F(std::forward<ExtraParams>(extra_params),
1450  std::forward<Params>(params)),
1451  0)...,
1452  };
1453  }
1454  };
1455 };
1456 
1457 template <typename... Args>
1458 struct EnumerateImpl {
1459  private:
1460  template <size_t _i, typename _T>
1461  struct Item {
1462  static const constexpr size_t i = _i;
1463  using T = _T;
1464  };
1465 
1466  template <typename...>
1467  struct Zipper;
1468 
1469  template <std::size_t... id>
1470  struct Zipper<std::integer_sequence<std::size_t, id...>> {
1471  using WithoutArg = typename EnumeratedParamPack<Item<id, Args>...>::InvokeWithoutArg;
1472  using WithArg = typename EnumeratedParamPack<Item<id, Args>...>::InvokeWithArg;
1473  };
1474 
1475  public:
1476  using WithoutArg = typename Zipper<std::index_sequence_for<Args...>>::WithoutArg;
1477  using WithArg = typename Zipper<std::index_sequence_for<Args...>>::WithArg;
1478 };
1479 
1480 template <typename... Args>
1481 using EnumerateWithoutArg = typename EnumerateImpl<Args...>::WithoutArg;
1482 
1483 template <typename... Args>
1484 using EnumerateWithArg = typename EnumerateImpl<Args...>::WithArg;
1485 
1486 template <typename... Args>
1487 struct ParamPack {
1488  template <template <size_t i, typename TArgument> class Functor, typename ExtraParams>
1489  static void InvokeWithoutArg(ExtraParams&& extra_params) {
1490  EnumerateWithoutArg<Args...>::template F<Functor, ExtraParams>(
1491  std::forward<ExtraParams>(extra_params));
1492  }
1493 };
1494 
1495 } // namespace parameter_pack
1496 
1501 template <typename T>
1502 struct func_signature_helper {
1503  using FType = void;
1504 };
1505 
1506 template <typename T, typename R, typename... Args>
1507 struct func_signature_helper<R (T::*)(Args...)> {
1508  using FType = R(Args...);
1509  using ParamType = parameter_pack::ParamPack<Args...>;
1510  using RetType = R;
1511  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1512 };
1513 
1514 template <typename T, typename R, typename... Args>
1515 struct func_signature_helper<R (T::*)(Args...) const> {
1516  using FType = R(Args...);
1517  using ParamType = parameter_pack::ParamPack<Args...>;
1518  using RetType = R;
1519  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1520 };
1521 
1526 template <typename T>
1527 struct function_signature {
1528  using FType = typename func_signature_helper<decltype(&T::operator())>::FType;
1529  using ParamType = typename func_signature_helper<decltype(&T::operator())>::ParamType;
1530  using RetType = typename func_signature_helper<decltype(&T::operator())>::RetType;
1531 };
1532 
1533 // handle case of function.
1534 template <typename R, typename... Args>
1535 struct function_signature<R(Args...)> {
1536  using FType = R(Args...);
1537  using ParamType = parameter_pack::ParamPack<Args...>;
1538  using RetType = R;
1539  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1540 };
1541 
1542 // handle case of function ptr.
1543 template <typename R, typename... Args>
1544 struct function_signature<R (*)(Args...)> {
1545  using FType = R(Args...);
1546  using ParamType = detail::parameter_pack::ParamPack<Args...>;
1547  using RetType = R;
1548  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1549 };
1550 
1551 template <typename TSignature>
1552 struct SignaturePrinter;
1553 
1554 namespace type2str {
1555 
1556 template <typename T>
1557 struct TypeSimplifier;
1558 
1559 template <typename T>
1560 struct Type2Str {
1561  template <typename = std::enable_if_t<std::is_base_of<ObjectRef, T>::value>>
1562  static std::string v() {
1563  return T::ContainerType::_type_key;
1564  }
1565 };
1566 template <>
1567 struct Type2Str<int> {
1568  static std::string v() { return "int"; }
1569 };
1570 template <>
1571 struct Type2Str<double> {
1572  static std::string v() { return "double"; }
1573 };
1574 template <>
1575 struct Type2Str<int64_t> {
1576  static std::string v() { return "int64_t"; }
1577 };
1578 template <>
1579 struct Type2Str<uint64_t> {
1580  static std::string v() { return "uint64_t"; }
1581 };
1582 template <>
1583 struct Type2Str<bool> {
1584  static std::string v() { return "bool"; }
1585 };
1586 template <>
1587 struct Type2Str<void> {
1588  static std::string v() { return "void"; }
1589 };
1590 template <>
1591 struct Type2Str<std::basic_string<char>> {
1592  static std::string v() { return "basic_string<char>"; }
1593 };
1594 template <typename K, typename V>
1595 struct Type2Str<Map<K, V>> {
1596  static std::string v() {
1597  return "Map<" + TypeSimplifier<K>::v() + ", " + TypeSimplifier<V>::v() + ">";
1598  }
1599 };
1600 template <>
1601 struct Type2Str<DLDevice> {
1602  static std::string v() { return "DLDevice"; }
1603 };
1604 template <>
1605 struct Type2Str<DLTensor> {
1606  static std::string v() { return "DLTensor"; }
1607 };
1608 template <>
1609 struct Type2Str<DataType> {
1610  static std::string v() { return "DataType"; }
1611 };
1612 template <>
1613 struct Type2Str<DLDataType> {
1614  static std::string v() { return "DLDataType"; }
1615 };
1616 template <>
1617 struct Type2Str<TVMRetValue> {
1618  static std::string v() { return "TVMRetValue"; }
1619 };
1620 template <>
1621 struct Type2Str<TVMArgValue> {
1622  static std::string v() { return "TVMArgValue"; }
1623 };
1624 template <>
1625 struct Type2Str<TVMByteArray> {
1626  static std::string v() { return "TVMByteArray"; }
1627 };
1628 template <typename FType>
1629 struct Type2Str<TypedPackedFunc<FType>> {
1630  static std::string v() { return SignaturePrinter<function_signature<FType>>::F(); }
1631 };
1632 template <typename T>
1633 struct Type2Str<Array<T>> {
1634  static std::string v() { return "Array<" + TypeSimplifier<T>::v() + ">"; }
1635 };
1636 
1641 template <typename T>
1642 struct TypeSimplifier {
1643  static std::string v() {
1644  using U = typename std::remove_cv<
1645  typename std::remove_reference<typename std::remove_pointer<T>::type>::type>::type;
1646  return (std::is_const<T>::value ? "const " : "") + Type2Str<U>::v() +
1647  (std::is_pointer<T>::value ? "*" : "") + (std::is_reference<T>::value ? "&" : "");
1648  }
1649 };
1650 
1651 } // namespace type2str
1652 
1657 template <typename TSignature>
1658 struct SignaturePrinter {
1659  using ParamType = typename TSignature::ParamType;
1660  using RetType = typename TSignature::RetType;
1661 
1662  template <size_t i, typename TArgument>
1663  struct PrintParamType {
1664  static void F(std::ostream& os) {
1665  os << (i == 0 ? "" : ", ") << i << ": " << type2str::TypeSimplifier<TArgument>::v();
1666  }
1667  };
1668 
1669  static std::string F() {
1670  std::ostringstream oss;
1671  oss << "(";
1672  ParamType::template InvokeWithoutArg<PrintParamType>(oss);
1673  oss << ") -> " << type2str::TypeSimplifier<RetType>::v();
1674  return oss.str();
1675  }
1676 };
1677 } // namespace detail
1678 
1679 /* \brief argument settter to PackedFunc */
1681  public:
1682  TVMArgsSetter(TVMValue* values, int* type_codes) : values_(values), type_codes_(type_codes) {}
1683  // setters for POD types
1684  template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
1685  TVM_ALWAYS_INLINE void operator()(size_t i, T value) const {
1686  values_[i].v_int64 = static_cast<int64_t>(value);
1687  type_codes_[i] = kDLInt;
1688  }
1689  TVM_ALWAYS_INLINE void operator()(size_t i, uint64_t value) const {
1690  values_[i].v_int64 = static_cast<int64_t>(value);
1691  ICHECK_LE(value, static_cast<uint64_t>(std::numeric_limits<int64_t>::max()));
1692  type_codes_[i] = kDLInt;
1693  }
1694  TVM_ALWAYS_INLINE void operator()(size_t i, double value) const {
1695  values_[i].v_float64 = value;
1696  type_codes_[i] = kDLFloat;
1697  }
1698  TVM_ALWAYS_INLINE void operator()(size_t i, std::nullptr_t value) const {
1699  values_[i].v_handle = value;
1700  type_codes_[i] = kTVMNullptr;
1701  }
1702  TVM_ALWAYS_INLINE void operator()(size_t i, const TVMArgValue& value) const {
1703  values_[i] = value.value_;
1704  type_codes_[i] = value.type_code_;
1705  }
1706  TVM_ALWAYS_INLINE void operator()(size_t i, void* value) const {
1707  values_[i].v_handle = value;
1708  type_codes_[i] = kTVMOpaqueHandle;
1709  }
1710  TVM_ALWAYS_INLINE void operator()(size_t i, DLTensor* value) const {
1711  values_[i].v_handle = value;
1712  type_codes_[i] = kTVMDLTensorHandle;
1713  }
1714  TVM_ALWAYS_INLINE void operator()(size_t i, Device value) const {
1715  values_[i].v_device = value;
1716  type_codes_[i] = kDLDevice;
1717  }
1718  TVM_ALWAYS_INLINE void operator()(size_t i, DLDataType value) const {
1719  values_[i].v_type = value;
1720  type_codes_[i] = kTVMDataType;
1721  }
1722  TVM_ALWAYS_INLINE void operator()(size_t i, DataType dtype) const {
1723  operator()(i, dtype.operator DLDataType());
1724  }
1725  TVM_ALWAYS_INLINE void operator()(size_t i, const char* value) const {
1726  values_[i].v_str = value;
1727  type_codes_[i] = kTVMStr;
1728  }
1729  // setters for container types
1730  TVM_ALWAYS_INLINE void operator()(size_t i, const std::string& value) const {
1731  values_[i].v_str = value.c_str();
1732  type_codes_[i] = kTVMStr;
1733  }
1734  TVM_ALWAYS_INLINE void operator()(size_t i, const TVMByteArray& value) const {
1735  values_[i].v_handle = const_cast<TVMByteArray*>(&value);
1736  type_codes_[i] = kTVMBytes;
1737  }
1738  template <typename FType>
1739  TVM_ALWAYS_INLINE void operator()(size_t i, const TypedPackedFunc<FType>& value) const {
1740  operator()(i, value.packed());
1741  }
1742  void operator()(size_t i, const TVMRetValue& value) const {
1743  if (value.type_code() == kTVMStr) {
1744  values_[i].v_str = value.ptr<std::string>()->c_str();
1745  type_codes_[i] = kTVMStr;
1746  } else {
1747  ICHECK_NE(value.type_code(), kTVMBytes) << "not handled.";
1748  values_[i] = value.value_;
1749  type_codes_[i] = value.type_code();
1750  }
1751  }
1752  // ObjectRef handling
1753  template <typename TObjectRef,
1754  typename = typename std::enable_if<std::is_base_of<ObjectRef, TObjectRef>::value>::type>
1755  TVM_ALWAYS_INLINE void operator()(size_t i, const TObjectRef& value) const {
1756  this->SetObject(i, value);
1757  }
1758 
1759  template <typename TObjectRef,
1760  typename = typename std::enable_if<std::is_base_of<
1761  ObjectRef, typename std::remove_reference<TObjectRef>::type>::value>::type>
1762  TVM_ALWAYS_INLINE void operator()(size_t i, TObjectRef&& value) const {
1763  this->SetObject(i, std::forward<TObjectRef>(value));
1764  }
1765 
1766  private:
1767  template <typename TObjectRef>
1768  inline void SetObject(size_t i, TObjectRef&& value) const;
1770  TVMValue* values_;
1772  int* type_codes_;
1773 };
1774 
1775 template <typename... Args>
1776 inline TVMRetValue PackedFunc::operator()(Args&&... args) const {
1777  const int kNumArgs = sizeof...(Args);
1778  const int kArraySize = kNumArgs > 0 ? kNumArgs : 1;
1779  TVMValue values[kArraySize];
1780  int type_codes[kArraySize];
1781  detail::for_each(TVMArgsSetter(values, type_codes), std::forward<Args>(args)...);
1782  TVMRetValue rv;
1783  (static_cast<PackedFuncObj*>(data_.get()))
1784  ->CallPacked(TVMArgs(values, type_codes, kNumArgs), &rv);
1785  return rv;
1786 }
1787 
1788 template <size_t i, typename T>
1790  static TVM_ALWAYS_INLINE void F(TVMArgsSetter* setter, T&& value) {
1791  (*setter)(i, std::forward<T>(value));
1792  }
1793 };
1794 
1795 template <typename... Args>
1796 void TVM_ALWAYS_INLINE PackArgs(TVMValue* values, int* type_codes, Args&&... args) {
1797  TVMArgsSetter setter(values, type_codes);
1798  detail::parameter_pack::EnumerateWithArg<Args...>::template F<TVMArgsSetterApply>(
1799  &setter, std::forward<Args>(args)...);
1800 }
1801 
1802 namespace detail {
1803 template <typename R, int nleft, int index, typename F>
1804 struct unpack_call_dispatcher {
1805  template <typename... Args>
1806  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1807  const TVMArgs& args_pack, TVMRetValue* rv,
1808  Args&&... unpacked_args) {
1809  // construct a movable argument value
1810  // which allows potential move of argument to the input of F.
1811  unpack_call_dispatcher<R, nleft - 1, index + 1, F>::run(
1812  optional_name, f_sig, f, args_pack, rv, std::forward<Args>(unpacked_args)...,
1813  TVMMovableArgValueWithContext_(args_pack.values[index], args_pack.type_codes[index], index,
1814  optional_name, f_sig));
1815  }
1816 };
1817 
1818 template <typename R, int index, typename F>
1819 struct unpack_call_dispatcher<R, 0, index, F> {
1820  template <typename... Args>
1821  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1822  const TVMArgs& args_pack, TVMRetValue* rv,
1823  Args&&... unpacked_args) {
1824  using RetType = decltype(f(std::forward<Args>(unpacked_args)...));
1825  if (std::is_same<RetType, R>::value) {
1826  *rv = f(std::forward<Args>(unpacked_args)...);
1827  } else {
1828  *rv = R(f(std::forward<Args>(unpacked_args)...));
1829  }
1830  }
1831 };
1832 
1833 template <int index, typename F>
1834 struct unpack_call_dispatcher<void, 0, index, F> {
1835  template <typename... Args>
1836  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1837  const TVMArgs& args_pack, TVMRetValue* rv,
1838  Args&&... unpacked_args) {
1839  f(std::forward<Args>(unpacked_args)...);
1840  }
1841 };
1842 
1843 template <typename R, int nargs, typename F>
1844 TVM_ALWAYS_INLINE void unpack_call(const std::string* optional_name, const F& f,
1845  const TVMArgs& args, TVMRetValue* rv) {
1846  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<F>>::F;
1847  CHECK_EQ(nargs, args.size()) << "Function "
1848  << (optional_name == nullptr ? "<anonymous>" : *optional_name)
1849  << (f_sig == nullptr ? "" : (*f_sig)()) << " expects " << nargs
1850  << " arguments but " << args.size() << " were provided";
1851  unpack_call_dispatcher<R, nargs, 0, F>::run(optional_name, f_sig, f, args, rv);
1852 }
1853 
1854 template <typename FType>
1855 struct unpack_call_by_signature {};
1856 
1857 template <typename R, typename... Args>
1858 struct unpack_call_by_signature<R(Args...)> {
1859  template <typename F>
1860  TVM_ALWAYS_INLINE static void run(const F& f, const TVMArgs& args, TVMRetValue* rv) {
1861  unpack_call<R, sizeof...(Args)>(nullptr, f, args, rv);
1862  }
1863 };
1864 
1865 template <typename R, typename... Args>
1866 TVM_ALWAYS_INLINE R call_packed(const PackedFunc& pf, Args&&... args) {
1867  return R(pf(std::forward<Args>(args)...));
1868 }
1869 
1870 template <typename R>
1871 struct typed_packed_call_dispatcher {
1872  template <typename... Args>
1873  TVM_ALWAYS_INLINE static R run(const PackedFunc& pf, Args&&... args) {
1874  return pf(std::forward<Args>(args)...);
1875  }
1876 };
1877 
1878 template <>
1879 struct typed_packed_call_dispatcher<void> {
1880  template <typename... Args>
1881  TVM_ALWAYS_INLINE static void run(const PackedFunc& pf, Args&&... args) {
1882  pf(std::forward<Args>(args)...);
1883  }
1884 };
1885 } // namespace detail
1886 
1887 template <typename R, typename... Args>
1888 TypedPackedFunc<R(Args...)>::TypedPackedFunc(PackedFunc packed) : packed_(packed) {}
1889 
1890 template <typename R, typename... Args>
1892  : packed_(value.operator PackedFunc()) {}
1893 
1894 template <typename R, typename... Args>
1896  : packed_(value.operator PackedFunc()) {}
1897 
1898 template <typename R, typename... Args>
1900  : packed_(value.operator PackedFunc()) {}
1901 
1902 template <typename R, typename... Args>
1903 template <typename FType>
1904 inline void TypedPackedFunc<R(Args...)>::AssignTypedLambda(FType flambda, std::string name) {
1905  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<FType>>::F;
1906  packed_ = PackedFunc([flambda, name, f_sig](const TVMArgs& args, TVMRetValue* rv) {
1907  if (args.size() != sizeof...(Args)) {
1908  LOG(FATAL) << "Function " << name << (f_sig == nullptr ? "" : (*f_sig)()) << " expects "
1909  << sizeof...(Args) << " arguments, but " << args.size() << " were provided.";
1910  }
1911  detail::unpack_call<R, sizeof...(Args)>(&name, flambda, args, rv);
1912  });
1913 }
1914 
1915 template <typename R, typename... Args>
1916 template <typename FType>
1917 inline void TypedPackedFunc<R(Args...)>::AssignTypedLambda(FType flambda) {
1918  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<FType>>::F;
1919  packed_ = PackedFunc([flambda, f_sig](const TVMArgs& args, TVMRetValue* rv) {
1920  if (args.size() != sizeof...(Args)) {
1921  LOG(FATAL) << "Function <anonymous> " << (*f_sig)() << " expects " << sizeof...(Args)
1922  << " arguments, but " << args.size() << " were provided.";
1923  }
1924  detail::unpack_call<R, sizeof...(Args)>(nullptr, flambda, args, rv);
1925  });
1926 }
1927 
1928 template <typename R, typename... Args>
1929 TVM_ALWAYS_INLINE R TypedPackedFunc<R(Args...)>::operator()(Args... args) const {
1930  return detail::typed_packed_call_dispatcher<R>::run(packed_, std::forward<Args>(args)...);
1931 }
1932 
1933 template <typename T>
1934 inline T TVMArgs::At(int i) const {
1935  TVMArgValue arg = operator[](i);
1936  try {
1937  return arg.operator T();
1938  } catch (const dmlc::Error& e) {
1939  LOG(FATAL) << "Argument " << i << " cannot be converted to type \""
1940  << tvm::runtime::detail::type2str::Type2Str<T>::v() << "\". Its type is \""
1941  << tvm::runtime::ArgTypeCode2Str(arg.type_code()) << "\".";
1942  }
1943  throw;
1944 }
1945 
1946 // ObjectRef related conversion handling
1947 // Object can have three possible type codes:
1948 // kTVMNDArrayHandle, kTVMModuleHandle, kTVMObjectHandle
1949 //
1950 // We use type traits to eliminate un-necessary checks.
1951 template <typename T>
1952 inline void TVMArgsSetter::SetObject(size_t i, T&& value) const {
1953  using ContainerType = typename std::remove_reference<T>::type::ContainerType;
1954  if (value.defined()) {
1955  Object* ptr = value.data_.data_;
1956  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value ||
1957  (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1959  values_[i].v_handle = NDArray::FFIGetHandle(value);
1960  type_codes_[i] = kTVMNDArrayHandle;
1961  } else if (std::is_base_of<Module::ContainerType, ContainerType>::value ||
1962  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1963  ptr->IsInstance<Module::ContainerType>())) {
1964  values_[i].v_handle = ptr;
1965  type_codes_[i] = kTVMModuleHandle;
1966  } else if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value ||
1967  (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
1969  values_[i].v_handle = ptr;
1970  type_codes_[i] = kTVMPackedFuncHandle;
1971  } else if (std::is_rvalue_reference<decltype(value)>::value) {
1972  values_[i].v_handle = const_cast<Object**>(&(value.data_.data_));
1973  type_codes_[i] = kTVMObjectRValueRefArg;
1974  } else {
1975  values_[i].v_handle = value.data_.data_;
1976  type_codes_[i] = kTVMObjectHandle;
1977  }
1978  } else {
1979  type_codes_[i] = kTVMNullptr;
1980  values_[i].v_handle = nullptr;
1981  }
1982 }
1983 
1984 template <typename TObjectRef, typename>
1985 inline bool TVMPODValue_::IsObjectRef() const {
1986  using ContainerType = typename TObjectRef::ContainerType;
1987  // NOTE: the following code can be optimized by constant folding.
1988  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value) {
1989  return type_code_ == kTVMNDArrayHandle &&
1991  ->IsInstance<ContainerType>();
1992  }
1993  if (std::is_base_of<Module::ContainerType, ContainerType>::value) {
1994  return type_code_ == kTVMModuleHandle &&
1995  static_cast<Object*>(value_.v_handle)->IsInstance<ContainerType>();
1996  }
1997  if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value) {
1998  return type_code_ == kTVMPackedFuncHandle &&
1999  static_cast<Object*>(value_.v_handle)->IsInstance<ContainerType>();
2000  }
2001  // NOTE: we don't pass NDArray and runtime::Module as RValue ref.
2004  }
2005  return (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
2007  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
2009  (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
2013 }
2014 
2015 template <typename TObjectRef>
2016 inline TObjectRef TVMPODValue_::AsObjectRef() const {
2017  static_assert(std::is_base_of<ObjectRef, TObjectRef>::value,
2018  "Conversion only works for ObjectRef");
2019  using ContainerType = typename TObjectRef::ContainerType;
2020 
2021  if (type_code_ == kTVMNullptr) {
2022  CHECK(TObjectRef::_type_is_nullable)
2023  << "Expect a not null value of " << ContainerType::_type_key;
2024  return TObjectRef(ObjectPtr<Object>(nullptr));
2025  }
2026  // NOTE: the following code can be optimized by constant folding.
2027  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value) {
2028  // Casting to a sub-class of NDArray
2030  ObjectPtr<Object> data =
2032  CHECK(data->IsInstance<ContainerType>())
2033  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
2034  return TObjectRef(data);
2035  }
2036  if (std::is_base_of<Module::ContainerType, ContainerType>::value) {
2037  // Casting to a sub-class of Module
2039  ObjectPtr<Object> data = GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle));
2040  CHECK(data->IsInstance<ContainerType>())
2041  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
2042  return TObjectRef(data);
2043  }
2044  if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value) {
2045  // Casting to a sub-class of PackedFunc
2047  ObjectPtr<Object> data = GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle));
2048  CHECK(data->IsInstance<ContainerType>())
2049  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
2050  return TObjectRef(data);
2051  }
2052  if (type_code_ == kTVMObjectHandle) {
2053  // normal object type check.
2054  Object* ptr = static_cast<Object*>(value_.v_handle);
2056  ICHECK(!checked_type.defined()) << "Expected " << ObjectTypeChecker<TObjectRef>::TypeName()
2057  << ", but got " << checked_type.value();
2058  return TObjectRef(GetObjectPtr<Object>(ptr));
2059  } else if (type_code_ == kTVMObjectRValueRefArg) {
2060  Object* ptr = *static_cast<Object**>(value_.v_handle);
2062  ICHECK(!checked_type.defined()) << "Expected " << ObjectTypeChecker<TObjectRef>::TypeName()
2063  << ", but got " << checked_type.value();
2064  return TObjectRef(GetObjectPtr<Object>(ptr));
2065  } else if (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
2067  // Casting to a base class that NDArray can sub-class
2068  ObjectPtr<Object> data =
2070  return TObjectRef(data);
2071  } else if (std::is_base_of<ContainerType, Module::ContainerType>::value &&
2073  // Casting to a base class that Module can sub-class
2074  return TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
2075  } else if (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
2077  // Casting to a base class that PackedFunc can sub-class
2078  return TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
2079  } else {
2081  return TObjectRef(ObjectPtr<Object>(nullptr));
2082  }
2083 }
2084 
2085 template <typename TObjectRef, typename>
2086 inline TVMRetValue& TVMRetValue::operator=(TObjectRef other) {
2087  using ContainerType = typename TObjectRef::ContainerType;
2088  const Object* ptr = other.get();
2089  if (ptr != nullptr) {
2090  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value ||
2091  (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
2092  ptr->IsInstance<NDArray::ContainerType>())) {
2093  return operator=(NDArray(std::move(other.data_)));
2094  }
2095  if (std::is_base_of<Module::ContainerType, ContainerType>::value ||
2096  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
2097  ptr->IsInstance<Module::ContainerType>())) {
2098  return operator=(Module(std::move(other.data_)));
2099  }
2100  if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value ||
2101  (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
2102  ptr->IsInstance<PackedFunc::ContainerType>())) {
2103  return operator=(PackedFunc(std::move(other.data_)));
2104  }
2105  SwitchToObject(kTVMObjectHandle, std::move(other.data_));
2106  } else {
2107  SwitchToPOD(kTVMNullptr);
2108  value_.v_handle = nullptr;
2109  }
2110  return *this;
2111 }
2112 
2113 template <typename T, typename>
2114 inline TVMArgValue::operator T() const {
2115  return PackedFuncValueConverter<T>::From(*this);
2116 }
2117 
2118 template <typename T, typename>
2119 inline TVMMovableArgValue_::operator T() const {
2120  if (type_code_ == kTVMObjectRValueRefArg) {
2121  auto** ref = static_cast<Object**>(value_.v_handle);
2122  if (ObjectTypeChecker<T>::Check(*ref)) {
2124  }
2125  }
2126  // fallback
2127  return PackedFuncValueConverter<T>::From(AsArgValue());
2128 }
2129 
2130 template <typename T, typename>
2131 inline TVMRetValue::operator T() const {
2132  return PackedFuncValueConverter<T>::From(*this);
2133 }
2134 
2135 inline PackedFunc Module::GetFunction(const String& name, bool query_imports) {
2136  return (*this)->GetFunction(name, query_imports);
2137 }
2138 
2139 // specializations of PackedFuncValueConverter
2140 template <>
2142  static String From(const TVMArgValue& val) {
2143  if (val.IsObjectRef<tvm::runtime::String>()) {
2144  return val.AsObjectRef<tvm::runtime::String>();
2145  } else {
2146  return tvm::runtime::String(val.operator std::string());
2147  }
2148  }
2149 
2150  static String From(const TVMRetValue& val) {
2151  if (val.IsObjectRef<tvm::runtime::String>()) {
2152  return val.AsObjectRef<tvm::runtime::String>();
2153  } else {
2154  return tvm::runtime::String(val.operator std::string());
2155  }
2156  }
2157 };
2158 
2159 template <typename T>
2161  static Optional<T> From(const TVMArgValue& val) {
2162  if (val.type_code() == kTVMNullptr) return Optional<T>(nullptr);
2164  }
2165  static Optional<T> From(const TVMRetValue& val) {
2166  if (val.type_code() == kTVMNullptr) return Optional<T>(nullptr);
2168  }
2169 };
2170 
2171 template <typename... VariantTypes>
2172 struct PackedFuncValueConverter<Variant<VariantTypes...>> {
2173  using VType = Variant<VariantTypes...>;
2174 
2175  // Can't just take `const TVMPODValue&` as an argument, because
2176  // `TVMArgValue` and `TVMRetValue` have different implementations
2177  // for `operator std::string()`.
2178  template <typename PODSubclass>
2179  static VType From(const PODSubclass& val) {
2180  if (auto opt = TryAsObjectRef<VariantTypes...>(val)) {
2181  return opt.value();
2182  }
2183 
2184  if (auto opt = TryValueConverter<PODSubclass, VariantTypes...>(val)) {
2185  return opt.value();
2186  }
2187 
2188  LOG(FATAL) << "Expected one of "
2189  << static_cast<const std::stringstream&>(
2190  (std::stringstream() << ... << VariantTypes::ContainerType::_type_key))
2191  .str()
2192  << " but got " << ArgTypeCode2Str(val.type_code());
2193  }
2194 
2195  template <typename VarFirst, typename... VarRest>
2197  if (val.IsObjectRef<VarFirst>()) {
2198  return VType(val.AsObjectRef<VarFirst>());
2199  } else if constexpr (sizeof...(VarRest)) {
2200  return TryAsObjectRef<VarRest...>(val);
2201  } else {
2202  return NullOpt;
2203  }
2204  }
2205 
2206  template <typename PODSubclass, typename VarFirst, typename... VarRest>
2207  static Optional<VType> TryValueConverter(const PODSubclass& val) {
2208  try {
2210  } catch (const InternalError&) {
2211  }
2212 
2213  if constexpr (sizeof...(VarRest)) {
2214  return TryValueConverter<PODSubclass, VarRest...>(val);
2215  } else {
2216  return NullOpt;
2217  }
2218  }
2219 };
2220 
2221 inline bool String::CanConvertFrom(const TVMArgValue& val) {
2222  return val.type_code() == kTVMStr || val.IsObjectRef<tvm::runtime::String>();
2223 }
2224 
2225 inline TVMArgValue::operator DLDataType() const {
2226  if (String::CanConvertFrom(*this)) {
2227  return String2DLDataType(PackedFuncValueConverter<String>::From(*this).operator std::string());
2228  }
2229  // None type
2230  if (type_code_ == kTVMNullptr) {
2231  DLDataType t;
2232  t.code = kTVMOpaqueHandle;
2233  t.bits = 0;
2234  t.lanes = 0;
2235  return t;
2236  }
2237  TVM_CHECK_TYPE_CODE(type_code_, kTVMDataType);
2238  return value_.v_type;
2239 }
2240 
2241 inline TVMArgValue::operator DataType() const { return DataType(operator DLDataType()); }
2242 
2243 } // namespace runtime // NOLINT(*)
2244 } // namespace tvm // NOLINT(*)
2245 #endif // TVM_RUNTIME_PACKED_FUNC_H_
Runtime Array container types.
@ kTVMPackedFuncHandle
Definition: c_runtime_api.h:184
@ kTVMNDArrayHandle
Definition: c_runtime_api.h:187
@ kTVMModuleHandle
Definition: c_runtime_api.h:183
@ kTVMBytes
Definition: c_runtime_api.h:186
@ kTVMDataType
Definition: c_runtime_api.h:179
@ kTVMDLTensorHandle
Definition: c_runtime_api.h:181
@ kDLDevice
Definition: c_runtime_api.h:180
@ kTVMOpaqueHandle
Definition: c_runtime_api.h:177
@ kTVMObjectHandle
Definition: c_runtime_api.h:182
@ kTVMObjectRValueRefArg
Definition: c_runtime_api.h:188
@ kTVMNullptr
Definition: c_runtime_api.h:178
@ kTVMStr
Definition: c_runtime_api.h:185
@ kDLMicroDev
Definition: c_runtime_api.h:124
@ kOpenGL
Definition: c_runtime_api.h:123
@ kDLSDAccel
Definition: c_runtime_api.h:122
@ kDLAOCL
Definition: c_runtime_api.h:121
DLTensor * TVMArrayHandle
the array handle
Definition: c_runtime_api.h:202
array node content in array
Definition: array.h:40
size_t size() const
Definition: array.h:43
Array, container representing a contiguous sequence of ObjectRefs.
Definition: array.h:289
Runtime primitive data type.
Definition: data_type.h:43
Shared content of all specializations of hash map.
Definition: map.h:174
Map container of NodeRef->NodeRef in DSL graph. Map implements copy on write semantics,...
Definition: map.h:1271
Base container of module.
Definition: module.h:142
Module container of TVM.
Definition: module.h:79
PackedFunc GetFunction(const String &name, bool query_imports=false)
Get packed function from current module by name.
Definition: packed_func.h:2135
Object container class that backs NDArray.
Definition: ndarray.h:288
Managed NDArray. The array is backed by reference counted blocks.
Definition: ndarray.h:51
static TVMArrayHandle FFIGetHandle(const ObjectRef &nd)
Get FFI Array handle from ndarray.
Definition: ndarray.h:416
static ObjectPtr< Object > FFIDataFromHandle(TVMArrayHandle handle)
Construct NDArray's Data field from array handle in FFI.
Definition: ndarray.h:411
static void FFIDecRef(TVMArrayHandle handle)
DecRef resource managed by an FFI array handle.
Definition: ndarray.h:424
A custom smart pointer for Object.
Definition: object.h:362
Base class of all object reference.
Definition: object.h:519
bool defined() const
Definition: object.h:552
static void FFIClearAfterMove(ObjectRef *ref)
Clear the object ref data field without DecRef after we successfully moved the field.
Definition: object.h:623
friend class TVMArgsSetter
Definition: object.h:637
const Object * get() const
Definition: object.h:554
ObjectPtr< Object > data_
Internal pointer that backs the reference.
Definition: object.h:605
base class of all object containers.
Definition: object.h:171
std::string GetTypeKey() const
Definition: object.h:184
bool IsInstance() const
Definition: object.h:870
Optional container that to represent to a Nullable variant of T.
Definition: optional.h:51
T value() const
Definition: optional.h:92
Object container class that backs PackedFunc.
Definition: packed_func.h:69
PackedFuncObj(FCallPacked *f_call_pack)
Constructing a packed function object from a function pointer.
Definition: packed_func.h:104
static constexpr const uint32_t _type_index
Definition: packed_func.h:78
TVM_DECLARE_FINAL_OBJECT_INFO(PackedFuncObj, Object)
FCallPacked * f_call_packed_
Internal callable function pointer used to call the packed function.
Definition: packed_func.h:110
static constexpr const char * _type_key
Definition: packed_func.h:79
PackedFuncObj()=delete
Delete the default constructor explicitly.
void(const PackedFuncObj *, TVMArgs, TVMRetValue *) FCallPacked
The internal callable function type.
Definition: packed_func.h:98
TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue *rv) const
Call the function in packed format.
Definition: packed_func.h:1255
Derived object class for constructing PackedFuncObj.
Definition: packed_func.h:115
PackedFuncSubObj(TCallable callable)
Derived object class for constructing PackedFuncObj.
Definition: packed_func.h:125
TStorage callable_
Type-erased filed for storing callable object.
Definition: packed_func.h:128
Packed function is a type-erased function. The arguments are passed by packed format.
Definition: packed_func.h:139
bool operator!=(std::nullptr_t null) const
Definition: packed_func.h:181
bool operator==(std::nullptr_t null) const
Definition: packed_func.h:179
TVMRetValue operator()(Args &&... args) const
Call packed function by directly passing in unpacked format.
Definition: packed_func.h:1776
TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue *rv) const
Call the function in packed format.
Definition: packed_func.h:1259
PackedFunc(TCallable data)
Constructing a packed function from a callable type whose signature is consistent with PackedFunc
Definition: packed_func.h:152
TVM_DEFINE_OBJECT_REF_METHODS(PackedFunc, ObjectRef, PackedFuncObj)
PackedFunc(std::nullptr_t null)
Constructor from null.
Definition: packed_func.h:142
Reference to string objects.
Definition: string.h:98
static bool CanConvertFrom(const TVMArgValue &val)
Check if a TVMArgValue can be converted to String, i.e. it can be std::string or String.
Definition: packed_func.h:2221
A single argument value to PackedFunc. Containing both type_code and TVMValue.
Definition: packed_func.h:657
TObjectRef AsObjectRef() const
Definition: packed_func.h:2016
const TVMValue & value() const
Definition: packed_func.h:699
TVMArgValue(TVMValue value, int type_code)
constructor
Definition: packed_func.h:666
bool IsObjectRef() const
Definition: packed_func.h:1985
TVMArgValue()
default constructor
Definition: packed_func.h:660
Definition: packed_func.h:1680
TVM_ALWAYS_INLINE void operator()(size_t i, DLTensor *value) const
Definition: packed_func.h:1710
TVM_ALWAYS_INLINE void operator()(size_t i, uint64_t value) const
Definition: packed_func.h:1689
TVM_ALWAYS_INLINE void operator()(size_t i, const TypedPackedFunc< FType > &value) const
Definition: packed_func.h:1739
TVM_ALWAYS_INLINE void operator()(size_t i, const TObjectRef &value) const
Definition: packed_func.h:1755
void operator()(size_t i, const TVMRetValue &value) const
Definition: packed_func.h:1742
TVM_ALWAYS_INLINE void operator()(size_t i, TObjectRef &&value) const
Definition: packed_func.h:1762
TVM_ALWAYS_INLINE void operator()(size_t i, double value) const
Definition: packed_func.h:1694
TVM_ALWAYS_INLINE void operator()(size_t i, T value) const
Definition: packed_func.h:1685
TVMArgsSetter(TVMValue *values, int *type_codes)
Definition: packed_func.h:1682
TVM_ALWAYS_INLINE void operator()(size_t i, const char *value) const
Definition: packed_func.h:1725
TVM_ALWAYS_INLINE void operator()(size_t i, Device value) const
Definition: packed_func.h:1714
TVM_ALWAYS_INLINE void operator()(size_t i, void *value) const
Definition: packed_func.h:1706
TVM_ALWAYS_INLINE void operator()(size_t i, const std::string &value) const
Definition: packed_func.h:1730
TVM_ALWAYS_INLINE void operator()(size_t i, std::nullptr_t value) const
Definition: packed_func.h:1698
TVM_ALWAYS_INLINE void operator()(size_t i, const TVMByteArray &value) const
Definition: packed_func.h:1734
TVM_ALWAYS_INLINE void operator()(size_t i, DataType dtype) const
Definition: packed_func.h:1722
TVM_ALWAYS_INLINE void operator()(size_t i, DLDataType value) const
Definition: packed_func.h:1718
TVM_ALWAYS_INLINE void operator()(size_t i, const TVMArgValue &value) const
Definition: packed_func.h:1702
Arguments into TVM functions.
Definition: packed_func.h:392
const TVMValue * values
Definition: packed_func.h:394
TVMArgs(const TVMValue *values, const int *type_codes, int num_args)
constructor
Definition: packed_func.h:403
TVMArgValue operator[](int i) const
Get i-th argument.
Definition: packed_func.h:1241
T At(int i) const
Get the i-th argument and do proper type checking with detailed error messages.
Definition: packed_func.h:1934
const int * type_codes
Definition: packed_func.h:395
int size() const
Definition: packed_func.h:1247
int num_args
Definition: packed_func.h:396
Internal auxiliary struct for TypedPackedFunc to indicate a movable argument with additional context ...
Definition: packed_func.h:762
TVMMovableArgValueWithContext_(TVMValue value, int type_code, int arg_index, const std::string *optional_name, FSig *f_sig)
move constructor from another return value.
Definition: packed_func.h:773
Internal auxiliary struct for TypedPackedFunc to indicate a movable argument.
Definition: packed_func.h:717
TVMMovableArgValue_(TVMValue value, int type_code)
Definition: packed_func.h:719
Internal base class to handle conversion to POD values.
Definition: packed_func.h:552
TObjectRef AsObjectRef() const
Definition: packed_func.h:2016
TVMPODValue_()
Definition: packed_func.h:642
bool IsObjectRef() const
Definition: packed_func.h:1985
TVMValue value_
The value.
Definition: packed_func.h:646
T * ptr() const
return handle as specific pointer type.
Definition: packed_func.h:628
int type_code_
the type code
Definition: packed_func.h:648
int type_code() const
Definition: packed_func.h:621
TVMPODValue_(TVMValue value, int type_code)
Definition: packed_func.h:643
Return Value container, Unlike TVMArgValue, which only holds reference and do not delete the underlyi...
Definition: packed_func.h:807
static TVMRetValue MoveFromCHost(TVMValue value, int type_code)
Construct a new TVMRetValue by moving from return value stored via C API.
Definition: packed_func.h:975
const TVMValue & value() const
Definition: packed_func.h:984
~TVMRetValue()
destructor
Definition: packed_func.h:820
TObjectRef AsObjectRef() const
Definition: packed_func.h:2016
TVMRetValue & operator=(DLDataType t)
Definition: packed_func.h:897
TVMRetValue & operator=(const TypedPackedFunc< FType > &f)
Definition: packed_func.h:937
TVMRetValue & operator=(std::nullptr_t value)
Definition: packed_func.h:872
TVMRetValue & operator=(TVMRetValue &&other)
Definition: packed_func.h:860
TVMRetValue & operator=(PackedFunc f)
Definition: packed_func.h:932
TVMRetValue & operator=(bool value)
Definition: packed_func.h:903
TVMRetValue & operator=(int value)
Definition: packed_func.h:887
bool IsObjectRef() const
Definition: packed_func.h:1985
void MoveToCHost(TVMValue *ret_value, int *ret_type_code)
Move the value back to front-end via C API. This marks the current container as null....
Definition: packed_func.h:961
TVMRetValue()
default constructor
Definition: packed_func.h:810
TVMRetValue & operator=(void *value)
Definition: packed_func.h:877
TVMRetValue & operator=(std::string value)
Definition: packed_func.h:908
TVMRetValue & operator=(const TVMArgValue &other)
Definition: packed_func.h:944
TVMRetValue(const TVMRetValue &other)
Definition: packed_func.h:836
TVMRetValue & operator=(double value)
Definition: packed_func.h:867
TVMRetValue(TVMRetValue &&other)
move constructor from another return value.
Definition: packed_func.h:815
TVMRetValue & operator=(const TVMRetValue &other)
Definition: packed_func.h:940
TVMRetValue & operator=(int64_t value)
Definition: packed_func.h:882
TVMRetValue & operator=(Module m)
Definition: packed_func.h:928
TVMRetValue & operator=(const DataType &other)
Definition: packed_func.h:902
TVMRetValue & operator=(DLDevice value)
Definition: packed_func.h:892
TVMRetValue & operator=(TVMMovableArgValue_ &&other)
Definition: packed_func.h:948
TVMRetValue & operator=(TVMByteArray value)
Definition: packed_func.h:912
TVMRetValue & operator=(NDArray other)
Definition: packed_func.h:916
A PackedFunc wrapper to provide typed function signature. It is backed by a PackedFunc internally.
Definition: packed_func.h:228
const PackedFunc & packed() const
Definition: packed_func.h:359
bool operator==(std::nullptr_t null) const
Definition: packed_func.h:361
TypedPackedFunc(const FLambda &typed_lambda)
construct from a lambda function with the same signature.
Definition: packed_func.h:310
TypedPackedFunc()
default constructor
Definition: packed_func.h:233
TypedPackedFunc(const FLambda &typed_lambda, std::string name)
construct from a lambda function with the same signature.
Definition: packed_func.h:287
TSelf & operator=(FLambda typed_lambda)
copy assignment operator from typed lambda
Definition: packed_func.h:332
TSelf & operator=(PackedFunc packed)
copy assignment operator from PackedFunc.
Definition: packed_func.h:341
bool operator!=(std::nullptr_t null) const
Definition: packed_func.h:363
TypedPackedFunc(std::nullptr_t null)
constructor from null
Definition: packed_func.h:235
Please refer to TypedPackedFunc<R(Args..)>.
Definition: packed_func.h:61
Definition: variant.h:69
struct TVMArgs TVMArgs
Runtime Map container types.
const char * ArgTypeCode2Str(int type_code)
Convert argument type code to string.
Definition: packed_func.h:1264
const char * DLDeviceType2Str(int type)
The name of DLDeviceType.
Definition: packed_func.h:1307
DLDataType String2DLDataType(std::string s)
convert a string to TVM type.
Definition: data_type.h:427
std::string() FSig
Using static function to output TypedPackedFunc signature.
Definition: packed_func.h:187
void TVM_ALWAYS_INLINE PackArgs(TVMValue *values, int *type_codes, Args &&... args)
Definition: packed_func.h:1796
std::string DLDataType2String(DLDataType t)
convert a TVM type to string.
Definition: data_type.h:420
std::ostream & operator<<(std::ostream &os, const ObjectRef &n)
Definition: repr_printer.h:97
Object * TVMArrayHandleToObjectHandle(TVMArrayHandle handle)
Definition: ndarray.h:428
runtime implementation for LibTorch/TorchScript.
Definition: analyzer.h:36
PrimExpr ret(PrimExpr value, Span span=Span())
Return the value.
PrimExpr max(PrimExpr a, PrimExpr b, Span span=Span())
take maximum of two values
runtime::DataType DataType
Definition: data_type.h:491
DLDevice Device
Definition: ndarray.h:43
PrimExpr min(PrimExpr a, PrimExpr b, Span span=Span())
take minimum of two values
constexpr runtime::NullOptType NullOpt
Definition: optional.h:169
A device-independent managed NDArray abstraction.
A managed object in the TVM runtime.
#define TVM_CHECK_TYPE_CODE(CODE, T)
Definition: packed_func.h:433
Runtime container of the functions generated by TVM, This is used to support dynamically link,...
Definition: packed_func.h:38
Byte array type used to pass in byte array When kTVMBytes is used as data type.
Definition: c_runtime_api.h:221
size_t size
Definition: c_runtime_api.h:223
const char * data
Definition: c_runtime_api.h:222
static std::string TypeName()
Definition: packed_func.h:511
static bool Check(const Object *ptr)
Definition: packed_func.h:500
static Optional< String > CheckAndGetMismatch(const Object *ptr)
Definition: packed_func.h:483
static bool Check(const Object *ptr)
Definition: packed_func.h:532
static Optional< String > CheckAndGetMismatch(const Object *ptr)
Definition: packed_func.h:515
static std::string TypeName()
Definition: packed_func.h:542
Type traits for runtime type check during FFI conversion.
Definition: packed_func.h:441
static std::string TypeName()
Definition: packed_func.h:474
static bool Check(const Object *ptr)
Check if an object matches the template type.
Definition: packed_func.h:469
static Optional< String > CheckAndGetMismatch(const Object *ptr)
Check if an object matches the template type and return the mismatched type if it exists.
Definition: packed_func.h:449
Internal struct for extracting the callable method from callable type.
Definition: packed_func.h:87
static void Call(const PackedFuncObj *obj, TVMArgs args, TVMRetValue *rv)
Extracting the callable method from callable type.
Definition: packed_func.h:1250
static Optional< T > From(const TVMRetValue &val)
Definition: packed_func.h:2165
static Optional< T > From(const TVMArgValue &val)
Definition: packed_func.h:2161
static VType From(const PODSubclass &val)
Definition: packed_func.h:2179
static Optional< VType > TryValueConverter(const PODSubclass &val)
Definition: packed_func.h:2207
static Optional< VType > TryAsObjectRef(const TVMPODValue_ &val)
Definition: packed_func.h:2196
static String From(const TVMArgValue &val)
Definition: packed_func.h:2142
static String From(const TVMRetValue &val)
Definition: packed_func.h:2150
Type trait to specify special value conversion rules from TVMArgValue and TVMRetValue.
Definition: packed_func.h:1104
static TObjectRef From(const TVMRetValue &val)
Convert a TObjectRef from a return value.
Definition: packed_func.h:1116
static TObjectRef From(const TVMArgValue &val)
Convert a TObjectRef from an argument value.
Definition: packed_func.h:1110
Definition: packed_func.h:63
Definition: packed_func.h:1789
static TVM_ALWAYS_INLINE void F(TVMArgsSetter *setter, T &&value)
Definition: packed_func.h:1790
@ kRuntimePackedFunc
runtime::PackedFunc.
Definition: object.h:74
Union type of values being passed through API and function calls.
Definition: c_runtime_api.h:208
DLDevice v_device
Definition: c_runtime_api.h:214
void * v_handle
Definition: c_runtime_api.h:211
DLDataType v_type
Definition: c_runtime_api.h:213
int64_t v_int64
Definition: c_runtime_api.h:209
const char * v_str
Definition: c_runtime_api.h:212
double v_float64
Definition: c_runtime_api.h:210
Runtime Variant container types.