tvm
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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 
30 #include <tvm/runtime/data_type.h>
31 #include <tvm/runtime/logging.h>
32 #include <tvm/runtime/module.h>
33 #include <tvm/runtime/ndarray.h>
34 #include <tvm/runtime/object.h>
35 
36 #include <functional>
37 #include <limits>
38 #include <memory>
39 #include <string>
40 #include <tuple>
41 #include <type_traits>
42 #include <utility>
43 #include <vector>
44 
45 // Whether use TVM runtime in header only mode.
46 #ifndef TVM_RUNTIME_HEADER_ONLY
47 #define TVM_RUNTIME_HEADER_ONLY 0
48 #endif
49 
50 namespace tvm {
51 namespace runtime {
52 
53 // forward declarations
54 class TVMArgs;
55 class TVMArgValue;
56 class TVMMovableArgValueWithContext_;
57 class TVMRetValue;
58 class TVMArgsSetter;
59 template <typename FType>
61 template <typename TSignature>
63 
68 class PackedFuncObj : public Object {
69  public:
75  TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue* rv) const;
76 
77  static constexpr const uint32_t _type_index = TypeIndex::kRuntimePackedFunc;
78  static constexpr const char* _type_key = "runtime.PackedFunc";
80 
81  protected:
85  template <class TPackedFuncSubObj>
86  struct Extractor {
93  static void Call(const PackedFuncObj* obj, TVMArgs args, TVMRetValue* rv);
94  };
95 
97  using FCallPacked = void(const PackedFuncObj*, TVMArgs, TVMRetValue*);
98 
103  explicit PackedFuncObj(FCallPacked* f_call_pack) : f_call_packed_(f_call_pack) {}
104 
106  PackedFuncObj() = delete;
107 
110 };
111 
113 template <class TCallable>
115  using TStorage = typename std::remove_cv<typename std::remove_reference<TCallable>::type>::type;
116 
117  public:
124  explicit PackedFuncSubObj(TCallable callable)
125  : PackedFuncObj(Extractor<TSelf>::Call), callable_(callable) {}
127  mutable TStorage callable_;
128 };
129 
138 class PackedFunc : public ObjectRef {
139  public:
141  PackedFunc(std::nullptr_t null) : ObjectRef(nullptr) {} // NOLINT(*)
147  template <typename TCallable,
148  typename = std::enable_if_t<
149  std::is_convertible<TCallable, std::function<void(TVMArgs, TVMRetValue*)>>::value &&
150  !std::is_base_of<TCallable, PackedFunc>::value>>
151  explicit PackedFunc(TCallable data) {
152  using ObjType = PackedFuncSubObj<TCallable>;
153  data_ = make_object<ObjType>(std::forward<TCallable>(data));
154  }
169  template <typename... Args>
170  inline TVMRetValue operator()(Args&&... args) const;
176  TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue* rv) const;
178  bool operator==(std::nullptr_t null) const { return data_ == nullptr; }
180  bool operator!=(std::nullptr_t null) const { return data_ != nullptr; }
181 
183 };
184 
186 using FSig = std::string();
187 
191 template <typename FType>
192 class TypedPackedFunc;
193 
226 template <typename R, typename... Args>
227 class TypedPackedFunc<R(Args...)> {
228  public:
230  using TSelf = TypedPackedFunc<R(Args...)>;
234  TypedPackedFunc(std::nullptr_t null) {} // NOLINT(*)
252  inline TypedPackedFunc(PackedFunc packed); // NOLINT(*)
257  inline TypedPackedFunc(const TVMRetValue& value); // NOLINT(*)
262  inline TypedPackedFunc(const TVMArgValue& value); // NOLINT(*)
267  inline TypedPackedFunc(TVMMovableArgValueWithContext_&& value); // NOLINT(*)
284  template <typename FLambda, typename = typename std::enable_if<std::is_convertible<
285  FLambda, std::function<R(Args...)>>::value>::type>
286  TypedPackedFunc(const FLambda& typed_lambda, std::string name) { // NOLINT(*)
287  this->AssignTypedLambda(typed_lambda, name);
288  }
307  template <typename FLambda, typename = typename std::enable_if<std::is_convertible<
308  FLambda, std::function<R(Args...)>>::value>::type>
309  TypedPackedFunc(const FLambda& typed_lambda) { // NOLINT(*)
310  this->AssignTypedLambda(typed_lambda);
311  }
328  template <typename FLambda, typename = typename std::enable_if<
329  std::is_convertible<FLambda,
330  std::function<R(Args...)>>::value>::type>
331  TSelf& operator=(FLambda typed_lambda) { // NOLINT(*)
332  this->AssignTypedLambda(typed_lambda);
333  return *this;
334  }
341  packed_ = packed;
342  return *this;
343  }
349  TVM_ALWAYS_INLINE R operator()(Args... args) const;
354  operator PackedFunc() const { return packed(); }
358  const PackedFunc& packed() const { return packed_; }
360  bool operator==(std::nullptr_t null) const { return packed_ == nullptr; }
362  bool operator!=(std::nullptr_t null) const { return packed_ != nullptr; }
363 
364  private:
365  friend class TVMRetValue;
367  PackedFunc packed_;
376  template <typename FLambda>
377  inline void AssignTypedLambda(FLambda flambda, std::string name);
386  template <typename FLambda>
387  inline void AssignTypedLambda(FLambda flambda);
388 };
389 
391 class TVMArgs {
392  public:
393  const TVMValue* values;
394  const int* type_codes;
395  int num_args;
402  TVMArgs(const TVMValue* values, const int* type_codes, int num_args)
405  inline int size() const;
411  inline TVMArgValue operator[](int i) const;
412 };
413 
419 inline const char* ArgTypeCode2Str(int type_code);
420 
421 // macro to check type code.
422 #define TVM_CHECK_TYPE_CODE(CODE, T) \
423  ICHECK_EQ(CODE, T) << "expected " << ArgTypeCode2Str(T) << " but got " << ArgTypeCode2Str(CODE)
424 
429 template <typename T>
439  using ContainerType = typename T::ContainerType;
440  if (ptr == nullptr) {
441  if (T::_type_is_nullable) {
442  return NullOpt;
443  } else {
444  return String("nullptr");
445  }
446  }
447  if (ptr->IsInstance<ContainerType>()) {
448  return NullOpt;
449  } else {
450  return String(ptr->GetTypeKey());
451  }
452  }
458  static bool Check(const Object* ptr) {
459  using ContainerType = typename T::ContainerType;
460  if (ptr == nullptr) return T::_type_is_nullable;
461  return ptr->IsInstance<ContainerType>();
462  }
463  static std::string TypeName() {
464  using ContainerType = typename T::ContainerType;
465  return ContainerType::_type_key;
466  }
467 };
468 
469 // Additional overloads for PackedFunc checking.
470 template <typename T>
473  if (ptr == nullptr) {
474  return NullOpt;
475  }
476  if (!ptr->IsInstance<ArrayNode>()) {
477  return String(ptr->GetTypeKey());
478  }
479  const ArrayNode* n = static_cast<const ArrayNode*>(ptr);
480  for (size_t i = 0; i < n->size(); i++) {
481  const ObjectRef& p = (*n)[i];
483  if (check_subtype.defined()) {
484  return String("Array[index " + std::to_string(i) + ": " + check_subtype.value() + "]");
485  }
486  }
487  return NullOpt;
488  }
489  static bool Check(const Object* ptr) {
490  if (ptr == nullptr) return true;
491  if (!ptr->IsInstance<ArrayNode>()) return false;
492  const ArrayNode* n = static_cast<const ArrayNode*>(ptr);
493  for (const ObjectRef& p : *n) {
494  if (!ObjectTypeChecker<T>::Check(p.get())) {
495  return false;
496  }
497  }
498  return true;
499  }
500  static std::string TypeName() { return "Array[" + ObjectTypeChecker<T>::TypeName() + "]"; }
501 };
502 template <typename K, typename V>
503 struct ObjectTypeChecker<Map<K, V>> {
505  if (ptr == nullptr) return NullOpt;
506  if (!ptr->IsInstance<MapNode>()) return String(ptr->GetTypeKey());
507  const MapNode* n = static_cast<const MapNode*>(ptr);
508  for (const auto& kv : *n) {
510  Optional<String> value_type = ObjectTypeChecker<K>::CheckAndGetMismatch(kv.first.get());
511  if (key_type.defined() || value_type.defined()) {
512  std::string key_name =
513  key_type.defined() ? std::string(key_type.value()) : ObjectTypeChecker<K>::TypeName();
514  std::string value_name = value_type.defined() ? std::string(value_type.value())
516  return String("Map[" + key_name + ", " + value_name + "]");
517  }
518  }
519  return NullOpt;
520  }
521  static bool Check(const Object* ptr) {
522  if (ptr == nullptr) return true;
523  if (!ptr->IsInstance<MapNode>()) return false;
524  const MapNode* n = static_cast<const MapNode*>(ptr);
525  for (const auto& kv : *n) {
526  if (!ObjectTypeChecker<K>::Check(kv.first.get())) return false;
527  if (!ObjectTypeChecker<V>::Check(kv.second.get())) return false;
528  }
529  return true;
530  }
531  static std::string TypeName() {
533  ']';
534  }
535 };
536 
542  public:
543  operator double() const {
544  // Allow automatic conversion from int to float
545  // This avoids errors when user pass in int from
546  // the frontend while the API expects a float.
547  if (type_code_ == kDLInt) {
548  return static_cast<double>(value_.v_int64);
549  }
550  TVM_CHECK_TYPE_CODE(type_code_, kDLFloat);
551  return value_.v_float64;
552  }
553  operator int64_t() const {
555  return value_.v_int64;
556  }
557  operator uint64_t() const {
559  return value_.v_int64;
560  }
561  operator int() const {
565  return static_cast<int>(value_.v_int64);
566  }
567  operator bool() const {
569  return value_.v_int64 != 0;
570  }
571  operator void*() const {
572  if (type_code_ == kTVMNullptr) return nullptr;
575  return value_.v_handle;
576  }
577  operator DLTensor*() const {
579  return static_cast<DLTensor*>(value_.v_handle);
580  } else {
581  if (type_code_ == kTVMNullptr) return nullptr;
582  LOG(FATAL) << "Expected "
583  << "DLTensor* or NDArray but got " << ArgTypeCode2Str(type_code_);
584  return nullptr;
585  }
586  }
587  operator NDArray() const {
588  if (type_code_ == kTVMNullptr) return NDArray(ObjectPtr<Object>(nullptr));
591  }
592  operator Module() const {
593  if (type_code_ == kTVMNullptr) {
594  return Module(ObjectPtr<Object>(nullptr));
595  }
597  return Module(ObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
598  }
599  operator PackedFunc() const {
600  if (type_code_ == kTVMNullptr) {
601  return PackedFunc(ObjectPtr<Object>(nullptr));
602  }
604  return PackedFunc(ObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
605  }
606  operator Device() const {
608  return value_.v_device;
609  }
610  int type_code() const { return type_code_; }
616  template <typename T>
617  T* ptr() const {
618  return static_cast<T*>(value_.v_handle);
619  }
620  // ObjectRef handling
621  template <typename TObjectRef,
622  typename = typename std::enable_if<std::is_base_of<ObjectRef, TObjectRef>::value>::type>
623  inline bool IsObjectRef() const;
624  template <typename TObjectRef>
625  inline TObjectRef AsObjectRef() const;
626 
627  protected:
628  friend class TVMArgsSetter;
629  friend class TVMRetValue;
630  friend class TVMMovableArgValue_;
633 
638 };
639 
646 class TVMArgValue : public TVMPODValue_ {
647  public:
656  // reuse converter from parent
657  using TVMPODValue_::operator double;
658  using TVMPODValue_::operator int64_t;
659  using TVMPODValue_::operator uint64_t;
660  using TVMPODValue_::operator int;
661  using TVMPODValue_::operator bool;
662  using TVMPODValue_::operator void*;
663  using TVMPODValue_::operator DLTensor*;
664  using TVMPODValue_::operator NDArray;
665  using TVMPODValue_::operator Device;
666  using TVMPODValue_::operator Module;
667  using TVMPODValue_::operator PackedFunc;
670 
671  // conversion operator.
672  operator std::string() const {
673  if (type_code_ == kTVMDataType) {
674  return DLDataType2String(operator DLDataType());
675  } else if (type_code_ == kTVMBytes) {
676  TVMByteArray* arr = static_cast<TVMByteArray*>(value_.v_handle);
677  return std::string(arr->data, arr->size);
678  } else if (type_code_ == kTVMStr) {
679  return std::string(value_.v_str);
680  } else {
681  ICHECK(IsObjectRef<tvm::runtime::String>())
682  << "Could not convert TVM object of type " << runtime::Object::TypeIndex2Key(type_code_)
683  << " to a string.";
684  return AsObjectRef<tvm::runtime::String>().operator std::string();
685  }
686  }
687  template <typename FType>
688  operator TypedPackedFunc<FType>() const {
689  return TypedPackedFunc<FType>(operator PackedFunc());
690  }
691  const TVMValue& value() const { return value_; }
692 
693  template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
694  inline operator T() const;
695  inline operator DLDataType() const;
696  inline operator DataType() const;
697 };
698 
710  public:
712  // reuse converter from parent
713  using TVMPODValue_::operator double;
714  using TVMPODValue_::operator int64_t;
715  using TVMPODValue_::operator uint64_t;
716  using TVMPODValue_::operator int;
717  using TVMPODValue_::operator bool;
718  using TVMPODValue_::operator void*;
719  using TVMPODValue_::operator DLTensor*;
720  using TVMPODValue_::operator NDArray;
721  using TVMPODValue_::operator Device;
722  using TVMPODValue_::operator Module;
723  using TVMPODValue_::operator PackedFunc;
724  // reuse conversion rule from ArgValue.
725  operator std::string() const { return AsArgValue().operator std::string(); }
726  template <typename FType>
727  operator TypedPackedFunc<FType>() const {
728  return TypedPackedFunc<FType>(operator PackedFunc());
729  }
730  operator DLDataType() const { return AsArgValue().operator DLDataType(); }
731  operator DataType() const { return AsArgValue().operator DataType(); }
732  operator TVMArgValue() const { return AsArgValue(); }
738  template <typename T,
739  typename = typename std::enable_if<std::is_base_of<ObjectRef, T>::value>::type>
740  inline operator T() const;
741 
742  private:
744  TVMArgValue AsArgValue() const { return TVMArgValue(value_, type_code_); }
745 };
746 
755  public:
765  TVMMovableArgValueWithContext_(TVMValue value, int type_code, int arg_index,
766  const std::string* optional_name, FSig* f_sig)
767  : value_(value, type_code),
768  arg_index_(arg_index),
769  optional_name_(optional_name),
770  f_sig_(f_sig) {}
771 
772  template <typename T>
773  operator T() const {
774  try {
775  return value_; // implicit conversion happens here
776  } catch (dmlc::Error& e) {
777  LOG(FATAL) << "In function " << (optional_name_ == nullptr ? "<anonymous>" : *optional_name_)
778  << (f_sig_ == nullptr ? "" : (*f_sig_)()) << ": error while converting argument "
779  << arg_index_ << ": " << e.what();
780  throw; // never reached, LOG(FATAL) throws, but this silences a warning.
781  }
782  }
783 
784  private:
785  TVMMovableArgValue_ value_;
786  int arg_index_;
787  const std::string* optional_name_;
788  FSig* f_sig_;
789 };
790 
799 class TVMRetValue : public TVMPODValue_ {
800  public:
808  other.value_.v_handle = nullptr;
809  other.type_code_ = kTVMNullptr;
810  }
812  ~TVMRetValue() { this->Clear(); }
813  // reuse converter from parent
814  using TVMPODValue_::operator double;
815  using TVMPODValue_::operator int64_t;
816  using TVMPODValue_::operator uint64_t;
817  using TVMPODValue_::operator int;
818  using TVMPODValue_::operator bool;
819  using TVMPODValue_::operator void*;
820  using TVMPODValue_::operator DLTensor*;
821  using TVMPODValue_::operator Device;
822  using TVMPODValue_::operator NDArray;
823  using TVMPODValue_::operator Module;
824  using TVMPODValue_::operator PackedFunc;
827 
828  TVMRetValue(const TVMRetValue& other) : TVMPODValue_() { this->Assign(other); }
829  // conversion operators
830  operator std::string() const {
831  if (type_code_ == kTVMDataType) {
832  return DLDataType2String(operator DLDataType());
833  } else if (type_code_ == kTVMBytes) {
834  return *ptr<std::string>();
835  }
837  return *ptr<std::string>();
838  }
839  operator DLDataType() const {
840  if (type_code_ == kTVMStr) {
841  return String2DLDataType(operator std::string());
842  }
844  return value_.v_type;
845  }
846  operator DataType() const { return DataType(operator DLDataType()); }
847  template <typename FType>
848  operator TypedPackedFunc<FType>() const {
849  return TypedPackedFunc<FType>(operator PackedFunc());
850  }
851  // Assign operators
853  this->Clear();
854  value_ = other.value_;
855  type_code_ = other.type_code_;
856  other.type_code_ = kTVMNullptr;
857  return *this;
858  }
860  this->SwitchToPOD(kDLFloat);
862  return *this;
863  }
864  TVMRetValue& operator=(std::nullptr_t value) {
865  this->SwitchToPOD(kTVMNullptr);
867  return *this;
868  }
870  this->SwitchToPOD(kTVMOpaqueHandle);
872  return *this;
873  }
875  this->SwitchToPOD(kDLInt);
876  value_.v_int64 = value;
877  return *this;
878  }
880  this->SwitchToPOD(kDLInt);
881  value_.v_int64 = value;
882  return *this;
883  }
885  this->SwitchToPOD(kDLDevice);
887  return *this;
888  }
889  TVMRetValue& operator=(DLDataType t) {
890  this->SwitchToPOD(kTVMDataType);
891  value_.v_type = t;
892  return *this;
893  }
894  TVMRetValue& operator=(const DataType& other) { return operator=(other.operator DLDataType()); }
896  this->SwitchToPOD(kDLInt);
897  value_.v_int64 = value;
898  return *this;
899  }
900  TVMRetValue& operator=(std::string value) {
901  this->SwitchToClass(kTVMStr, value);
902  return *this;
903  }
905  this->SwitchToClass(kTVMBytes, std::string(value.data, value.size));
906  return *this;
907  }
909  if (other.data_ != nullptr) {
910  this->Clear();
914  } else {
915  SwitchToPOD(kTVMNullptr);
916  value_.v_handle = nullptr;
917  }
918  return *this;
919  }
921  SwitchToObject(kTVMModuleHandle, std::move(m.data_));
922  return *this;
923  }
925  this->SwitchToObject(kTVMPackedFuncHandle, std::move(f.data_));
926  return *this;
927  }
928  template <typename FType>
930  return operator=(f.packed());
931  }
932  TVMRetValue& operator=(const TVMRetValue& other) { // NOLINT(*0
933  this->Assign(other);
934  return *this;
935  }
937  this->Assign(other);
938  return *this;
939  }
941  this->Assign(other);
942  return *this;
943  }
953  void MoveToCHost(TVMValue* ret_value, int* ret_type_code) {
954  // cannot move str; need specially handle.
955  ICHECK(type_code_ != kTVMStr && type_code_ != kTVMBytes);
956  *ret_value = value_;
957  *ret_type_code = type_code_;
959  }
968  // Can move POD and everything under the object system.
971  ret.value_ = value;
972  ret.type_code_ = type_code;
973  return ret;
974  }
976  const TVMValue& value() const {
979  << "TVMRetValue.value can only be used for POD data";
980  return value_;
981  }
982  // ObjectRef handling
983  template <typename TObjectRef,
984  typename = typename std::enable_if<std::is_base_of<ObjectRef, TObjectRef>::value>::type>
985  inline TVMRetValue& operator=(TObjectRef other);
986  template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
987  inline operator T() const;
988 
989  private:
990  template <typename T>
991  void Assign(const T& other) {
992  switch (other.type_code()) {
993  case kTVMStr: {
994  SwitchToClass<std::string>(kTVMStr, other);
995  break;
996  }
997  case kTVMBytes: {
998  SwitchToClass<std::string>(kTVMBytes, other);
999  break;
1000  }
1001  case kTVMPackedFuncHandle: {
1002  *this = other.operator PackedFunc();
1003  break;
1004  }
1005  case kTVMModuleHandle: {
1006  *this = other.operator Module();
1007  break;
1008  }
1009  case kTVMNDArrayHandle: {
1010  *this = other.operator NDArray();
1011  break;
1012  }
1013  case kTVMObjectHandle: {
1014  // Avoid operator ObjectRef as we already know it is not NDArray/Module
1015  SwitchToObject(kTVMObjectHandle,
1016  GetObjectPtr<Object>(static_cast<Object*>(other.value_.v_handle)));
1017  break;
1018  }
1019  case kTVMObjectRValueRefArg: {
1020  operator=(other.operator ObjectRef());
1021  break;
1022  }
1023  default: {
1024  SwitchToPOD(other.type_code());
1025  value_ = other.value_;
1026  break;
1027  }
1028  }
1029  }
1030  // get the internal container.
1031  void SwitchToPOD(int type_code) {
1032  if (type_code_ != type_code) {
1033  this->Clear();
1035  }
1036  }
1037  template <typename T>
1038  void SwitchToClass(int type_code, T v) {
1039  if (type_code_ != type_code) {
1040  this->Clear();
1042  value_.v_handle = new T(v);
1043  } else {
1044  *static_cast<T*>(value_.v_handle) = v;
1045  }
1046  }
1047  void SwitchToObject(int type_code, ObjectPtr<Object> other) {
1048  if (other.data_ != nullptr) {
1049  this->Clear();
1051  // move the handle out
1052  value_.v_handle = other.data_;
1053  other.data_ = nullptr;
1054  } else {
1055  SwitchToPOD(kTVMNullptr);
1056  value_.v_handle = nullptr;
1057  }
1058  }
1059  void Clear() {
1060  if (type_code_ == kTVMNullptr) return;
1061  switch (type_code_) {
1062  case kTVMStr:
1063  case kTVMBytes:
1064  delete ptr<std::string>();
1065  break;
1066  case kTVMPackedFuncHandle:
1067  static_cast<Object*>(value_.v_handle)->DecRef();
1068  break;
1069  case kTVMNDArrayHandle: {
1071  break;
1072  }
1073  case kTVMModuleHandle: {
1074  static_cast<Object*>(value_.v_handle)->DecRef();
1075  break;
1076  }
1077  case kTVMObjectHandle: {
1078  static_cast<Object*>(value_.v_handle)->DecRef();
1079  break;
1080  }
1081  }
1083  }
1084 };
1085 
1095 template <typename TObjectRef>
1102  static TObjectRef From(const TVMArgValue& val) { return val.AsObjectRef<TObjectRef>(); }
1108  static TObjectRef From(const TVMRetValue& val) { return val.AsObjectRef<TObjectRef>(); }
1109 };
1110 
1130 #define TVM_DLL_EXPORT_PACKED_FUNC(ExportName, Function) \
1131  extern "C" { \
1132  TVM_DLL int ExportName(TVMValue* args, int* type_code, int num_args, TVMValue* out_value, \
1133  int* out_type_code, void* resource_handle); \
1134  int ExportName(TVMValue* args, int* type_code, int num_args, TVMValue* out_value, \
1135  int* out_type_code, void* resource_handle) { \
1136  try { \
1137  ::tvm::runtime::TVMRetValue rv; \
1138  Function(::tvm::runtime::TVMArgs(args, type_code, num_args), &rv); \
1139  rv.MoveToCHost(out_value, out_type_code); \
1140  return 0; \
1141  } catch (const ::std::exception& _except_) { \
1142  TVMAPISetLastError(_except_.what()); \
1143  return -1; \
1144  } \
1145  } \
1146  }
1147 
1183 #define TVM_DLL_EXPORT_TYPED_FUNC(ExportName, Function) \
1184  extern "C" { \
1185  TVM_DLL int ExportName(TVMValue* args, int* type_code, int num_args, TVMValue* out_value, \
1186  int* out_type_code, void* resource_handle) { \
1187  try { \
1188  auto f = Function; \
1189  using FType = ::tvm::runtime::detail::function_signature<decltype(f)>::FType; \
1190  ::tvm::runtime::TVMRetValue rv; \
1191  ::tvm::runtime::detail::unpack_call_by_signature<FType>::run( \
1192  f, ::tvm::runtime::TVMArgs(args, type_code, num_args), &rv); \
1193  rv.MoveToCHost(out_value, out_type_code); \
1194  return 0; \
1195  } catch (const ::std::exception& _except_) { \
1196  TVMAPISetLastError(_except_.what()); \
1197  return -1; \
1198  } \
1199  } \
1200  }
1201 
1202 inline TVMArgValue TVMArgs::operator[](int i) const {
1203  ICHECK_LT(i, num_args) << "not enough argument passed, " << num_args << " passed"
1204  << " but request arg[" << i << "].";
1205  return TVMArgValue(values[i], type_codes[i]);
1206 }
1207 
1208 inline int TVMArgs::size() const { return num_args; }
1209 
1210 template <class TPackedFuncSubObj>
1212  TVMRetValue* rv) {
1213  (static_cast<const TPackedFuncSubObj*>(obj))->callable_(args, rv);
1214 }
1215 
1216 TVM_ALWAYS_INLINE void PackedFuncObj::CallPacked(TVMArgs args, TVMRetValue* rv) const {
1217  (*f_call_packed_)(this, args, rv);
1218 }
1219 
1220 TVM_ALWAYS_INLINE void PackedFunc::CallPacked(TVMArgs args, TVMRetValue* rv) const {
1221  (static_cast<PackedFuncObj*>(data_.get()))->CallPacked(args, rv);
1222 }
1223 
1224 // internal namespace
1225 inline const char* ArgTypeCode2Str(int type_code) {
1226  switch (type_code) {
1227  case kDLInt:
1228  return "int";
1229  case kDLUInt:
1230  return "uint";
1231  case kDLFloat:
1232  return "float";
1233  case kTVMStr:
1234  return "str";
1235  case kTVMBytes:
1236  return "bytes";
1237  case kTVMOpaqueHandle:
1238  return "handle";
1239  case kTVMNullptr:
1240  return "NULL";
1241  case kTVMDLTensorHandle:
1242  return "ArrayHandle";
1243  case kTVMDataType:
1244  return "DLDataType";
1245  case kDLDevice:
1246  return "DLDevice";
1247  case kTVMPackedFuncHandle:
1248  return "FunctionHandle";
1249  case kTVMModuleHandle:
1250  return "ModuleHandle";
1251  case kTVMNDArrayHandle:
1252  return "NDArrayContainer";
1253  case kTVMObjectHandle:
1254  return "Object";
1256  return "ObjectRValueRefArg";
1257  default:
1258  LOG(FATAL) << "unknown type_code=" << static_cast<int>(type_code);
1259  }
1260 }
1261 
1262 namespace detail {
1263 
1264 template <bool stop, std::size_t I, typename F>
1265 struct for_each_dispatcher {
1266  template <typename T, typename... Args>
1267  static void run(const F& f, T&& value, Args&&... args) { // NOLINT(*)
1268  f(I, std::forward<T>(value));
1269  for_each_dispatcher<sizeof...(Args) == 0, (I + 1), F>::run(f, std::forward<Args>(args)...);
1270  }
1271 };
1272 
1273 template <std::size_t I, typename F>
1274 struct for_each_dispatcher<true, I, F> {
1275  static void run(const F& f) {} // NOLINT(*)
1276 };
1277 
1278 template <typename F, typename... Args>
1279 inline void for_each(const F& f, Args&&... args) { // NOLINT(*)
1280  for_each_dispatcher<sizeof...(Args) == 0, 0, F>::run(f, std::forward<Args>(args)...);
1281 }
1282 
1283 namespace parameter_pack {
1284 
1285 template <typename... EnumArgs>
1286 struct EnumeratedParamPack {
1287  struct Invoke {
1288  template <template <size_t i, typename TArgument> class Functor, typename... ExtraParams>
1289  static void F(ExtraParams&&... extra_params) {
1290  using TExpander = int[];
1291  (void)TExpander{
1292  0,
1293  (Functor<EnumArgs::i, typename EnumArgs::T>::F(extra_params...), 0)...,
1294  };
1295  }
1296  };
1297 };
1298 
1299 template <typename... Args>
1300 struct EnumerateImpl {
1301  private:
1302  template <size_t _i, typename _T>
1303  struct Item {
1304  static const constexpr size_t i = _i;
1305  using T = _T;
1306  };
1307 
1308  template <typename...>
1309  struct Zipper;
1310 
1311  template <std::size_t... id>
1312  struct Zipper<std::integer_sequence<std::size_t, id...>> {
1313  using T = EnumeratedParamPack<Item<id, Args>...>;
1314  };
1315 
1316  public:
1317  using T = typename Zipper<std::index_sequence_for<Args...>>::T;
1318 };
1319 
1320 template <typename... Args>
1321 using Enumerate = typename EnumerateImpl<Args...>::T;
1322 
1323 template <typename... Args>
1324 struct ParamPack {
1325  template <template <size_t i, typename TArgument> class Functor, typename... ExtraParams>
1326  static void InvokeWithoutArg(ExtraParams&&... extra_params) {
1327  Enumerate<Args...>::Invoke::template F<Functor, ExtraParams...>(
1328  std::forward<ExtraParams>(extra_params)...);
1329  }
1330 };
1331 
1332 } // namespace parameter_pack
1333 
1338 template <typename T>
1339 struct func_signature_helper {
1340  using FType = void;
1341 };
1342 
1343 template <typename T, typename R, typename... Args>
1344 struct func_signature_helper<R (T::*)(Args...)> {
1345  using FType = R(Args...);
1346  using ParamType = parameter_pack::ParamPack<Args...>;
1347  using RetType = R;
1348  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1349 };
1350 
1351 template <typename T, typename R, typename... Args>
1352 struct func_signature_helper<R (T::*)(Args...) const> {
1353  using FType = R(Args...);
1354  using ParamType = parameter_pack::ParamPack<Args...>;
1355  using RetType = R;
1356  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1357 };
1358 
1363 template <typename T>
1364 struct function_signature {
1365  using FType = typename func_signature_helper<decltype(&T::operator())>::FType;
1366  using ParamType = typename func_signature_helper<decltype(&T::operator())>::ParamType;
1367  using RetType = typename func_signature_helper<decltype(&T::operator())>::RetType;
1368 };
1369 
1370 // handle case of function.
1371 template <typename R, typename... Args>
1372 struct function_signature<R(Args...)> {
1373  using FType = R(Args...);
1374  using ParamType = parameter_pack::ParamPack<Args...>;
1375  using RetType = R;
1376  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1377 };
1378 
1379 // handle case of function ptr.
1380 template <typename R, typename... Args>
1381 struct function_signature<R (*)(Args...)> {
1382  using FType = R(Args...);
1383  using ParamType = detail::parameter_pack::ParamPack<Args...>;
1384  using RetType = R;
1385  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1386 };
1387 
1388 template <typename TSignature>
1389 struct SignaturePrinter;
1390 
1391 namespace type2str {
1392 
1393 template <typename T>
1394 struct TypeSimplifier;
1395 
1396 template <typename T>
1397 struct Type2Str {
1398  template <typename = std::enable_if_t<std::is_base_of<ObjectRef, T>::value>>
1399  static std::string v() {
1400  return T::ContainerType::_type_key;
1401  }
1402 };
1403 template <>
1404 struct Type2Str<int> {
1405  static std::string v() { return "int"; }
1406 };
1407 template <>
1408 struct Type2Str<double> {
1409  static std::string v() { return "double"; }
1410 };
1411 template <>
1412 struct Type2Str<int64_t> {
1413  static std::string v() { return "int64_t"; }
1414 };
1415 template <>
1416 struct Type2Str<uint64_t> {
1417  static std::string v() { return "uint64_t"; }
1418 };
1419 template <>
1420 struct Type2Str<bool> {
1421  static std::string v() { return "bool"; }
1422 };
1423 template <>
1424 struct Type2Str<void> {
1425  static std::string v() { return "void"; }
1426 };
1427 template <>
1428 struct Type2Str<std::basic_string<char>> {
1429  static std::string v() { return "basic_string<char>"; }
1430 };
1431 template <typename K, typename V>
1432 struct Type2Str<Map<K, V>> {
1433  static std::string v() {
1434  return "Map<" + TypeSimplifier<K>::v() + ", " + TypeSimplifier<V>::v() + ">";
1435  }
1436 };
1437 template <>
1438 struct Type2Str<DLDevice> {
1439  static std::string v() { return "DLDevice"; }
1440 };
1441 template <>
1442 struct Type2Str<DLTensor> {
1443  static std::string v() { return "DLTensor"; }
1444 };
1445 template <>
1446 struct Type2Str<DataType> {
1447  static std::string v() { return "DataType"; }
1448 };
1449 template <>
1450 struct Type2Str<DLDataType> {
1451  static std::string v() { return "DLDataType"; }
1452 };
1453 template <>
1454 struct Type2Str<TVMRetValue> {
1455  static std::string v() { return "TVMRetValue"; }
1456 };
1457 template <>
1458 struct Type2Str<TVMArgValue> {
1459  static std::string v() { return "TVMArgValue"; }
1460 };
1461 template <>
1462 struct Type2Str<TVMByteArray> {
1463  static std::string v() { return "TVMByteArray"; }
1464 };
1465 template <typename FType>
1466 struct Type2Str<TypedPackedFunc<FType>> {
1467  static std::string v() { return SignaturePrinter<function_signature<FType>>::F(); }
1468 };
1469 template <typename T>
1470 struct Type2Str<Array<T>> {
1471  static std::string v() { return "Array<" + TypeSimplifier<T>::v() + ">"; }
1472 };
1473 
1478 template <typename T>
1479 struct TypeSimplifier {
1480  static std::string v() {
1481  using U = typename std::remove_cv<
1482  typename std::remove_reference<typename std::remove_pointer<T>::type>::type>::type;
1483  return (std::is_const<T>::value ? "const " : "") + Type2Str<U>::v() +
1484  (std::is_pointer<T>::value ? "*" : "") + (std::is_reference<T>::value ? "&" : "");
1485  }
1486 };
1487 
1488 } // namespace type2str
1489 
1494 template <typename TSignature>
1495 struct SignaturePrinter {
1496  using ParamType = typename TSignature::ParamType;
1497  using RetType = typename TSignature::RetType;
1498 
1499  template <size_t i, typename TArgument>
1500  struct PrintParamType {
1501  static void F(std::ostream& os) {
1502  os << (i == 0 ? "" : ", ") << i << ": " << type2str::TypeSimplifier<TArgument>::v();
1503  }
1504  };
1505 
1506  static std::string F() {
1507  std::ostringstream oss;
1508  oss << "(";
1509  ParamType::template InvokeWithoutArg<PrintParamType>(oss);
1510  oss << ") -> " << type2str::TypeSimplifier<RetType>::v();
1511  return oss.str();
1512  }
1513 };
1514 } // namespace detail
1515 
1516 /* \brief argument settter to PackedFunc */
1518  public:
1519  TVMArgsSetter(TVMValue* values, int* type_codes) : values_(values), type_codes_(type_codes) {}
1520  // setters for POD types
1521  template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
1522  TVM_ALWAYS_INLINE void operator()(size_t i, T value) const {
1523  values_[i].v_int64 = static_cast<int64_t>(value);
1524  type_codes_[i] = kDLInt;
1525  }
1526  TVM_ALWAYS_INLINE void operator()(size_t i, uint64_t value) const {
1527  values_[i].v_int64 = static_cast<int64_t>(value);
1528  ICHECK_LE(value, static_cast<uint64_t>(std::numeric_limits<int64_t>::max()));
1529  type_codes_[i] = kDLInt;
1530  }
1531  TVM_ALWAYS_INLINE void operator()(size_t i, double value) const {
1532  values_[i].v_float64 = value;
1533  type_codes_[i] = kDLFloat;
1534  }
1535  TVM_ALWAYS_INLINE void operator()(size_t i, std::nullptr_t value) const {
1536  values_[i].v_handle = value;
1537  type_codes_[i] = kTVMNullptr;
1538  }
1539  TVM_ALWAYS_INLINE void operator()(size_t i, const TVMArgValue& value) const {
1540  values_[i] = value.value_;
1541  type_codes_[i] = value.type_code_;
1542  }
1543  TVM_ALWAYS_INLINE void operator()(size_t i, void* value) const {
1544  values_[i].v_handle = value;
1545  type_codes_[i] = kTVMOpaqueHandle;
1546  }
1547  TVM_ALWAYS_INLINE void operator()(size_t i, DLTensor* value) const {
1548  values_[i].v_handle = value;
1549  type_codes_[i] = kTVMDLTensorHandle;
1550  }
1551  TVM_ALWAYS_INLINE void operator()(size_t i, Device value) const {
1552  values_[i].v_device = value;
1553  type_codes_[i] = kDLDevice;
1554  }
1555  TVM_ALWAYS_INLINE void operator()(size_t i, DLDataType value) const {
1556  values_[i].v_type = value;
1557  type_codes_[i] = kTVMDataType;
1558  }
1559  TVM_ALWAYS_INLINE void operator()(size_t i, DataType dtype) const {
1560  operator()(i, dtype.operator DLDataType());
1561  }
1562  TVM_ALWAYS_INLINE void operator()(size_t i, const char* value) const {
1563  values_[i].v_str = value;
1564  type_codes_[i] = kTVMStr;
1565  }
1566  // setters for container types
1567  TVM_ALWAYS_INLINE void operator()(size_t i, const std::string& value) const {
1568  values_[i].v_str = value.c_str();
1569  type_codes_[i] = kTVMStr;
1570  }
1571  TVM_ALWAYS_INLINE void operator()(size_t i, const TVMByteArray& value) const {
1572  values_[i].v_handle = const_cast<TVMByteArray*>(&value);
1573  type_codes_[i] = kTVMBytes;
1574  }
1575  template <typename FType>
1576  TVM_ALWAYS_INLINE void operator()(size_t i, const TypedPackedFunc<FType>& value) const {
1577  operator()(i, value.packed());
1578  }
1579  void operator()(size_t i, const TVMRetValue& value) const {
1580  if (value.type_code() == kTVMStr) {
1581  values_[i].v_str = value.ptr<std::string>()->c_str();
1582  type_codes_[i] = kTVMStr;
1583  } else {
1584  ICHECK_NE(value.type_code(), kTVMBytes) << "not handled.";
1585  values_[i] = value.value_;
1586  type_codes_[i] = value.type_code();
1587  }
1588  }
1589  // ObjectRef handling
1590  template <typename TObjectRef,
1591  typename = typename std::enable_if<std::is_base_of<ObjectRef, TObjectRef>::value>::type>
1592  TVM_ALWAYS_INLINE void operator()(size_t i, const TObjectRef& value) const {
1593  this->SetObject(i, value);
1594  }
1595 
1596  template <typename TObjectRef,
1597  typename = typename std::enable_if<std::is_base_of<
1598  ObjectRef, typename std::remove_reference<TObjectRef>::type>::value>::type>
1599  TVM_ALWAYS_INLINE void operator()(size_t i, TObjectRef&& value) const {
1600  this->SetObject(i, std::forward<TObjectRef>(value));
1601  }
1602 
1603  private:
1604  template <typename TObjectRef>
1605  inline void SetObject(size_t i, TObjectRef&& value) const;
1607  TVMValue* values_;
1609  int* type_codes_;
1610 };
1611 
1612 template <typename... Args>
1613 inline TVMRetValue PackedFunc::operator()(Args&&... args) const {
1614  const int kNumArgs = sizeof...(Args);
1615  const int kArraySize = kNumArgs > 0 ? kNumArgs : 1;
1616  TVMValue values[kArraySize];
1617  int type_codes[kArraySize];
1618  detail::for_each(TVMArgsSetter(values, type_codes), std::forward<Args>(args)...);
1619  TVMRetValue rv;
1620  (static_cast<PackedFuncObj*>(data_.get()))
1621  ->CallPacked(TVMArgs(values, type_codes, kNumArgs), &rv);
1622  return rv;
1623 }
1624 
1625 namespace detail {
1626 template <typename R, int nleft, int index, typename F>
1627 struct unpack_call_dispatcher {
1628  template <typename... Args>
1629  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1630  const TVMArgs& args_pack, TVMRetValue* rv,
1631  Args&&... unpacked_args) {
1632  // construct a movable argument value
1633  // which allows potential move of argument to the input of F.
1634  unpack_call_dispatcher<R, nleft - 1, index + 1, F>::run(
1635  optional_name, f_sig, f, args_pack, rv, std::forward<Args>(unpacked_args)...,
1636  TVMMovableArgValueWithContext_(args_pack.values[index], args_pack.type_codes[index], index,
1637  optional_name, f_sig));
1638  }
1639 };
1640 
1641 template <typename R, int index, typename F>
1642 struct unpack_call_dispatcher<R, 0, index, F> {
1643  template <typename... Args>
1644  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1645  const TVMArgs& args_pack, TVMRetValue* rv,
1646  Args&&... unpacked_args) {
1647  using RetType = decltype(f(std::forward<Args>(unpacked_args)...));
1648  if (std::is_same<RetType, R>::value) {
1649  *rv = f(std::forward<Args>(unpacked_args)...);
1650  } else {
1651  *rv = R(f(std::forward<Args>(unpacked_args)...));
1652  }
1653  }
1654 };
1655 
1656 template <int index, typename F>
1657 struct unpack_call_dispatcher<void, 0, index, F> {
1658  template <typename... Args>
1659  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1660  const TVMArgs& args_pack, TVMRetValue* rv,
1661  Args&&... unpacked_args) {
1662  f(std::forward<Args>(unpacked_args)...);
1663  }
1664 };
1665 
1666 template <typename R, int nargs, typename F>
1667 TVM_ALWAYS_INLINE void unpack_call(const std::string* optional_name, const F& f,
1668  const TVMArgs& args, TVMRetValue* rv) {
1669  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<F>>::F;
1670  CHECK_EQ(nargs, args.size()) << "Function "
1671  << (optional_name == nullptr ? "<anonymous>" : *optional_name)
1672  << (f_sig == nullptr ? "" : (*f_sig)()) << " expects " << nargs
1673  << " arguments but " << args.size() << " were provided";
1674  unpack_call_dispatcher<R, nargs, 0, F>::run(optional_name, f_sig, f, args, rv);
1675 }
1676 
1677 template <typename FType>
1678 struct unpack_call_by_signature {};
1679 
1680 template <typename R, typename... Args>
1681 struct unpack_call_by_signature<R(Args...)> {
1682  template <typename F>
1683  TVM_ALWAYS_INLINE static void run(const F& f, const TVMArgs& args, TVMRetValue* rv) {
1684  unpack_call<R, sizeof...(Args)>(nullptr, f, args, rv);
1685  }
1686 };
1687 
1688 template <typename R, typename... Args>
1689 TVM_ALWAYS_INLINE R call_packed(const PackedFunc& pf, Args&&... args) {
1690  return R(pf(std::forward<Args>(args)...));
1691 }
1692 
1693 template <typename R>
1694 struct typed_packed_call_dispatcher {
1695  template <typename... Args>
1696  TVM_ALWAYS_INLINE static R run(const PackedFunc& pf, Args&&... args) {
1697  return pf(std::forward<Args>(args)...);
1698  }
1699 };
1700 
1701 template <>
1702 struct typed_packed_call_dispatcher<void> {
1703  template <typename... Args>
1704  TVM_ALWAYS_INLINE static void run(const PackedFunc& pf, Args&&... args) {
1705  pf(std::forward<Args>(args)...);
1706  }
1707 };
1708 } // namespace detail
1709 
1710 template <typename R, typename... Args>
1711 TypedPackedFunc<R(Args...)>::TypedPackedFunc(PackedFunc packed) : packed_(packed) {}
1712 
1713 template <typename R, typename... Args>
1715  : packed_(value.operator PackedFunc()) {}
1716 
1717 template <typename R, typename... Args>
1719  : packed_(value.operator PackedFunc()) {}
1720 
1721 template <typename R, typename... Args>
1723  : packed_(value.operator PackedFunc()) {}
1724 
1725 template <typename R, typename... Args>
1726 template <typename FType>
1727 inline void TypedPackedFunc<R(Args...)>::AssignTypedLambda(FType flambda, std::string name) {
1728  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<FType>>::F;
1729  packed_ = PackedFunc([flambda, name, f_sig](const TVMArgs& args, TVMRetValue* rv) {
1730  if (args.size() != sizeof...(Args)) {
1731  LOG(FATAL) << "Function " << name << (f_sig == nullptr ? "" : (*f_sig)()) << " expects "
1732  << sizeof...(Args) << " arguments, but " << args.size() << " were provided.";
1733  }
1734  detail::unpack_call<R, sizeof...(Args)>(&name, flambda, args, rv);
1735  });
1736 }
1737 
1738 template <typename R, typename... Args>
1739 template <typename FType>
1740 inline void TypedPackedFunc<R(Args...)>::AssignTypedLambda(FType flambda) {
1741  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<FType>>::F;
1742  packed_ = PackedFunc([flambda, f_sig](const TVMArgs& args, TVMRetValue* rv) {
1743  if (args.size() != sizeof...(Args)) {
1744  LOG(FATAL) << "Function <anonymous> " << (*f_sig)() << " expects " << sizeof...(Args)
1745  << " arguments, but " << args.size() << " were provided.";
1746  }
1747  detail::unpack_call<R, sizeof...(Args)>(nullptr, flambda, args, rv);
1748  });
1749 }
1750 
1751 template <typename R, typename... Args>
1752 TVM_ALWAYS_INLINE R TypedPackedFunc<R(Args...)>::operator()(Args... args) const {
1753  return detail::typed_packed_call_dispatcher<R>::run(packed_, std::forward<Args>(args)...);
1754 }
1755 
1756 // ObjectRef related conversion handling
1757 // Object can have three possible type codes:
1758 // kTVMNDArrayHandle, kTVMModuleHandle, kTVMObjectHandle
1759 //
1760 // We use type traits to eliminate un-necessary checks.
1761 template <typename T>
1762 inline void TVMArgsSetter::SetObject(size_t i, T&& value) const {
1763  using ContainerType = typename std::remove_reference<T>::type::ContainerType;
1764  if (value.defined()) {
1765  Object* ptr = value.data_.data_;
1766  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value ||
1767  (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1769  values_[i].v_handle = NDArray::FFIGetHandle(value);
1770  type_codes_[i] = kTVMNDArrayHandle;
1771  } else if (std::is_base_of<Module::ContainerType, ContainerType>::value ||
1772  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1773  ptr->IsInstance<Module::ContainerType>())) {
1774  values_[i].v_handle = ptr;
1775  type_codes_[i] = kTVMModuleHandle;
1776  } else if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value ||
1777  (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
1779  values_[i].v_handle = ptr;
1780  type_codes_[i] = kTVMPackedFuncHandle;
1781  } else if (std::is_rvalue_reference<decltype(value)>::value) {
1782  values_[i].v_handle = const_cast<Object**>(&(value.data_.data_));
1783  type_codes_[i] = kTVMObjectRValueRefArg;
1784  } else {
1785  values_[i].v_handle = value.data_.data_;
1786  type_codes_[i] = kTVMObjectHandle;
1787  }
1788  } else {
1789  type_codes_[i] = kTVMNullptr;
1790  values_[i].v_handle = nullptr;
1791  }
1792 }
1793 
1794 template <typename TObjectRef, typename>
1795 inline bool TVMPODValue_::IsObjectRef() const {
1796  using ContainerType = typename TObjectRef::ContainerType;
1797  // NOTE: the following code can be optimized by constant folding.
1798  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value) {
1799  return type_code_ == kTVMNDArrayHandle &&
1801  ->IsInstance<ContainerType>();
1802  }
1803  if (std::is_base_of<Module::ContainerType, ContainerType>::value) {
1804  return type_code_ == kTVMModuleHandle &&
1805  static_cast<Object*>(value_.v_handle)->IsInstance<ContainerType>();
1806  }
1807  if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value) {
1808  return type_code_ == kTVMPackedFuncHandle &&
1809  static_cast<Object*>(value_.v_handle)->IsInstance<ContainerType>();
1810  }
1811  // NOTE: we don't pass NDArray and runtime::Module as RValue ref.
1814  }
1815  return (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1817  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1819  (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
1823 }
1824 
1825 template <typename TObjectRef>
1826 inline TObjectRef TVMPODValue_::AsObjectRef() const {
1827  static_assert(std::is_base_of<ObjectRef, TObjectRef>::value,
1828  "Conversion only works for ObjectRef");
1829  using ContainerType = typename TObjectRef::ContainerType;
1830 
1831  if (type_code_ == kTVMNullptr) {
1832  CHECK(TObjectRef::_type_is_nullable)
1833  << "Expect a not null value of " << ContainerType::_type_key;
1834  return TObjectRef(ObjectPtr<Object>(nullptr));
1835  }
1836  // NOTE: the following code can be optimized by constant folding.
1837  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value) {
1838  // Casting to a sub-class of NDArray
1840  ObjectPtr<Object> data =
1842  CHECK(data->IsInstance<ContainerType>())
1843  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
1844  return TObjectRef(data);
1845  }
1846  if (std::is_base_of<Module::ContainerType, ContainerType>::value) {
1847  // Casting to a sub-class of Module
1849  ObjectPtr<Object> data = GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle));
1850  CHECK(data->IsInstance<ContainerType>())
1851  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
1852  return TObjectRef(data);
1853  }
1854  if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value) {
1855  // Casting to a sub-class of PackedFunc
1857  ObjectPtr<Object> data = GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle));
1858  CHECK(data->IsInstance<ContainerType>())
1859  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
1860  return TObjectRef(data);
1861  }
1862  if (type_code_ == kTVMObjectHandle) {
1863  // normal object type check.
1864  Object* ptr = static_cast<Object*>(value_.v_handle);
1866  ICHECK(!checked_type.defined()) << "Expected " << ObjectTypeChecker<TObjectRef>::TypeName()
1867  << ", but got " << checked_type.value();
1868  return TObjectRef(GetObjectPtr<Object>(ptr));
1869  } else if (type_code_ == kTVMObjectRValueRefArg) {
1870  Object* ptr = *static_cast<Object**>(value_.v_handle);
1872  ICHECK(!checked_type.defined()) << "Expected " << ObjectTypeChecker<TObjectRef>::TypeName()
1873  << ", but got " << checked_type.value();
1874  return TObjectRef(GetObjectPtr<Object>(ptr));
1875  } else if (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1877  // Casting to a base class that NDArray can sub-class
1878  ObjectPtr<Object> data =
1880  return TObjectRef(data);
1881  } else if (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1883  // Casting to a base class that Module can sub-class
1884  return TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
1885  } else if (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
1887  // Casting to a base class that PackedFunc can sub-class
1888  return TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
1889  } else {
1891  return TObjectRef(ObjectPtr<Object>(nullptr));
1892  }
1893 }
1894 
1895 template <typename TObjectRef, typename>
1896 inline TVMRetValue& TVMRetValue::operator=(TObjectRef other) {
1897  using ContainerType = typename TObjectRef::ContainerType;
1898  const Object* ptr = other.get();
1899  if (ptr != nullptr) {
1900  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value ||
1901  (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1902  ptr->IsInstance<NDArray::ContainerType>())) {
1903  return operator=(NDArray(std::move(other.data_)));
1904  }
1905  if (std::is_base_of<Module::ContainerType, ContainerType>::value ||
1906  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1907  ptr->IsInstance<Module::ContainerType>())) {
1908  return operator=(Module(std::move(other.data_)));
1909  }
1910  if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value ||
1911  (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
1912  ptr->IsInstance<PackedFunc::ContainerType>())) {
1913  return operator=(PackedFunc(std::move(other.data_)));
1914  }
1915  SwitchToObject(kTVMObjectHandle, std::move(other.data_));
1916  } else {
1917  SwitchToPOD(kTVMNullptr);
1918  value_.v_handle = nullptr;
1919  }
1920  return *this;
1921 }
1922 
1923 template <typename T, typename>
1924 inline TVMArgValue::operator T() const {
1925  return PackedFuncValueConverter<T>::From(*this);
1926 }
1927 
1928 template <typename T, typename>
1929 inline TVMMovableArgValue_::operator T() const {
1930  if (type_code_ == kTVMObjectRValueRefArg) {
1931  auto** ref = static_cast<Object**>(value_.v_handle);
1932  if (ObjectTypeChecker<T>::Check(*ref)) {
1934  }
1935  }
1936  // fallback
1937  return PackedFuncValueConverter<T>::From(AsArgValue());
1938 }
1939 
1940 template <typename T, typename>
1941 inline TVMRetValue::operator T() const {
1942  return PackedFuncValueConverter<T>::From(*this);
1943 }
1944 
1945 inline PackedFunc Module::GetFunction(const String& name, bool query_imports) {
1946  return (*this)->GetFunction(name, query_imports);
1947 }
1948 
1949 // specializations of PackedFuncValueConverter
1950 template <>
1952  static String From(const TVMArgValue& val) {
1953  if (val.IsObjectRef<tvm::runtime::String>()) {
1954  return val.AsObjectRef<tvm::runtime::String>();
1955  } else {
1956  return tvm::runtime::String(val.operator std::string());
1957  }
1958  }
1959 
1960  static String From(const TVMRetValue& val) {
1961  if (val.IsObjectRef<tvm::runtime::String>()) {
1962  return val.AsObjectRef<tvm::runtime::String>();
1963  } else {
1964  return tvm::runtime::String(val.operator std::string());
1965  }
1966  }
1967 };
1968 
1969 template <typename T>
1971  static Optional<T> From(const TVMArgValue& val) {
1972  if (val.type_code() == kTVMNullptr) return Optional<T>(nullptr);
1974  }
1975  static Optional<T> From(const TVMRetValue& val) {
1976  if (val.type_code() == kTVMNullptr) return Optional<T>(nullptr);
1978  }
1979 };
1980 
1981 inline bool String::CanConvertFrom(const TVMArgValue& val) {
1982  return val.type_code() == kTVMStr || val.IsObjectRef<tvm::runtime::String>();
1983 }
1984 
1985 inline TVMArgValue::operator DLDataType() const {
1986  if (String::CanConvertFrom(*this)) {
1987  return String2DLDataType(PackedFuncValueConverter<String>::From(*this).operator std::string());
1988  }
1989  // None type
1990  if (type_code_ == kTVMNullptr) {
1991  DLDataType t;
1992  t.code = kTVMOpaqueHandle;
1993  t.bits = 0;
1994  t.lanes = 0;
1995  return t;
1996  }
1997  TVM_CHECK_TYPE_CODE(type_code_, kTVMDataType);
1998  return value_.v_type;
1999 }
2000 
2001 inline TVMArgValue::operator DataType() const { return DataType(operator DLDataType()); }
2002 
2003 } // namespace runtime
2004 } // namespace tvm
2005 #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
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:42
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:1945
Object container class that backs NDArray.
Definition: ndarray.h:286
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:422
static ObjectPtr< Object > FFIDataFromHandle(TVMArrayHandle handle)
Construct NDArray's Data field from array handle in FFI.
Definition: ndarray.h:417
static void FFIDecRef(TVMArrayHandle handle)
DecRef resource managed by an FFI array handle.
Definition: ndarray.h:430
A custom smart pointer for Object.
Definition: object.h:358
Base class of all object reference.
Definition: object.h:515
bool defined() const
Definition: object.h:548
static void FFIClearAfterMove(ObjectRef *ref)
Clear the object ref data field without DecRef after we successfully moved the field.
Definition: object.h:619
friend class TVMArgsSetter
Definition: object.h:633
const Object * get() const
Definition: object.h:550
ObjectPtr< Object > data_
Internal pointer that backs the reference.
Definition: object.h:601
base class of all object containers.
Definition: object.h:167
std::string GetTypeKey() const
Definition: object.h:180
static std::string TypeIndex2Key(uint32_t tindex)
Get the type key of the corresponding index from runtime.
bool IsInstance() const
Definition: object.h:856
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:68
PackedFuncObj(FCallPacked *f_call_pack)
Constructing a packed function object from a function pointer.
Definition: packed_func.h:103
static constexpr const uint32_t _type_index
Definition: packed_func.h:77
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:109
static constexpr const char * _type_key
Definition: packed_func.h:78
PackedFuncObj()=delete
Delete the default constructor explicitly.
void(const PackedFuncObj *, TVMArgs, TVMRetValue *) FCallPacked
The internal callable function type.
Definition: packed_func.h:97
TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue *rv) const
Call the function in packed format.
Definition: packed_func.h:1216
Derived object class for constructing PackedFuncObj.
Definition: packed_func.h:114
PackedFuncSubObj(TCallable callable)
Derived object class for constructing PackedFuncObj.
Definition: packed_func.h:124
TStorage callable_
Type-erased filed for storing callable object.
Definition: packed_func.h:127
Packed function is a type-erased function. The arguments are passed by packed format.
Definition: packed_func.h:138
bool operator!=(std::nullptr_t null) const
Definition: packed_func.h:180
bool operator==(std::nullptr_t null) const
Definition: packed_func.h:178
TVMRetValue operator()(Args &&... args) const
Call packed function by directly passing in unpacked format.
Definition: packed_func.h:1613
TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue *rv) const
Call the function in packed format.
Definition: packed_func.h:1220
PackedFunc(TCallable data)
Constructing a packed function from a callable type whose signature is consistent with PackedFunc
Definition: packed_func.h:151
TVM_DEFINE_OBJECT_REF_METHODS(PackedFunc, ObjectRef, PackedFuncObj)
PackedFunc(std::nullptr_t null)
Constructor from null.
Definition: packed_func.h:141
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:1981
A single argument value to PackedFunc. Containing both type_code and TVMValue.
Definition: packed_func.h:646
TObjectRef AsObjectRef() const
Definition: packed_func.h:1826
const TVMValue & value() const
Definition: packed_func.h:691
TVMArgValue(TVMValue value, int type_code)
constructor
Definition: packed_func.h:655
bool IsObjectRef() const
Definition: packed_func.h:1795
TVMArgValue()
default constructor
Definition: packed_func.h:649
Definition: packed_func.h:1517
TVM_ALWAYS_INLINE void operator()(size_t i, DLTensor *value) const
Definition: packed_func.h:1547
TVM_ALWAYS_INLINE void operator()(size_t i, uint64_t value) const
Definition: packed_func.h:1526
TVM_ALWAYS_INLINE void operator()(size_t i, const TypedPackedFunc< FType > &value) const
Definition: packed_func.h:1576
TVM_ALWAYS_INLINE void operator()(size_t i, const TObjectRef &value) const
Definition: packed_func.h:1592
void operator()(size_t i, const TVMRetValue &value) const
Definition: packed_func.h:1579
TVM_ALWAYS_INLINE void operator()(size_t i, TObjectRef &&value) const
Definition: packed_func.h:1599
TVM_ALWAYS_INLINE void operator()(size_t i, double value) const
Definition: packed_func.h:1531
TVM_ALWAYS_INLINE void operator()(size_t i, T value) const
Definition: packed_func.h:1522
TVMArgsSetter(TVMValue *values, int *type_codes)
Definition: packed_func.h:1519
TVM_ALWAYS_INLINE void operator()(size_t i, const char *value) const
Definition: packed_func.h:1562
TVM_ALWAYS_INLINE void operator()(size_t i, Device value) const
Definition: packed_func.h:1551
TVM_ALWAYS_INLINE void operator()(size_t i, void *value) const
Definition: packed_func.h:1543
TVM_ALWAYS_INLINE void operator()(size_t i, const std::string &value) const
Definition: packed_func.h:1567
TVM_ALWAYS_INLINE void operator()(size_t i, std::nullptr_t value) const
Definition: packed_func.h:1535
TVM_ALWAYS_INLINE void operator()(size_t i, const TVMByteArray &value) const
Definition: packed_func.h:1571
TVM_ALWAYS_INLINE void operator()(size_t i, DataType dtype) const
Definition: packed_func.h:1559
TVM_ALWAYS_INLINE void operator()(size_t i, DLDataType value) const
Definition: packed_func.h:1555
TVM_ALWAYS_INLINE void operator()(size_t i, const TVMArgValue &value) const
Definition: packed_func.h:1539
Arguments into TVM functions.
Definition: packed_func.h:391
const TVMValue * values
Definition: packed_func.h:393
TVMArgs(const TVMValue *values, const int *type_codes, int num_args)
constructor
Definition: packed_func.h:402
TVMArgValue operator[](int i) const
Get i-th argument.
Definition: packed_func.h:1202
const int * type_codes
Definition: packed_func.h:394
int size() const
Definition: packed_func.h:1208
int num_args
Definition: packed_func.h:395
Internal auxiliary struct for TypedPackedFunc to indicate a movable argument with additional context ...
Definition: packed_func.h:754
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:765
Internal auxiliary struct for TypedPackedFunc to indicate a movable argument.
Definition: packed_func.h:709
TVMMovableArgValue_(TVMValue value, int type_code)
Definition: packed_func.h:711
Internal base class to handle conversion to POD values.
Definition: packed_func.h:541
TObjectRef AsObjectRef() const
Definition: packed_func.h:1826
TVMPODValue_()
Definition: packed_func.h:631
bool IsObjectRef() const
Definition: packed_func.h:1795
TVMValue value_
The value.
Definition: packed_func.h:635
T * ptr() const
return handle as specific pointer type.
Definition: packed_func.h:617
int type_code_
the type code
Definition: packed_func.h:637
int type_code() const
Definition: packed_func.h:610
TVMPODValue_(TVMValue value, int type_code)
Definition: packed_func.h:632
Return Value container, Unlike TVMArgValue, which only holds reference and do not delete the underlyi...
Definition: packed_func.h:799
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:967
const TVMValue & value() const
Definition: packed_func.h:976
~TVMRetValue()
destructor
Definition: packed_func.h:812
TObjectRef AsObjectRef() const
Definition: packed_func.h:1826
TVMRetValue & operator=(DLDataType t)
Definition: packed_func.h:889
TVMRetValue & operator=(const TypedPackedFunc< FType > &f)
Definition: packed_func.h:929
TVMRetValue & operator=(std::nullptr_t value)
Definition: packed_func.h:864
TVMRetValue & operator=(TVMRetValue &&other)
Definition: packed_func.h:852
TVMRetValue & operator=(PackedFunc f)
Definition: packed_func.h:924
TVMRetValue & operator=(bool value)
Definition: packed_func.h:895
TVMRetValue & operator=(int value)
Definition: packed_func.h:879
bool IsObjectRef() const
Definition: packed_func.h:1795
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:953
TVMRetValue()
default constructor
Definition: packed_func.h:802
TVMRetValue & operator=(void *value)
Definition: packed_func.h:869
TVMRetValue & operator=(std::string value)
Definition: packed_func.h:900
TVMRetValue & operator=(const TVMArgValue &other)
Definition: packed_func.h:936
TVMRetValue(const TVMRetValue &other)
Definition: packed_func.h:828
TVMRetValue & operator=(double value)
Definition: packed_func.h:859
TVMRetValue(TVMRetValue &&other)
move constructor from another return value.
Definition: packed_func.h:807
TVMRetValue & operator=(const TVMRetValue &other)
Definition: packed_func.h:932
TVMRetValue & operator=(int64_t value)
Definition: packed_func.h:874
TVMRetValue & operator=(Module m)
Definition: packed_func.h:920
TVMRetValue & operator=(const DataType &other)
Definition: packed_func.h:894
TVMRetValue & operator=(DLDevice value)
Definition: packed_func.h:884
TVMRetValue & operator=(TVMMovableArgValue_ &&other)
Definition: packed_func.h:940
TVMRetValue & operator=(TVMByteArray value)
Definition: packed_func.h:904
TVMRetValue & operator=(NDArray other)
Definition: packed_func.h:908
A PackedFunc wrapper to provide typed function signature. It is backed by a PackedFunc internally.
Definition: packed_func.h:227
const PackedFunc & packed() const
Definition: packed_func.h:358
bool operator==(std::nullptr_t null) const
Definition: packed_func.h:360
TypedPackedFunc(const FLambda &typed_lambda)
construct from a lambda function with the same signature.
Definition: packed_func.h:309
TypedPackedFunc()
default constructor
Definition: packed_func.h:232
TypedPackedFunc(const FLambda &typed_lambda, std::string name)
construct from a lambda function with the same signature.
Definition: packed_func.h:286
TSelf & operator=(FLambda typed_lambda)
copy assignment operator from typed lambda
Definition: packed_func.h:331
TSelf & operator=(PackedFunc packed)
copy assignment operator from PackedFunc.
Definition: packed_func.h:340
bool operator!=(std::nullptr_t null) const
Definition: packed_func.h:362
TypedPackedFunc(std::nullptr_t null)
constructor from null
Definition: packed_func.h:234
Please refer to TypedPackedFunc<R(Args..)>.
Definition: packed_func.h:60
struct TVMArgs TVMArgs
Runtime Map container types.
const char * ArgTypeCode2Str(int type_code)
Convert argument type code to string.
Definition: packed_func.h:1225
DLDataType String2DLDataType(std::string s)
convert a string to TVM type.
Definition: data_type.h:376
std::string() FSig
Using static function to output TypedPackedFunc signature.
Definition: packed_func.h:186
std::string DLDataType2String(DLDataType t)
convert a TVM type to string.
Definition: data_type.h:369
Object * TVMArrayHandleToObjectHandle(TVMArrayHandle handle)
Definition: ndarray.h:434
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:432
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:422
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:500
static bool Check(const Object *ptr)
Definition: packed_func.h:489
static Optional< String > CheckAndGetMismatch(const Object *ptr)
Definition: packed_func.h:472
static bool Check(const Object *ptr)
Definition: packed_func.h:521
static Optional< String > CheckAndGetMismatch(const Object *ptr)
Definition: packed_func.h:504
static std::string TypeName()
Definition: packed_func.h:531
Type traits for runtime type check during FFI conversion.
Definition: packed_func.h:430
static std::string TypeName()
Definition: packed_func.h:463
static bool Check(const Object *ptr)
Check if an object matches the template type.
Definition: packed_func.h:458
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:438
Internal struct for extracting the callable method from callable type.
Definition: packed_func.h:86
static void Call(const PackedFuncObj *obj, TVMArgs args, TVMRetValue *rv)
Extracting the callable method from callable type.
Definition: packed_func.h:1211
static Optional< T > From(const TVMRetValue &val)
Definition: packed_func.h:1975
static Optional< T > From(const TVMArgValue &val)
Definition: packed_func.h:1971
static String From(const TVMArgValue &val)
Definition: packed_func.h:1952
static String From(const TVMRetValue &val)
Definition: packed_func.h:1960
Type trait to specify special value conversion rules from TVMArgValue and TVMRetValue.
Definition: packed_func.h:1096
static TObjectRef From(const TVMRetValue &val)
Convert a TObjectRef from a return value.
Definition: packed_func.h:1108
static TObjectRef From(const TVMArgValue &val)
Convert a TObjectRef from an argument value.
Definition: packed_func.h:1102
Definition: packed_func.h:62
@ 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