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 
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)
403  : values(values), type_codes(type_codes), num_args(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 {
554  TVM_CHECK_TYPE_CODE(type_code_, kDLInt);
555  return value_.v_int64;
556  }
557  operator uint64_t() const {
558  TVM_CHECK_TYPE_CODE(type_code_, kDLInt);
559  return value_.v_int64;
560  }
561  operator int() const {
562  TVM_CHECK_TYPE_CODE(type_code_, kDLInt);
563  ICHECK_LE(value_.v_int64, std::numeric_limits<int>::max());
564  ICHECK_GE(value_.v_int64, std::numeric_limits<int>::min());
565  return static_cast<int>(value_.v_int64);
566  }
567  operator bool() const {
568  TVM_CHECK_TYPE_CODE(type_code_, kDLInt);
569  return value_.v_int64 != 0;
570  }
571  operator void*() const {
572  if (type_code_ == kTVMNullptr) return nullptr;
573  if (type_code_ == kTVMDLTensorHandle) return value_.v_handle;
575  return value_.v_handle;
576  }
577  operator DLTensor*() const {
578  if (type_code_ == kTVMDLTensorHandle || type_code_ == kTVMNDArrayHandle) {
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));
590  return NDArray(NDArray::FFIDataFromHandle(static_cast<TVMArrayHandle>(value_.v_handle)));
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 {
607  TVM_CHECK_TYPE_CODE(type_code_, kDLDevice);
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_;
631  TVMPODValue_() : type_code_(kTVMNullptr) {}
632  TVMPODValue_(TVMValue value, int type_code) : value_(value), type_code_(type_code) {}
633 
638 };
639 
646 class TVMArgValue : public TVMPODValue_ {
647  public:
655  TVMArgValue(TVMValue value, int type_code) : TVMPODValue_(value, type_code) {}
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:
711  TVMMovableArgValue_(TVMValue value, int type_code) : TVMPODValue_(value, type_code) {}
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:
807  TVMRetValue(TVMRetValue&& other) : TVMPODValue_(other.value_, other.type_code_) {
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  }
836  TVM_CHECK_TYPE_CODE(type_code_, kTVMStr);
837  return *ptr<std::string>();
838  }
839  operator DLDataType() const {
840  if (type_code_ == kTVMStr) {
841  return String2DLDataType(operator std::string());
842  }
843  TVM_CHECK_TYPE_CODE(type_code_, kTVMDataType);
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  }
859  TVMRetValue& operator=(double value) {
860  this->SwitchToPOD(kDLFloat);
861  value_.v_float64 = value;
862  return *this;
863  }
864  TVMRetValue& operator=(std::nullptr_t value) {
865  this->SwitchToPOD(kTVMNullptr);
866  value_.v_handle = value;
867  return *this;
868  }
869  TVMRetValue& operator=(void* value) {
870  this->SwitchToPOD(kTVMOpaqueHandle);
871  value_.v_handle = value;
872  return *this;
873  }
874  TVMRetValue& operator=(int64_t value) {
875  this->SwitchToPOD(kDLInt);
876  value_.v_int64 = value;
877  return *this;
878  }
879  TVMRetValue& operator=(int value) {
880  this->SwitchToPOD(kDLInt);
881  value_.v_int64 = value;
882  return *this;
883  }
884  TVMRetValue& operator=(DLDevice value) {
885  this->SwitchToPOD(kDLDevice);
886  value_.v_device = value;
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()); }
895  TVMRetValue& operator=(bool value) {
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  }
908  TVMRetValue& operator=(NDArray other) {
909  if (other.data_ != nullptr) {
910  this->Clear();
911  type_code_ = kTVMNDArrayHandle;
912  value_.v_handle = NDArray::FFIGetHandle(other);
914  } else {
915  SwitchToPOD(kTVMNullptr);
916  value_.v_handle = nullptr;
917  }
918  return *this;
919  }
920  TVMRetValue& operator=(Module m) {
921  SwitchToObject(kTVMModuleHandle, std::move(m.data_));
922  return *this;
923  }
924  TVMRetValue& operator=(PackedFunc f) {
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_;
958  type_code_ = kTVMNullptr;
959  }
967  static TVMRetValue MoveFromCHost(TVMValue value, int type_code) {
968  // Can move POD and everything under the object system.
969  ICHECK(type_code <= kTVMPackedFuncHandle || type_code == kTVMNDArrayHandle);
971  ret.value_ = value;
972  ret.type_code_ = type_code;
973  return ret;
974  }
976  const TVMValue& value() const {
977  ICHECK(type_code_ != kTVMObjectHandle && type_code_ != kTVMPackedFuncHandle &&
978  type_code_ != kTVMModuleHandle && type_code_ != kTVMStr)
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();
1034  type_code_ = type_code;
1035  }
1036  }
1037  template <typename T>
1038  void SwitchToClass(int type_code, T v) {
1039  if (type_code_ != type_code) {
1040  this->Clear();
1041  type_code_ = type_code;
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();
1050  type_code_ = type_code;
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: {
1070  NDArray::FFIDecRef(static_cast<TVMArrayHandle>(value_.v_handle));
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  }
1082  type_code_ = kTVMNullptr;
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  return "";
1260  }
1261 }
1262 
1263 namespace detail {
1264 
1265 template <bool stop, std::size_t I, typename F>
1266 struct for_each_dispatcher {
1267  template <typename T, typename... Args>
1268  static void run(const F& f, T&& value, Args&&... args) { // NOLINT(*)
1269  f(I, std::forward<T>(value));
1270  for_each_dispatcher<sizeof...(Args) == 0, (I + 1), F>::run(f, std::forward<Args>(args)...);
1271  }
1272 };
1273 
1274 template <std::size_t I, typename F>
1275 struct for_each_dispatcher<true, I, F> {
1276  static void run(const F& f) {} // NOLINT(*)
1277 };
1278 
1279 template <typename F, typename... Args>
1280 inline void for_each(const F& f, Args&&... args) { // NOLINT(*)
1281  for_each_dispatcher<sizeof...(Args) == 0, 0, F>::run(f, std::forward<Args>(args)...);
1282 }
1283 
1284 namespace parameter_pack {
1285 
1286 template <typename... EnumArgs>
1287 struct EnumeratedParamPack {
1288  struct Invoke {
1289  template <template <size_t i, typename TArgument> class Functor, typename... ExtraParams>
1290  static void F(ExtraParams&&... extra_params) {
1291  using TExpander = int[];
1292  (void)TExpander{
1293  0,
1294  (Functor<EnumArgs::i, typename EnumArgs::T>::F(extra_params...), 0)...,
1295  };
1296  }
1297  };
1298 };
1299 
1300 template <typename... Args>
1301 struct EnumerateImpl {
1302  private:
1303  template <size_t _i, typename _T>
1304  struct Item {
1305  static const constexpr size_t i = _i;
1306  using T = _T;
1307  };
1308 
1309  template <typename...>
1310  struct Zipper;
1311 
1312  template <std::size_t... id>
1313  struct Zipper<std::integer_sequence<std::size_t, id...>> {
1314  using T = EnumeratedParamPack<Item<id, Args>...>;
1315  };
1316 
1317  public:
1318  using T = typename Zipper<std::index_sequence_for<Args...>>::T;
1319 };
1320 
1321 template <typename... Args>
1322 using Enumerate = typename EnumerateImpl<Args...>::T;
1323 
1324 template <typename... Args>
1325 struct ParamPack {
1326  template <template <size_t i, typename TArgument> class Functor, typename... ExtraParams>
1327  static void InvokeWithoutArg(ExtraParams&&... extra_params) {
1328  Enumerate<Args...>::Invoke::template F<Functor, ExtraParams...>(
1329  std::forward<ExtraParams>(extra_params)...);
1330  }
1331 };
1332 
1333 } // namespace parameter_pack
1334 
1339 template <typename T>
1340 struct func_signature_helper {
1341  using FType = void;
1342 };
1343 
1344 template <typename T, typename R, typename... Args>
1345 struct func_signature_helper<R (T::*)(Args...)> {
1346  using FType = R(Args...);
1347  using ParamType = parameter_pack::ParamPack<Args...>;
1348  using RetType = R;
1349  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1350 };
1351 
1352 template <typename T, typename R, typename... Args>
1353 struct func_signature_helper<R (T::*)(Args...) const> {
1354  using FType = R(Args...);
1355  using ParamType = parameter_pack::ParamPack<Args...>;
1356  using RetType = R;
1357  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1358 };
1359 
1364 template <typename T>
1365 struct function_signature {
1366  using FType = typename func_signature_helper<decltype(&T::operator())>::FType;
1367  using ParamType = typename func_signature_helper<decltype(&T::operator())>::ParamType;
1368  using RetType = typename func_signature_helper<decltype(&T::operator())>::RetType;
1369 };
1370 
1371 // handle case of function.
1372 template <typename R, typename... Args>
1373 struct function_signature<R(Args...)> {
1374  using FType = R(Args...);
1375  using ParamType = parameter_pack::ParamPack<Args...>;
1376  using RetType = R;
1377  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1378 };
1379 
1380 // handle case of function ptr.
1381 template <typename R, typename... Args>
1382 struct function_signature<R (*)(Args...)> {
1383  using FType = R(Args...);
1384  using ParamType = detail::parameter_pack::ParamPack<Args...>;
1385  using RetType = R;
1386  static_assert(!std::is_reference<R>::value, "TypedPackedFunc return reference");
1387 };
1388 
1389 template <typename TSignature>
1390 struct SignaturePrinter;
1391 
1392 namespace type2str {
1393 
1394 template <typename T>
1395 struct TypeSimplifier;
1396 
1397 template <typename T>
1398 struct Type2Str {
1399  template <typename = std::enable_if_t<std::is_base_of<ObjectRef, T>::value>>
1400  static std::string v() {
1401  return T::ContainerType::_type_key;
1402  }
1403 };
1404 template <>
1405 struct Type2Str<int> {
1406  static std::string v() { return "int"; }
1407 };
1408 template <>
1409 struct Type2Str<double> {
1410  static std::string v() { return "double"; }
1411 };
1412 template <>
1413 struct Type2Str<int64_t> {
1414  static std::string v() { return "int64_t"; }
1415 };
1416 template <>
1417 struct Type2Str<uint64_t> {
1418  static std::string v() { return "uint64_t"; }
1419 };
1420 template <>
1421 struct Type2Str<bool> {
1422  static std::string v() { return "bool"; }
1423 };
1424 template <>
1425 struct Type2Str<void> {
1426  static std::string v() { return "void"; }
1427 };
1428 template <>
1429 struct Type2Str<std::basic_string<char>> {
1430  static std::string v() { return "basic_string<char>"; }
1431 };
1432 template <typename K, typename V>
1433 struct Type2Str<Map<K, V>> {
1434  static std::string v() {
1435  return "Map<" + TypeSimplifier<K>::v() + ", " + TypeSimplifier<V>::v() + ">";
1436  }
1437 };
1438 template <>
1439 struct Type2Str<DLDevice> {
1440  static std::string v() { return "DLDevice"; }
1441 };
1442 template <>
1443 struct Type2Str<DLTensor> {
1444  static std::string v() { return "DLTensor"; }
1445 };
1446 template <>
1447 struct Type2Str<DataType> {
1448  static std::string v() { return "DataType"; }
1449 };
1450 template <>
1451 struct Type2Str<DLDataType> {
1452  static std::string v() { return "DLDataType"; }
1453 };
1454 template <>
1455 struct Type2Str<TVMRetValue> {
1456  static std::string v() { return "TVMRetValue"; }
1457 };
1458 template <>
1459 struct Type2Str<TVMArgValue> {
1460  static std::string v() { return "TVMArgValue"; }
1461 };
1462 template <typename FType>
1463 struct Type2Str<TypedPackedFunc<FType>> {
1464  static std::string v() { return SignaturePrinter<function_signature<FType>>::F(); }
1465 };
1466 template <typename T>
1467 struct Type2Str<Array<T>> {
1468  static std::string v() { return "Array<" + TypeSimplifier<T>::v() + ">"; }
1469 };
1470 
1475 template <typename T>
1476 struct TypeSimplifier {
1477  static std::string v() {
1478  using U = typename std::remove_cv<
1479  typename std::remove_reference<typename std::remove_pointer<T>::type>::type>::type;
1480  return (std::is_const<T>::value ? "const " : "") + Type2Str<U>::v() +
1481  (std::is_pointer<T>::value ? "*" : "") + (std::is_reference<T>::value ? "&" : "");
1482  }
1483 };
1484 
1485 } // namespace type2str
1486 
1491 template <typename TSignature>
1492 struct SignaturePrinter {
1493  using ParamType = typename TSignature::ParamType;
1494  using RetType = typename TSignature::RetType;
1495 
1496  template <size_t i, typename TArgument>
1497  struct PrintParamType {
1498  static void F(std::ostream& os) {
1499  os << (i == 0 ? "" : ", ") << i << ": " << type2str::TypeSimplifier<TArgument>::v();
1500  }
1501  };
1502 
1503  static std::string F() {
1504  std::ostringstream oss;
1505  oss << "(";
1506  ParamType::template InvokeWithoutArg<PrintParamType>(oss);
1507  oss << ") -> " << type2str::TypeSimplifier<RetType>::v();
1508  return oss.str();
1509  }
1510 };
1511 } // namespace detail
1512 
1513 /* \brief argument settter to PackedFunc */
1515  public:
1516  TVMArgsSetter(TVMValue* values, int* type_codes) : values_(values), type_codes_(type_codes) {}
1517  // setters for POD types
1518  template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
1519  TVM_ALWAYS_INLINE void operator()(size_t i, T value) const {
1520  values_[i].v_int64 = static_cast<int64_t>(value);
1521  type_codes_[i] = kDLInt;
1522  }
1523  TVM_ALWAYS_INLINE void operator()(size_t i, uint64_t value) const {
1524  values_[i].v_int64 = static_cast<int64_t>(value);
1525  ICHECK_LE(value, static_cast<uint64_t>(std::numeric_limits<int64_t>::max()));
1526  type_codes_[i] = kDLInt;
1527  }
1528  TVM_ALWAYS_INLINE void operator()(size_t i, double value) const {
1529  values_[i].v_float64 = value;
1530  type_codes_[i] = kDLFloat;
1531  }
1532  TVM_ALWAYS_INLINE void operator()(size_t i, std::nullptr_t value) const {
1533  values_[i].v_handle = value;
1534  type_codes_[i] = kTVMNullptr;
1535  }
1536  TVM_ALWAYS_INLINE void operator()(size_t i, const TVMArgValue& value) const {
1537  values_[i] = value.value_;
1538  type_codes_[i] = value.type_code_;
1539  }
1540  TVM_ALWAYS_INLINE void operator()(size_t i, void* value) const {
1541  values_[i].v_handle = value;
1542  type_codes_[i] = kTVMOpaqueHandle;
1543  }
1544  TVM_ALWAYS_INLINE void operator()(size_t i, DLTensor* value) const {
1545  values_[i].v_handle = value;
1546  type_codes_[i] = kTVMDLTensorHandle;
1547  }
1548  TVM_ALWAYS_INLINE void operator()(size_t i, Device value) const {
1549  values_[i].v_device = value;
1550  type_codes_[i] = kDLDevice;
1551  }
1552  TVM_ALWAYS_INLINE void operator()(size_t i, DLDataType value) const {
1553  values_[i].v_type = value;
1554  type_codes_[i] = kTVMDataType;
1555  }
1556  TVM_ALWAYS_INLINE void operator()(size_t i, DataType dtype) const {
1557  operator()(i, dtype.operator DLDataType());
1558  }
1559  TVM_ALWAYS_INLINE void operator()(size_t i, const char* value) const {
1560  values_[i].v_str = value;
1561  type_codes_[i] = kTVMStr;
1562  }
1563  // setters for container types
1564  TVM_ALWAYS_INLINE void operator()(size_t i, const std::string& value) const {
1565  values_[i].v_str = value.c_str();
1566  type_codes_[i] = kTVMStr;
1567  }
1568  TVM_ALWAYS_INLINE void operator()(size_t i, const TVMByteArray& value) const {
1569  values_[i].v_handle = const_cast<TVMByteArray*>(&value);
1570  type_codes_[i] = kTVMBytes;
1571  }
1572  template <typename FType>
1573  TVM_ALWAYS_INLINE void operator()(size_t i, const TypedPackedFunc<FType>& value) const {
1574  operator()(i, value.packed());
1575  }
1576  void operator()(size_t i, const TVMRetValue& value) const {
1577  if (value.type_code() == kTVMStr) {
1578  values_[i].v_str = value.ptr<std::string>()->c_str();
1579  type_codes_[i] = kTVMStr;
1580  } else {
1581  ICHECK_NE(value.type_code(), kTVMBytes) << "not handled.";
1582  values_[i] = value.value_;
1583  type_codes_[i] = value.type_code();
1584  }
1585  }
1586  // ObjectRef handling
1587  template <typename TObjectRef,
1588  typename = typename std::enable_if<std::is_base_of<ObjectRef, TObjectRef>::value>::type>
1589  TVM_ALWAYS_INLINE void operator()(size_t i, const TObjectRef& value) const {
1590  this->SetObject(i, value);
1591  }
1592 
1593  template <typename TObjectRef,
1594  typename = typename std::enable_if<std::is_base_of<
1595  ObjectRef, typename std::remove_reference<TObjectRef>::type>::value>::type>
1596  TVM_ALWAYS_INLINE void operator()(size_t i, TObjectRef&& value) const {
1597  this->SetObject(i, std::forward<TObjectRef>(value));
1598  }
1599 
1600  private:
1601  template <typename TObjectRef>
1602  inline void SetObject(size_t i, TObjectRef&& value) const;
1604  TVMValue* values_;
1606  int* type_codes_;
1607 };
1608 
1609 template <typename... Args>
1610 inline TVMRetValue PackedFunc::operator()(Args&&... args) const {
1611  const int kNumArgs = sizeof...(Args);
1612  const int kArraySize = kNumArgs > 0 ? kNumArgs : 1;
1613  TVMValue values[kArraySize];
1614  int type_codes[kArraySize];
1615  detail::for_each(TVMArgsSetter(values, type_codes), std::forward<Args>(args)...);
1616  TVMRetValue rv;
1617  (static_cast<PackedFuncObj*>(data_.get()))
1618  ->CallPacked(TVMArgs(values, type_codes, kNumArgs), &rv);
1619  return rv;
1620 }
1621 
1622 namespace detail {
1623 template <typename R, int nleft, int index, typename F>
1624 struct unpack_call_dispatcher {
1625  template <typename... Args>
1626  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1627  const TVMArgs& args_pack, TVMRetValue* rv,
1628  Args&&... unpacked_args) {
1629  // construct a movable argument value
1630  // which allows potential move of argument to the input of F.
1631  unpack_call_dispatcher<R, nleft - 1, index + 1, F>::run(
1632  optional_name, f_sig, f, args_pack, rv, std::forward<Args>(unpacked_args)...,
1633  TVMMovableArgValueWithContext_(args_pack.values[index], args_pack.type_codes[index], index,
1634  optional_name, f_sig));
1635  }
1636 };
1637 
1638 template <typename R, int index, typename F>
1639 struct unpack_call_dispatcher<R, 0, index, F> {
1640  template <typename... Args>
1641  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1642  const TVMArgs& args_pack, TVMRetValue* rv,
1643  Args&&... unpacked_args) {
1644  using RetType = decltype(f(std::forward<Args>(unpacked_args)...));
1645  if (std::is_same<RetType, R>::value) {
1646  *rv = f(std::forward<Args>(unpacked_args)...);
1647  } else {
1648  *rv = R(f(std::forward<Args>(unpacked_args)...));
1649  }
1650  }
1651 };
1652 
1653 template <int index, typename F>
1654 struct unpack_call_dispatcher<void, 0, index, F> {
1655  template <typename... Args>
1656  TVM_ALWAYS_INLINE static void run(const std::string* optional_name, FSig* f_sig, const F& f,
1657  const TVMArgs& args_pack, TVMRetValue* rv,
1658  Args&&... unpacked_args) {
1659  f(std::forward<Args>(unpacked_args)...);
1660  }
1661 };
1662 
1663 template <typename R, int nargs, typename F>
1664 TVM_ALWAYS_INLINE void unpack_call(const std::string* optional_name, const F& f,
1665  const TVMArgs& args, TVMRetValue* rv) {
1666  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<F>>::F;
1667  CHECK_EQ(nargs, args.size()) << "Function "
1668  << (optional_name == nullptr ? "<anonymous>" : *optional_name)
1669  << (f_sig == nullptr ? "" : (*f_sig)()) << " expects " << nargs
1670  << " arguments but " << args.size() << " were provided";
1671  unpack_call_dispatcher<R, nargs, 0, F>::run(optional_name, f_sig, f, args, rv);
1672 }
1673 
1674 template <typename FType>
1675 struct unpack_call_by_signature {};
1676 
1677 template <typename R, typename... Args>
1678 struct unpack_call_by_signature<R(Args...)> {
1679  template <typename F>
1680  TVM_ALWAYS_INLINE static void run(const F& f, const TVMArgs& args, TVMRetValue* rv) {
1681  unpack_call<R, sizeof...(Args)>(nullptr, f, args, rv);
1682  }
1683 };
1684 
1685 template <typename R, typename... Args>
1686 TVM_ALWAYS_INLINE R call_packed(const PackedFunc& pf, Args&&... args) {
1687  return R(pf(std::forward<Args>(args)...));
1688 }
1689 
1690 template <typename R>
1691 struct typed_packed_call_dispatcher {
1692  template <typename... Args>
1693  TVM_ALWAYS_INLINE static R run(const PackedFunc& pf, Args&&... args) {
1694  return pf(std::forward<Args>(args)...);
1695  }
1696 };
1697 
1698 template <>
1699 struct typed_packed_call_dispatcher<void> {
1700  template <typename... Args>
1701  TVM_ALWAYS_INLINE static void run(const PackedFunc& pf, Args&&... args) {
1702  pf(std::forward<Args>(args)...);
1703  }
1704 };
1705 } // namespace detail
1706 
1707 template <typename R, typename... Args>
1708 TypedPackedFunc<R(Args...)>::TypedPackedFunc(PackedFunc packed) : packed_(packed) {}
1709 
1710 template <typename R, typename... Args>
1712  : packed_(value.operator PackedFunc()) {}
1713 
1714 template <typename R, typename... Args>
1716  : packed_(value.operator PackedFunc()) {}
1717 
1718 template <typename R, typename... Args>
1720  : packed_(value.operator PackedFunc()) {}
1721 
1722 template <typename R, typename... Args>
1723 template <typename FType>
1724 inline void TypedPackedFunc<R(Args...)>::AssignTypedLambda(FType flambda, std::string name) {
1725  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<FType>>::F;
1726  packed_ = PackedFunc([flambda, name, f_sig](const TVMArgs& args, TVMRetValue* rv) {
1727  if (args.size() != sizeof...(Args)) {
1728  LOG(FATAL) << "Function " << name << (f_sig == nullptr ? "" : (*f_sig)()) << " expects "
1729  << sizeof...(Args) << " arguments, but " << args.size() << " were provided.";
1730  }
1731  detail::unpack_call<R, sizeof...(Args)>(&name, flambda, args, rv);
1732  });
1733 }
1734 
1735 template <typename R, typename... Args>
1736 template <typename FType>
1737 inline void TypedPackedFunc<R(Args...)>::AssignTypedLambda(FType flambda) {
1738  FSig* f_sig = detail::SignaturePrinter<detail::function_signature<FType>>::F;
1739  packed_ = PackedFunc([flambda, f_sig](const TVMArgs& args, TVMRetValue* rv) {
1740  if (args.size() != sizeof...(Args)) {
1741  LOG(FATAL) << "Function <anonymous> " << (*f_sig)() << " expects " << sizeof...(Args)
1742  << " arguments, but " << args.size() << " were provided.";
1743  }
1744  detail::unpack_call<R, sizeof...(Args)>(nullptr, flambda, args, rv);
1745  });
1746 }
1747 
1748 template <typename R, typename... Args>
1749 TVM_ALWAYS_INLINE R TypedPackedFunc<R(Args...)>::operator()(Args... args) const {
1750  return detail::typed_packed_call_dispatcher<R>::run(packed_, std::forward<Args>(args)...);
1751 }
1752 
1753 // ObjectRef related conversion handling
1754 // Object can have three possible type codes:
1755 // kTVMNDArrayHandle, kTVMModuleHandle, kTVMObjectHandle
1756 //
1757 // We use type traits to eliminate un-necessary checks.
1758 template <typename T>
1759 inline void TVMArgsSetter::SetObject(size_t i, T&& value) const {
1760  using ContainerType = typename std::remove_reference<T>::type::ContainerType;
1761  if (value.defined()) {
1762  Object* ptr = value.data_.data_;
1763  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value ||
1764  (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1766  values_[i].v_handle = NDArray::FFIGetHandle(value);
1767  type_codes_[i] = kTVMNDArrayHandle;
1768  } else if (std::is_base_of<Module::ContainerType, ContainerType>::value ||
1769  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1770  ptr->IsInstance<Module::ContainerType>())) {
1771  values_[i].v_handle = ptr;
1772  type_codes_[i] = kTVMModuleHandle;
1773  } else if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value ||
1774  (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
1776  values_[i].v_handle = ptr;
1777  type_codes_[i] = kTVMPackedFuncHandle;
1778  } else if (std::is_rvalue_reference<decltype(value)>::value) {
1779  values_[i].v_handle = const_cast<Object**>(&(value.data_.data_));
1780  type_codes_[i] = kTVMObjectRValueRefArg;
1781  } else {
1782  values_[i].v_handle = value.data_.data_;
1783  type_codes_[i] = kTVMObjectHandle;
1784  }
1785  } else {
1786  type_codes_[i] = kTVMNullptr;
1787  values_[i].v_handle = nullptr;
1788  }
1789 }
1790 
1791 template <typename TObjectRef, typename>
1792 inline bool TVMPODValue_::IsObjectRef() const {
1793  using ContainerType = typename TObjectRef::ContainerType;
1794  // NOTE: the following code can be optimized by constant folding.
1795  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value) {
1796  return type_code_ == kTVMNDArrayHandle &&
1797  TVMArrayHandleToObjectHandle(static_cast<TVMArrayHandle>(value_.v_handle))
1798  ->IsInstance<ContainerType>();
1799  }
1800  if (std::is_base_of<Module::ContainerType, ContainerType>::value) {
1801  return type_code_ == kTVMModuleHandle &&
1802  static_cast<Object*>(value_.v_handle)->IsInstance<ContainerType>();
1803  }
1804  if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value) {
1805  return type_code_ == kTVMPackedFuncHandle &&
1806  static_cast<Object*>(value_.v_handle)->IsInstance<ContainerType>();
1807  }
1808  // NOTE: we don't pass NDArray and runtime::Module as RValue ref.
1809  if (type_code_ == kTVMObjectRValueRefArg) {
1810  return ObjectTypeChecker<TObjectRef>::Check(*static_cast<Object**>(value_.v_handle));
1811  }
1812  return (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1813  type_code_ == kTVMNDArrayHandle) ||
1814  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1815  type_code_ == kTVMModuleHandle) ||
1816  (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
1817  type_code_ == kTVMPackedFuncHandle) ||
1818  (type_code_ == kTVMObjectHandle &&
1819  ObjectTypeChecker<TObjectRef>::Check(static_cast<Object*>(value_.v_handle)));
1820 }
1821 
1822 template <typename TObjectRef>
1823 inline TObjectRef TVMPODValue_::AsObjectRef() const {
1824  static_assert(std::is_base_of<ObjectRef, TObjectRef>::value,
1825  "Conversion only works for ObjectRef");
1826  using ContainerType = typename TObjectRef::ContainerType;
1827 
1828  if (type_code_ == kTVMNullptr) {
1829  CHECK(TObjectRef::_type_is_nullable)
1830  << "Expect a not null value of " << ContainerType::_type_key;
1831  return TObjectRef(ObjectPtr<Object>(nullptr));
1832  }
1833  // NOTE: the following code can be optimized by constant folding.
1834  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value) {
1835  // Casting to a sub-class of NDArray
1837  ObjectPtr<Object> data =
1838  NDArray::FFIDataFromHandle(static_cast<TVMArrayHandle>(value_.v_handle));
1839  CHECK(data->IsInstance<ContainerType>())
1840  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
1841  return TObjectRef(data);
1842  }
1843  if (std::is_base_of<Module::ContainerType, ContainerType>::value) {
1844  // Casting to a sub-class of Module
1846  ObjectPtr<Object> data = GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle));
1847  CHECK(data->IsInstance<ContainerType>())
1848  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
1849  return TObjectRef(data);
1850  }
1851  if (std::is_base_of<PackedFunc::ContainerType, ContainerType>::value) {
1852  // Casting to a sub-class of PackedFunc
1854  ObjectPtr<Object> data = GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle));
1855  CHECK(data->IsInstance<ContainerType>())
1856  << "Expected " << ContainerType::_type_key << " but got " << data->GetTypeKey();
1857  return TObjectRef(data);
1858  }
1859  if (type_code_ == kTVMObjectHandle) {
1860  // normal object type check.
1861  Object* ptr = static_cast<Object*>(value_.v_handle);
1863  ICHECK(!checked_type.defined()) << "Expected " << ObjectTypeChecker<TObjectRef>::TypeName()
1864  << ", but got " << checked_type.value();
1865  return TObjectRef(GetObjectPtr<Object>(ptr));
1866  } else if (type_code_ == kTVMObjectRValueRefArg) {
1867  Object* ptr = *static_cast<Object**>(value_.v_handle);
1869  ICHECK(!checked_type.defined()) << "Expected " << ObjectTypeChecker<TObjectRef>::TypeName()
1870  << ", but got " << checked_type.value();
1871  return TObjectRef(GetObjectPtr<Object>(ptr));
1872  } else if (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1873  type_code_ == kTVMNDArrayHandle) {
1874  // Casting to a base class that NDArray can sub-class
1875  ObjectPtr<Object> data =
1876  NDArray::FFIDataFromHandle(static_cast<TVMArrayHandle>(value_.v_handle));
1877  return TObjectRef(data);
1878  } else if (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1879  type_code_ == kTVMModuleHandle) {
1880  // Casting to a base class that Module can sub-class
1881  return TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
1882  } else if (std::is_base_of<ContainerType, PackedFunc::ContainerType>::value &&
1883  type_code_ == kTVMPackedFuncHandle) {
1884  // Casting to a base class that PackedFunc can sub-class
1885  return TObjectRef(GetObjectPtr<Object>(static_cast<Object*>(value_.v_handle)));
1886  } else {
1888  return TObjectRef(ObjectPtr<Object>(nullptr));
1889  }
1890 }
1891 
1892 template <typename TObjectRef, typename>
1893 inline TVMRetValue& TVMRetValue::operator=(TObjectRef other) {
1894  using ContainerType = typename TObjectRef::ContainerType;
1895  const Object* ptr = other.get();
1896  if (ptr != nullptr) {
1897  if (std::is_base_of<NDArray::ContainerType, ContainerType>::value ||
1898  (std::is_base_of<ContainerType, NDArray::ContainerType>::value &&
1900  return operator=(NDArray(std::move(other.data_)));
1901  }
1902  if (std::is_base_of<Module::ContainerType, ContainerType>::value ||
1903  (std::is_base_of<ContainerType, Module::ContainerType>::value &&
1904  ptr->IsInstance<Module::ContainerType>())) {
1905  return operator=(Module(std::move(other.data_)));
1906  }
1907  SwitchToObject(kTVMObjectHandle, std::move(other.data_));
1908  } else {
1909  SwitchToPOD(kTVMNullptr);
1910  value_.v_handle = nullptr;
1911  }
1912  return *this;
1913 }
1914 
1915 template <typename T, typename>
1916 inline TVMArgValue::operator T() const {
1917  return PackedFuncValueConverter<T>::From(*this);
1918 }
1919 
1920 template <typename T, typename>
1921 inline TVMMovableArgValue_::operator T() const {
1922  if (type_code_ == kTVMObjectRValueRefArg) {
1923  auto** ref = static_cast<Object**>(value_.v_handle);
1924  if (ObjectTypeChecker<T>::Check(*ref)) {
1926  }
1927  }
1928  // fallback
1929  return PackedFuncValueConverter<T>::From(AsArgValue());
1930 }
1931 
1932 template <typename T, typename>
1933 inline TVMRetValue::operator T() const {
1934  return PackedFuncValueConverter<T>::From(*this);
1935 }
1936 
1937 inline PackedFunc Module::GetFunction(const std::string& name, bool query_imports) {
1938  return (*this)->GetFunction(name, query_imports);
1939 }
1940 
1941 // specializations of PackedFuncValueConverter
1942 template <>
1944  static String From(const TVMArgValue& val) {
1945  if (val.IsObjectRef<tvm::runtime::String>()) {
1946  return val.AsObjectRef<tvm::runtime::String>();
1947  } else {
1948  return tvm::runtime::String(val.operator std::string());
1949  }
1950  }
1951 
1952  static String From(const TVMRetValue& 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 
1961 template <typename T>
1963  static Optional<T> From(const TVMArgValue& val) {
1964  if (val.type_code() == kTVMNullptr) return Optional<T>(nullptr);
1966  }
1967  static Optional<T> From(const TVMRetValue& val) {
1968  if (val.type_code() == kTVMNullptr) return Optional<T>(nullptr);
1970  }
1971 };
1972 
1973 inline bool String::CanConvertFrom(const TVMArgValue& val) {
1974  return val.type_code() == kTVMStr || val.IsObjectRef<tvm::runtime::String>();
1975 }
1976 
1977 inline TVMArgValue::operator DLDataType() const {
1978  if (String::CanConvertFrom(*this)) {
1979  return String2DLDataType(PackedFuncValueConverter<String>::From(*this).operator std::string());
1980  }
1981  // None type
1982  if (type_code_ == kTVMNullptr) {
1983  DLDataType t;
1984  t.code = kTVMOpaqueHandle;
1985  t.bits = 0;
1986  t.lanes = 0;
1987  return t;
1988  }
1989  TVM_CHECK_TYPE_CODE(type_code_, kTVMDataType);
1990  return value_.v_type;
1991 }
1992 
1993 inline TVMArgValue::operator DataType() const { return DataType(operator DLDataType()); }
1994 
1995 } // namespace runtime
1996 } // namespace tvm
1997 #endif // TVM_RUNTIME_PACKED_FUNC_H_
static TObjectRef From(const TVMArgValue &val)
Convert a TObjectRef from an argument value.
Definition: packed_func.h:1102
const char * ArgTypeCode2Str(int type_code)
Convert argument type code to string.
Definition: packed_func.h:1225
int num_args
Definition: packed_func.h:395
TVMArgValue()
default constructor
Definition: packed_func.h:649
static bool Check(const Object *ptr)
Definition: packed_func.h:489
TVMRetValue & operator=(std::string value)
Definition: packed_func.h:900
array node content in array
Definition: array.h:38
Return Value container, Unlike TVMArgValue, which only holds reference and do not delete the underlyi...
Definition: packed_func.h:799
PackedFunc GetFunction(const std::string &name, bool query_imports=false)
Get packed function from current module by name.
Definition: packed_func.h:1937
static void FFIDecRef(TVMArrayHandle handle)
DecRef resource managed by an FFI array handle.
Definition: ndarray.h:429
TVMRetValue & operator=(TVMMovableArgValue_ &&other)
Definition: packed_func.h:940
TVM_ALWAYS_INLINE void operator()(size_t i, TObjectRef &&value) const
Definition: packed_func.h:1596
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. The managed resources are moved to the front-end. The front end should take charge in managing them.
Definition: packed_func.h:953
PrimExpr min(PrimExpr a, PrimExpr b, Span span=Span())
take minimum of two values
A custom smart pointer for Object.
Definition: object.h:358
TVMArgs(const TVMValue *values, const int *type_codes, int num_args)
constructor
Definition: packed_func.h:402
A PackedFunc wrapper to provide typed function signature. It is backed by a PackedFunc internally...
Definition: packed_func.h:227
static void Call(const PackedFuncObj *obj, TVMArgs args, TVMRetValue *rv)
Extracting the callable method from callable type.
Definition: packed_func.h:1211
TVM_ALWAYS_INLINE void operator()(size_t i, const char *value) const
Definition: packed_func.h:1559
bool operator!=(std::nullptr_t null) const
Definition: packed_func.h:180
TVMRetValue & operator=(bool value)
Definition: packed_func.h:895
int type_code_
the type code
Definition: packed_func.h:637
Internal base class to handle conversion to POD values.
Definition: packed_func.h:541
static constexpr const uint32_t _type_index
Definition: packed_func.h:77
std::string DLDataType2String(DLDataType t)
convert a TVM type to string.
Definition: data_type.h:332
void * v_handle
Definition: c_runtime_api.h:147
const PackedFunc & packed() const
Definition: packed_func.h:358
Definition: c_runtime_api.h:124
runtime implementation for LibTorch/TorchScript.
Definition: analyzer.h:36
struct TVMArgs TVMArgs
static Optional< String > CheckAndGetMismatch(const Object *ptr)
Definition: packed_func.h:504
TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue *rv) const
Call the function in packed format.
Definition: packed_func.h:1220
Definition: c_runtime_api.h:119
TVMMovableArgValue_(TVMValue value, int type_code)
Definition: packed_func.h:711
TVM_ALWAYS_INLINE void operator()(size_t i, DLTensor *value) const
Definition: packed_func.h:1544
~TVMRetValue()
destructor
Definition: packed_func.h:812
Definition: c_runtime_api.h:115
const TVMValue * values
Definition: packed_func.h:393
Definition: c_runtime_api.h:120
TVMArgValue operator[](int i) const
Get i-th argument.
Definition: packed_func.h:1202
size_t size
Definition: c_runtime_api.h:159
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
Union type of values being passed through API and function calls.
Definition: c_runtime_api.h:144
base class of all object containers.
Definition: object.h:167
Definition: c_runtime_api.h:118
const char * data
Definition: c_runtime_api.h:158
Object * TVMArrayHandleToObjectHandle(TVMArrayHandle handle)
Definition: ndarray.h:433
TVMValue value_
The value.
Definition: packed_func.h:635
TVMRetValue()
default constructor
Definition: packed_func.h:802
Managed NDArray. The array is backed by reference counted blocks.
Definition: ndarray.h:59
TVMRetValue & operator=(int value)
Definition: packed_func.h:879
static void FFIClearAfterMove(ObjectRef *ref)
Clear the object ref data field without DecRef after we successfully moved the field.
Definition: object.h:592
TVMRetValue & operator=(TVMRetValue &&other)
Definition: packed_func.h:852
Byte array type used to pass in byte array When kTVMBytes is used as data type.
Definition: c_runtime_api.h:157
TVMRetValue & operator=(TVMByteArray value)
Definition: packed_func.h:904
TypedPackedFunc(const FLambda &typed_lambda)
construct from a lambda function with the same signature.
Definition: packed_func.h:309
Internal struct for extracting the callable method from callable type.
Definition: packed_func.h:86
void DecRef()
developer function, decrease reference counter.
Definition: object.h:801
bool IsInstance() const
Definition: object.h:829
TVMRetValue & operator=(const TVMArgValue &other)
Definition: packed_func.h:936
TVMRetValue & operator=(double value)
Definition: packed_func.h:859
TVM_ALWAYS_INLINE void operator()(size_t i, const TVMByteArray &value) const
Definition: packed_func.h:1568
Runtime Array container types.
Definition: packed_func.h:38
Internal auxiliary struct for TypedPackedFunc to indicate a movable argument.
Definition: packed_func.h:709
static bool Check(const Object *ptr)
Definition: packed_func.h:521
TVM_ALWAYS_INLINE void operator()(size_t i, T value) const
Definition: packed_func.h:1519
static Optional< T > From(const TVMRetValue &val)
Definition: packed_func.h:1967
A device-independent managed NDArray abstraction.
DLDataType String2DLDataType(std::string s)
convert a string to TVM type.
Definition: data_type.h:339
static String From(const TVMRetValue &val)
Definition: packed_func.h:1952
static ObjectPtr< Object > FFIDataFromHandle(TVMArrayHandle handle)
Construct NDArray&#39;s Data field from array handle in FFI.
Definition: ndarray.h:416
Type traits for runtime type check during FFI conversion.
Definition: packed_func.h:430
bool IsObjectRef() const
Definition: packed_func.h:1792
static Optional< T > From(const TVMArgValue &val)
Definition: packed_func.h:1963
Runtime primitive data type.
Definition: data_type.h:41
bool defined() const
Definition: object.h:544
TVM_ALWAYS_INLINE void operator()(size_t i, Device value) const
Definition: packed_func.h:1548
Arguments into TVM functions.
Definition: packed_func.h:391
TVMRetValue(TVMRetValue &&other)
move constructor from another return value.
Definition: packed_func.h:807
TSelf & operator=(FLambda typed_lambda)
copy assignment operator from typed lambda
Definition: packed_func.h:331
PackedFunc(TCallable data)
Constructing a packed function from a callable type whose signature is consistent with PackedFunc ...
Definition: packed_func.h:151
T value() const
Definition: optional.h:92
Array, container representing a contiguous sequence of ObjectRefs.
Definition: array.h:270
Definition: c_runtime_api.h:123
TypedPackedFunc(const FLambda &typed_lambda, std::string name)
construct from a lambda function with the same signature.
Definition: packed_func.h:286
TVM_ALWAYS_INLINE void operator()(size_t i, uint64_t value) const
Definition: packed_func.h:1523
static std::string TypeName()
Definition: packed_func.h:500
TSelf & operator=(PackedFunc packed)
copy assignment operator from PackedFunc.
Definition: packed_func.h:340
runtime::PackedFunc.
Definition: object.h:74
TVMRetValue & operator=(Module m)
Definition: packed_func.h:920
Object container class that backs NDArray.
Definition: ndarray.h:294
TVMRetValue & operator=(PackedFunc f)
Definition: packed_func.h:924
PackedFuncObj(FCallPacked *f_call_pack)
Constructing a packed function object from a function pointer.
Definition: packed_func.h:103
TVM_ALWAYS_INLINE void operator()(size_t i, const TObjectRef &value) const
Definition: packed_func.h:1589
const int * type_codes
Definition: packed_func.h:394
ObjectPtr< Object > data_
Internal pointer that backs the reference.
Definition: object.h:574
TVMRetValue & operator=(DLDataType t)
Definition: packed_func.h:889
bool operator==(std::nullptr_t null) const
Definition: packed_func.h:178
TObjectRef AsObjectRef() const
Definition: packed_func.h:1823
PrimExpr max(PrimExpr a, PrimExpr b, Span span=Span())
take maximum of two values
TVM_ALWAYS_INLINE void operator()(size_t i, const std::string &value) const
Definition: packed_func.h:1564
Reference to string objects.
Definition: string.h:124
void(const PackedFuncObj *, TVMArgs, TVMRetValue *) FCallPacked
The internal callable function type.
Definition: packed_func.h:97
Please refer to TypedPackedFunc<R(Args..)>.
Definition: packed_func.h:60
Object container class that backs PackedFunc.
Definition: packed_func.h:68
TVM_ALWAYS_INLINE void operator()(size_t i, DataType dtype) const
Definition: packed_func.h:1556
TVMPODValue_(TVMValue value, int type_code)
Definition: packed_func.h:632
#define TVM_DEFINE_OBJECT_REF_METHODS(TypeName, ParentType, ObjectName)
Definition: object.h:713
TVM_ALWAYS_INLINE void operator()(size_t i, double value) const
Definition: packed_func.h:1528
TVM_ALWAYS_INLINE void operator()(size_t i, std::nullptr_t value) const
Definition: packed_func.h:1532
T * ptr() const
return handle as specific pointer type.
Definition: packed_func.h:617
DLDevice Device
Definition: ndarray.h:43
Definition: c_runtime_api.h:113
const Object * get() const
Definition: object.h:546
TVMRetValue & operator=(const TypedPackedFunc< FType > &f)
Definition: packed_func.h:929
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
Object & operator=(const Object &other)
Definition: object.h:251
TVMRetValue & operator=(DLDevice value)
Definition: packed_func.h:884
TVM_DECLARE_FINAL_OBJECT_INFO(PackedFuncObj, Object)
TStorage callable_
Type-erased filed for storing callable object.
Definition: packed_func.h:127
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
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:1973
Base class of all object reference.
Definition: object.h:511
Base container of module.
Definition: module.h:113
TVM_ALWAYS_INLINE void CallPacked(TVMArgs args, TVMRetValue *rv) const
Call the function in packed format.
Definition: packed_func.h:1216
int size() const
Definition: packed_func.h:1208
std::string GetTypeKey() const
Definition: object.h:180
TVMRetValue & operator=(const DataType &other)
Definition: packed_func.h:894
Shared content of all specializations of hash map.
Definition: map.h:174
TVMRetValue & operator=(int64_t value)
Definition: packed_func.h:874
A managed object in the TVM runtime.
TVM_ALWAYS_INLINE void operator()(size_t i, const TVMArgValue &value) const
Definition: packed_func.h:1536
static TVMArrayHandle FFIGetHandle(const ObjectRef &nd)
Get FFI Array handle from ndarray.
Definition: ndarray.h:421
void operator()(size_t i, const TVMRetValue &value) const
Definition: packed_func.h:1576
Runtime container of the functions generated by TVM, This is used to support dynamically link...
bool operator==(std::nullptr_t null) const
Definition: packed_func.h:360
Module container of TVM.
Definition: module.h:50
bool operator!=(std::nullptr_t null) const
Definition: packed_func.h:362
Map container of NodeRef->NodeRef in DSL graph. Map implements copy on write semantics, which means map is mutable but copy will happen when array is referenced in more than two places.
Definition: map.h:1268
static std::string TypeIndex2Key(uint32_t tindex)
Get the type key of the corresponding index from runtime.
PrimExpr ret(PrimExpr value, Span span=Span())
Return the value.
Runtime Map container types.
static String From(const TVMArgValue &val)
Definition: packed_func.h:1944
static std::string TypeName()
Definition: packed_func.h:531
Definition: c_runtime_api.h:114
int type_code() const
Definition: packed_func.h:610
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
A single argument value to PackedFunc. Containing both type_code and TVMValue.
Definition: packed_func.h:646
Packed function is a type-erased function. The arguments are passed by packed format.
Definition: packed_func.h:138
Optional container that to represent to a Nullable variant of T.
Definition: optional.h:51
const TVMValue & value() const
Definition: packed_func.h:691
FCallPacked * f_call_packed_
Internal callable function pointer used to call the packed function.
Definition: packed_func.h:109
TVMRetValue operator()(Args &&... args) const
Call packed function by directly passing in unpacked format.
Definition: packed_func.h:1610
PackedFuncObj()=delete
Delete the default constructor explicitly.
Definition: packed_func.h:1514
constexpr runtime::NullOptType NullOpt
Definition: optional.h:160
TVMArgsSetter(TVMValue *values, int *type_codes)
Definition: packed_func.h:1516
static constexpr const char * _type_key
Definition: packed_func.h:78
Derived object class for constructing PackedFuncObj.
Definition: packed_func.h:114
TypedPackedFunc(std::nullptr_t null)
constructor from null
Definition: packed_func.h:234
TVMRetValue(const TVMRetValue &other)
Definition: packed_func.h:828
PackedFunc(std::nullptr_t null)
Constructor from null.
Definition: packed_func.h:141
const TVMValue & value() const
Definition: packed_func.h:976
Definition: c_runtime_api.h:116
TVMArgValue(TVMValue value, int type_code)
constructor
Definition: packed_func.h:655
TVMRetValue & operator=(const TVMRetValue &other)
Definition: packed_func.h:932
#define TVM_CHECK_TYPE_CODE(CODE, T)
Definition: packed_func.h:422
TVM_ALWAYS_INLINE void operator()(size_t i, void *value) const
Definition: packed_func.h:1540
std::string() FSig
Using static function to output TypedPackedFunc signature.
Definition: packed_func.h:186
Definition: c_runtime_api.h:122
PackedFuncSubObj(TCallable callable)
Derived object class for constructing PackedFuncObj.
Definition: packed_func.h:124
TVMRetValue & operator=(std::nullptr_t value)
Definition: packed_func.h:864
static Optional< String > CheckAndGetMismatch(const Object *ptr)
Definition: packed_func.h:472
runtime::DataType DataType
Definition: data_type.h:389
Definition: c_runtime_api.h:121
TVMRetValue & operator=(NDArray other)
Definition: packed_func.h:908
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
Definition: c_runtime_api.h:117
Definition: packed_func.h:62
TypedPackedFunc()
default constructor
Definition: packed_func.h:232
Internal auxiliary struct for TypedPackedFunc to indicate a movable argument with additional context ...
Definition: packed_func.h:754
TVMRetValue & operator=(void *value)
Definition: packed_func.h:869
TVM_ALWAYS_INLINE void operator()(size_t i, const TypedPackedFunc< FType > &value) const
Definition: packed_func.h:1573
TVM_ALWAYS_INLINE void operator()(size_t i, DLDataType value) const
Definition: packed_func.h:1552
TVMPODValue_()
Definition: packed_func.h:631