tqchen commented on code in PR #402:
URL: https://github.com/apache/tvm-ffi/pull/402#discussion_r2687487736


##########
docs/concepts/abi_overview.rst:
##########
@@ -0,0 +1,527 @@
+..  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.
+
+ABI Overview
+============
+
+.. hint::
+
+    Authoritative ABI specifications are defined in
+
+    - C header `tvm/ffi/c_api.h 
<https://github.com/apache/tvm-ffi/blob/main/include/tvm/ffi/c_api.h>`_, which 
contains the core ABI, and
+    - C header `tvm/ffi/extra/c_env_api.h 
<https://github.com/apache/tvm-ffi/blob/main/include/tvm/ffi/extra/c_env_api.h>`_,
 which contains extra support features.
+
+The TVM-FFI ABI is designed around the following key principles:
+
+- **Minimal and efficient.** Keep things simple and deliver close-to-metal 
performance.
+- **Stability guarantee.** The ABI remains stable across compiler versions and 
is independent of host languages or frameworks.
+- **Expressive for machine learning.** Native support for tensors, shapes, and 
data types commonly used in ML workloads.
+- **Extensible.** The ABI supports user-defined types and features through a 
dynamic type registration system.
+
+This tutorial covers common concepts and usage patterns of the TVM-FFI ABI, 
with low-level C code examples for precise reference.
+
+.. important::
+  C code is used for clarity, precision and friendliness to compiler builders.
+  And C code can be readily translated into code generators such as LLVM IR 
builder.
+
+Any and AnyView
+---------------
+
+.. seealso::
+
+   :doc:`any` for :cpp:class:`~tvm::ffi::Any` and 
:cpp:class:`~tvm::ffi::AnyView` usage patterns.
+
+At the core of TVM-FFI is :cpp:class:`TVMFFIAny`, a 16-byte tagged union that 
can hold any value
+recognized by the FFI system. It enables type-erased value passing across 
language boundaries.
+
+.. dropdown:: C ABI Reference: :cpp:class:`TVMFFIAny`
+   :icon: code
+
+   .. literalinclude:: ../../include/tvm/ffi/c_api.h
+      :language: c
+      :start-after: [TVMFFIAny.begin]
+      :end-before: [TVMFFIAny.end]
+      :caption: tvm/ffi/c_api.h
+
+**Ownership.** :cpp:class:`TVMFFIAny` struct can represent either an owning or 
a borrowing reference.
+These two ownership patterns are formalized by the C++ wrapper classes 
:cpp:class:`~tvm::ffi::Any` and :cpp:class:`~tvm::ffi::AnyView`,
+which have identical memory layouts but different :ref:`ownership semantics 
<any-ownership>`:
+
+- **Owning:** :cpp:class:`tvm::ffi::Any` - reference-counted, manages object 
lifetime
+- **Borrowing:** :cpp:class:`tvm::ffi::AnyView` - non-owning view, caller must 
ensure validity
+
+.. note::
+   To convert a borrowing :cpp:class:`~tvm::ffi::AnyView` to an owning 
:cpp:class:`~tvm::ffi::Any`, use :cpp:func:`TVMFFIAnyViewToOwnedAny`.
+
+**Runtime Type Index.** The ``type_index`` field identifies what kind of value 
is stored:
+
+- :ref:`Atomic POD types <any-atomic-types>` (``type_index`` < 
:cpp:enumerator:`kTVMFFIStaticObjectBegin 
<TVMFFITypeIndex::kTVMFFIStaticObjectBegin>`):
+  Stored inline in the payload union without heap allocation or reference 
counting.
+- :ref:`Object types <any-heap-allocated-objects>` (``type_index`` >= 
:cpp:enumerator:`kTVMFFIStaticObjectBegin 
<TVMFFITypeIndex::kTVMFFIStaticObjectBegin>`):
+  Stored as pointers to heap-allocated, reference-counted TVM-FFI objects.
+
+.. important::
+   The TVM-FFI type index system does not rely on C++ RTTI.
+
+
+Construct Any
+~~~~~~~~~~~~~
+
+**From atomic POD types.** The following C code constructs a 
:cpp:class:`TVMFFIAny` from an integer:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Any_AnyView.FromInt_Float.begin]
+  :end-before: [Any_AnyView.FromInt_Float.end]
+
+Set the ``type_index`` from :cpp:enum:`TVMFFITypeIndex` and assign the 
corresponding payload field.
+
+.. important::
+
+   Always zero the ``zero_padding`` field and any unused bytes in the value 
union.
+   This invariant enables direct byte comparison and hashing of 
:cpp:class:`TVMFFIAny` values.
+
+**From object types.** The following C code constructs a 
:cpp:class:`TVMFFIAny` from a heap-allocated object:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Any_AnyView.FromObjectPtr.begin]
+  :end-before: [Any_AnyView.FromObjectPtr.end]
+
+When ``IS_OWNING_ANY`` is ``true`` (owning :cpp:class:`~tvm::ffi::Any`), this 
increments the object's reference count.
+
+.. _abi-destruct-any:
+
+Destruct Any
+~~~~~~~~~~~~
+
+The following C code destroys a :cpp:class:`TVMFFIAny`:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Any_AnyView.Destroy.begin]
+  :end-before: [Any_AnyView.Destroy.end]
+
+When ``IS_OWNING_ANY`` is ``true`` (owning :cpp:class:`~tvm::ffi::Any`), this 
decrements the object's reference count.
+
+Extract from Any
+~~~~~~~~~~~~~~~~
+
+**Extract an atomic POD.** The following C code extracts an integer or float 
from a :cpp:class:`TVMFFIAny`:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Any_AnyView.GetInt_Float.begin]
+  :end-before: [Any_AnyView.GetInt_Float.end]
+
+Implicit type conversion may occur. For example, when extracting a float from 
a :cpp:class:`TVMFFIAny`
+that holds an integer, the integer is cast to a float.
+
+**Extract a DLTensor.** A :c:struct:`DLTensor` may originate from either a raw 
pointer or a heap-allocated :cpp:class:`~tvm::ffi::TensorObj`:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Any_AnyView.GetDLTensor.begin]
+  :end-before: [Any_AnyView.GetDLTensor.end]
+
+**Extract a TVM-FFI object.** TVM-FFI objects are always heap-allocated and 
reference-counted,
+with ``type_index`` >= :cpp:enumerator:`kTVMFFIStaticObjectBegin 
<TVMFFITypeIndex::kTVMFFIStaticObjectBegin>`:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Any_AnyView.GetObject.begin]
+  :end-before: [Any_AnyView.GetObject.end]
+
+To take ownership of the returned value, increment the reference count via 
:cpp:func:`TVMFFIObjectIncRef`.
+Release ownership later via :cpp:func:`TVMFFIObjectDecRef`.
+
+.. _abi-object:
+
+Object
+------
+
+.. seealso::
+
+   :doc:`object_and_class` for the object system and reflection.
+
+TVM-FFI Object (:cpp:class:`TVMFFIObject`) is the cornerstone of TVM-FFI's 
stable yet extensible type system.
+
+.. dropdown:: C ABI Reference: :cpp:class:`TVMFFIObject`
+   :icon: code
+
+   .. literalinclude:: ../../include/tvm/ffi/c_api.h
+      :language: c
+      :start-after: [TVMFFIObject.begin]
+      :end-before: [TVMFFIObject.end]
+      :caption: tvm/ffi/c_api.h
+
+All TVM-FFI objects share these characteristics:
+
+- Heap-allocated and reference-counted
+- Layout-stable 24-byte header containing reference counts, type index, and 
deleter callback
+- Type index >= :cpp:enumerator:`kTVMFFIStaticObjectBegin 
<TVMFFITypeIndex::kTVMFFIStaticObjectBegin>`
+
+**Dynamic Type System.** Classes can be registered at runtime via 
:cpp:func:`TVMFFITypeGetOrAllocIndex`,
+with support for single inheritance. See :ref:`type-checking-and-casting` for 
usage details.
+
+A small **static section** between :cpp:enumerator:`kTVMFFIStaticObjectBegin 
<TVMFFITypeIndex::kTVMFFIStaticObjectBegin>`
+and :cpp:enumerator:`kTVMFFIDynObjectBegin 
<TVMFFITypeIndex::kTVMFFIDynObjectBegin>`
+is reserved for static object types, for example,
+
+- Strings (:cpp:enumerator:`kTVMFFIStr <TVMFFITypeIndex::kTVMFFIStr>`) and 
Bytes (:cpp:enumerator:`kTVMFFIBytes <TVMFFITypeIndex::kTVMFFIBytes>`): Section 
:ref:`abi-string-and-byte`
+- Errors (:cpp:enumerator:`kTVMFFIError <TVMFFITypeIndex::kTVMFFIError>`): 
Section :ref:`abi-exception`.
+- Functions (:cpp:enumerator:`kTVMFFIFunction 
<TVMFFITypeIndex::kTVMFFIFunction>`): Section :ref:`abi-function`.
+- Tensors (:cpp:enumerator:`kTVMFFITensor <TVMFFITypeIndex::kTVMFFITensor>`): 
Section :ref:`abi-tensor`.
+- Miscellaneous:
+  Modules (:cpp:enumerator:`kTVMFFIModule <TVMFFITypeIndex::kTVMFFIModule>`),
+  Arrays (:cpp:enumerator:`kTVMFFIArray <TVMFFITypeIndex::kTVMFFIArray>`),
+  Maps (:cpp:enumerator:`kTVMFFIMap <TVMFFITypeIndex::kTVMFFIMap>`),
+  Shapes (:cpp:enumerator:`kTVMFFIShape <TVMFFITypeIndex::kTVMFFIShape>`),
+  Opaque Python objects (:cpp:enumerator:`kTVMFFIOpaquePyObject 
<TVMFFITypeIndex::kTVMFFIOpaquePyObject>`).
+
+.. _abi-object-ownership:
+
+Ownership Management
+~~~~~~~~~~~~~~~~~~~~
+
+Ownership is managed via reference counting, which includes both strong and 
weak references.
+Two C APIs manage strong reference counting:
+
+- :cpp:func:`TVMFFIObjectIncRef`: Acquire strong ownership by incrementing the 
reference count
+- :cpp:func:`TVMFFIObjectDecRef`: Release strong ownership by decrementing the 
reference count
+
+The ``deleter`` callback (:cpp:member:`TVMFFIObject::deleter`) executes when 
the strong or weak count reaches zero with different flags.
+See :ref:`object-reference-counting` for details.
+
+**Move ownership from Any/AnyView.** The following C code transfers ownership 
from an owning :cpp:class:`~tvm::ffi::Any` to an object pointer:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Object.MoveFromAny.begin]
+  :end-before: [Object.MoveFromAny.end]
+
+Since :cpp:class:`~tvm::ffi::AnyView` is non-owning (``IS_OWNING_ANY`` is 
``false``),
+acquiring ownership requires explicitly incrementing the reference count.
+
+**Release ownership.** The following C code releases ownership of a TVM-FFI 
object:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :name: ABI.Object.Destroy
+  :start-after: [Object.Destroy.begin]
+  :end-before: [Object.Destroy.end]
+
+Inheritance Checking
+~~~~~~~~~~~~~~~~~~~~
+
+TVM-FFI models single inheritance as a tree where each node points to its 
parent.
+Each type has a unique type index, and the system tracks ancestors, 
inheritance depth, and other metadata.
+This information is available via :cpp:func:`TVMFFIGetTypeInfo`.
+
+The following C code checks whether a type is a subclass of another:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Object.IsInstance.begin]
+  :end-before: [Object.IsInstance.end]
+
+.. _abi-tensor:
+
+Tensor
+------
+
+.. seealso::
+
+   :doc:`tensor` for details about TVM-FFI tensors and DLPack interoperability.
+
+TVM-FFI provides :cpp:class:`tvm::ffi::TensorObj`, a DLPack-native tensor 
class that is also a standard TVM-FFI object.
+This means tensors can be managed using the same reference counting mechanisms 
as other objects.
+
+.. dropdown:: C ABI Reference: :cpp:class:`tvm::ffi::TensorObj`
+   :icon: code
+
+   .. code-block:: cpp
+    :caption: tvm/ffi/container/tensor.h
+
+     class TensorObj : public Object, public DLTensor {
+      // no other members besides those from Object and DLTensor
+     };
+
+
+Access Tensor Metadata
+~~~~~~~~~~~~~~~~~~~~~~
+
+The following C code obtains a :c:struct:`DLTensor` pointer from a 
:cpp:class:`~tvm::ffi::TensorObj`:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Tensor.AccessDLTensor.begin]
+  :end-before: [Tensor.AccessDLTensor.end]
+
+The :c:struct:`DLTensor` pointer provides access to shape, dtype, device, data 
pointer, and other tensor metadata.
+
+Construct Tensor from DLPack
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following C code constructs a :cpp:class:`~tvm::ffi::TensorObj` from a 
:c:struct:`DLManagedTensorVersioned`:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Tensor_FromDLPack.begin]
+  :end-before: [Tensor_FromDLPack.end]
+
+.. hint::
+   TVM-FFI's Python API automatically wraps framework tensors (e.g., 
:py:class:`torch.Tensor`) as :cpp:class:`~tvm::ffi::TensorObj`,
+   so manual conversion is typically unnecessary.
+
+Destruct Tensor
+~~~~~~~~~~~~~~~
+
+As a standard TVM-FFI object, :cpp:class:`~tvm::ffi::TensorObj` follows the 
:ref:`standard destruction pattern <ABI.Object.Destroy>`.
+When the reference count reaches zero, the deleter callback 
(:cpp:member:`TVMFFIObject::deleter`) executes.
+
+Export Tensor to DLPack
+~~~~~~~~~~~~~~~~~~~~~~~
+
+To share a :cpp:class:`~tvm::ffi::TensorObj` with other frameworks, export it 
as a :c:struct:`DLManagedTensorVersioned`:
+
+.. literalinclude:: ../../examples/abi_overview/example_code.c
+  :language: c
+  :start-after: [Tensor_ToDLPackVersioned.begin]
+  :end-before: [Tensor_ToDLPackVersioned.end]
+
+Note that the caller takes ownership of the returned 
:c:struct:`DLManagedTensorVersioned* <DLManagedTensorVersioned>`
+and must call its ``deleter`` to release the tensor.
+
+.. _abi-function:
+
+Function
+--------
+
+.. seealso::
+
+   :ref:`sec:function` for a detailed description of TVM-FFI functions.
+
+All functions in TVM-FFI follow a unified C calling convention that enables 
ABI-stable,
+type-erased, and cross-language function calls, defined by 
:cpp:type:`TVMFFISafeCallType`.
+
+**Calling convention.** The signature includes:
+
+- ``handle`` (``void*``): Optional resource handle passed to the callee; 
typically ``NULL`` for exported symbols
+- ``args`` (``TVMFFIAny*``) and ``num_args`` (``int``): Array of non-owning 
:cpp:class:`~tvm::ffi::AnyView` input arguments
+- ``result`` (``TVMFFIAny*``): Owning :cpp:class:`~tvm::ffi::Any` output value
+- Return value: ``0`` for success; ``-1`` or ``-2`` for errors (see 
:ref:`sec:exception`)
+
+See :ref:`sec:function-calling-convention` for more details.

Review Comment:
   need note
   
   ```
   
   Before calling the function, caller must set `result->type_index` to be 
kTVMFFINone, or any type index that do not corresponds to an on-heap object.
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to