Program Listing for File c_api.h

Program Listing for File c_api.h#

Return to documentation for file (tvm/ffi/c_api.h)

v0 = AddNode(x, 1)
v1 = AddNode(x, 1)
v2 = AddNode(v0, v0)
v3 = AddNode(v1, v0)
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * \file tvm/ffi/c_api.h
 * \brief This file defines the C convention of the FFI convention
 */
#ifndef TVM_FFI_C_API_H_
#define TVM_FFI_C_API_H_

#include <dlpack/dlpack.h>
#include <stdint.h>

// Macros to do weak linking
#ifdef _MSC_VER
#define TVM_FFI_WEAK __declspec(selectany)
#else
#define TVM_FFI_WEAK __attribute__((weak))
#endif

// Defines two macros
// TVM_FFI_DLL: marks the function as a DLL export/import
//              depending on whether TVM_FFI_EXPORTS is defined
// TVM_FFI_DLL_EXPORT: always marks the function as a DLL export
#if !defined(TVM_FFI_DLL) && defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
#define TVM_FFI_DLL EMSCRIPTEN_KEEPALIVE
#define TVM_FFI_DLL_EXPORT EMSCRIPTEN_KEEPALIVE
#endif
#if !defined(TVM_FFI_DLL) && defined(_MSC_VER)
#ifdef TVM_FFI_EXPORTS
#define TVM_FFI_DLL __declspec(dllexport)
#else
#define TVM_FFI_DLL __declspec(dllimport)
#endif
#define TVM_FFI_DLL_EXPORT __declspec(dllexport)
#endif
#ifndef TVM_FFI_DLL
#define TVM_FFI_DLL __attribute__((visibility("default")))
#define TVM_FFI_DLL_EXPORT __attribute__((visibility("default")))
#endif

#ifdef __cplusplus
extern "C" {
#endif

// TODO(tqchen): remove this once dlpack.h is updated
typedef struct DLManagedTensorVersioned DLManagedTensorVersioned;

/*
 * \brief C-style Allocator that allocates memory for a DLPack tensor.
 * \param prototype The prototype DLTensor to offer details about device and shape.
 * \param out The output DLManagedTensorVersioned.
 * \param error_ctx The context to set the error.
 * \param SetError The function to set the error.
 * \return 0 on success, -1 on failure.
 *         call SetError(error_ctx, kind, message) to set the error kind and message.
 * \note Error propagation via SetError.
 */
typedef int (*DLPackTensorAllocator)(                                         //
    DLTensor* prototype, DLManagedTensorVersioned** out, void* error_ctx,     //
    void (*SetError)(void* error_ctx, const char* kind, const char* message)  //
);

#ifdef __cplusplus
enum TVMFFITypeIndex : int32_t {
#else
typedef enum {
#endif
  /*
   * \brief The root type of all FFI objects.
   *
   * We include it so TypeIndex captures all possible runtime values.
   * `kTVMFFIAny` code will never appear in Any::type_index.
   * However, it may appear in field annotations during reflection.
   */
  kTVMFFIAny = -1,
  // [Section] On-stack POD and special types: [0, kTVMFFIStaticObjectBegin)
  // N.B. `kTVMFFIRawStr` is a string backed by a `\0`-terminated char array,
  // which is not owned by TVMFFIAny. It is required that the following
  // invariant holds:
  // - `Any::type_index` is never `kTVMFFIRawStr`
  // - `AnyView::type_index` can be `kTVMFFIRawStr`
  //
  kTVMFFINone = 0,
  kTVMFFIInt = 1,
  kTVMFFIBool = 2,
  kTVMFFIFloat = 3,
  kTVMFFIOpaquePtr = 4,
  kTVMFFIDataType = 5,
  kTVMFFIDevice = 6,
  kTVMFFIDLTensorPtr = 7,
  kTVMFFIRawStr = 8,
  kTVMFFIByteArrayPtr = 9,
  kTVMFFIObjectRValueRef = 10,
  kTVMFFISmallStr = 11,
  kTVMFFISmallBytes = 12,
  kTVMFFIStaticObjectBegin = 64,
  kTVMFFIObject = 64,
  kTVMFFIStr = 65,
  kTVMFFIBytes = 66,
  kTVMFFIError = 67,
  kTVMFFIFunction = 68,
  kTVMFFIShape = 69,
  kTVMFFITensor = 70,
  kTVMFFIArray = 71,
  //----------------------------------------------------------------
  // more complex objects
  //----------------------------------------------------------------
  kTVMFFIMap = 72,
  kTVMFFIModule = 73,
  kTVMFFIOpaquePyObject = 74,
  kTVMFFIStaticObjectEnd,
  // [Section] Dynamic Boxed: [kTVMFFIDynObjectBegin, +oo)
  kTVMFFIDynObjectBegin = 128
#ifdef __cplusplus
};
#else
} TVMFFITypeIndex;
#endif

typedef void* TVMFFIObjectHandle;

#ifdef __cplusplus
enum TVMFFIObjectDeleterFlagBitMask : int32_t {
#else
typedef enum {
#endif
  kTVMFFIObjectDeleterFlagBitMaskStrong = 1 << 0,
  kTVMFFIObjectDeleterFlagBitMaskWeak = 1 << 1,
  kTVMFFIObjectDeleterFlagBitMaskBoth =
      (kTVMFFIObjectDeleterFlagBitMaskStrong | kTVMFFIObjectDeleterFlagBitMaskWeak),
#ifdef __cplusplus
};
#else
} TVMFFIObjectDeleterFlagBitMask;
#endif

typedef struct {
  uint64_t combined_ref_count;
  int32_t type_index;
  uint32_t __padding;
#if !defined(TVM_FFI_DOXYGEN_MODE)
  union {
#endif
    void (*deleter)(void* self, int flags);
    int64_t __ensure_align;
#if !defined(TVM_FFI_DOXYGEN_MODE)
  };
#endif
} TVMFFIObject;

typedef struct {
  int32_t type_index;
#if !defined(TVM_FFI_DOXYGEN_MODE)
  union {  // 4 bytes
#endif
    uint32_t zero_padding;
    uint32_t small_str_len;
#if !defined(TVM_FFI_DOXYGEN_MODE)
  };
#endif
#if !defined(TVM_FFI_DOXYGEN_MODE)
  union {  // 8 bytes
#endif
    int64_t v_int64;
    double v_float64;
    void* v_ptr;
    const char* v_c_str;
    TVMFFIObject* v_obj;
    DLDataType v_dtype;
    DLDevice v_device;
    char v_bytes[8];
    uint64_t v_uint64;
#if !defined(TVM_FFI_DOXYGEN_MODE)
  };
#endif
} TVMFFIAny;

typedef struct {
  const char* data;
  size_t size;
} TVMFFIByteArray;

typedef struct {
  const int64_t* data;
  size_t size;
} TVMFFIShapeCell;

#ifdef __cplusplus
enum TVMFFIBacktraceUpdateMode : int32_t {
#else
typedef enum {
#endif
  kTVMFFIBacktraceUpdateModeReplace = 0,
  kTVMFFIBacktraceUpdateModeAppend = 1,
#ifdef __cplusplus
};
#else
} TVMFFIBacktraceUpdateMode;
#endif

typedef struct {
  TVMFFIByteArray kind;
  TVMFFIByteArray message;
  TVMFFIByteArray backtrace;
  void (*update_backtrace)(TVMFFIObjectHandle self, const TVMFFIByteArray* backtrace,
                           int32_t update_mode);
} TVMFFIErrorCell;

typedef int (*TVMFFISafeCallType)(void* handle, const TVMFFIAny* args, int32_t num_args,
                                  TVMFFIAny* result);

typedef struct {
  TVMFFISafeCallType safe_call;
  void* cpp_call;
} TVMFFIFunctionCell;

typedef struct {
  void* handle;
} TVMFFIOpaqueObjectCell;

//------------------------------------------------------------
// Section: Basic object API
//------------------------------------------------------------
TVM_FFI_DLL int TVMFFIObjectIncRef(TVMFFIObjectHandle obj);

TVM_FFI_DLL int TVMFFIObjectDecRef(TVMFFIObjectHandle obj);

TVM_FFI_DLL int TVMFFIObjectCreateOpaque(void* handle, int32_t type_index,
                                         void (*deleter)(void* handle), TVMFFIObjectHandle* out);

TVM_FFI_DLL int TVMFFITypeKeyToIndex(const TVMFFIByteArray* type_key, int32_t* out_tindex);

//-----------------------------------------------------------------------
// Section: Basic function calling API for function implementation
//-----------------------------------------------------------------------
TVM_FFI_DLL int TVMFFIFunctionCreate(void* self, TVMFFISafeCallType safe_call,
                                     void (*deleter)(void* self), TVMFFIObjectHandle* out);

TVM_FFI_DLL int TVMFFIFunctionGetGlobal(const TVMFFIByteArray* name, TVMFFIObjectHandle* out);

TVM_FFI_DLL int TVMFFIAnyViewToOwnedAny(const TVMFFIAny* any_view, TVMFFIAny* out);

TVM_FFI_DLL int TVMFFIFunctionCall(TVMFFIObjectHandle func, TVMFFIAny* args, int32_t num_args,
                                   TVMFFIAny* result);

TVM_FFI_DLL void TVMFFIErrorMoveFromRaised(TVMFFIObjectHandle* result);

TVM_FFI_DLL void TVMFFIErrorSetRaised(TVMFFIObjectHandle error);

TVM_FFI_DLL void TVMFFIErrorSetRaisedFromCStr(const char* kind, const char* message);

TVM_FFI_DLL int TVMFFIErrorCreate(const TVMFFIByteArray* kind, const TVMFFIByteArray* message,
                                  const TVMFFIByteArray* backtrace, TVMFFIObjectHandle* out);

//------------------------------------------------------------
// Section: DLPack support APIs
//------------------------------------------------------------
TVM_FFI_DLL int TVMFFITensorFromDLPack(DLManagedTensor* from, int32_t require_alignment,
                                       int32_t require_contiguous, TVMFFIObjectHandle* out);

TVM_FFI_DLL int TVMFFITensorToDLPack(TVMFFIObjectHandle from, DLManagedTensor** out);

TVM_FFI_DLL int TVMFFITensorFromDLPackVersioned(DLManagedTensorVersioned* from,
                                                int32_t require_alignment,
                                                int32_t require_contiguous,
                                                TVMFFIObjectHandle* out);

TVM_FFI_DLL int TVMFFITensorToDLPackVersioned(TVMFFIObjectHandle from,
                                              DLManagedTensorVersioned** out);
//---------------------------------------------------------------
// Section: string/bytes support APIs.
// These APIs are used to simplify the string/bytes construction
//---------------------------------------------------------------
TVM_FFI_DLL int TVMFFIStringFromByteArray(const TVMFFIByteArray* input, TVMFFIAny* out);

TVM_FFI_DLL int TVMFFIBytesFromByteArray(const TVMFFIByteArray* input, TVMFFIAny* out);

//---------------------------------------------------------------
// Section: dtype string support APIs.
// These APIs are used to simplify the dtype printings during FFI
//---------------------------------------------------------------

TVM_FFI_DLL int TVMFFIDataTypeFromString(const TVMFFIByteArray* str, DLDataType* out);

TVM_FFI_DLL int TVMFFIDataTypeToString(const DLDataType* dtype, TVMFFIAny* out);

//------------------------------------------------------------
// Section: Type reflection support APIs
//
// The reflec
//------------------------------------------------------------
typedef int (*TVMFFIFieldGetter)(void* field, TVMFFIAny* result);

typedef int (*TVMFFIFieldSetter)(void* field, const TVMFFIAny* value);

typedef int (*TVMFFIObjectCreator)(TVMFFIObjectHandle* result);

#ifdef __cplusplus
enum TVMFFIFieldFlagBitMask : int32_t {
#else
typedef enum {
#endif
  kTVMFFIFieldFlagBitMaskWritable = 1 << 0,
  kTVMFFIFieldFlagBitMaskHasDefault = 1 << 1,
  kTVMFFIFieldFlagBitMaskIsStaticMethod = 1 << 2,
  kTVMFFIFieldFlagBitMaskSEqHashIgnore = 1 << 3,
  kTVMFFIFieldFlagBitMaskSEqHashDef = 1 << 4,
#ifdef __cplusplus
};
#else
} TVMFFIFieldFlagBitMask;
#endif

#ifdef __cplusplus
enum TVMFFISEqHashKind : int32_t {
#else
typedef enum {
#endif
  kTVMFFISEqHashKindUnsupported = 0,
  kTVMFFISEqHashKindTreeNode = 1,
  kTVMFFISEqHashKindFreeVar = 2,
  kTVMFFISEqHashKindDAGNode = 3,
  kTVMFFISEqHashKindConstTreeNode = 4,
  kTVMFFISEqHashKindUniqueInstance = 5,
#ifdef __cplusplus
};
#else
} TVMFFISEqHashKind;
#endif

typedef struct {
  TVMFFIByteArray name;
  TVMFFIByteArray doc;
  TVMFFIByteArray metadata;
  int64_t flags;
  int64_t size;
  int64_t alignment;
  int64_t offset;
  TVMFFIFieldGetter getter;
  TVMFFIFieldSetter setter;
  TVMFFIAny default_value;
  int32_t field_static_type_index;
} TVMFFIFieldInfo;

typedef struct {
  TVMFFIByteArray name;
  TVMFFIByteArray doc;
  // Rationale: We separate the docstring from the metadata since docstrings
  // can be unstructured and sometimes large, while metadata can be focused
  // on storing structured information.
  TVMFFIByteArray metadata;
  int64_t flags;
  TVMFFIAny method;
} TVMFFIMethodInfo;

typedef struct {
  TVMFFIByteArray doc;
  TVMFFIObjectCreator creator;
  int32_t total_size;
  TVMFFISEqHashKind structural_eq_hash_kind;
} TVMFFITypeMetadata;

typedef struct {
  const TVMFFIAny* data;
  size_t size;
} TVMFFITypeAttrColumn;

#ifdef __cplusplus
struct TVMFFITypeInfo {
#else
typedef struct TVMFFITypeInfo {
#endif
  int32_t type_index;
  int32_t type_depth;
  TVMFFIByteArray type_key;
  const struct TVMFFITypeInfo** type_ancestors;
  // The following fields are used for reflection
  uint64_t type_key_hash;
  int32_t num_fields;
  int32_t num_methods;
  const TVMFFIFieldInfo* fields;
  const TVMFFIMethodInfo* methods;
  const TVMFFITypeMetadata* metadata;
#ifdef __cplusplus
};
#else
} TVMFFITypeInfo;
#endif

TVM_FFI_DLL int TVMFFIFunctionSetGlobal(const TVMFFIByteArray* name, TVMFFIObjectHandle f,
                                        int allow_override);

TVM_FFI_DLL int TVMFFIFunctionSetGlobalFromMethodInfo(const TVMFFIMethodInfo* method_info,
                                                      int allow_override);

TVM_FFI_DLL int TVMFFITypeRegisterField(int32_t type_index, const TVMFFIFieldInfo* info);

TVM_FFI_DLL int TVMFFITypeRegisterMethod(int32_t type_index, const TVMFFIMethodInfo* info);

TVM_FFI_DLL int TVMFFITypeRegisterMetadata(int32_t type_index, const TVMFFITypeMetadata* metadata);

TVM_FFI_DLL int TVMFFITypeRegisterAttr(int32_t type_index, const TVMFFIByteArray* attr_name,
                                       const TVMFFIAny* attr_value);

TVM_FFI_DLL const TVMFFITypeAttrColumn* TVMFFIGetTypeAttrColumn(const TVMFFIByteArray* attr_name);

//------------------------------------------------------------
// Section: Backend noexcept functions for internal use
//
// These functions are used internally and do not throw error
// instead the error will be logged and abort the process
// These are function are being called in startup or exit time
// so exception handling do not apply
//------------------------------------------------------------
TVM_FFI_DLL const TVMFFIByteArray* TVMFFIBacktrace(const char* filename, int lineno,
                                                   const char* func, int cross_ffi_boundary);

TVM_FFI_DLL int32_t TVMFFITypeGetOrAllocIndex(const TVMFFIByteArray* type_key,
                                              int32_t static_type_index, int32_t type_depth,
                                              int32_t num_child_slots,
                                              int32_t child_slots_can_overflow,
                                              int32_t parent_type_index);

TVM_FFI_DLL const TVMFFITypeInfo* TVMFFIGetTypeInfo(int32_t type_index);

#ifdef __cplusplus
}  // TVM_FFI_EXTERN_C
#endif

//---------------------------------------------------------------
// The following API defines static object attribute accessors
// for language bindings.
//
// They are defined in C++ inline functions for cleaner code.
// Note that they only have to do with address offset computation.
// So they can always be reimplemented in bindings when c++ is
// not available or when binding only wants to refer to the dll.
//----------------------------------------------------------------
#ifdef __cplusplus
inline int32_t TVMFFIObjectGetTypeIndex(TVMFFIObjectHandle obj) {
  return static_cast<TVMFFIObject*>(obj)->type_index;
}

inline TVMFFIByteArray TVMFFISmallBytesGetContentByteArray(const TVMFFIAny* value) {
  return TVMFFIByteArray{value->v_bytes, static_cast<size_t>(value->small_str_len)};
}

inline TVMFFIByteArray* TVMFFIBytesGetByteArrayPtr(TVMFFIObjectHandle obj) {
  return reinterpret_cast<TVMFFIByteArray*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
}

inline TVMFFIErrorCell* TVMFFIErrorGetCellPtr(TVMFFIObjectHandle obj) {
  return reinterpret_cast<TVMFFIErrorCell*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
}

inline TVMFFIFunctionCell* TVMFFIFunctionGetCellPtr(TVMFFIObjectHandle obj) {
  return reinterpret_cast<TVMFFIFunctionCell*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
}

inline TVMFFIOpaqueObjectCell* TVMFFIOpaqueObjectGetCellPtr(TVMFFIObjectHandle obj) {
  return reinterpret_cast<TVMFFIOpaqueObjectCell*>(reinterpret_cast<char*>(obj) +
                                                   sizeof(TVMFFIObject));
}

inline TVMFFIShapeCell* TVMFFIShapeGetCellPtr(TVMFFIObjectHandle obj) {
  return reinterpret_cast<TVMFFIShapeCell*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
}

inline DLTensor* TVMFFITensorGetDLTensorPtr(TVMFFIObjectHandle obj) {
  return reinterpret_cast<DLTensor*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
}

inline DLDevice TVMFFIDLDeviceFromIntPair(int32_t device_type, int32_t device_id) {
  return DLDevice{static_cast<DLDeviceType>(device_type), device_id};
}
#endif  // __cplusplus
#endif  // TVM_FFI_C_API_H_