You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by tq...@apache.org on 2025/09/14 10:58:48 UTC

(tvm) branch main updated: [REFACTOR][FFI] Split tvm-ffi into a separate repo (#18314)

This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new 70e9164814 [REFACTOR][FFI] Split tvm-ffi into a separate repo (#18314)
70e9164814 is described below

commit 70e9164814e8b5f556c04c3f4a4dd8c75e81e13a
Author: Tianqi Chen <tq...@users.noreply.github.com>
AuthorDate: Sun Sep 14 06:58:43 2025 -0400

    [REFACTOR][FFI] Split tvm-ffi into a separate repo (#18314)
    
    This PR updates the code so we split tvm-ffi into a separate repo
---
 .github/actions/setup/action.yml                   |    2 +-
 .gitmodules                                        |    3 +
 3rdparty/tvm-ffi                                   |    1 +
 CMakeLists.txt                                     |    2 +-
 apps/android_rpc/app/src/main/jni/Android.mk       |    4 +-
 apps/android_rpc/app/src/main/jni/tvm_runtime.h    |   24 +-
 apps/ios_rpc/tvmrpc/TVMRuntime.mm                  |    2 +-
 docs/install/from_source.rst                       |    2 +-
 ffi/.clang-format                                  |    8 -
 ffi/CMakeLists.txt                                 |  262 ---
 ffi/README.md                                      |   18 -
 ffi/cmake/Utils/AddGoogleTest.cmake                |   56 -
 ffi/cmake/Utils/AddLibbacktrace.cmake              |   68 -
 ffi/cmake/Utils/CxxWarning.cmake                   |   30 -
 ffi/cmake/Utils/Library.cmake                      |   88 -
 ffi/cmake/Utils/Sanitizer.cmake                    |   35 -
 ffi/cmake/tvm_ffi-config.cmake                     |   58 -
 ffi/docs/.gitignore                                |    2 -
 ffi/docs/Makefile                                  |   41 -
 ffi/docs/README.md                                 |   46 -
 ffi/docs/concepts/abi_overview.md                  |  430 -----
 ffi/docs/conf.py                                   |  228 ---
 ffi/docs/get_started/install.md                    |   83 -
 ffi/docs/get_started/quick_start.md                |  213 ---
 ffi/docs/guides/cpp_guide.md                       |  584 -------
 ffi/docs/guides/packaging.md                       |  282 ----
 ffi/docs/guides/python_guide.md                    |  242 ---
 ffi/docs/index.rst                                 |   53 -
 ffi/docs/reference/cpp/index.rst                   |  107 --
 ffi/docs/reference/python/index.rst                |   69 -
 ffi/docs/requirements.txt                          |   21 -
 ffi/examples/inline_module/main.py                 |   87 -
 ffi/examples/packaging/CMakeLists.txt              |   73 -
 ffi/examples/packaging/README.md                   |   61 -
 ffi/examples/packaging/pyproject.toml              |   58 -
 .../packaging/python/my_ffi_extension/__init__.py  |   48 -
 .../packaging/python/my_ffi_extension/_ffi_api.py  |   24 -
 .../packaging/python/my_ffi_extension/base.py      |   37 -
 ffi/examples/packaging/run_example.py              |   40 -
 ffi/examples/packaging/src/extension.cc            |   89 -
 ffi/examples/quick_start/CMakeLists.txt            |   65 -
 ffi/examples/quick_start/README.md                 |   58 -
 ffi/examples/quick_start/run_example.py            |   82 -
 ffi/examples/quick_start/run_example.sh            |   27 -
 ffi/examples/quick_start/src/add_one_cpu.cc        |   41 -
 ffi/examples/quick_start/src/add_one_cuda.cu       |   58 -
 ffi/examples/quick_start/src/run_example.cc        |   53 -
 ffi/include/tvm/ffi/any.h                          |  692 --------
 ffi/include/tvm/ffi/base_details.h                 |  297 ----
 ffi/include/tvm/ffi/c_api.h                        | 1097 ------------
 ffi/include/tvm/ffi/cast.h                         |   79 -
 ffi/include/tvm/ffi/container/array.h              | 1147 -------------
 ffi/include/tvm/ffi/container/container_details.h  |  356 ----
 ffi/include/tvm/ffi/container/map.h                | 1762 --------------------
 ffi/include/tvm/ffi/container/shape.h              |  247 ---
 ffi/include/tvm/ffi/container/tensor.h             |  468 ------
 ffi/include/tvm/ffi/container/tuple.h              |  317 ----
 ffi/include/tvm/ffi/container/variant.h            |  302 ----
 ffi/include/tvm/ffi/dtype.h                        |  192 ---
 ffi/include/tvm/ffi/endian.h                       |   89 -
 ffi/include/tvm/ffi/error.h                        |  335 ----
 ffi/include/tvm/ffi/extra/base.h                   |   48 -
 ffi/include/tvm/ffi/extra/base64.h                 |  142 --
 ffi/include/tvm/ffi/extra/c_env_api.h              |  142 --
 ffi/include/tvm/ffi/extra/json.h                   |   84 -
 ffi/include/tvm/ffi/extra/module.h                 |  262 ---
 ffi/include/tvm/ffi/extra/serialization.h          |   72 -
 ffi/include/tvm/ffi/extra/structural_equal.h       |   78 -
 ffi/include/tvm/ffi/extra/structural_hash.h        |   57 -
 ffi/include/tvm/ffi/function.h                     |  880 ----------
 ffi/include/tvm/ffi/function_details.h             |  210 ---
 ffi/include/tvm/ffi/memory.h                       |  229 ---
 ffi/include/tvm/ffi/object.h                       | 1142 -------------
 ffi/include/tvm/ffi/optional.h                     |  419 -----
 ffi/include/tvm/ffi/reflection/access_path.h       |  440 -----
 ffi/include/tvm/ffi/reflection/accessor.h          |  260 ---
 ffi/include/tvm/ffi/reflection/creator.h           |  120 --
 ffi/include/tvm/ffi/reflection/registry.h          |  564 -------
 ffi/include/tvm/ffi/rvalue_ref.h                   |  155 --
 ffi/include/tvm/ffi/string.h                       | 1014 -----------
 ffi/include/tvm/ffi/type_traits.h                  |  781 ---------
 ffi/licenses/LICENSE.dlpack.txt                    |  201 ---
 ffi/licenses/LICENSE.libbacktrace.txt              |   29 -
 ffi/licenses/LICENSE.pytorch.txt                   |   84 -
 ffi/licenses/NOTICE.pytorch.txt                    |  456 -----
 ffi/pyproject.toml                                 |  159 --
 ffi/python/tvm_ffi/.gitignore                      |    2 -
 ffi/python/tvm_ffi/__init__.py                     |   73 -
 ffi/python/tvm_ffi/_convert.py                     |   65 -
 ffi/python/tvm_ffi/_dtype.py                       |  141 --
 ffi/python/tvm_ffi/_ffi_api.py                     |   20 -
 ffi/python/tvm_ffi/_optional_torch_c_dlpack.py     |  404 -----
 ffi/python/tvm_ffi/_tensor.py                      |   88 -
 ffi/python/tvm_ffi/access_path.py                  |  181 --
 ffi/python/tvm_ffi/base.py                         |   53 -
 ffi/python/tvm_ffi/config.py                       |   92 -
 ffi/python/tvm_ffi/container.py                    |  252 ---
 ffi/python/tvm_ffi/cpp/__init__.py                 |   18 -
 ffi/python/tvm_ffi/cpp/load_inline.py              |  437 -----
 ffi/python/tvm_ffi/cython/base.pxi                 |  393 -----
 ffi/python/tvm_ffi/cython/core.pyx                 |   26 -
 ffi/python/tvm_ffi/cython/device.pxi               |  191 ---
 ffi/python/tvm_ffi/cython/dtype.pxi                |  116 --
 ffi/python/tvm_ffi/cython/error.pxi                |  134 --
 ffi/python/tvm_ffi/cython/function.pxi             |  853 ----------
 ffi/python/tvm_ffi/cython/object.pxi               |  295 ----
 ffi/python/tvm_ffi/cython/string.pxi               |   80 -
 ffi/python/tvm_ffi/cython/tensor.pxi               |  362 ----
 ffi/python/tvm_ffi/cython/tvm_ffi_python_helpers.h |  580 -------
 ffi/python/tvm_ffi/error.py                        |  193 ---
 ffi/python/tvm_ffi/libinfo.py                      |  167 --
 ffi/python/tvm_ffi/module.py                       |  275 ---
 ffi/python/tvm_ffi/registry.py                     |  226 ---
 ffi/python/tvm_ffi/serialization.py                |   67 -
 ffi/python/tvm_ffi/testing.py                      |   63 -
 ffi/python/tvm_ffi/utils/__init__.py               |   18 -
 ffi/python/tvm_ffi/utils/lockfile.py               |  113 --
 ffi/scripts/benchmark_dlpack.py                    |  448 -----
 ffi/scripts/run_tests.sh                           |   27 -
 ffi/src/ffi/container.cc                           |   88 -
 ffi/src/ffi/dtype.cc                               |  328 ----
 ffi/src/ffi/error.cc                               |   81 -
 ffi/src/ffi/extra/buffer_stream.h                  |  127 --
 ffi/src/ffi/extra/env_c_api.cc                     |  148 --
 ffi/src/ffi/extra/env_context.cc                   |  120 --
 ffi/src/ffi/extra/json_parser.cc                   |  731 --------
 ffi/src/ffi/extra/json_writer.cc                   |  307 ----
 ffi/src/ffi/extra/library_module.cc                |  199 ---
 ffi/src/ffi/extra/library_module_dynamic_lib.cc    |  118 --
 ffi/src/ffi/extra/library_module_system_lib.cc     |  143 --
 ffi/src/ffi/extra/module.cc                        |  157 --
 ffi/src/ffi/extra/module_internal.h                |  114 --
 ffi/src/ffi/extra/reflection_extra.cc              |  144 --
 ffi/src/ffi/extra/serialization.cc                 |  430 -----
 ffi/src/ffi/extra/structural_equal.cc              |  439 -----
 ffi/src/ffi/extra/structural_hash.cc               |  317 ----
 ffi/src/ffi/extra/testing.cc                       |  133 --
 ffi/src/ffi/function.cc                            |  229 ---
 ffi/src/ffi/object.cc                              |  513 ------
 ffi/src/ffi/tensor.cc                              |   82 -
 ffi/src/ffi/traceback.cc                           |  188 ---
 ffi/src/ffi/traceback.h                            |  182 --
 ffi/src/ffi/traceback_win.cc                       |  142 --
 ffi/tests/cpp/CMakeLists.txt                       |   33 -
 ffi/tests/cpp/extra/test_json_parser.cc            |  394 -----
 ffi/tests/cpp/extra/test_json_writer.cc            |  241 ---
 ffi/tests/cpp/extra/test_serialization.cc          |  372 -----
 ffi/tests/cpp/extra/test_structural_equal_hash.cc  |  178 --
 ffi/tests/cpp/test_any.cc                          |  415 -----
 ffi/tests/cpp/test_array.cc                        |  286 ----
 ffi/tests/cpp/test_c_ffi_abi.cc                    |   31 -
 ffi/tests/cpp/test_dtype.cc                        |  130 --
 ffi/tests/cpp/test_error.cc                        |   70 -
 ffi/tests/cpp/test_example.cc                      |  288 ----
 ffi/tests/cpp/test_function.cc                     |  239 ---
 ffi/tests/cpp/test_map.cc                          |  366 ----
 ffi/tests/cpp/test_object.cc                       |  258 ---
 ffi/tests/cpp/test_optional.cc                     |  202 ---
 ffi/tests/cpp/test_reflection.cc                   |  269 ---
 ffi/tests/cpp/test_rvalue_ref.cc                   |   97 --
 ffi/tests/cpp/test_shape.cc                        |   72 -
 ffi/tests/cpp/test_string.cc                       |  430 -----
 ffi/tests/cpp/test_tensor.cc                       |  164 --
 ffi/tests/cpp/test_tuple.cc                        |  168 --
 ffi/tests/cpp/test_variant.cc                      |  164 --
 ffi/tests/cpp/testing_object.h                     |  296 ----
 ffi/tests/python/test_access_path.py               |  133 --
 ffi/tests/python/test_container.py                 |  124 --
 ffi/tests/python/test_device.py                    |   94 --
 ffi/tests/python/test_dtype.py                     |   85 -
 ffi/tests/python/test_error.py                     |  113 --
 ffi/tests/python/test_examples.py                  |   47 -
 ffi/tests/python/test_function.py                  |  221 ---
 ffi/tests/python/test_load_inline.py               |  324 ----
 ffi/tests/python/test_object.py                    |   91 -
 ffi/tests/python/test_string.py                    |   54 -
 ffi/tests/python/test_tensor.py                    |   68 -
 jvm/native/linux-x86_64/pom.xml                    |    2 +-
 jvm/native/osx-x86_64/pom.xml                      |    2 +-
 pyproject.toml                                     |    2 +-
 python/tvm/libinfo.py                              |    7 +-
 python/tvm/relax/frontend/nn/extern.py             |   18 +-
 tests/lint/cpplint.sh                              |    1 -
 tests/scripts/task_python_adreno.sh                |    2 +-
 tests/scripts/task_python_arm_compute_library.sh   |    2 +-
 tests/scripts/task_python_docs.sh                  |    4 +-
 tests/scripts/task_python_hexagon.sh               |    2 +-
 tests/scripts/task_python_integration.sh           |    2 +-
 tests/scripts/task_python_nightly.sh               |    2 +-
 tests/scripts/task_python_unittest.sh              |    2 +-
 tests/scripts/task_web_wasm.sh                     |    2 +-
 tests/scripts/unity/task_python_relax.sh           |    2 +-
 web/Makefile                                       |    4 +-
 web/emcc/wasm_runtime.cc                           |   22 +-
 194 files changed, 63 insertions(+), 37818 deletions(-)

diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml
index 88b3888179..77271319b2 100644
--- a/.github/actions/setup/action.yml
+++ b/.github/actions/setup/action.yml
@@ -39,4 +39,4 @@ runs:
   - name: Install tvm-ffi pip package
     shell: bash -l {0}
     run: |
-      pip install -v ./ffi
+      pip install -v ./3rdparty/tvm-ffi
diff --git a/.gitmodules b/.gitmodules
index 32a70d37ae..6b14c3524f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -28,3 +28,6 @@
 [submodule "ffi/3rdparty/dlpack"]
 	path = ffi/3rdparty/dlpack
 	url = https://github.com/dmlc/dlpack.git
+[submodule "3rdparty/tvm-ffi"]
+	path = 3rdparty/tvm-ffi
+	url = https://github.com/apache/tvm-ffi
diff --git a/3rdparty/tvm-ffi b/3rdparty/tvm-ffi
new file mode 160000
index 0000000000..3e07df45af
--- /dev/null
+++ b/3rdparty/tvm-ffi
@@ -0,0 +1 @@
+Subproject commit 3e07df45afbc8ea968ef03c34d84dc348ba6dfb0
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b05e5e1657..5e5a61490d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -567,7 +567,7 @@ if(USE_IOS_RPC)
   add_subdirectory("apps/ios_rpc")
 endif()
 
-add_subdirectory(ffi)
+add_subdirectory(3rdparty/tvm-ffi)
 
 if(TVM_DEBUG_WITH_ABI_CHANGE)
   message(STATUS "Building with debug code that may cause ABI changes...")
diff --git a/apps/android_rpc/app/src/main/jni/Android.mk b/apps/android_rpc/app/src/main/jni/Android.mk
index 692a339013..d482f94295 100644
--- a/apps/android_rpc/app/src/main/jni/Android.mk
+++ b/apps/android_rpc/app/src/main/jni/Android.mk
@@ -37,8 +37,8 @@ LOCAL_SRC_FILES := org_apache_tvm_native_c_api.cc
 LOCAL_LDFLAGS := -L$(SYSROOT)/usr/lib/ -llog
 
 LOCAL_C_INCLUDES := $(ROOT_PATH)/include \
-                    $(ROOT_PATH)/ffi/include \
-                    $(ROOT_PATH)/ffi/3rdparty/dlpack/include \
+                    $(ROOT_PATH)/3rdparty/tvm-ffi/include \
+                    $(ROOT_PATH)/3rdparty/tvm-ffi/3rdparty/dlpack/include \
                     $(ROOT_PATH)/3rdparty/dmlc-core/include \
                     $(ROOT_PATH)/3rdparty/OpenCL-Headers
 
diff --git a/apps/android_rpc/app/src/main/jni/tvm_runtime.h b/apps/android_rpc/app/src/main/jni/tvm_runtime.h
index b0cb033e88..6bda78cef0 100644
--- a/apps/android_rpc/app/src/main/jni/tvm_runtime.h
+++ b/apps/android_rpc/app/src/main/jni/tvm_runtime.h
@@ -34,18 +34,18 @@
 #define TVM_LOG_CUSTOMIZE 1
 #define TVM_FFI_USE_LIBBACKTRACE 0
 
-#include "../ffi/src/ffi/container.cc"
-#include "../ffi/src/ffi/dtype.cc"
-#include "../ffi/src/ffi/error.cc"
-#include "../ffi/src/ffi/extra/library_module.cc"
-#include "../ffi/src/ffi/extra/library_module_dynamic_lib.cc"
-#include "../ffi/src/ffi/extra/library_module_system_lib.cc"
-#include "../ffi/src/ffi/extra/module.cc"
-#include "../ffi/src/ffi/extra/testing.cc"
-#include "../ffi/src/ffi/function.cc"
-#include "../ffi/src/ffi/object.cc"
-#include "../ffi/src/ffi/tensor.cc"
-#include "../ffi/src/ffi/traceback.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/container.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/dtype.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/error.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/extra/library_module.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/extra/library_module_dynamic_lib.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/extra/library_module_system_lib.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/extra/module.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/extra/testing.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/function.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/object.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/tensor.cc"
+#include "../3rdparty/tvm-ffi/src/ffi/traceback.cc"
 #include "../src/runtime/cpu_device_api.cc"
 #include "../src/runtime/device_api.cc"
 #include "../src/runtime/file_utils.cc"
diff --git a/apps/ios_rpc/tvmrpc/TVMRuntime.mm b/apps/ios_rpc/tvmrpc/TVMRuntime.mm
index 8831210242..5dfff0cd86 100644
--- a/apps/ios_rpc/tvmrpc/TVMRuntime.mm
+++ b/apps/ios_rpc/tvmrpc/TVMRuntime.mm
@@ -33,7 +33,7 @@
 
 #if defined(USE_CUSTOM_DSO_LOADER) && USE_CUSTOM_DSO_LOADER == 1
 // internal TVM header to achieve Library class
-#include <../../../ffi/src/ffi/extra/library_module.h>
+#include <../../../3rdparty/tvm-ffi/src/ffi/extra/library_module.h>
 #include <custom_dlfcn.h>
 #endif
 
diff --git a/docs/install/from_source.rst b/docs/install/from_source.rst
index 2fc3a9e88b..ee81f84778 100644
--- a/docs/install/from_source.rst
+++ b/docs/install/from_source.rst
@@ -135,7 +135,7 @@ Therefore, after we finish the build, we need to install the tvm-ffi package.
 
 .. code-block:: bash
 
-    cd ffi; pip install .; cd ..
+    cd 3rdparty/tvm-ffi; pip install .; cd ..
 
 
 Leaving the build environment ``tvm-build-venv``, there are two ways to install the successful build into your environment:
diff --git a/ffi/.clang-format b/ffi/.clang-format
deleted file mode 100644
index 9d622b98ba..0000000000
--- a/ffi/.clang-format
+++ /dev/null
@@ -1,8 +0,0 @@
-# Run the following command to reformat a file:
-# clang-format -i -style=Google <file>
-# Or use clang-format-diff to only reformat the changed lines:
-# https://clang.llvm.org/docs/ClangFormat.html
-BasedOnStyle: Google
-DerivePointerAlignment: false
-ColumnLimit:     100
-PointerAlignment: Left
diff --git a/ffi/CMakeLists.txt b/ffi/CMakeLists.txt
deleted file mode 100644
index 2767669bce..0000000000
--- a/ffi/CMakeLists.txt
+++ /dev/null
@@ -1,262 +0,0 @@
-# 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.
-cmake_minimum_required(VERSION 3.18)
-
-project(
-  tvm_ffi
-  LANGUAGES CXX C
-)
-
-option(TVM_FFI_USE_LIBBACKTRACE "Enable libbacktrace" ON)
-option(TVM_FFI_USE_EXTRA_CXX_API "Enable extra CXX API in shared lib" ON)
-option(TVM_FFI_BACKTRACE_ON_SEGFAULT "Set signal handler to print traceback on segfault" ON)
-
-if (TVM_FFI_USE_LIBBACKTRACE)
-  include(${CMAKE_CURRENT_LIST_DIR}/cmake/Utils/AddLibbacktrace.cmake)
-endif()
-
-include(${CMAKE_CURRENT_LIST_DIR}/cmake/Utils/Library.cmake)
-
-
-########## Target: `tvm_ffi_header` ##########
-
-# they can be used in cases where user do not want to link into the library
-# in cases like deferred linking
-add_library(tvm_ffi_header INTERFACE)
-target_compile_features(tvm_ffi_header INTERFACE cxx_std_17)
-target_include_directories(
-  tvm_ffi_header INTERFACE
-  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-  $<INSTALL_INTERFACE:include>
-)
-target_include_directories(
-  tvm_ffi_header INTERFACE
-  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/dlpack/include>
-  $<INSTALL_INTERFACE:include>
-)
-
-########## Target: `tvm_ffi_objs` ##########
-
-set(tvm_ffi_objs_sources
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/traceback.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/traceback_win.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/object.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/error.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/function.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/tensor.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/dtype.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/container.cc"
-)
-
-set(tvm_ffi_extra_objs_sources
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/structural_equal.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/structural_hash.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/json_parser.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/json_writer.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/serialization.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/reflection_extra.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/module.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/library_module.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/library_module_system_lib.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/library_module_dynamic_lib.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/env_context.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/env_c_api.cc"
-  "${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/extra/testing.cc"
-)
-if (TVM_FFI_USE_EXTRA_CXX_API)
-  list(APPEND tvm_ffi_objs_sources ${tvm_ffi_extra_objs_sources})
-endif()
-
-add_library(tvm_ffi_objs OBJECT ${tvm_ffi_objs_sources})
-target_compile_features(tvm_ffi_objs PRIVATE cxx_std_17)
-
-set_target_properties(
-  tvm_ffi_objs PROPERTIES
-  POSITION_INDEPENDENT_CODE ON
-  CXX_EXTENSIONS OFF
-  CXX_STANDARD_REQUIRED ON
-  CXX_VISIBILITY_PRESET hidden
-  VISIBILITY_INLINES_HIDDEN ON
-  PREFIX "lib"
-)
-
-# add the include path as public so they are visible to downstreams
-target_link_libraries(tvm_ffi_objs PUBLIC tvm_ffi_header)
-
-if (TVM_FFI_USE_LIBBACKTRACE)
-  message(STATUS "Setting C++ macro TVM_FFI_USE_LIBBACKTRACE - 1")
-  target_compile_definitions(tvm_ffi_objs PRIVATE TVM_FFI_USE_LIBBACKTRACE=1)
-else()
-  message(STATUS "Setting C++ macro TVM_FFI_USE_LIBBACKTRACE - 0")
-  target_compile_definitions(tvm_ffi_objs PRIVATE TVM_FFI_USE_LIBBACKTRACE=0)
-endif()
-
-if (TVM_FFI_BACKTRACE_ON_SEGFAULT)
-  message(STATUS "Setting C++ macro TVM_FFI_BACKTRACE_ON_SEGFAULT - 1")
-  target_compile_definitions(tvm_ffi_objs PRIVATE TVM_FFI_BACKTRACE_ON_SEGFAULT=1)
-else()
-  message(STATUS "Setting C++ macro TVM_FFI_BACKTRACE_ON_SEGFAULT - 0")
-  target_compile_definitions(tvm_ffi_objs PRIVATE TVM_FFI_BACKTRACE_ON_SEGFAULT=0)
-endif()
-
-tvm_ffi_add_msvc_flags(tvm_ffi_objs)
-tvm_ffi_add_target_from_obj(tvm_ffi tvm_ffi_objs)
-
-if (TARGET libbacktrace)
-  target_link_libraries(tvm_ffi_objs PRIVATE libbacktrace)
-  target_link_libraries(tvm_ffi_shared PRIVATE libbacktrace)
-  target_link_libraries(tvm_ffi_static PRIVATE libbacktrace)
-endif ()
-
-if (MSVC)
-  target_link_libraries(tvm_ffi_objs PRIVATE DbgHelp.lib)
-  target_link_libraries(tvm_ffi_shared PRIVATE DbgHelp.lib)
-  target_link_libraries(tvm_ffi_static PRIVATE DbgHelp.lib)
-  # produce pdb file
-  target_link_options(tvm_ffi_shared PRIVATE /DEBUG)
-endif ()
-
-# expose the headers as public dependencies
-target_link_libraries(tvm_ffi_objs PUBLIC tvm_ffi_header)
-target_link_libraries(tvm_ffi_shared PUBLIC tvm_ffi_header)
-target_link_libraries(tvm_ffi_static PUBLIC tvm_ffi_header)
-
-#----------------------------------------------------------------------------
-# The following code section only is triggered when the project is the root
-# and will be skipped when the project is a subproject.
-#----------------------------------------------------------------------------
-if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
-  return()
-endif()
-
-option(TVM_FFI_ATTACH_DEBUG_SYMBOLS "Attach debug symbols even in release mode" OFF)
-option(TVM_FFI_BUILD_TESTS "Adding test targets." OFF)
-
-if (TVM_FFI_ATTACH_DEBUG_SYMBOLS)
-  if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
-    target_compile_options(tvm_ffi_objs PRIVATE -g1)
-  endif()
-endif()
-
-include(cmake/Utils/CxxWarning.cmake)
-include(cmake/Utils/Sanitizer.cmake)
-
-# remap the file name to the source directory so we can see the
-# exact file name in traceback relative to the project source root
-tvm_ffi_add_prefix_map(tvm_ffi_objs ${CMAKE_SOURCE_DIR})
-
-########## Adding cpp tests ##########
-
-# logics below are only executed when the project is the root project.
-# but not when the project is a subproject.
-if (TVM_FFI_BUILD_TESTS)
-  enable_testing()
-  message(STATUS "Enable Testing")
-  include(cmake/Utils/AddGoogleTest.cmake)
-  add_subdirectory(tests/cpp/)
-  tvm_ffi_add_cxx_warning(tvm_ffi_objs)
-endif()
-
-########## Adding python module ##########
-option(TVM_FFI_BUILD_PYTHON_MODULE "Adding python module." OFF)
-
-if (TVM_FFI_BUILD_PYTHON_MODULE)
-  # Helper function to build the cython module
-  message(STATUS "Building cython module..")
-  find_package(
-    Python COMPONENTS Interpreter Development.Module Development.SABIModule
-    REQUIRED)
-  set(core_cpp ${CMAKE_CURRENT_BINARY_DIR}/core.cpp)
-  set(core_pyx ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/core.pyx)
-  set(cython_sources
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/core.pyx
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/base.pxi
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/device.pxi
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/dtype.pxi
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/error.pxi
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/function.pxi
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/tensor.pxi
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/object.pxi
-    ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/string.pxi
-  )
-  # set working directory to source so we can see the exact file name in traceback
-  # relatived to the project source root
-  add_custom_command(
-      OUTPUT ${core_cpp}
-      COMMAND ${Python_EXECUTABLE} -m cython --cplus ${core_pyx} -o ${core_cpp}
-      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-      COMMENT "Transpiling ${core_pyx} to ${core_cpp}"
-      DEPENDS ${cython_sources}
-      VERBATIM
-  )
-  if(Python_VERSION VERSION_GREATER_EQUAL "3.12")
-    # >= Python3.12, use Use_SABI version
-    Python_add_library(tvm_ffi_cython MODULE "${core_cpp}" USE_SABI 3.12)
-    set_target_properties(tvm_ffi_cython PROPERTIES OUTPUT_NAME "core")
-    if(NOT WIN32)
-      set_target_properties(tvm_ffi_cython PROPERTIES SUFFIX ".abi3.so")
-    endif()
-  else()
-    # before Python3.12, use WITH_SOABI version
-    Python_add_library(tvm_ffi_cython MODULE "${core_cpp}" WITH_SOABI)
-    set_target_properties(tvm_ffi_cython PROPERTIES OUTPUT_NAME "core")
-  endif()
-  target_include_directories(tvm_ffi_cython PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython)
-  target_compile_features(tvm_ffi_cython PRIVATE cxx_std_17)
-  target_link_libraries(tvm_ffi_cython PRIVATE tvm_ffi_header)
-  target_link_libraries(tvm_ffi_cython PRIVATE tvm_ffi_shared)
-  # Set RPATH for tvm_ffi_cython to find tvm_ffi_shared.so relatively
-  if(APPLE)
-    # macOS uses @loader_path
-    set_target_properties(tvm_ffi_cython PROPERTIES INSTALL_RPATH "@loader_path/lib")
-  elseif(LINUX)
-      # Linux uses $ORIGIN
-    set_target_properties(tvm_ffi_cython PROPERTIES INSTALL_RPATH "\$ORIGIN/lib")
-  endif()
-  install(TARGETS tvm_ffi_cython DESTINATION .)
-
-  ########## Installing the source ##########
-  install(
-    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/dlpack/include DESTINATION 3rdparty/dlpack/include
-  )
-  install(
-    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/libbacktrace DESTINATION 3rdparty/libbacktrace
-    PATTERN ".git" EXCLUDE
-    PATTERN ".git*" EXCLUDE
-    PATTERN "*.tmp" EXCLUDE
-  )
-  install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/ffi/ DESTINATION src/ffi/)
-  install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Utils/ DESTINATION cmake/Utils)
-  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt DESTINATION .)
-  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/tvm_ffi-config.cmake DESTINATION cmake)
-endif()
-
-########## Install the related for normal cmake library ##########
-
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/tvm/ffi/ DESTINATION include/tvm/ffi/)
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/dlpack/include/ DESTINATION include/)
-install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/python/tvm_ffi/cython/tvm_ffi_python_helpers.h DESTINATION include/)
-install(TARGETS tvm_ffi_shared  DESTINATION lib)
-# ship additional dSYM files for debugging symbols on if available
-if (APPLE)
-  install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib/ DESTINATION lib FILES_MATCHING PATTERN "*.dSYM")
-endif()
-
-if (NOT TVM_FFI_BUILD_PYTHON_MODULE)
-  # when building wheel, we do not ship static as we already ships source and dll
-  install(TARGETS tvm_ffi_static DESTINATION lib)
-endif()
diff --git a/ffi/README.md b/ffi/README.md
deleted file mode 100644
index 3b1b1199c2..0000000000
--- a/ffi/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--- 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. -->
-
-# tvm ffi
diff --git a/ffi/cmake/Utils/AddGoogleTest.cmake b/ffi/cmake/Utils/AddGoogleTest.cmake
deleted file mode 100644
index af841752c6..0000000000
--- a/ffi/cmake/Utils/AddGoogleTest.cmake
+++ /dev/null
@@ -1,56 +0,0 @@
-# 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.
-
-include(FetchContent)
-set(gtest_force_shared_crt ON CACHE BOOL "Always use msvcrt.dll" FORCE)
-set(BUILD_GMOCK ON CACHE BOOL "" FORCE)
-set(BUILD_GTEST ON CACHE BOOL "" FORCE)
-FetchContent_Declare(
-  googletest
-  GIT_REPOSITORY https://github.com/google/googletest.git
-  GIT_TAG        v1.14.0
-)
-FetchContent_GetProperties(googletest)
-if (NOT googletest_POPULATED)
-  FetchContent_MakeAvailable(googletest)
-  include(GoogleTest)
-  set_target_properties(gtest      PROPERTIES EXPORT_COMPILE_COMMANDS OFF EXCLUDE_FROM_ALL ON FOLDER 3rdparty)
-  set_target_properties(gtest_main PROPERTIES EXPORT_COMPILE_COMMANDS OFF EXCLUDE_FROM_ALL ON FOLDER 3rdparty)
-  set_target_properties(gmock      PROPERTIES EXPORT_COMPILE_COMMANDS OFF EXCLUDE_FROM_ALL ON FOLDER 3rdparty)
-  set_target_properties(gmock_main PROPERTIES EXPORT_COMPILE_COMMANDS OFF EXCLUDE_FROM_ALL ON FOLDER 3rdparty)
-  mark_as_advanced(
-      BUILD_GMOCK BUILD_GTEST BUILD_SHARED_LIBS
-      gmock_build_tests gtest_build_samples gtest_build_tests
-      gtest_disable_pthreads gtest_force_shared_crt gtest_hide_internal_symbols
-  )
-endif()
-
-macro(tvm_ffi_add_googletest target_name)
-  add_test(
-    NAME ${target_name}
-    COMMAND ${target_name}
-    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-  )
-  target_link_libraries(${target_name} PRIVATE gtest_main)
-  gtest_discover_tests(${target_name}
-    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-    DISCOVERY_MODE PRE_TEST
-    PROPERTIES
-      VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
-  )
-  set_target_properties(${target_name} PROPERTIES FOLDER tests)
-endmacro()
diff --git a/ffi/cmake/Utils/AddLibbacktrace.cmake b/ffi/cmake/Utils/AddLibbacktrace.cmake
deleted file mode 100644
index e920a1f199..0000000000
--- a/ffi/cmake/Utils/AddLibbacktrace.cmake
+++ /dev/null
@@ -1,68 +0,0 @@
-# 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.
-
-include(ExternalProject)
-
-function(_libbacktrace_compile)
-  set(_libbacktrace_source ${CMAKE_CURRENT_LIST_DIR}/../../3rdparty/libbacktrace)
-  set(_libbacktrace_prefix ${CMAKE_CURRENT_BINARY_DIR}/libbacktrace)
-  if(CMAKE_SYSTEM_NAME MATCHES "Darwin" AND (CMAKE_C_COMPILER MATCHES "^/Library" OR CMAKE_C_COMPILER MATCHES "^/Applications"))
-    set(_cmake_c_compiler "/usr/bin/cc")
-  else()
-    set(_cmake_c_compiler "${CMAKE_C_COMPILER}")
-  endif()
-
-  message(STATUS CMAKC_C_COMPILER="${CMAKE_C_COMPILER}")
-
-  file(MAKE_DIRECTORY ${_libbacktrace_prefix}/include)
-  file(MAKE_DIRECTORY ${_libbacktrace_prefix}/lib)
-
-  ExternalProject_Add(project_libbacktrace
-    PREFIX libbacktrace
-    SOURCE_DIR ${_libbacktrace_source}
-    BINARY_DIR ${_libbacktrace_prefix}
-    CONFIGURE_COMMAND
-      "sh"
-      "${_libbacktrace_source}/configure"
-      "--prefix=${_libbacktrace_prefix}"
-      --with-pic
-      "CC=${_cmake_c_compiler}"
-      "CPP=${_cmake_c_compiler} -E"
-      "CFLAGS=${CMAKE_C_FLAGS}"
-      "LDFLAGS=${CMAKE_EXE_LINKER_FLAGS}"
-      "NM=${CMAKE_NM}"
-      "STRIP=${CMAKE_STRIP}"
-      "--host=${MACHINE_NAME}"
-  INSTALL_DIR ${_libbacktrace_prefix}
-  BUILD_COMMAND make
-  INSTALL_COMMAND make install
-  BUILD_BYPRODUCTS "${_libbacktrace_prefix}/lib/libbacktrace.a"
-                   "${_libbacktrace_prefix}/include/backtrace.h"
-  )
-  ExternalProject_Add_Step(project_libbacktrace checkout DEPENDERS configure DEPENDEES download)
-  set_target_properties(project_libbacktrace PROPERTIES EXCLUDE_FROM_ALL TRUE)
-  add_library(libbacktrace STATIC IMPORTED)
-  add_dependencies(libbacktrace project_libbacktrace)
-  set_target_properties(libbacktrace PROPERTIES
-    IMPORTED_LOCATION ${_libbacktrace_prefix}/lib/libbacktrace.a
-    INTERFACE_INCLUDE_DIRECTORIES ${_libbacktrace_prefix}/include
-  )
-endfunction()
-
-if(NOT MSVC)
-  _libbacktrace_compile()
-endif()
diff --git a/ffi/cmake/Utils/CxxWarning.cmake b/ffi/cmake/Utils/CxxWarning.cmake
deleted file mode 100644
index a85e58825b..0000000000
--- a/ffi/cmake/Utils/CxxWarning.cmake
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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.
-
-function(tvm_ffi_add_cxx_warning target_name)
-  # GNU, Clang, or AppleClang
-  if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
-    target_compile_options(${target_name} PRIVATE "-Werror" "-Wall" "-Wextra" "-Wpedantic" "-Wno-unused-parameter")
-    return()
-  endif()
-  # MSVC
-  if(MSVC)
-    # target_compile_options(${target_name} PRIVATE "/W4" "/WX")
-    return()
-  endif()
-  message(FATAL_ERROR "Unsupported compiler: ${CMAKE_CXX_COMPILER_ID}")
-endfunction()
diff --git a/ffi/cmake/Utils/Library.cmake b/ffi/cmake/Utils/Library.cmake
deleted file mode 100644
index 611f972dce..0000000000
--- a/ffi/cmake/Utils/Library.cmake
+++ /dev/null
@@ -1,88 +0,0 @@
-# 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.
-
-function(tvm_ffi_add_prefix_map target_name prefix_path)
-  # Add prefix map so the path displayed becomes relative to prefix_path
-  if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
-    target_compile_options(${target_name} PRIVATE "-ffile-prefix-map=${prefix_path}/=")
-  endif()
-endfunction()
-
-function(tvm_ffi_add_apple_dsymutil target_name)
-  # running dsymutil on macos to generate debugging symbols for backtraces
-  if(APPLE AND TVM_FFI_USE_LIBBACKTRACE)
-    find_program(DSYMUTIL dsymutil)
-    mark_as_advanced(DSYMUTIL)
-    add_custom_command(TARGET ${target_name}
-        POST_BUILD
-        COMMAND ${DSYMUTIL} ARGS $<TARGET_FILE:${target_name}>
-        COMMENT "[COMMAND] dsymutil $<TARGET_FILE:${target_name}>"
-        VERBATIM
-    )
-  endif()
-endfunction()
-
-function(tvm_ffi_add_msvc_flags target_name)
-  # running if we are under msvc
-  if(MSVC)
-    target_compile_definitions(${target_name} PUBLIC -DWIN32_LEAN_AND_MEAN)
-    target_compile_definitions(${target_name} PUBLIC -D_CRT_SECURE_NO_WARNINGS)
-    target_compile_definitions(${target_name} PUBLIC -D_SCL_SECURE_NO_WARNINGS)
-    target_compile_definitions(${target_name} PUBLIC -D_ENABLE_EXTENDED_ALIGNED_STORAGE)
-    target_compile_definitions(${target_name} PUBLIC -DNOMINMAX)
-    target_compile_options(${target_name} PRIVATE "/Zi")
-  endif()
-endfunction()
-
-function(tvm_ffi_add_target_from_obj target_name obj_target_name)
-  add_library(${target_name}_static STATIC $<TARGET_OBJECTS:${obj_target_name}>)
-  set_target_properties(
-    ${target_name}_static PROPERTIES
-    OUTPUT_NAME "${target_name}_static"
-    ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
-    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
-    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
-    )
-  add_library(${target_name}_shared SHARED $<TARGET_OBJECTS:${obj_target_name}>)
-  set_target_properties(
-    ${target_name}_shared PROPERTIES
-    OUTPUT_NAME "${target_name}"
-    ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
-    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
-    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
-  )
-  if (WIN32)
-    target_compile_definitions(${obj_target_name} PRIVATE TVM_FFI_EXPORTS)
-    # set the output directory for each config type so msbuild also get into lib
-    # without appending the config type to the output directory
-    # do both Release and RELEASE suffix, since while cmake docs suggest Release is ok.
-    # real runs on MSbuild suggest that we might need RELEASE instead
-    foreach(CONFIG_TYPE Release RELEASE)
-      set_target_properties(${target_name}_shared PROPERTIES
-        RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPE} "${CMAKE_BINARY_DIR}/lib"
-        LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPE} "${CMAKE_BINARY_DIR}/lib"
-        ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPE} "${CMAKE_BINARY_DIR}/lib"
-      )
-      set_target_properties(${target_name}_static PROPERTIES
-        RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPE} "${CMAKE_BINARY_DIR}/lib"
-        LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPE} "${CMAKE_BINARY_DIR}/lib"
-        ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPE} "${CMAKE_BINARY_DIR}/lib"
-      )
-    endforeach()
-  endif()
-  tvm_ffi_add_apple_dsymutil(${target_name}_shared)
-endfunction()
diff --git a/ffi/cmake/Utils/Sanitizer.cmake b/ffi/cmake/Utils/Sanitizer.cmake
deleted file mode 100644
index a20eead0c8..0000000000
--- a/ffi/cmake/Utils/Sanitizer.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-# 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.
-
-function(add_sanitizer_address target_name)
-  if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
-    include(CheckCXXCompilerFlag)
-    set (_saved_CRF ${CMAKE_REQUIRED_FLAGS})
-    set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
-    check_cxx_source_compiles("int main() { return 0; }" COMPILER_SUPPORTS_ASAN)
-    set (CMAKE_REQUIRED_FLAGS ${_saved_CRF})
-    get_target_property(_saved_type ${target_name} TYPE)
-    if (${_saved_type} STREQUAL "INTERFACE_LIBRARY")
-      set(_saved_type INTERFACE)
-    else()
-      set(_saved_type PRIVATE)
-    endif()
-    target_link_options(${target_name} ${_saved_type} "-fsanitize=address")
-    target_compile_options(${target_name} ${_saved_type} "-fsanitize=address" "-fno-omit-frame-pointer" "-g")
-    return()
-  endif()
-endfunction()
diff --git a/ffi/cmake/tvm_ffi-config.cmake b/ffi/cmake/tvm_ffi-config.cmake
deleted file mode 100644
index 01f60ca10b..0000000000
--- a/ffi/cmake/tvm_ffi-config.cmake
+++ /dev/null
@@ -1,58 +0,0 @@
-# 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.
-
-find_package(Python COMPONENTS Interpreter REQUIRED)
-
-# call tvm_ffi.config to get the cmake directory and set it to tvm_ffi_ROOT
-execute_process(
-    COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --includedir
-    OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE tvm_ffi_INCLUDE_DIR)
-
-execute_process(
-    COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --dlpack-includedir
-    OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE tvm_ffi_DLPACK_INCLUDE_DIR)
-
-execute_process(
-    COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --libfiles
-    OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE tvm_ffi_LIB_FILES)
-
-message(STATUS "Finding libfiles ${tvm_ffi_LIB_FILES}")
-
-add_library(tvm_ffi_header INTERFACE)
-target_compile_features(tvm_ffi_header INTERFACE cxx_std_17)
-target_include_directories(tvm_ffi_header INTERFACE "${tvm_ffi_INCLUDE_DIR}")
-target_include_directories(tvm_ffi_header INTERFACE "${tvm_ffi_DLPACK_INCLUDE_DIR}")
-
-add_library(tvm_ffi_shared SHARED IMPORTED)
-target_compile_features(tvm_ffi_shared INTERFACE cxx_std_17)
-
-if(WIN32)
-  set_target_properties(
-    tvm_ffi_shared PROPERTIES IMPORTED_IMPLIB "${tvm_ffi_LIB_FILES}"
-  )
-else()
-  set_target_properties(
-    tvm_ffi_shared PROPERTIES IMPORTED_LOCATION "${tvm_ffi_LIB_FILES}"
-  )
-endif()
-
-set_target_properties(
-  tvm_ffi_shared PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
-  "${tvm_ffi_INCLUDE_DIR};${tvm_ffi_DLPACK_INCLUDE_DIR}"
-)
-# extra cmake functions
-include(${CMAKE_CURRENT_LIST_DIR}/Utils/Library.cmake)
diff --git a/ffi/docs/.gitignore b/ffi/docs/.gitignore
deleted file mode 100644
index d7ab85b91f..0000000000
--- a/ffi/docs/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-_build
-**/generated/*
diff --git a/ffi/docs/Makefile b/ffi/docs/Makefile
deleted file mode 100644
index 51e4de21d3..0000000000
--- a/ffi/docs/Makefile
+++ /dev/null
@@ -1,41 +0,0 @@
-# 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.
-# You can set these variables from the command line, and also
-# from the environment for the first two.
-SPHINXOPTS    ?=
-SPHINXBUILD   ?= python3 -m sphinx
-SOURCEDIR     = .
-BUILDDIR      = _build
-
-# Put it first so that "make" without argument is like "make help".
-help:
-	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-
-.PHONY: help Makefile livehtml clean
-
-livehtml:
-	@sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) --ignore reference/cpp/generated
-
-clean:
-	rm -rf $(BUILDDIR)
-	rm -rf reference/python/generated
-	rm -rf reference/cpp/generated
-
-# Catch-all target: route all unknown targets to Sphinx using the new
-# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
-%: Makefile
-	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/ffi/docs/README.md b/ffi/docs/README.md
deleted file mode 100644
index 39fff194df..0000000000
--- a/ffi/docs/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-<!--- 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. -->
-# TVM FFI Documentation
-
-To build locally
-
-First install the tvm-ffi package
-```bash
-pip install ..
-```
-
-Install all the requirements to build docs
-
-```bash
-pip install -r requirements.txt
-```
-
-Then build the doc
-```bash
-make livehtml
-```
-
-## Build with C++ Docs
-
-To build with C++ docs, we need to first install Doxygen. Then
-set the environment variable `BUILD_CPP_DOCS=1`, to turn on c++ docs.
-
-```bash
-BUILD_CPP_DOCS=1 make livehtml
-```
-
-Building c++ docs can take longer, so it is not on by default.
diff --git a/ffi/docs/concepts/abi_overview.md b/ffi/docs/concepts/abi_overview.md
deleted file mode 100644
index 1182578964..0000000000
--- a/ffi/docs/concepts/abi_overview.md
+++ /dev/null
@@ -1,430 +0,0 @@
-<!--- 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
-
-This section provides an overview of the ABI convention of TVM FFI. The ABI
-is designed around the following key principles:
-
-- **Stable C ABI:** Core ABI is defined on top of a stable C ABI.
-- **Minimal and efficient:** Keep things simple when possible and bring close-to-metal efficiency.
-- **Focus on machine learning systems:** while also ensuring reasonable extensibility.
-
-To explain the concepts in the following sections, we will write in **low-level C/C++ code** when possible,
-so the code itself illustrates the low-level semantics of how to work with the ABI convention.
-These can serve as references for how to build language bindings and compiler codegen for the ABI.
-
-```{note}
-The authoritative ABI specifications are defined in [tvm/ffi/c_api.h](https://github.com/apache/tvm/blob/main/ffi/include/tvm/ffi/c_api.h) for core ABI,
-and [tvm/ffi/extra/c_env_api.h](https://github.com/apache/tvm/blob/main/ffi/include/tvm/ffi/extra/c_env_api.h) for extra support features
-such as stream handling. This document provides explanations about design concepts and rationales.
-```
-
-## Simplified Example
-
-Before diving into details, it is helpful to review at a high level
-what happens when a function is called in TVM FFI ABI.
-One main design goal here is to represent all kinds of functions in a single
-unified C signature. Please review the following
-simplified code example that illustrates the key idea:
-
-```c++
-// simplified struct for TVMFFIAny
-typedef struct TVMFFIAny {
-  int32_t type_index;
-  uint32_t zero_padding;
-  // union values
-  union {
-    int64_t v_int64;       // integers
-    double v_float64;      // floating-point numbers
-    const char* v_c_str;   // raw C-string
-  };
-};
-
-// This is the signature of TVM FFI function ABI
-typedef int (*TVMFFISafeCallType)(
-   void* handle, const TVMFFIAny* args, int32_t num_args, TVMFFIAny* result
-);
-
-// An example function signature
-int MyFunc(const char* param0, int param1);
-
-// This is what MyFunc looks like when exposed through TVM FFI ABI
-int MyFuncTVMFFISafeCall(
-  void* handle, const TVMFFIAny* args, int32_t num_args, TVMFFIAny* result
-) {
-  assert(args[0].type_index == kTVMFFIRawStr);
-  assert(args[1].type_index == kTVMFFInt);
-  result->type_index = kTVMFFInt;
-  result->v_int64 = MyFunc(args[0].v_c_str, args[1].v_int64);
-  // return value indicates no error occurred
-  return 0;
-}
-
-// This is how we call the MyFuncTVMFFISafeCall
-// this can happen on the caller side in another language (e.g. python)
-int CallTVMFFISafeCall(const char* param0, int param1) {
-  // arguments on stack
-  TVMFFIAny args[2], result;
-  args[0].type_index = kTVMFFIRawStr;
-  args[0].v_c_str = param0;
-  args[1].type_index = kTVMFFInt;
-  args[1].v_int64 = param1;
-  result.type_index = kTVMFFINone;
-  // In this case we do not need handle
-  // handle is used to hold closure pointers
-  void* handle = nullptr;
-  int num_args = 2;
-  MyFuncTVMFFISafeCall(handle, args, num_args, &result);
-  return result.v_int64;
-}
-```
-
-At a high level, the `TVMFFISafeCallType` signature does the following things:
-- Arguments and return values are stored in structured `TVMFFIAny`
-  - Each value comes with a `type_index` to indicate its type
-  - Values are stored in union fields, depending on the specific type.
-- Caller can explicitly store the type index and value into
-  a stack of `TVMFFIAny`.
-- Callee can load the parameters from args and check their type indices.
-
-In this way, the same `TVMFFISafeCallType` can be used to represent any function
-that contains an arbitrary number of arguments and types that can be identified by `type_index`.
-Of course, this is a simplified example and we did not touch on specific details
-like Any value format and error handling. The following sections will provide a more systematic
-treatment of each of these specific topics.
-You can keep this example in mind as the overall picture and refine it as you read through
-the following sections.
-
-
-## TVMFFIAny Storage Format
-
-To start with, we need a mechanism to store the values that are passed across machine learning frameworks.
-It achieves this using a core data structure called TVMFFIAny.
-
-```c++
-typedef struct TVMFFIAny {
-  int32_t type_index;
-  union {  // 4 bytes
-    uint32_t zero_padding;
-    uint32_t small_str_len;
-  };
-  // union values
-  union {
-    int64_t v_int64;       // integers
-    double v_float64;      // floating-point numbers
-    void* v_ptr;           // typeless pointers
-    const char* v_c_str;   // raw C-string
-    TVMFFIObject* v_obj;   // ref counted objects
-    DLDataType v_dtype;    // data type
-    DLDevice v_device;     // device
-    char v_bytes[8];       // small string
-    ...
-  };
-} TVMFFIAny;
-```
-
-TVMFFIAny is a 16-byte C structure that follows the design principle of tagged-union:
-
-- `type_index` helps us identify the type being stored.
-- The value union part is designed to store the value:
-  - Small POD values (like integers and floats) are stored directly as "on-stack" values.
-  - `v_obj` can also point to a managed heap-allocated object, which we will discuss next.
-- The second field stores metadata for small strings.
-
-
-### Storing a POD Value
-
-There are many values that are plain-old-data types. In such cases, we store them directly
-on-stack in the value part of the TVMFFIAny. The following example shows how to store
-an int.
-
-```c++
-void SetIntValue(TVMFFIAny* any, int value) {
-  // must zero the entire space first
-  any->type_index = kTVMFFIInt;
-  any->zero_padding = 0;
-  any->v_int64 = value;
-}
-```
-
-:::{note}
-
-We **must zero the content that is not being used** by
-the current value type. The following example shows a common place
-where mistakes can be made when we forget to zero the value field
-on 32-bit platforms (where pointers only fill the 32-bit part of the value).
-
-```c++
-void SetOpaquePtrValue(TVMFFIAny* any, void* opaque_ptr) {
-  any->type_index = kTVMFFIOpaquePtr;
-  // must zero the padding
-  any->zero_padding = 0;
-  // the zeroing is needed for 32-bit platforms!
-  any->v_uint64 = 0;
-  any->v_ptr = opaque_ptr;
-}
-```
-
-**Rationale:** Such invariants allow us to directly compare
-and hash TVMFFIAny in bytes for quick equality checks without going through
-type index switching.
-:::
-
-
-## Object Storage Format
-
-When TVMFFIAny points to a heap-allocated object (such as n-dimensional arrays),
-we adopt a unified object storage format, defined as follows:
-
-```c++
-typedef struct TVMFFIObject {
-  int32_t type_index;
-  uint32_t weak_ref_count;
-  uint64_t strong_ref_count;
-  union {
-    void (*deleter)(struct TVMFFIObject* self, int flags);
-    int64_t __ensure_align;
-  };
-} TVMFFIObject;
-```
-
-`TVMFFIObject` defines a common 24-byte intrusive header that all in-memory objects share:
-
-- `type_index` helps us identify the type being stored, which is consistent with `TVMFFIAny.type_index`.
-- `weak_ref_count` stores the weak atomic reference counter of the object.
-- `strong_ref_count` stores the strong atomic reference counter of the object.
-- `deleter` should be called when either the strong or weak ref counter goes to zero.
-  - The flags are set to indicate the event of either weak or strong going to zero, or both.
-  - When `strong_ref_count` gets to zero, the deleter needs to call the destructor of the object.
-  - When `weak_ref_count` gets to zero, the deleter needs to free the memory allocated by self.
-
-**Rationales:** There are several considerations when designing the data structure:
-- `type_index` enables runtime dynamic type checking and casting.
-- We introduce weak/strong ref counters so we can be compatible with systems that need weak pointers.
-- The weak ref counter is kept as 32-bit so we can pack the object header as 24 bytes.
-- `deleter` ensures that objects allocated from one language/runtime can be safely deleted in another.
-
-The object format provides a unified way to manage object life-cycle and dynamic type casting
-for heap-allocated objects, including Shape, Tensor,
-Function, Array, Map and other custom objects.
-
-
-### DLPack Compatible Tensor
-
-We provide first-class support for DLPack raw unmanaged pointer support as well as a managed Tensor object that
-directly adopts the DLPack DLTensor layout. The overall layout of the Tensor object is as follows:
-
-```c++
-struct TensorObj: public ffi::Object, public DLTensor {
-};
-```
-
-That means we can read out the array buffer information from an `TVMFFIAny`
-in the following way:
-
-```c++
-DLTensor* ReadDLTensorPtr(const TVMFFIAny *value) {
-  if (value->type_index == kTVMFFIDLTensorPtr) {
-    return static_cast<DLTensor*>(value->v_ptr);
-  }
-  assert(value->type_index == kTVMFFITensor);
-  return reinterpret_cast<DLTensor*>(
-    reinterpret_cast<char*>(value->v_obj) + sizeof(TVMFFIObject));
-}
-```
-The above code can be used as a reference to implement compiler codegen for data.
-Note that the C++ API automatically handles such conversion.
-
-### Advanced: Dynamic Type Index
-
-The `TVMFFITypeIndex` defines a set of type indices. Each built-in type has a corresponding statically
-assigned type index that is defined in the enum. Static type indices should be sufficient for most
-library use cases.
-For advanced use cases we also support user-defined objects whose `type_index` are assigned at startup time
-by calling `TVMFFITypeGetOrAllocIndex` with a unique
-`type_key` string. This design allows us to enable decentralized extension of the objects as long as the `type_key`
-values are unique by appending namespace prefix to the key.
-
-## AnyView and Managed Any
-
-An `TVMFFIAny` can either be treated as a strongly managed value (corresponding to `ffi::Any` in C++),
-or an unmanaged value (corresponding to `ffi::AnyView` in C++).
-- For POD types, there is no difference between the two
-- For object types, copying of AnyView should not change reference counters, while copying and deletion
-  of managed Any should result in increase and decrease of strong reference counters.
-- When we convert AnyView to Any, we will convert raw C string `const char*` and `const TVMFFIByteArray*`
-  into their managed counterparts (String and Bytes).
-- C API function `TVMFFIAnyViewToOwnedAny` is provided to perform such conversion.
-
-Unless the user is writing a compiler backend that needs low-level C style access, we encourage use of the
-C++ API to automatically manage conversion and casting between normal types and Any. The following code
-shows some example usage of the C++ API.
-
-```c++
-#include <tvm/ffi/any.h>
-
-void AnyExample() {
-  namespace ffi = tvm::ffi;
-  // Here is a managed any
-  ffi::Any value = "hello world";
-  // explicit cast to a specific type
-  ffi::String str_value = value.cast<ffi::String>();
-  // copy int to value
-  value = 1;
-  // copy into a view
-  ffi::AnyView view = value;
-  // cast view back to int
-  std::cout << "Value is " << view.cast<int>() << std::endl;
-}
-```
-
-`ffi::Any` can serve as a container type to hold managed values that can be recognized by the TVM FFI system.
-They can be composed with container structures such as `Map<String, Any>`, `Array<Any>` to represent various
-broad patterns in APIs that may appear in ML systems.
-
-## Function Calling Convention
-
-As discussed in the overview, we need to consider foreign function calls as first-class citizens. We adopt a single standard C function as follows:
-
-```c++
-typedef int (*TVMFFISafeCallType)(
-   void* handle, const TVMFFIAny* args, int32_t num_args, TVMFFIAny* result
-);
-```
-
-The handle contains the pointer to the function object itself, allowing us to support closures. args and num_args describe the input arguments and results store the return value. When args and results contain heap-managed objects, we expect the caller to own args and result.
-
-```{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.
-
-**Rationale:** Simplifies callee implementation as initial state of result can be viewed as managed Any.
-```
-
-We call this approach a packed function, as it provides a single signature to represent all functions in a "type-erased" way. It saves the need to declare and jit shim for each FFI function call while maintaining reasonable efficiency. This mechanism enables the following scenarios:
-- Calling from Dynamic Languages (e.g., Python): we provide a tvm_ffi binding that prepares the args based on dynamically examining Python arguments passed in.
-- Calling from Static Languages (e.g., C++): For static languages, we can leverage C++ templates to directly instantiate the arguments on the stack, saving the need for dynamic examination.
-- Dynamic language Callbacks: the signature enables us to easily bring dynamic language (Python) callbacks as ffi::Function, as we can take each argument and convert to the dynamic values.
-- Efficiency: In practice, we find this approach is sufficient for machine learning focused workloads. For example, we can get to microsecond level overhead for Python/C++ calls, which is generally similar to overhead for eager mode. When both sides of calls are static languages, the overhead will go down to tens of nanoseconds. As a side note, although we did not find it necessary, the signature still leaves room for link time optimization (LTO), when both sides are static languages wit [...]
-
-We support first-class Function objects that allow us to also pass function/closures from different places around, enabling cool usages such as quick python callback for prototyping, and dynamic Functor creation for driver-based kernel launching.
-
-
-## Error Handling
-
-Most TVM FFI C API calls, including `TVMFFISafeCallType` uses the return value to
-indicate whether an error happens. When an error happens during a function call,
-a non-zero value will be returned. The callee needs also to set the error through `TVMFFIErrorSetRaisedFromCStr` or `TVMFFIErrorSetRaised` API, which stores
-the error on a thread-local storage.
-
-```c++
-// Example function that raises an error
-int ErrorFunc(void* handle, const TVMFFIAny* args, int num_args, TVMFFIAny *result) {
-  const char* error_kind = "RuntimeError";
-  const char* error_msg = "error message";
-  // set the thread-local error state
-  TVMFFIErrorSetRaisedFromCStr(error_kind, error_msg);
-  return -1;
-}
-```
-
-The caller can retrieve the error from thread-local error storage
-using `TVMFFIErrorMoveFromRaised` function.
-The ABI stores Error also as a specific Object,
-the overall error object is stored as follows
-```c++
-typedef struct {
-  /*! \brief The kind of the error. */
-  TVMFFIByteArray kind;
-  /*! \brief The message of the error. */
-  TVMFFIByteArray message;
-  /*! \brief The traceback of the error. */
-  TVMFFIByteArray traceback;
-  /*!
-   * \brief Function handle to update the traceback of the error.
-   * \param self The self object handle.
-   * \param traceback The traceback to update.
-   */
-  void (*update_traceback)(TVMFFIObjectHandle self, const TVMFFIByteArray* traceback);
-} TVMFFIErrorCell;
-
-// error object
-class ErrorObj : public ffi::Object, public TVMFFIErrorCell {
-};
-```
-
-The error object stores kind, message and traceback as string. When possible,
-we store the traceback in the same format of python traceback (see an example as follows):
-```
-File "src/extension.cc", line 45, in void my_ffi_extension::RaiseError(tvm::ffi::String)
-```
-
-We provide C++ object `ffi::Error` that can be throwed as exception in c++ environment. When we encounter
-the C ABI boundary, we will catch the error and call `TVMFFIErrorSetRaised` to propagate the error
-to the caller safely.
-`TVMFFIErrorSetRaisedFromCStr` is a convenient method to set error directly from C string and can be useful in compiler backend construction to implement features such as assert.
-
-**Rationales:** The error object contains minimal but sufficient information to reconstruct structured
-error in python side. We opt-for thread-local error state as it simplifies overall support.
-
-## String and Bytes
-
-The ABI supports strings and bytes as first-class citizens. A string can take multiple forms that are identified by
-its `type_index`.
-
-- `kTVMFFIRawStr`: raw C string terminated by `\0`.
-- `kTVMFFISmallStr`: small string, the length is stored in `small_str_len` and data is stored in `v_bytes`.
-- `kTVMFFIStr`: on-heap string object for strings that are longer than 7 characters.
-
-The following code shows the layout of the on-heap string object.
-```c++
-// span-like data structure to store header and length
-typedef struct {
-  const char* data;
-  size_t size;
-} TVMFFIByteArray;
-
-// showcase the layout of the on-heap string.
-class StringObj : public ffi::Object, public TVMFFIByteArray {
-};
-```
-
-The following code shows how to read a string from `TVMFFIAny`
-```c++
-TVMFFIByteArray ReadString(const TVMFFIAny *value) {
-  TVMFFIByteArray ret;
-  if (value->type_index == kTVMFFIRawStr) {
-    ret.data = value->v_c_str;
-    ret.size = strlen(ret.data);
-  } else if (value->type_index == kTVMFFISmallStr) {
-    ret.data = value->v_bytes;
-    ret.size = value->small_str_len;
-  } else {
-    assert(value->type_index == kTVMFFIStr);
-    ret = *reinterpret_cast<TVMFFIByteArray*>(
-      reinterpret_cast<char*>(value->v_obj) + sizeof(TVMFFIObject));
-  }
-  return ret;
-}
-```
-
-Similarly, we have type indices to represent bytes. The C++ API provides classes
-`ffi::String` and `ffi::Bytes` to enable the automatic conversion of these values with Any storage format.
-
-**Rationales:** Separate string and bytes enable clear mappings from the Python side. Small string allows us to
-store short names on-stack. To favor 8-byte alignment (v_bytes) and keep things simple, we did not further
-pack characters into the `small_len` field.
diff --git a/ffi/docs/conf.py b/ffi/docs/conf.py
deleted file mode 100644
index 139254fd97..0000000000
--- a/ffi/docs/conf.py
+++ /dev/null
@@ -1,228 +0,0 @@
-# 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.
-# -*- coding: utf-8 -*-
-import os
-import sys
-
-import tomli
-
-
-os.environ["TVM_FFI_BUILD_DOCS"] = "1"
-
-build_exhale = os.environ.get("BUILD_CPP_DOCS", "0") == "1"
-
-
-# -- General configuration ------------------------------------------------
-
-# Load version from pyproject.toml
-with open("../pyproject.toml", "rb") as f:
-    pyproject_data = tomli.load(f)
-__version__ = pyproject_data["project"]["version"]
-
-project = "tvm-ffi"
-
-version = __version__
-release = __version__
-
-# -- Extensions and extension configurations --------------------------------
-
-extensions = [
-    "breathe",
-    "myst_parser",
-    "nbsphinx",
-    "autodocsumm",
-    "sphinx.ext.autodoc",
-    "sphinx.ext.autosectionlabel",
-    "sphinx.ext.autosummary",
-    "sphinx.ext.intersphinx",
-    "sphinx.ext.mathjax",
-    "sphinx.ext.napoleon",
-    "sphinx.ext.viewcode",
-    "sphinx.ext.ifconfig",
-    "sphinx_copybutton",
-    "sphinx_reredirects",
-    "sphinx_tabs.tabs",
-    "sphinx_toolbox.collapse",
-    "sphinxcontrib.httpdomain",
-    "sphinxcontrib.mermaid",
-]
-
-if build_exhale:
-    extensions.append("exhale")
-
-breathe_default_project = "tvm-ffi"
-
-breathe_projects = {"tvm-ffi": "./_build/doxygen/xml"}
-
-exhaleDoxygenStdin = """
-INPUT = ../include
-PREDEFINED  += TVM_FFI_DLL= TVM_FFI_INLINE= TVM_FFI_EXTRA_CXX_API= __cplusplus=201703
-
-EXCLUDE_SYMBOLS   += *details*  *TypeTraits* std \
-                         *use_default_type_traits_v* *is_optional_type_v* *operator* \
-
-EXCLUDE_PATTERNS   += *details.h
-ENABLE_PREPROCESSING   = YES
-MACRO_EXPANSION        = YES
-"""
-
-exhaleAfterTitleDescription = """
-This page contains the full API index for the C++ API.
-"""
-
-# Setup the exhale extension
-exhale_args = {
-    "containmentFolder": "reference/cpp/generated",
-    "rootFileName": "index.rst",
-    "doxygenStripFromPath": "../include",
-    "rootFileTitle": "Full API Index",
-    "createTreeView": True,
-    "exhaleExecutesDoxygen": True,
-    "exhaleDoxygenStdin": exhaleDoxygenStdin,
-    "afterTitleDescription": exhaleAfterTitleDescription,
-}
-nbsphinx_allow_errors = True
-nbsphinx_execute = "never"
-
-autosectionlabel_prefix_document = True
-nbsphinx_allow_directives = True
-
-myst_enable_extensions = [
-    "dollarmath",
-    "amsmath",
-    "deflist",
-    "colon_fence",
-    "html_image",
-    "linkify",
-    "attrs_block",
-    "substitution",
-]
-
-myst_heading_anchors = 3
-myst_ref_domains = ["std", "py"]
-myst_all_links_external = False
-
-intersphinx_mapping = {
-    "python": ("https://docs.python.org/3.12", None),
-    "typing_extensions": ("https://typing-extensions.readthedocs.io/en/latest", None),
-    "pillow": ("https://pillow.readthedocs.io/en/stable", None),
-    "numpy": ("https://numpy.org/doc/stable", None),
-    "torch": ("https://pytorch.org/docs/stable", None),
-}
-
-autodoc_mock_imports = ["torch"]
-autodoc_default_options = {
-    "members": True,
-    "undoc-members": True,
-    "show-inheritance": True,
-    "inherited-members": False,
-    "member-order": "bysource",
-}
-
-# -- Other Options --------------------------------------------------------
-
-templates_path = []
-
-redirects = {}
-
-source_suffix = {".rst": "restructuredtext", ".md": "markdown"}
-
-language = "en"
-
-exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "README.md"]
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = "sphinx"
-
-# A list of ignored prefixes for module index sorting.
-# If true, `todo` and `todoList` produce output, else they produce nothing.
-todo_include_todos = False
-
-# -- Options for HTML output ----------------------------------------------
-
-html_theme = "sphinx_book_theme"
-html_title = project
-html_copy_source = True
-html_last_updated_fmt = ""
-
-html_favicon = "https://tvm.apache.org/images/logo/tvm-logo-square.png"
-
-
-footer_dropdown = {
-    "name": "ASF",
-    "items": [
-        ("ASF Homepage", "https://apache.org/"),
-        ("License", "https://www.apache.org/licenses/"),
-        ("Sponsorship", "https://www.apache.org/foundation/sponsorship.html"),
-        ("Security", "https://tvm.apache.org/docs/reference/security.html"),
-        ("Thanks", "https://www.apache.org/foundation/thanks.html"),
-        ("Events", "https://www.apache.org/events/current-event"),
-    ],
-}
-
-
-footer_copyright = "Copyright © 2025, Apache Software Foundation"
-footer_note = (
-    "Apache TVM, Apache, the Apache feather, and the Apache TVM project "
-    + "logo are either trademarks or registered trademarks of the Apache Software Foundation."
-)
-
-
-def footer_html():
-    # Create footer HTML with two-line layout
-    # Generate dropdown menu items
-    dropdown_items = ""
-    for item_name, item_url in footer_dropdown["items"]:
-        dropdown_items += f'<li><a class="dropdown-item" href="{item_url}" target="_blank" style="font-size: 0.9em;">{item_name}</a></li>\n'
-
-    footer_dropdown_html = f"""
-  <div class="footer-container" style="margin: 5px 0; font-size: 0.9em; color: #6c757d;">
-      <div class="footer-line1" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 3px;">
-          <div class="footer-copyright-short">
-              {footer_copyright}
-          </div>
-          <div class="footer-dropdown">
-              <div class="dropdown">
-                  <button class="btn btn-link dropdown-toggle" type="button" id="footerDropdown" data-bs-toggle="dropdown"
-                  aria-expanded="false" style="font-size: 0.9em; color: #6c757d; text-decoration: none; padding: 0; border: none; background: none;">
-                      {footer_dropdown['name']}
-                  </button>
-                  <ul class="dropdown-menu" aria-labelledby="footerDropdown" style="font-size: 0.9em;">
-{dropdown_items}                  </ul>
-              </div>
-          </div>
-      </div>
-      <div class="footer-line2" style="font-size: 0.9em; color: #6c757d;">
-          {footer_note}
-      </div>
-  </div>
-  """
-    return footer_dropdown_html
-
-
-html_theme_options = {
-    "repository_url": "https://github.com/apache/tvm",
-    "use_repository_button": True,
-    "extra_footer": footer_html(),
-}
-
-html_context = {
-    "display_github": True,
-    "github_user": "apache",
-    "github_version": "main",
-    "conf_py_path": "/ffi/docs/",
-}
diff --git a/ffi/docs/get_started/install.md b/ffi/docs/get_started/install.md
deleted file mode 100644
index 87223d0114..0000000000
--- a/ffi/docs/get_started/install.md
+++ /dev/null
@@ -1,83 +0,0 @@
-<!--- 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. -->
-# Installation
-
-TVM FFI is built and tested on Windows, macOS, and various
-Linux distributions. You can install tvm-ffi using one of the
-methods below
-
-## Quick Start
-
-The easiest way to try it out is to install from PyPI.
-
-```bash
-pip install apache-tvm-ffi
-```
-
-After installation, you can run the following command to confirm that
-the installation was successful
-
-```bash
-tvm-ffi-config -h
-```
-
-This configuration tool is also useful in various ways to help you build
-libraries with tvm-ffi.
-
-
-## Install From Source
-
-You can also build and install tvm-ffi from source.
-
-### Dependencies
-
-- CMake (>= 3.24.0)
-- Git
-- A recent C++ compiler supporting C++17, at minimum:
-    - GCC 7.1
-    - Clang 5.0
-    - Apple Clang 9.3
-    - Visual Studio 2019 (v16.7)
-- Python (>= 3.9)
-
-
-Developers can clone the source repository from GitHub.
-
-```bash
-git clone --recursive https://github.com/apache/tvm tvm
-```
-
-```{note}
-It's important to use the ``--recursive`` flag when cloning the repository, which will
-automatically clone the submodules. If you forget to use this flag, you can manually clone the submodules
-by running ``git submodule update --init --recursive`` in the root directory.
-```
-
-Then you can install directly in development mode
-
-```bash
-cd tvm/ffi
-pip install -ve .
-```
-
-The additional `-e` flag will install the Python files in `editable` mode,
-which allows direct editing of the Python files to be immediately reflected in the package
-and is useful for development.
-
-## What to Do Next
-
-Now that you have installed TVM FFI, we recommend reading the [Quick Start](./quick_start.md) tutorial.
diff --git a/ffi/docs/get_started/quick_start.md b/ffi/docs/get_started/quick_start.md
deleted file mode 100644
index 4861aa87b2..0000000000
--- a/ffi/docs/get_started/quick_start.md
+++ /dev/null
@@ -1,213 +0,0 @@
-<!--- 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. -->
-# Quick Start
-
-This is a quick start guide explaining the basic features and usage of tvm-ffi.
-The source code can be found at `examples/quick_start` in the project source.
-
-## Build and Run the Example
-
-Let us first get started by build and run the example. The example will show us:
-
-- How to expose c++ functions as tvm ffi ABI function
-- How to load and run tvm-ffi based library from python
-- How to load and run tvm-ffi based library from c++
-
-
-Before starting, ensure you have:
-
-- TVM FFI installed following [installation](./install.md)
-- C++ compiler with C++17 support
-- CMake 3.18 or later
-- (Optional) CUDA toolkit for GPU examples
-- (Optional) PyTorch for checking torch integrations
-
-Then obtain a copy of the tvm-ffi source code.
-
-```bash
-git clone https://github.com/apache/tvm --recursive
-cd tvm/ffi
-```
-
-The examples are now in the example folder, you can quickly build
-the example using the following command.
-```bash
-cd examples/quick_start
-cmake -B build -S .
-cmake --build build
-```
-
-After the build finishes, you can run the python examples by
-```
-python run_example.py
-```
-
-You can also run the c++ example
-
-```
-./build/example
-```
-
-## Walk through the Example
-
-Now we have quickly try things out. Let us now walk through the details of the example.
-Specifically, in this example, we create a simple "add one" operation that adds 1 to each element of an input
-tensor and expose that function as TVM FFI compatible function. The key file structures are as follows:
-
-```
-examples/quick_start/
-├── src/
-│   ├── add_one_cpu.cc      # CPU implementation
-│   ├── add_one_cuda.cu     # CUDA implementation
-│   └── run_example.cc      # C++ usage example
-├── run_example.py          # Python usage example
-├── run_example.sh          # Build and run script
-└── CMakeLists.txt          # Build configuration
-```
-
-### CPU Implementation
-
-```cpp
-#include <tvm/ffi/dtype.h>
-#include <tvm/ffi/error.h>
-#include <tvm/ffi/function.h>
-
-namespace tvm_ffi_example {
-
-void AddOne(DLTensor* x, DLTensor* y) {
-  // Validate inputs
-  TVM_FFI_ICHECK(x->ndim == 1) << "x must be a 1D tensor";
-  DLDataType f32_dtype{kDLFloat, 32, 1};
-  TVM_FFI_ICHECK(x->dtype == f32_dtype) << "x must be a float tensor";
-  TVM_FFI_ICHECK(y->ndim == 1) << "y must be a 1D tensor";
-  TVM_FFI_ICHECK(y->dtype == f32_dtype) << "y must be a float tensor";
-  TVM_FFI_ICHECK(x->shape[0] == y->shape[0]) << "x and y must have the same shape";
-
-  // Perform the computation
-  for (int i = 0; i < x->shape[0]; ++i) {
-    static_cast<float*>(y->data)[i] = static_cast<float*>(x->data)[i] + 1;
-  }
-}
-
-// Expose the function through TVM FFI
-TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one_cpu, tvm_ffi_example::AddOne);
-}
-```
-
-**Key Points:**
-- Functions take `DLTensor*` parameters for cross-language compatibility
-- The `TVM_FFI_DLL_EXPORT_TYPED_FUNC` macro exposes the function with a given name
-
-### CUDA Implementation
-
-```cpp
-void AddOneCUDA(DLTensor* x, DLTensor* y) {
-  // Validation (same as CPU version)
-  // ...
-
-  int64_t n = x->shape[0];
-  int64_t nthread_per_block = 256;
-  int64_t nblock = (n + nthread_per_block - 1) / nthread_per_block;
-
-  // Get current CUDA stream from environment
-  cudaStream_t stream = static_cast<cudaStream_t>(
-      TVMFFIEnvGetStream(x->device.device_type, x->device.device_id));
-
-  // Launch kernel
-  AddOneKernel<<<nblock, nthread_per_block, 0, stream>>>(
-      static_cast<float*>(x->data), static_cast<float*>(y->data), n);
-}
-
-TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one_cuda, tvm_ffi_example::AddOneCUDA);
-```
-
-**Key Points:**
-- We use `TVMFFIEnvGetStream` to obtain the current stream from the environement
-- When invoking ffi Function from python end with PyTorch tensor as argument,
-  the stream will be populated with torch's current stream.
-
-
-### Working with PyTorch
-
-Atfer build, we will create library such as `build/add_one_cuda.so`, that can be loaded by
-with api {py:func}`tvm_ffi.load_module` that returns a {py:class}`tvm_ffi.Module`
-Then the function will become available as property of the loaded module.
-The tensor arguments in the ffi functions automatically consumes `torch.Tensor`. The following code shows how
-to use the function in torch.
-
-```python
-import torch
-import tvm_ffi
-
-if torch.cuda.is_available():
-    mod = tvm_ffi.load_module("build/add_one_cuda.so")
-
-    x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32, device="cuda")
-    y = torch.empty_like(x)
-
-    # TVM FFI automatically handles CUDA streams
-    stream = torch.cuda.Stream()
-    with torch.cuda.stream(stream):
-        mod.add_one_cuda(x, y)
-    stream.synchronize()
-```
-
-### Working with Python Data Arrays
-
-TVM FFI functions works automaticaly with python data arrays that are compatible with dlpack.
-The following examples how to use the function with numpy.
-
-```python
-import tvm_ffi
-import numpy as np
-
-# Load the compiled module
-mod = tvm_ffi.load_module("build/add_one_cpu.so")
-
-# Create input and output arrays
-x = np.array([1, 2, 3, 4, 5], dtype=np.float32)
-y = np.empty_like(x)
-
-# Call the function
-mod.add_one_cpu(x, y)
-print("Result:", y)  # [2, 3, 4, 5, 6]
-```
-
-### Working with C++
-
-One important design goal of tvm-ffi is to be universally portable.
-As a result, the result libraries do not have explicit dependencies in python
-and can be loaded in other language environments, such as c++. The following code
-shows how to run the example exported function in C++.
-
-```cpp
-#include <tvm/ffi/container/tensor.h>
-#include <tvm/ffi/extra/module.h>
-
-void CallAddOne(DLTensor* x, DLTensor *y) {
-  namespace ffi = tvm::ffi;
-  ffi::Module mod = ffi::Module::LoadFromFile("build/add_one_cpu.so");
-  ffi::Function add_one_cpu = mod->GetFunction("add_one_cpu").value();
-  add_one_cpu(x, y);
-}
-```
-
-## Summary Key Concepts
-
-- **TVM_FFI_DLL_EXPORT_TYPED_FUNC** exposes a c++ function into tvm-ffi C ABI
-- **DLTensor** is a universal tensor structure that enables zero-copy exchange of array data
-- **Module loading** is provided by tvm ffi APIs in multiple languages.
diff --git a/ffi/docs/guides/cpp_guide.md b/ffi/docs/guides/cpp_guide.md
deleted file mode 100644
index a27fe2dac1..0000000000
--- a/ffi/docs/guides/cpp_guide.md
+++ /dev/null
@@ -1,584 +0,0 @@
-<!--- 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. -->
-{#cpp-guide}
-
-# C++ Guide
-
-This guide introduces the tvm-ffi C++ API.
-We provide C++ API on top of the stable C ABI to provide a type-safe and efficient way to work with the tvm-ffi.
-The C++ API is designed to abstract away the complexity of the C ABI while maintaining full compatibility.
-The C++ API builds around the following key concepts:
-
-- **Any and AnyView**: Type-erased containers that can hold values of any supported type in tvm-ffi.
-- **Function**: A type-erased "packed" function that can be invoked like normal functions.
-- **Objects and ObjectRefs**: Reference-counted objects to manage on-heap data types.
-
-Code examples in this guide use `EXPECT_EQ` for demonstration purposes, which is a testing framework macro. In actual applications, you would use standard C++ assertions or error handling.
-You can find runnable code of the examples under tests/cpp/test_example.cc.
-
-## Any and AnyView
-
-`Any` and `AnyView` are the foundation of tvm-ffi, providing
-ways to store values that are compatible with the ffi system.
-The following example shows how we can interact with Any and AnyView.
-
-```cpp
-
-#include <tvm/ffi/any.h>
-
-void ExampleAny() {
-  namespace ffi = tvm::ffi;
-  // Create an Any from various types
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  ffi::Any int_value = 42;
-  ffi::Any float_value = 3.14;
-  ffi::Any string_value = "hello world";
-
-  // AnyView provides a lightweight view without ownership
-  ffi::AnyView view = int_value;
-  // we can cast Any/AnyView to a specific type
-  int extracted = view.cast<int>();
-  EXPECT_EQ(extracted, 42);
-
-  // If we are not sure about the type
-  // we can use as to get an optional value
-  std::optional<int> maybe_int = view.as<int>();
-  if (maybe_int.has_value()) {
-    EXPECT_EQ(maybe_int.value(), 42);
-  }
-  // Try cast is another version that will try to run the type
-  // conversion even if the type does not exactly match
-  std::optional<int> maybe_int_try = view.try_cast<int>();
-  if (maybe_int_try.has_value()) {
-    EXPECT_EQ(maybe_int_try.value(), 42);
-  }
-}
-```
-
-At a high level, we can perform the following operations:
-
-- We can store a value into Any, under the hood, Any will record the type of the value by its type_index.
-- We can fetch a value from Any or AnyView using the `cast` function.
-- If we are unsure about the type in Any, we can use `as` or `try_cast` function to get an optional value.
-
-Under the hood, Any and AnyView store the value via the ABI convention and also manage the reference
-counting correctly when the stored value is an on-heap object.
-
-## Object and ObjectRef
-
-The tvm-ffi object system provides the foundation for all managed, reference-counted objects
-in the system. It enables type safety, cross-language compatibility, and efficient memory management.
-
-The object system is built around three key classes: Object, ObjectPtr, and ObjectRef.
-The `Object` class is the base class of all heap-allocated objects. It contains a common header
-that includes the `type_index`, reference counter and deleter for the object.
-Users do not need to explicitly manage these fields as part of the C++ API. Instead,
-they are automatically managed through a smart pointer `ObjectPtr` which points
-to a heap-allocated object instance.
-The following code shows an example object and the creation of an `ObjectPtr`:
-
-```cpp
-#include <tvm/ffi/object.h>
-#include <tvm/ffi/memory.h>
-
-class MyIntPairObj : public tvm::ffi::Object {
- public:
-  int64_t a;
-  int64_t b;
-
-  MyIntPairObj() = default;
-  MyIntPairObj(int64_t a, int64_t b) : a(a), b(b) {}
-
-  // Required: declare type information
-  // to register a dynamic type index through the system
-TVM_FFI_DECLARE_OBJECT_INFO_FINAL("example.MyIntPair", MyIntPairObj, tvm::ffi::Object);
-};
-
-void ExampleObjectPtr() {
-  namespace ffi = tvm::ffi;
-  // make_object automatically sets up the deleter correctly
-  // This function creates a new ObjectPtr with proper memory management
-  // It handles allocation, initialization, and sets up the reference counting system
-  ffi::ObjectPtr<MyIntPairObj> obj = ffi::make_object<MyIntPairObj>(100, 200);
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(obj->a, 100);
-  EXPECT_EQ(obj->b, 200);
-}
-```
-
-We typically provide a reference class that wraps the ObjectPtr.
-The `ObjectRef` base class provides the interface and reference counting
-functionality for these wrapper classes.
-```cpp
-#include <tvm/ffi/object.h>
-#include <tvm/ffi/memory.h>
-
-class MyIntPair : public tvm::ffi::ObjectRef {
- public:
-  // Constructor
-  explicit MyIntPair(int64_t a, int64_t b) {
-    data_ = tvm::ffi::make_object<MyIntPairObj>(a, b);
-  }
-
-  // Required: define object reference methods
-  // This macro provides the necessary methods for ObjectRef functionality
-  TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(MyIntPair, tvm::ffi::ObjectRef, MyIntPairObj);
-};
-
-void ExampleObjectRef() {
-  namespace ffi = tvm::ffi;
-  MyIntPair pair(100, 200);
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(pair->a, 100);
-  EXPECT_EQ(pair->b, 200);
-}
-```
-
-**Note:** The ObjectRef provides a user-friendly interface while ObjectPtr handles the low-level memory management.
-The ObjectRef acts as a smart pointer wrapper that automatically manages the ObjectPtr lifecycle.
-
-The overall implementation pattern is as follows:
-- **Object Class**: Inherits from `ffi::Object`, stores data and implements the core functionality.
-- **ObjectPtr**: Smart pointer that manages the Object lifecycle and reference counting.
-- **Ref Class**: Inherits from `ffi::ObjectRef`, provides a user-friendly interface and automatic memory management.
-
-This design ensures efficient memory management while providing a clean API for users. Once we define an ObjectRef class,
-we can integrate it with the Any, AnyView and Functions.
-
-```cpp
-#include <tvm/ffi/object.h>
-#include <tvm/ffi/any.h>
-
-void ExampleObjectRefAny() {
-  namespace ffi = tvm::ffi;
-  MyIntPair pair(100, 200);
-  ffi::Any any = pair;
-  MyIntPair pair2 = any.cast<MyIntPair>();
-  // Note: EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(pair2->a, 100);
-  EXPECT_EQ(pair2->b, 200);
-}
-
-```
-
-Under the hood, ObjectPtr manages the lifecycle of the object through the same mechanism as shared pointers. We designed
-the object to be intrusive, which means the reference counter and type index metadata are embedded at the header of each object.
-This design allows us to allocate the control block and object memory together. As we will see in future sections,
-all of our heap-allocated classes such as Function, on-heap String, Array and Map are managed using subclasses of Object,
-and the user-facing classes such as Function are ObjectRefs.
-
-
-We provide a collection of built-in object and reference types, which are sufficient for common cases.
-Developers can also bring new object types as shown in the example of this section. We provide mechanisms
-to expose these objects to other language bindings such as Python.
-
-
-## Function
-
-The `Function` class provides a type-safe way to create and invoke callable objects
-through tvm-ffi ABI convention. We can create a `ffi::Function` from an existing typed lambda function.
-
-```cpp
-#include <tvm/ffi/function.h>
-
-void ExampleFunctionFromTyped() {
-  namespace ffi = tvm::ffi;
-  // Create a function from a typed lambda
-  ffi::Function fadd1 = ffi::Function::FromTyped(
-    [](const int a) -> int { return a + 1; }
-  );
-  int b = fadd1(1).cast<int>();
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(b, 2);
-}
-```
-
-Under the hood, tvm-ffi leverages Any and AnyView to create a unified ABI for
-all functions. The following example demonstrates the low-level way of defining
-a "packed" function for the same `fadd1`.
-
-```cpp
-void ExampleFunctionFromPacked() {
-  namespace ffi = tvm::ffi;
-  // Create a function from a typed lambda
-  ffi::Function fadd1 = ffi::Function::FromPacked(
-    [](const ffi::AnyView* args, int32_t num_args, ffi::Any* rv) {
-      // Check that we have exactly one argument
-      TVM_FFI_ICHECK_EQ(num_args, 1);
-      int a = args[0].cast<int>();
-      *rv = a + 1;
-    }
-  );
-  int b = fadd1(1).cast<int>();
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(b, 2);
-}
-```
-
-At a high level, `ffi::Function` implements function calling by the following convention:
-- The arguments are passed through an on-stack array of `ffi::AnyView`
-- Return values are passed through `ffi::Any`
-
-Because the return value is `ffi::Any`, we need to explicitly call `cast` to convert the return
-value to the desirable type. Importantly, `ffi::Function` itself is a value type that is compatible
-with tvm-ffi, which means we can pass it as an argument and return values. The following code shows
-an example of passing a function as an argument and applying it inside.
-
-```cpp
-void ExampleFunctionPassFunction() {
-  namespace ffi = tvm::ffi;
-  // Create a function from a typed lambda
-  ffi::Function fapply = ffi::Function::FromTyped(
-      [](const ffi::Function f, ffi::Any param) { return f(param.cast<int>()); });
-  ffi::Function fadd1 = ffi::Function::FromTyped(  //
-      [](const int a) -> int { return a + 1; });
-  int b = fapply(fadd1, 2).cast<int>();
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(b, 3);
-}
-```
-
-This pattern is very powerful because we can construct `ffi::Function` not only from C++,
-but from any languages that expose to the tvm-ffi ABI. For example, this means we can easily call functions
-passed in or registered from Python for quick debugging or other purposes.
-
-
-### Global Function Registry
-
-Besides creating functions locally, tvm-ffi provides a global function registry that allows
-functions to be registered and called across different modules and languages.
-The following code shows an example
-
-```cpp
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-
-void ExampleGlobalFunctionRegistry() {
-  namespace ffi = tvm::ffi;
-  ffi::reflection::GlobalDef().def("xyz.add1", [](const int a) -> int { return a + 1; });
-  ffi::Function fadd1 = ffi::Function::GetGlobalRequired("xyz.add1");
-  int b = fadd1(1).cast<int>();
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(b, 2);
-}
-```
-
-You can also access and register global functions from the Python API.
-
-### Exporting as Library Symbol
-
-Besides the API that allows registration of functions into the global table,
-we also provide a macro to export static functions as `TVMFFISafeCallType` symbols in a dynamic library.
-
-```c++
-void AddOne(DLTensor* x, DLTensor* y) {
-  // ... implementation omitted ...
-}
-
-TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one, my_ffi_extension::AddOne);
-```
-
-The new `add_one` takes the signature of `TVMFFISafeCallType` and can be wrapped as `ffi::Function`
-through the C++ `ffi::Module` API.
-
-```cpp
-ffi::Module mod = ffi::Module::LoadFromFile("path/to/export_lib.so");
-ffi::Function func = mod->GetFunction("add_one").value();
-```
-
-## Error Handling
-
-We provide a specific `ffi::Error` type that is also made compatible with the ffi ABI.
-We also provide a macro `TVM_FFI_THROW` to simplify the error throwing step.
-
-```cpp
-// file: cpp/test_example.cc
-#include <tvm/ffi/error.h>
-
-void FuncThrowError() {
-  namespace ffi = tvm::ffi;
-  TVM_FFI_THROW(TypeError) << "test0";
-}
-
-void ExampleErrorHandling() {
-  namespace ffi = tvm::ffi;
-  try {
-    FuncThrowError();
-  } catch (const ffi::Error& e) {
-    EXPECT_EQ(e.kind(), "TypeError");
-    EXPECT_EQ(e.message(), "test0");
-    std::cout << e.traceback() << std::endl;
-  }
-}
-```
-The structured error class records kind, message and traceback that can be mapped to
-Pythonic style error types and tracebacks. The traceback follows the Python style,
-tvm-ffi will try to preserve the traceback when possible. In the above example,
-you can see the traceback output as
-```
-... more lines omitted
-File "cpp/test_example.cc", line 106, in ExampleErrorHandling
-File "cpp/test_example.cc", line 100, in void FuncThrowError()
-```
-
-The ffi ABI provides minimal but sufficient mechanisms to propagate these errors across
-language boundaries.
-So when we call the function from Python, the Error will be translated into a corresponding
-Error type. Similarly, when we call a Python callback from C++, the error will be translated
-into the right error kind and message.
-
-
-## Tensor
-
-For many use cases, we do not need to manage the nd-array/Tensor memory.
-In such cases, `DLTensor*` can be used as the function arguments.
-There can be cases for a managed container for multi-dimensional arrays.
-`ffi::Tensor` is a minimal container to provide such support.
-Notably, specific logic of device allocations and array operations are non-goals
-of the FFI. Instead, we provide minimal generic API `ffi::Tensor::FromNDAlloc`
-to enable flexible customization of Tensor allocation.
-
-```cpp
-#include <tvm/ffi/container/tensor.h>
-#include <tvm/ffi/container/shape.h>
-
-struct CPUNDAlloc {
-  void AllocData(DLTensor* tensor) {
-    tensor->data = malloc(tvm::ffi::GetDataSize(*tensor));
-  }
-  void FreeData(DLTensor* tensor) { free(tensor->data); }
-};
-
-void ExampleTensor() {
-  namespace ffi = tvm::ffi;
-  ffi::Shape shape = {1, 2, 3};
-  DLDataType dtype = {kDLFloat, 32, 1};
-  DLDevice device = {kDLCPU, 0};
-  ffi::Tensor tensor = ffi::Tensor::FromNDAlloc(CPUNDAlloc(), shape, dtype, device);
-  // now tensor is a managed tensor
-}
-```
-
-The above example shows how we define `CPUNDAlloc` that customizes `AllocData`
-and `FreeData` behavior. The CPUNDAlloc struct will be kept alive with the Tensor object.
-This pattern allows us to implement various Tensor allocations using the same API:
-
-- For CUDA allocation, we can change malloc to cudaMalloc
-- For memory-pool based allocation, we can update `CPUNDAlloc` to keep a strong reference to the pool,
-  so we can keep memory-pool alive when the array is alive.
-
-**Working with Shapes** As you may have noticed in the example, we have a `ffi::Shape` container that is used
-to represent the shapes in nd-array. This container allows us to have compact and efficient representation
-of managed shapes and we provide quick conversions from standard vector types.
-
-### DLPack Conversion
-
-We provide first-class DLPack support to the `ffi::Tensor` that enables efficient exchange
-through the DLPack Protocol.
-
-```cpp
-#include <tvm/ffi/container/tensor.h>
-
-void ExampleTensorDLPack() {
-  namespace ffi = tvm::ffi;
-  ffi::Shape shape = {1, 2, 3};
-  DLDataType dtype = {kDLFloat, 32, 1};
-  DLDevice device = {kDLCPU, 0};
-  ffi::Tensor tensor = ffi::Tensor::FromNDAlloc(CPUNDAlloc(), shape, dtype, device);
-  // convert to DLManagedTensorVersioned
-  DLManagedTensorVersioned* dlpack = nd.ToDLPackVersioned();
-  // load back from DLManagedTensorVersioned
-  ffi::Tensor tensor2 = ffi::Tensor::FromDLPackVersioned(dlpack);
-}
-```
-
-These APIs are also available through the C APIs
-`TVMFFITensorFromDLPackVersioned` and `TVMFFITensorToDLPackVersioned`.
-
-## String and Bytes
-
-The tvm-ffi provides first-class support for `String` and `Bytes` types that are efficient,
-FFI-compatible, and interoperable with standard C++ string types.
-
-```cpp
-#include <tvm/ffi/string.h>
-
-void ExampleString() {
-  namespace ffi = tvm::ffi;
-  ffi::String str = "hello world";
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(str.size(), 11);
-  std::string std_str = str;
-  EXPECT_EQ(std_str, "hello world");
-}
-```
-
-Alternatively, users can always directly use `std::string` in function arguments, conversion
-will happen automatically.
-
-**Rationale:** We need to have separate Bytes and String so they map well to corresponding Python types.
-`ffi::String` is backed by a possibly managed object that makes it more compatible with the Object system.
-
-## Container Types
-
-To enable effective passing and storing of collections of values that are compatible with tvm-ffi,
-we provide several built-in container types.
-
-### Array
-
-`Array<T>` provides an array data type that can be used as function arguments.
-When we use `Array<T>` as an argument of a Function, it will
-perform runtime checks of the elements to ensure the values match the expected type.
-
-```cpp
-#include <tvm/ffi/container/array.h>
-
-
-void ExampleArray() {
-  namespace ffi = tvm::ffi;
-  ffi::Array<int> numbers = {1, 2, 3};
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(numbers.size(), 3);
-  EXPECT_EQ(numbers[0], 1);
-
-  ffi::Function head = ffi::Function::FromTyped([](const ffi::Array<int> a) {
-    return a[0];
-  });
-  EXPECT_EQ(head(numbers).cast<int>(), 1);
-
-  try {
-    // throw an error because 2.2 is not int
-    head(ffi::Array<ffi::Any>({1, 2.2}));
-  } catch (const ffi::Error& e) {
-    EXPECT_EQ(e.kind(), "TypeError");
-  }
-}
-```
-
-Under the hood, Array is backed by a reference-counted Object `ArrayObj` that stores
-a collection of Any values. Note that conversion from Any to `Array<T>` will result in
-runtime checks of elements because the type index only indicates `ArrayObj` as the backing storage.
-If you want to defer such checks at the FFI function boundary, consider using `Array<Any>` instead.
-When passing lists and tuples from Python, the values will be converted to `Array<Any>` before
-being passed into the Function.
-
-**Performance note:** Repeatedly converting Any to `Array<T>` can incur repeated
-checking overhead at each element. Consider using `Array<Any>` to defer checking or only run conversion once.
-
-### Tuple
-
-`Tuple<Types...>` provides type-safe fixed-size collections.
-
-```cpp
-#include <tvm/ffi/container/tuple.h>
-
-void ExampleTuple() {
-  namespace ffi = tvm::ffi;
-  ffi::Tuple<int, ffi::String, bool> tup(42, "hello", true);
-
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(tup.get<0>(), 42);
-  EXPECT_EQ(tup.get<1>(), "hello");
-  EXPECT_EQ(tup.get<2>(), true);
-}
-```
-
-Under the hood, Tuple is backed by the same `ArrayObj` as the Array container.
-This enables zero-cost exchange with input arguments.
-
-**Rationale:** This design unifies the conversion rules from Python list/tuple to
-Array/Tuple. We always need a container representation for tuples
-to be stored in Any.
-
-### Map
-
-`Map<K, V>` provides a key-value based hashmap container that can accept dict-style parameters.
-
-```cpp
-#include <tvm/ffi/container/map.h>
-
-void ExampleMap() {
-  namespace ffi = tvm::ffi;
-
-  ffi::Map<ffi::String, int> map0 = {{"Alice", 100}, {"Bob", 95}};
-
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(map0.size(), 2);
-  EXPECT_EQ(map0.at("Alice"), 100);
-  EXPECT_EQ(map0.count("Alice"), 1);
-}
-```
-
-
-Under the hood, Map is backed by a reference-counted Object `MapObj` that stores
-a collection of Any values. The implementation provides a SmallMap variant that stores
-values as an array and another variant that is based on a hashmap. The Map preserves insertion
-order like Python dictionaries. Conversion from Any to `Map<K, V>` will result in
-runtime checks of its elements because the type index only indicates `MapObj` as the backing storage.
-If you want to defer such checks at the FFI function boundary, consider using `Map<Any, Any>` instead.
-When passing dictionaries from Python, the values will be converted to `Map<Any, Any>` before
-being passed into the Function.
-
-**Performance note:** Repeatedly converting Any to `Map<K, V>` can incur repeated
-checking overhead at each element. Consider using `Map<Any, Any>` to defer checking or only run conversion once.
-
-### Optional
-
-`Optional<T>` provides a safe way to handle values that may or may not exist.
-We specialize Optional for `ffi::String` and Object types to be more compact,
-using nullptr to indicate non-existence.
-
-```cpp
-#include <tvm/ffi/container/optional.h>
-
-void ExampleOptional() {
-  namespace ffi = tvm::ffi;
-  ffi::Optional<int> opt0 = 100;
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(opt0.has_value(), true);
-  EXPECT_EQ(opt0.value(), 100);
-
-  ffi::Optional<ffi::String> opt1;
-  EXPECT_EQ(opt1.has_value(), false);
-  EXPECT_EQ(opt1.value_or("default"), "default");
-}
-```
-
-
-### Variant
-
-`Variant<Types...>` provides a type-safe union of different types.
-
-```cpp
-#include <tvm/ffi/container/variant.h>
-
-void ExampleVariant() {
-  namespace ffi = tvm::ffi;
-  ffi::Variant<int, ffi::String> var0 = 100;
-  // EXPECT_EQ is used here for demonstration purposes (testing framework)
-  EXPECT_EQ(var0.get<int>(), 100);
-
-  var0 = ffi::String("hello");
-  std::optional<ffi::String> maybe_str = var0.as<ffi::String>();
-  EXPECT_EQ(maybe_str.value(), "hello");
-
-  std::optional<int> maybe_int2 = var0.as<int>();
-  EXPECT_EQ(maybe_int2.has_value(), false);
-}
-```
-
-Under the hood, Variant is a wrapper around Any that restricts the type to the specific types in the list.
diff --git a/ffi/docs/guides/packaging.md b/ffi/docs/guides/packaging.md
deleted file mode 100644
index c12fe4e307..0000000000
--- a/ffi/docs/guides/packaging.md
+++ /dev/null
@@ -1,282 +0,0 @@
-<!--- 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. -->
-# Packaging
-
-This guide explains how to package a tvm-ffi-based library into a Python ABI-agnostic wheel.
-It demonstrates both source-level builds (for cross-compilation) and builds based on pre-shipped shared libraries.
-At a high level, packaging with tvm-ffi offers several benefits:
-
-- **ABI-agnostic wheels**: Works across different Python versions with minimal dependency.
-- **Universally deployable**: Build once with tvm-ffi and ship to different environments, including Python and non-Python environments.
-
-While this guide shows how to build a wheel package, the resulting `my_ffi_extension.so` is agnostic
-to Python, comes with minimal dependencies, and can be used in other deployment scenarios.
-
-## Build and Run the Example
-
-Let's start by building and running the example.
-First, obtain a copy of the tvm-ffi source code.
-
-```bash
-git clone https://github.com/apache/tvm --recursive
-cd tvm/ffi
-```
-
-The examples are now in the examples folder. You can quickly build
-and install the example using the following command.
-```bash
-cd examples/packaging
-pip install -v .
-```
-
-Then you can run examples that leverage the built wheel package.
-
-```bash
-python run_example.py add_one
-```
-
-## Setup pyproject.toml
-
-A typical tvm-ffi-based project has the following structure:
-
-```
-├── CMakeLists.txt          # CMake build configuration
-├── pyproject.toml          # Python packaging configuration
-├── src/
-│   └── extension.cc        # C++ source code
-├── python/
-│   └── my_ffi_extension/
-│       ├── __init__.py     # Python package initialization
-│       ├── base.py         # Library loading logic
-│       └── _ffi_api.py     # FFI API registration
-└── README.md               # Project documentation
-```
-
-The `pyproject.toml` file configures the build system and project metadata.
-
-```toml
-[project]
-name = "my-ffi-extension"
-version = "0.1.0"
-# ... more project metadata omitted ...
-
-[build-system]
-requires = ["scikit-build-core>=0.10.0", "apache-tvm-ffi"]
-build-backend = "scikit_build_core.build"
-
-[tool.scikit-build]
-# ABI-agnostic wheel
-wheel.py-api = "py3"
-# ... more build configuration omitted ...
-```
-
-We use scikit-build-core for building the wheel. Make sure you add tvm-ffi as a build-system requirement.
-Importantly, we should set `wheel.py-api` to `py3` to indicate it is ABI-generic.
-
-## Setup CMakeLists.txt
-
-The CMakeLists.txt handles the build and linking of the project.
-There are two ways you can build with tvm-ffi:
-
-- Link the pre-built `libtvm_ffi` shipped from the pip package
-- Build tvm-ffi from source
-
-For common cases, using the pre-built library and linking tvm_ffi_shared is sufficient.
-To build with the pre-built library, you can do:
-
-```cmake
-cmake_minimum_required(VERSION 3.18)
-project(my_ffi_extension)
-
-find_package(Python COMPONENTS Interpreter REQUIRED)
-execute_process(
-  COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --cmakedir
-  OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE tvm_ffi_ROOT)
-# find the prebuilt package
-find_package(tvm_ffi CONFIG REQUIRED)
-
-# ... more cmake configuration omitted ...
-
-# linking the library
-target_link_libraries(my_ffi_extension tvm_ffi_shared)
-```
-
-There are cases where one may want to cross-compile or bundle part of tvm_ffi objects directly
-into the project. In such cases, you should build from source.
-
-```cmake
-execute_process(
-  COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --sourcedir
-  OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE tvm_ffi_ROOT)
-# add the shipped source code as a cmake subdirectory
-add_subdirectory(${tvm_ffi_ROOT} tvm_ffi)
-
-# ... more cmake configuration omitted ...
-
-# linking the library
-target_link_libraries(my_ffi_extension tvm_ffi_shared)
-```
-Note that it is always safe to build from source, and the extra cost of building tvm-ffi is small
-because tvm-ffi is a lightweight library. If you are in doubt,
-you can always choose to build tvm-ffi from source.
-In Python or other cases when we dynamically load libtvm_ffi shipped with the dedicated pip package,
-you do not need to ship libtvm_ffi.so in your package even if you build tvm-ffi from source.
-The built objects are only used to supply the linking information.
-
-## Exposing C++ Functions
-
-The C++ implementation is defined in `src/extension.cc`.
-There are two ways one can expose a function in C++ to the FFI library.
-First, `TVM_FFI_DLL_EXPORT_TYPED_FUNC` can be used to expose the function directly as a C symbol that follows the tvm-ffi ABI,
-which can later be accessed via `tvm_ffi.load_module`.
-
-Here's a basic example of the function implementation:
-
-```c++
-void AddOne(DLTensor* x, DLTensor* y) {
-  // ... implementation omitted ...
-}
-
-TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one, my_ffi_extension::AddOne);
-```
-
-We can also register a function into the global function table with a given name:
-
-```c++
-void RaiseError(ffi::String msg) {
-  TVM_FFI_THROW(RuntimeError) << msg;
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
-  namespace refl = tvm::ffi::reflection;
-  refl::GlobalDef()
-    .def("my_ffi_extension.raise_error", RaiseError);
-}
-```
-
-Make sure to have a unique name across all registered functions when registering a global function.
-Always prefix with a package namespace name to avoid name collisions.
-The function can then be found via `tvm_ffi.get_global_func(name)`
-and is expected to stay throughout the lifetime of the program.
-
-We recommend using `TVM_FFI_DLL_EXPORT_TYPED_FUNC` for functions that are supposed to be dynamically
-loaded (such as JIT scenarios) so they won't be exposed to the global function table.
-
-## Library Loading in Python
-
-The base module handles loading the compiled extension:
-
-```python
-import tvm_ffi
-import os
-import sys
-
-def _load_lib():
-    file_dir = os.path.dirname(os.path.realpath(__file__))
-
-    # Platform-specific library names
-    if sys.platform.startswith("win32"):
-        lib_name = "my_ffi_extension.dll"
-    elif sys.platform.startswith("darwin"):
-        lib_name = "my_ffi_extension.dylib"
-    else:
-        lib_name = "my_ffi_extension.so"
-
-    lib_path = os.path.join(file_dir, lib_name)
-    return tvm_ffi.load_module(lib_path)
-
-_LIB = _load_lib()
-```
-
-Effectively, it leverages the `tvm_ffi.load_module` call to load the library
-extension DLL shipped along with the package. The `_ffi_api.py` contains a function
-call to `tvm_ffi.init_ffi_api` that registers all global functions prefixed
-with `my_ffi_extension` into the module.
-
-```python
-# _ffi_api.py
-import tvm_ffi
-from .base import _LIB
-
-# Register all global functions prefixed with 'my_ffi_extension.'
-# This makes functions registered via TVM_FFI_STATIC_INIT_BLOCK available
-tvm_ffi.init_ffi_api("my_ffi_extension", __name__)
-```
-
-Then we can redirect the calls to the related functions.
-
-```python
-from .base import _LIB
-from . import _ffi_api
-
-def add_one(x, y):
-    # ... docstring omitted ...
-    return _LIB.add_one(x, y)
-
-def raise_error(msg):
-    # ... docstring omitted ...
-    return _ffi_api.raise_error(msg)
-```
-
-## Build and Use the Package
-
-First, build the wheel:
-```bash
-pip wheel -v -w dist .
-```
-
-Then install the built wheel:
-```bash
-pip install dist/*.whl
-```
-
-Then you can try it out:
-
-```python
-import torch
-import my_ffi_extension
-
-# Create input and output tensors
-x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32)
-y = torch.empty_like(x)
-
-# Call the function
-my_ffi_extension.add_one(x, y)
-print(y)  # Output: tensor([2., 3., 4., 5., 6.])
-```
-
-You can also run the following command to see how errors are raised and propagated
-across language boundaries:
-
-```python
-python run_example.py raise_error
-```
-
-When possible, tvm-ffi will try to preserve tracebacks across language boundaries. You will see tracebacks like:
-```
-File "src/extension.cc", line 45, in void my_ffi_extension::RaiseError(tvm::ffi::String)
-```
-
-## Wheel Auditing
-
-When using `auditwheel`, exclude `libtvm_ffi` as it will be shipped with the `tvm_ffi` package.
-
-```bash
-auditwheel repair --exclude libtvm_ffi.so dist/*.whl
-```
-
-As long as you import `tvm_ffi` first before loading the library, the symbols will be available.
diff --git a/ffi/docs/guides/python_guide.md b/ffi/docs/guides/python_guide.md
deleted file mode 100644
index 0ab56eb9c4..0000000000
--- a/ffi/docs/guides/python_guide.md
+++ /dev/null
@@ -1,242 +0,0 @@
-<!--- 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. -->
-# Python Guide
-
-This guide introduces the `tvm_ffi` Python package.
-At a high level, the `tvm_ffi` Python package provides first-class Python support for
-
-- Pythonic classes to represent values in TVM FFI Any ABI.
-- Mechanisms to call into TVM FFI ABI compatible functions.
-- Conversion between Python values and `tvm_ffi` values.
-
-In this guide, we will run examples that make use of pre-registered testing functions in `tvm_ffi`.
-If so, we will also briefly copy snippets that show the corresponding C++ behavior.
-
-## Load and Run Module
-
-The most common use case of TVM FFI is to load a runnable module and run the corresponding function.
-You can follow the [quick start guide](../get_started/quick_start.md) for details on building the
-library `build/add_one_cpu.so`. Let's walk through the load and run example again for NumPy
-
-```python
-import tvm_ffi
-import numpy as np
-
-# Load the compiled module
-mod = tvm_ffi.load_module("build/add_one_cpu.so")
-
-# Create input and output arrays
-x = np.array([1, 2, 3, 4, 5], dtype=np.float32)
-y = np.empty_like(x)
-
-# Call the function
-mod.add_one_cpu(x, y)
-```
-
-In this case, {py:func}`tvm_ffi.load_module` will return a {py:class}`tvm_ffi.Module` class that contains
-the exported functions. You can access the functions by their names.
-
-## Tensor
-
-`tvm_ffi` provides a managed DLPack-compatible Tensor.
-
-```python
-import numpy as np
-import tvm_ffi
-
-# Demonstrate DLPack conversion between NumPy and TVM FFI
-np_data = np.array([1, 2, 3, 4], dtype=np.float32)
-tvm_array = tvm_ffi.from_dlpack(np_data)
-# Convert back to NumPy
-np_result = np.from_dlpack(tvm_array)
-```
-
-In most cases, however, you do not have to explicitly create Tensors.
-The Python interface can take in `torch.Tensor` and `numpy.ndarray` objects
-and automatically convert them to {py:class}`tvm_ffi.Tensor`.
-
-## Functions and Callbacks
-
-{py:class}`tvm_ffi.Function` provides the Python interface for `ffi::Function` in the C++.
-You can retrieve globally registered functions via {py:func}`tvm_ffi.get_global_func`.
-
-```python
-import tvm_ffi
-
-# testing.echo is defined and registered in C++
-# [](ffi::Any x) { return x; }
-fecho = tvm_ffi.get_global_func("testing.echo")
-assert fecho(1) == 1
-```
-
-You can pass a Python function as an argument to another FFI function as callbacks.
-Under the hood, {py:func}`tvm_ffi.convert` is called to convert the Python function into a
-{py:class}`tvm_ffi.Function`.
-
-```python
-import tvm_ffi
-
-# testing.apply is registered in C++
-# [](ffi::Function f, ffi::Any val) { return f(x); }
-fapply = tvm_ffi.get_global_func("testing.apply")
-# invoke fapply with lambda callback as f
-assert fapply(lambda x: x + 1, 1) == 2
-```
-
-This is a very powerful pattern that allows us to inject Python callbacks into the C++ code.
-You can also register a Python callback as a global function.
-
-```python
-import tvm_ffi
-
-@tvm_ffi.register_global_func("example.add_one")
-def add_one(a):
-    return a + 1
-
-assert tvm_ffi.get_global_func("example.add_one")(1) == 2
-```
-
-## Container Types
-
-When an FFI function takes arguments from lists/tuples, they will be converted into {py:class}`tvm_ffi.Array`.
-
-```python
-import tvm_ffi
-
-# Lists become Arrays
-arr = tvm_ffi.convert([1, 2, 3, 4])
-assert isinstance(arr, tvm_ffi.Array)
-assert len(arr) == 4
-assert arr[0] == 1
-```
-
-Dictionaries will be converted to {py:class}`tvm_ffi.Map`
-
-```python
-import tvm_ffi
-
-map_obj = tvm_ffi.convert({"a": 1, "b": 2})
-assert isinstance(map_obj, tvm_ffi.Map)
-assert len(map_obj) == 2
-assert map_obj["a"] == 1
-assert map_obj["b"] == 2
-```
-
-When container values are returned from FFI functions, they are also stored in these
-types respectively.
-
-
-## Error Handling
-
-An FFI function may raise an error. In such cases, the Python package will automatically
-translate the error to the corresponding error kind in Python
-
-```python
-import tvm_ffi
-
-# defined in C++
-# [](String kind, String msg) { throw Error(kind, msg, traceback); }
-test_raise_error = tvm_ffi.get_global_func("testing.test_raise_error")
-
-test_raise_error("ValueError", "message")
-```
-The above code shows an example where an error is raised in C++, resulting in the following error trace
-```
-Traceback (most recent call last):
-File "example.py", line 7, in <module>
-  test_raise_error("ValueError", "message")
-  ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
-File "python/tvm_ffi/cython/function.pxi", line 325, in core.Function.__call__
-  raise move_from_last_error().py_error()
-  ^^^
-File "src/ffi/extra/testing.cc", line 60, in void tvm::ffi::TestRaiseError(tvm::ffi::String, tvm::ffi::String)
-  throw ffi::Error(kind, msg, TVMFFITraceback(__FILE__, __LINE__, TVM_FFI_FUNC_SIG, 0));
-```
-
-We register common error kinds. You can also register extra error dispatch via the {py:func}`tvm_ffi.register_error` function.
-
-## Advanced: Register Your Own Object
-
-For advanced use cases, you may want to register your own objects. This can be achieved through the
-reflection registry in the TVM-FFI API. First, let's review the C++ side of the code. For this
-example, you do not need to change the C++ side as this code is pre-shipped with the testing module of the `tvm_ffi` package.
-
-```cpp
-#include <tvm/ffi/reflection/registry.h>
-
-// Step 1: Define the object class (stores the actual data)
-class TestIntPairObj : public tvm::ffi::Object {
-public:
-  int64_t a;
-  int64_t b;
-
-  TestIntPairObj() = default;
-  TestIntPairObj(int64_t a, int64_t b) : a(a), b(b) {}
-
-  // Required: declare type information
-TVM_FFI_DECLARE_OBJECT_INFO_FINAL("testing.TestIntPair", TestIntPairObj, tvm::ffi::Object);
-};
-
-// Step 2: Define the reference wrapper (user-facing interface)
-class TestIntPair : public tvm::ffi::ObjectRef {
-public:
-  // Constructor
-  explicit TestIntPair(int64_t a, int64_t b) {
-    data_ = tvm::ffi::make_object<TestIntPairObj>(a, b);
-  }
-
-  // Required: define object reference methods
-  TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestIntPair, tvm::ffi::ObjectRef, TestIntPairObj);
-};
-
-TVM_FFI_STATIC_INIT_BLOCK() {
-  namespace refl = tvm::ffi::reflection;
-  // register the object into the system
-  // register field accessors and a global static function `__create__` as ffi::Function
-  refl::ObjectDef<TestIntPairObj>()
-    .def_ro("a", &TestIntPairObj::a)
-    .def_ro("b", &TestIntPairObj::b)
-    .def_static("__create__", [](int64_t a, int64_t b) -> TestIntPair {
-      return TestIntPair(a, b);
-    });
-}
-```
-
-You can then create wrapper classes for objects that are in the library as follows:
-
-```python
-import tvm_ffi
-
-# Register the class
-@tvm_ffi.register_object("testing.TestIntPair")
-class TestIntPair(tvm_ffi.Object):
-    def __init__(self, a, b):
-        # This is a special method to call an FFI function whose return
-        # value exactly initializes the object handle of the object
-        self.__init_handle_by_constructor__(TestIntPair.__create__, a, b)
-
-test_int_pair = TestIntPair(1, 2)
-# We can access the fields by name
-# The properties are populated by the reflection mechanism
-assert test_int_pair.a == 1
-assert test_int_pair.b == 2
-```
-Under the hood, we leverage the information registered through the reflection registry to
-generate efficient field accessors and methods for each class.
-
-Importantly, when you have multiple inheritance, you need to call {py:func}`tvm_ffi.register_object`
-on both the base class and the child class.
diff --git a/ffi/docs/index.rst b/ffi/docs/index.rst
deleted file mode 100644
index 643ee41791..0000000000
--- a/ffi/docs/index.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-..  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.
-
-Apache TVM FFI Documentation
-============================
-
-Welcome to the documentation for TVM FFI. You can get started by reading the get started section,
-or reading through the guides and concepts sections.
-
-
-.. toctree::
-   :maxdepth: 1
-   :caption: Get Started
-
-   get_started/install.md
-   get_started/quick_start.md
-
-.. toctree::
-   :maxdepth: 1
-   :caption: Guides
-
-   guides/packaging.md
-   guides/cpp_guide.md
-   guides/python_guide.md
-
-
-.. toctree::
-   :maxdepth: 1
-   :caption: Concepts
-
-   concepts/abi_overview.md
-
-
-.. toctree::
-   :maxdepth: 1
-   :caption: Reference
-
-   reference/python/index.rst
-   reference/cpp/index.rst
diff --git a/ffi/docs/reference/cpp/index.rst b/ffi/docs/reference/cpp/index.rst
deleted file mode 100644
index ac9b1d73f9..0000000000
--- a/ffi/docs/reference/cpp/index.rst
+++ /dev/null
@@ -1,107 +0,0 @@
-..  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.
-
-C++ API
-=======
-
-This page contains the API reference for the C++ API. The full API index below
-can be a bit dense, so we recommend the following tips first:
-
-- Please read the :ref:`C++ Guide<cpp-guide>` for a high-level overview of the C++ API.
-
-  - The C++ Guide and examples will likely be sufficient to get started with most use cases.
-
-- The :ref:`cpp-key-classes` lists the key classes that are most commonly used.
-- You can go to the Full API Index at the bottom of this page to access the full list of APIs.
-
-  - We usually group the APIs by files. You can look at the file hierarchy in the
-    full API index and navigate to the specific file to find the APIs in that file.
-
-Header Organization
--------------------
-
-The C++ APIs are organized into the following folders:
-
-.. list-table::
-   :header-rows: 1
-   :widths: 30 70
-
-   * - Folder
-     - Description
-   * - ``tvm/ffi/``
-     - Core functionalities that support Function, Any, Object, etc.
-   * - ``tvm/ffi/container/``
-     - Additional container types such as Array, Map, Shape, Tensor, Variant ...
-   * - ``tvm/ffi/reflection/``
-     - Reflection support for function and type information registration.
-   * - ``tvm/ffi/extra/``
-     - Extra APIs that are built on top.
-
-
-.. _cpp-key-classes:
-
-Key Classes
------------
-
-.. list-table::
-   :header-rows: 1
-   :widths: 30 70
-
-   * - Class
-     - Description
-   * - :cpp:class:`tvm::ffi::Function`
-     - Type-erased function that implements the ABI.
-   * - :cpp:class:`tvm::ffi::Any`
-     - Type-erased container for any supported value.
-   * - :cpp:class:`tvm::ffi::AnyView`
-     - Lightweight view of Any without ownership.
-   * - :cpp:class:`tvm::ffi::Object`
-     - Base class for all heap-allocated FFI objects.
-   * - :cpp:class:`tvm::ffi::ObjectRef`
-     - Reference class for objects.
-   * - :cpp:class:`tvm::ffi::Tensor`
-     - Multi-dimensional tensor with DLPack support.
-   * - :cpp:class:`tvm::ffi::Shape`
-     - Tensor shape container.
-   * - :cpp:class:`tvm::ffi::Module`
-     - Dynamic library module that can load exported functions.
-   * - :cpp:class:`tvm::ffi::String`
-     - String type for FFI.
-   * - :cpp:class:`tvm::ffi::Bytes`
-     - Byte array type.
-   * - :cpp:class:`tvm::ffi::Array`
-     - Dynamic array container.
-   * - :cpp:class:`tvm::ffi::Tuple`
-     - Heterogeneous tuple container.
-   * - :cpp:class:`tvm::ffi::Map`
-     - Key-value map container.
-   * - :cpp:class:`tvm::ffi::Optional`
-     - Optional value wrapper.
-   * - :cpp:class:`tvm::ffi::Variant`
-     - Type-safe union container.
-
-
-
-.. _cpp-full-api-index:
-
-Full API Index
---------------
-
-.. toctree::
-   :maxdepth: 2
-
-   generated/index.rst
diff --git a/ffi/docs/reference/python/index.rst b/ffi/docs/reference/python/index.rst
deleted file mode 100644
index 13008089f3..0000000000
--- a/ffi/docs/reference/python/index.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-..  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.
-
-Python API
-==========
-
-.. automodule:: tvm_ffi
-  :no-members:
-
-.. currentmodule:: tvm_ffi
-
-Object
-------
-.. autosummary::
-  :toctree: generated/
-
-  Object
-  register_object
-
-
-Function and Module
--------------------
-.. autosummary::
-  :toctree: generated/
-
-
-  Function
-  Module
-  register_global_func
-  get_global_func
-  system_lib
-  load_module
-  init_ffi_api
-  register_error
-  convert
-
-
-Tensor
-------
-.. autosummary::
-  :toctree: generated/
-
-  Shape
-  Tensor
-  Device
-  from_dlpack
-
-
-Containers
-----------
-.. autosummary::
-  :toctree: generated/
-
-  Array
-  Map
diff --git a/ffi/docs/requirements.txt b/ffi/docs/requirements.txt
deleted file mode 100644
index 74784b5153..0000000000
--- a/ffi/docs/requirements.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-autodocsumm
-exhale
-breathe
-linkify-it-py
-matplotlib
-myst-parser
-nbconvert
-nbsphinx
-nbstripout
-sphinx
-sphinx-autobuild
-sphinx-book-theme
-sphinx-copybutton
-sphinx-reredirects==0.1.2
-sphinx-tabs == 3.4.1
-sphinx-toolbox == 3.4.0
-sphinxcontrib-mermaid
-sphinxcontrib-napoleon==0.7
-sphinxcontrib_httpdomain==1.8.1
-tomli
-urllib3>=2.5.0
diff --git a/ffi/examples/inline_module/main.py b/ffi/examples/inline_module/main.py
deleted file mode 100644
index 5cfcd41bec..0000000000
--- a/ffi/examples/inline_module/main.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# 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.
-
-import torch
-import tvm_ffi.cpp
-from tvm_ffi.module import Module
-
-
-def main():
-    mod: Module = tvm_ffi.cpp.load_inline(
-        name="hello",
-        cpp_sources=r"""
-            void add_one_cpu(DLTensor* x, DLTensor* y) {
-              // implementation of a library function
-              TVM_FFI_ICHECK(x->ndim == 1) << "x must be a 1D tensor";
-              DLDataType f32_dtype{kDLFloat, 32, 1};
-              TVM_FFI_ICHECK(x->dtype == f32_dtype) << "x must be a float tensor";
-              TVM_FFI_ICHECK(y->ndim == 1) << "y must be a 1D tensor";
-              TVM_FFI_ICHECK(y->dtype == f32_dtype) << "y must be a float tensor";
-              TVM_FFI_ICHECK(x->shape[0] == y->shape[0]) << "x and y must have the same shape";
-              for (int i = 0; i < x->shape[0]; ++i) {
-                static_cast<float*>(y->data)[i] = static_cast<float*>(x->data)[i] + 1;
-              }
-            }
-
-            void add_one_cuda(DLTensor* x, DLTensor* y);
-        """,
-        cuda_sources=r"""
-            __global__ void AddOneKernel(float* x, float* y, int n) {
-              int idx = blockIdx.x * blockDim.x + threadIdx.x;
-              if (idx < n) {
-                y[idx] = x[idx] + 1;
-              }
-            }
-
-            void add_one_cuda(DLTensor* x, DLTensor* y) {
-              // implementation of a library function
-              TVM_FFI_ICHECK(x->ndim == 1) << "x must be a 1D tensor";
-              DLDataType f32_dtype{kDLFloat, 32, 1};
-              TVM_FFI_ICHECK(x->dtype == f32_dtype) << "x must be a float tensor";
-              TVM_FFI_ICHECK(y->ndim == 1) << "y must be a 1D tensor";
-              TVM_FFI_ICHECK(y->dtype == f32_dtype) << "y must be a float tensor";
-              TVM_FFI_ICHECK(x->shape[0] == y->shape[0]) << "x and y must have the same shape";
-
-              int64_t n = x->shape[0];
-              int64_t nthread_per_block = 256;
-              int64_t nblock = (n + nthread_per_block - 1) / nthread_per_block;
-              // Obtain the current stream from the environment
-              // it will be set to torch.cuda.current_stream() when calling the function
-              // with torch.Tensors
-              cudaStream_t stream = static_cast<cudaStream_t>(
-                  TVMFFIEnvGetStream(x->device.device_type, x->device.device_id));
-              // launch the kernel
-              AddOneKernel<<<nblock, nthread_per_block, 0, stream>>>(static_cast<float*>(x->data),
-                                                                     static_cast<float*>(y->data), n);
-            }
-        """,
-        functions=["add_one_cpu", "add_one_cuda"],
-    )
-
-    x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32)
-    y = torch.empty_like(x)
-    mod.add_one_cpu(x, y)
-    torch.testing.assert_close(x + 1, y)
-
-    x_cuda = x.cuda()
-    y_cuda = torch.empty_like(x_cuda)
-    mod.add_one_cuda(x_cuda, y_cuda)
-    torch.testing.assert_close(x_cuda + 1, y_cuda)
-
-
-if __name__ == "__main__":
-    main()
diff --git a/ffi/examples/packaging/CMakeLists.txt b/ffi/examples/packaging/CMakeLists.txt
deleted file mode 100644
index ed55f7ca33..0000000000
--- a/ffi/examples/packaging/CMakeLists.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-# 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.
-
-cmake_minimum_required(VERSION 3.18)
-project(my_ffi_extension)
-
-option(TVM_FFI_EXT_FROM_SOURCE "Build tvm_ffi from source, useful for cross compilation." ON)
-option(TVM_FFI_EXT_SHIP_DEBUG_SYMBOLS "Ship debug symbols" ON)
-
-# There are two ways to include tvm_ffi
-#
-# 1. Build tvm_ffi from source, which is reasonably cheap since tvm ffi is small
-# 2. Use the pre-built tvm_ffi shipped from the pip
-#
-# This example shows both options, you only need to pick a specific one.
-#
-# - For common build cases, using pre-built and link tvm_ffi_shared is sufficient.
-# - For cases where you may want to cross-compile or bundle part of tvm_ffi_objects directly
-#   into your project, opt for building tvm_ffi from source path.
-#   Note that it is always safe to build from source and extra cost of building tvm_ffi is small.
-#   So when in doubt, you can always choose to the building tvm_ffi from source route.
-#
-# In python or other cases when we dynamically load libtvm_ffi_shared. Even when you build
-# from source, you do not need to ship libtvm_ffi.so built here as they are only
-# used to supply the linking information.
-# first find python related components
-find_package(Python COMPONENTS Interpreter REQUIRED)
-if (TVM_FFI_BUILD_FROM_SOURCE)
-  execute_process(
-    COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --sourcedir
-    OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE tvm_ffi_ROOT)
-  message(STATUS "Building tvm_ffi from source: ${tvm_ffi_ROOT}")
-  add_subdirectory(${tvm_ffi_ROOT} tvm_ffi)
-else()
-  # call tvm_ffi.config to get the cmake directory and set it to tvm_ffi_ROOT
-  execute_process(
-    COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --cmakedir
-    OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE tvm_ffi_ROOT)
-  find_package(tvm_ffi CONFIG REQUIRED)
-endif()
-
-# use the projects as usual
-add_library(my_ffi_extension SHARED src/extension.cc)
-target_link_libraries(my_ffi_extension tvm_ffi_header)
-target_link_libraries(my_ffi_extension tvm_ffi_shared)
-
-# show as my_ffi_extension.so
-set_target_properties(
-  my_ffi_extension PROPERTIES PREFIX ""
-)
-
-if (TVM_FFI_EXT_SHIP_DEBUG_SYMBOLS)
-  # ship debugging symbols for backtrace on macos
-  tvm_ffi_add_prefix_map(my_ffi_extension ${CMAKE_CURRENT_SOURCE_DIR})
-  tvm_ffi_add_apple_dsymutil(my_ffi_extension)
-  install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ DESTINATION . FILES_MATCHING PATTERN "*.dSYM")
-endif()
-
-install(TARGETS my_ffi_extension DESTINATION .)
diff --git a/ffi/examples/packaging/README.md b/ffi/examples/packaging/README.md
deleted file mode 100644
index 25bcc1ca3c..0000000000
--- a/ffi/examples/packaging/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--- 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. -->
-
-# TVM FFI Packaging Example
-
-This is an example project that packages a tvm-ffi based library
-into a Python ABI-agnostic wheel.
-
-This example can also serve as a guideline for general
-packaging as well.
-
-- Source-level build for cross-compilation support in CMake
-- Registration via global function table
-
-## Install the wheel
-
-```bash
-pip install .
-```
-
-### Note on build and auditwheel
-
-Note: When running the auditwheel process, make sure to skip
-`libtvm_ffi.so` as they are shipped via the tvm_ffi package.
-
-## Run the example
-
-After installing the `my_ffi_extension` example package, you can run the following example
-that invokes the `add_one` function exposed.
-
-```bash
-python run_example.py add_one
-```
-
-You can also run the following command to see how error is raised and propagated
-across the language boundaries.
-
-```python
-python run_example.py raise_error
-```
-
-When possible, tvm_ffi will try to preserve traceback across language boundary. You will see traceback like
-```
-File "src/extension.cc", line 45, in void my_ffi_extension::RaiseError(tvm::ffi::String)
-```
-If you are in an IDE like VSCode, you can click and jump to the C++ lines of error when
-the debug symbols are preserved.
diff --git a/ffi/examples/packaging/pyproject.toml b/ffi/examples/packaging/pyproject.toml
deleted file mode 100644
index 7825ca81ce..0000000000
--- a/ffi/examples/packaging/pyproject.toml
+++ /dev/null
@@ -1,58 +0,0 @@
-# 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.
-
-[project]
-name = "my-ffi-extension"
-version = "0.1.0"
-
-readme = "README.md"
-license = { text = "Apache 2.0" }
-classifiers = [
-  "License :: OSI Approved :: Apache Software License",
-  "Development Status :: 4 - Beta",
-  "Intended Audience :: Developers",
-  "Intended Audience :: Education",
-  "Intended Audience :: Science/Research",
-]
-keywords = ["machine learning", "inference"]
-requires-python = ">=3.9"
-
-dependencies = ["apache-tvm-ffi"]
-
-[build-system]
-requires = ["scikit-build-core>=0.10.0", "apache-tvm-ffi"]
-build-backend = "scikit_build_core.build"
-
-[tool.scikit-build]
-# the wheel is abi agnostic
-wheel.py-api = "py3"
-minimum-version = "build-system.requires"
-
-# Build configuration
-build-dir = "build"
-build.verbose = true
-
-# CMake configuration
-cmake.version = "CMakeLists.txt"
-cmake.build-type = "RelWithDebugInfo"
-
-# Logging
-logging.level = "INFO"
-
-# Wheel configuration
-wheel.packages = ["python/my_ffi_extension"]
-wheel.install-dir = "my_ffi_extension"
diff --git a/ffi/examples/packaging/python/my_ffi_extension/__init__.py b/ffi/examples/packaging/python/my_ffi_extension/__init__.py
deleted file mode 100644
index 4cd4207df1..0000000000
--- a/ffi/examples/packaging/python/my_ffi_extension/__init__.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# 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.
-from .base import _LIB
-from . import _ffi_api
-
-
-def add_one(x, y):
-    """
-    Adds one to the input tensor.
-
-    Parameters
-    ----------
-    x : Tensor
-      The input tensor.
-    y : Tensor
-      The output tensor.
-    """
-    return _LIB.add_one(x, y)
-
-
-def raise_error(msg):
-    """
-    Raises an error with the given message.
-
-    Parameters
-    ----------
-    msg : str
-        The message to raise the error with.
-
-    Raises
-    ------
-    RuntimeError
-        The error raised by the function.
-    """
-    return _ffi_api.raise_error(msg)
diff --git a/ffi/examples/packaging/python/my_ffi_extension/_ffi_api.py b/ffi/examples/packaging/python/my_ffi_extension/_ffi_api.py
deleted file mode 100644
index 616b1ee8e8..0000000000
--- a/ffi/examples/packaging/python/my_ffi_extension/_ffi_api.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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.
-
-import tvm_ffi
-
-# make sure lib is loaded first
-from .base import _LIB
-
-# this is a short cut to register all the global functions
-# prefixed by `my_ffi_extension.` to this module
-tvm_ffi.init_ffi_api("my_ffi_extension", __name__)
diff --git a/ffi/examples/packaging/python/my_ffi_extension/base.py b/ffi/examples/packaging/python/my_ffi_extension/base.py
deleted file mode 100644
index d65264eb71..0000000000
--- a/ffi/examples/packaging/python/my_ffi_extension/base.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# 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.
-# Base logic to load library for extension package
-import tvm_ffi
-import os
-import sys
-
-
-def _load_lib():
-    # first look at the directory of the current file
-    file_dir = os.path.dirname(os.path.realpath(__file__))
-
-    if sys.platform.startswith("win32"):
-        lib_dll_name = "my_ffi_extension.dll"
-    elif sys.platform.startswith("darwin"):
-        lib_dll_name = "my_ffi_extension.dylib"
-    else:
-        lib_dll_name = "my_ffi_extension.so"
-
-    lib_path = os.path.join(file_dir, lib_dll_name)
-    return tvm_ffi.load_module(lib_path)
-
-
-_LIB = _load_lib()
diff --git a/ffi/examples/packaging/run_example.py b/ffi/examples/packaging/run_example.py
deleted file mode 100644
index 11642257e8..0000000000
--- a/ffi/examples/packaging/run_example.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# 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.
-# Base logic to load library for extension package
-import torch
-import sys
-import my_ffi_extension
-
-
-def run_add_one():
-    x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32)
-    y = torch.empty_like(x)
-    my_ffi_extension.add_one(x, y)
-    print(y)
-
-
-def run_raise_error():
-    my_ffi_extension.raise_error("This is an error")
-
-
-if __name__ == "__main__":
-    if len(sys.argv) > 1:
-        if sys.argv[1] == "add_one":
-            run_add_one()
-        elif sys.argv[1] == "raise_error":
-            run_raise_error()
-    else:
-        print("Usage: python run_example.py <add_one|raise_error>")
diff --git a/ffi/examples/packaging/src/extension.cc b/ffi/examples/packaging/src/extension.cc
deleted file mode 100644
index 6a7324f410..0000000000
--- a/ffi/examples/packaging/src/extension.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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 example.cc
- * \brief Example of a tvm-ffi based library that registers various functions.
- *
- * It is a simple example that demonstrates how to package a tvm-ffi library into a python wheel.
- * The library is written in C++ and can be compiled into a shared library.
- * The shared library can then be loaded into python and used to call the functions.
- */
-#include <tvm/ffi/container/tensor.h>
-#include <tvm/ffi/dtype.h>
-#include <tvm/ffi/error.h>
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-
-namespace my_ffi_extension {
-
-namespace ffi = tvm::ffi;
-
-/*!
- * \brief Raises a runtime error
- *
- * This is an example function to show how to raise and propagate
- * an error across the language boundary.
- *
- * \param msg The message to raise the error with
- */
-void RaiseError(ffi::String msg) { TVM_FFI_THROW(RuntimeError) << msg; }
-
-void AddOne(ffi::Tensor x, ffi::Tensor y) {
-  // implementation of a library function
-  TVM_FFI_ICHECK(x->ndim == 1) << "x must be a 1D tensor";
-  DLDataType f32_dtype{kDLFloat, 32, 1};
-  TVM_FFI_ICHECK(x->dtype == f32_dtype) << "x must be a float tensor";
-  TVM_FFI_ICHECK(y->ndim == 1) << "y must be a 1D tensor";
-  TVM_FFI_ICHECK(y->dtype == f32_dtype) << "y must be a float tensor";
-  TVM_FFI_ICHECK(x->shape[0] == y->shape[0]) << "x and y must have the same shape";
-  for (int i = 0; i < x->shape[0]; ++i) {
-    static_cast<float*>(y->data)[i] = static_cast<float*>(x->data)[i] + 1;
-  }
-}
-
-// expose global symbol add_one
-TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one, my_ffi_extension::AddOne);
-
-// The static initialization block is
-// called once when the library is loaded.
-TVM_FFI_STATIC_INIT_BLOCK() {
-  namespace refl = tvm::ffi::reflection;
-  // In this particular example, we use the reflection mechanisms to
-  // register the functions directly into the global function table.
-  //
-  // This is an alternative approach to TVM_FFI_DLL_EXPORT_TYPED_FUNC
-  // that exports the function directly as C symbol that follows tvm-ffi abi.
-  //
-  // - For functions that are expected to be static part of tvm_ffi_example project,
-  //   one can use reflection mechanisms to register the globa function.
-  // - For functions that are compiled and dynamically loaded at runtime, consider
-  //   using the normal export mechanism so they won't be exposed to the global function table.
-  //
-  // Make sure to have a unique name across all registered functions,
-  // always prefix with a package namespace name to avoid name collision.
-  //
-  // The function can then be found via tvm_ffi.get_global_func(name)
-  // If the function is expected to stay throughout the lifetime of the program/
-  //
-  // When registering via reflection mechanisms, the library do not need to be loaded via
-  // tvm::ffi::Module::LoadFromFile, instead, just load the dll or simply bundle into the
-  // final project
-  refl::GlobalDef().def("my_ffi_extension.raise_error", RaiseError);
-}
-}  // namespace my_ffi_extension
diff --git a/ffi/examples/quick_start/CMakeLists.txt b/ffi/examples/quick_start/CMakeLists.txt
deleted file mode 100644
index 0553098800..0000000000
--- a/ffi/examples/quick_start/CMakeLists.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-# 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.
-
-cmake_minimum_required(VERSION 3.18)
-project(tvm_ffi_example)
-
-
-# first find python related components
-find_package(Python COMPONENTS Interpreter REQUIRED)
-
-# call tvm_ffi.config to get the cmake directory and set it to tvm_ffi_ROOT
-execute_process(
-  COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --cmakedir
-  OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE tvm_ffi_ROOT)
-# find package will automatically include the related projects
-find_package(tvm_ffi CONFIG REQUIRED)
-
-# use the projects as usual
-add_library(add_one_cpu SHARED src/add_one_cpu.cc)
-target_link_libraries(add_one_cpu tvm_ffi_header)
-target_link_libraries(add_one_cpu tvm_ffi_shared)
-# show as add_one_cpu.so
-set_target_properties(
-  add_one_cpu PROPERTIES
-  PREFIX ""
-  SUFFIX ".so"
-)
-
-# Check if CUDA is available
-if(NOT WIN32)
-  find_package(CUDA QUIET)
-  if(CUDA_FOUND)
-    enable_language(CUDA)
-    add_library(add_one_cuda SHARED src/add_one_cuda.cu)
-    target_link_libraries(add_one_cuda tvm_ffi_shared)
-
-    # show as add_one_cuda.so
-    set_target_properties(
-      add_one_cuda PROPERTIES
-      PREFIX ""
-      SUFFIX ".so"
-      )
-  endif()
-endif()
-
-add_executable(run_example src/run_example.cc)
-set_target_properties(
-  run_example PROPERTIES
-  CXX_STANDARD 17
-)
-target_link_libraries(run_example tvm_ffi_shared)
diff --git a/ffi/examples/quick_start/README.md b/ffi/examples/quick_start/README.md
deleted file mode 100644
index 002d4375a6..0000000000
--- a/ffi/examples/quick_start/README.md
+++ /dev/null
@@ -1,58 +0,0 @@
-<!--- 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. -->
-
-# Getting Started with TVM FFI
-
-This example demonstrates how to use tvm-ffi to expose a universal function
-that can be loaded in different environments.
-
-The example implements a simple "add one" operation that adds 1 to each element
-of an input tensor, showing how to create C++ functions callable from Python.
-
-You can run this quick start example by:
-
-```bash
-# ensure you installed tvm-ffi first
-pip install -e ../..
-
-# Build and run the complete example
-./run_example.sh
-```
-
-At a high level, the `TVM_FFI_DLL_EXPORT_TYPED_FUNC` macro helps to expose
-a C++ function into the TVM FFI C ABI convention for functions.
-Then the function can be accessed by different environments and languages
-that interface with the TVM FFI. The current example shows how to do so
-in Python and C++.
-
-## Key Files
-
-- `src/add_one_cpu.cc` - CPU implementation of the add_one function
-- `src/add_one_cuda.cu` - CUDA implementation for GPU operations
-- `run_example.py` - Python example showing how to call the functions
-- `run_example.cc` - C++ example demonstrating the same functionality
-
-## Compile without CMake
-
-You can also compile the modules directly using
-flags provided by the `tvm-ffi-config` tool.
-
-```bash
-g++ -shared -fPIC `tvm-ffi-config --cxxflags`  \
-    src/add_one_cpu.cc -o build/add_one_cpu.so \
-    `tvm-ffi-config --ldflags` `tvm-ffi-config --libs`
-```
diff --git a/ffi/examples/quick_start/run_example.py b/ffi/examples/quick_start/run_example.py
deleted file mode 100644
index a8f4fc00a6..0000000000
--- a/ffi/examples/quick_start/run_example.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# 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.
-import tvm_ffi
-
-try:
-    import torch
-except ImportError:
-    torch = None
-
-import numpy
-import ctypes
-
-
-def run_add_one_cpu():
-    """Load the add_one_cpu module and call the add_one_cpu function."""
-    mod = tvm_ffi.load_module("build/add_one_cpu.so")
-
-    x = numpy.array([1, 2, 3, 4, 5], dtype=numpy.float32)
-    y = numpy.empty_like(x)
-    # tvm-ffi automatically handles DLPack compatible tensors
-    # torch tensors can be viewed as ffi::Tensor or DLTensor*
-    # in the background
-    mod.add_one_cpu(x, y)
-    print("numpy.result after add_one(x, y)")
-    print(x)
-
-    if torch is None:
-        return
-
-    x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32)
-    y = torch.empty_like(x)
-    # tvm-ffi automatically handles DLPack compatible tensors
-    # torch tensors can be viewed as ffi::Tensor or DLTensor*
-    # in the background
-    mod.add_one_cpu(x, y)
-    print("torch.result after add_one(x, y)")
-    print(y)
-
-
-def run_add_one_cuda():
-    """Load the add_one_cuda module and call the add_one_cuda function."""
-    if torch is None or not torch.cuda.is_available():
-        return
-
-    mod = tvm_ffi.load_module("build/add_one_cuda.so")
-    x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32, device="cuda")
-    y = torch.empty_like(x)
-
-    stream = torch.cuda.Stream()
-    with torch.cuda.stream(stream):
-        # tvm-ffi automatically handles DLPack compatible tensors
-        # it also handles interactions with torch runtime
-        # torch.cuda.current_stream() will be set and available via TVMFFIEnvGetStream
-        # when calling the function
-        mod.add_one_cuda(x, y)
-    stream.synchronize()
-    print("torch.result after mod.add_one_cuda(x, y)")
-    print(y)
-
-
-def main():
-    """Main function to run the example."""
-    run_add_one_cpu()
-    run_add_one_cuda()
-
-
-if __name__ == "__main__":
-    main()
diff --git a/ffi/examples/quick_start/run_example.sh b/ffi/examples/quick_start/run_example.sh
deleted file mode 100755
index 0602b85f37..0000000000
--- a/ffi/examples/quick_start/run_example.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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.
-#!/bin/bash
-set -ex
-
-cmake -B build -S .
-cmake --build build
-
-# running python example
-python run_example.py
-
-# running c++ example
-./build/run_example
diff --git a/ffi/examples/quick_start/src/add_one_cpu.cc b/ffi/examples/quick_start/src/add_one_cpu.cc
deleted file mode 100644
index 76b9b3752c..0000000000
--- a/ffi/examples/quick_start/src/add_one_cpu.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-#include <tvm/ffi/container/tensor.h>
-#include <tvm/ffi/dtype.h>
-#include <tvm/ffi/error.h>
-#include <tvm/ffi/function.h>
-
-namespace tvm_ffi_example {
-
-void AddOne(tvm::ffi::Tensor x, tvm::ffi::Tensor y) {
-  // implementation of a library function
-  TVM_FFI_ICHECK(x->ndim == 1) << "x must be a 1D tensor";
-  DLDataType f32_dtype{kDLFloat, 32, 1};
-  TVM_FFI_ICHECK(x->dtype == f32_dtype) << "x must be a float tensor";
-  TVM_FFI_ICHECK(y->ndim == 1) << "y must be a 1D tensor";
-  TVM_FFI_ICHECK(y->dtype == f32_dtype) << "y must be a float tensor";
-  TVM_FFI_ICHECK(x->shape[0] == y->shape[0]) << "x and y must have the same shape";
-  for (int i = 0; i < x->shape[0]; ++i) {
-    static_cast<float*>(y->data)[i] = static_cast<float*>(x->data)[i] + 1;
-  }
-}
-
-// Expose global symbol `add_one_cpu` that follows tvm-ffi abi
-TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one_cpu, tvm_ffi_example::AddOne);
-}  // namespace tvm_ffi_example
diff --git a/ffi/examples/quick_start/src/add_one_cuda.cu b/ffi/examples/quick_start/src/add_one_cuda.cu
deleted file mode 100644
index 52f1e74825..0000000000
--- a/ffi/examples/quick_start/src/add_one_cuda.cu
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- */
-#include <tvm/ffi/container/tensor.h>
-#include <tvm/ffi/dtype.h>
-#include <tvm/ffi/error.h>
-#include <tvm/ffi/extra/c_env_api.h>
-#include <tvm/ffi/function.h>
-
-namespace tvm_ffi_example {
-
-__global__ void AddOneKernel(float* x, float* y, int n) {
-  int idx = blockIdx.x * blockDim.x + threadIdx.x;
-  if (idx < n) {
-    y[idx] = x[idx] + 1;
-  }
-}
-
-void AddOneCUDA(tvm::ffi::Tensor x, tvm::ffi::Tensor y) {
-  // implementation of a library function
-  TVM_FFI_ICHECK(x->ndim == 1) << "x must be a 1D tensor";
-  DLDataType f32_dtype{kDLFloat, 32, 1};
-  TVM_FFI_ICHECK(x->dtype == f32_dtype) << "x must be a float tensor";
-  TVM_FFI_ICHECK(y->ndim == 1) << "y must be a 1D tensor";
-  TVM_FFI_ICHECK(y->dtype == f32_dtype) << "y must be a float tensor";
-  TVM_FFI_ICHECK(x->shape[0] == y->shape[0]) << "x and y must have the same shape";
-
-  int64_t n = x->shape[0];
-  int64_t nthread_per_block = 256;
-  int64_t nblock = (n + nthread_per_block - 1) / nthread_per_block;
-  // Obtain the current stream from the environment
-  // it will be set to torch.cuda.current_stream() when calling the function
-  // with torch.Tensors
-  cudaStream_t stream =
-      static_cast<cudaStream_t>(TVMFFIEnvGetStream(x->device.device_type, x->device.device_id));
-  // launch the kernel
-  AddOneKernel<<<nblock, nthread_per_block, 0, stream>>>(static_cast<float*>(x->data),
-                                                         static_cast<float*>(y->data), n);
-}
-
-// Expose global symbol `add_one_cpu` that follows tvm-ffi abi
-TVM_FFI_DLL_EXPORT_TYPED_FUNC(add_one_cuda, tvm_ffi_example::AddOneCUDA);
-}  // namespace tvm_ffi_example
diff --git a/ffi/examples/quick_start/src/run_example.cc b/ffi/examples/quick_start/src/run_example.cc
deleted file mode 100644
index 90e61d170b..0000000000
--- a/ffi/examples/quick_start/src/run_example.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-#include <tvm/ffi/container/tensor.h>
-#include <tvm/ffi/extra/module.h>
-
-// This file shows how to load the same compiled module and interact with it in C++
-namespace ffi = tvm::ffi;
-
-struct CPUNDAlloc {
-  void AllocData(DLTensor* tensor) { tensor->data = malloc(ffi::GetDataSize(*tensor)); }
-  void FreeData(DLTensor* tensor) { free(tensor->data); }
-};
-
-inline ffi::Tensor Empty(ffi::Shape shape, DLDataType dtype, DLDevice device) {
-  return ffi::Tensor::FromNDAlloc(CPUNDAlloc(), shape, dtype, device);
-}
-
-int main() {
-  // load the module
-  ffi::Module mod = ffi::Module::LoadFromFile("build/add_one_cpu.so");
-
-  // create an Tensor, alternatively, one can directly pass in a DLTensor*
-  ffi::Tensor x = Empty({5}, DLDataType({kDLFloat, 32, 1}), DLDevice({kDLCPU, 0}));
-  for (int i = 0; i < 5; ++i) {
-    reinterpret_cast<float*>(x->data)[i] = static_cast<float>(i);
-  }
-
-  ffi::Function add_one_cpu = mod->GetFunction("add_one_cpu").value();
-  add_one_cpu(x, x);
-
-  std::cout << "x after add_one_cpu(x, x)" << std::endl;
-  for (int i = 0; i < 5; ++i) {
-    std::cout << reinterpret_cast<float*>(x->data)[i] << " ";
-  }
-  std::cout << std::endl;
-  return 0;
-}
diff --git a/ffi/include/tvm/ffi/any.h b/ffi/include/tvm/ffi/any.h
deleted file mode 100644
index 738adc4f86..0000000000
--- a/ffi/include/tvm/ffi/any.h
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * 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/any.h
- * \brief Any value support.
- */
-#ifndef TVM_FFI_ANY_H_
-#define TVM_FFI_ANY_H_
-
-#include <tvm/ffi/c_api.h>
-#include <tvm/ffi/string.h>
-#include <tvm/ffi/type_traits.h>
-
-#include <string>
-#include <utility>
-
-namespace tvm {
-namespace ffi {
-
-class Any;
-
-namespace details {
-// Helper to perform
-// unsafe operations related to object
-struct AnyUnsafe;
-}  // namespace details
-
-/*!
- * \brief AnyView allows us to take un-managed reference view of any value.
- */
-class AnyView {
- protected:
-  /*! \brief The underlying backing data of the any object */
-  TVMFFIAny data_;
-  // Any can see AnyView
-  friend class Any;
-
- public:
-  // NOTE: the following functions use style
-  // since they are common functions appearing in FFI.
-  /*!
-   * \brief Reset any view to None
-   */
-  void reset() {
-    data_.type_index = TypeIndex::kTVMFFINone;
-    // invariance: always set the union padding part to 0
-    data_.zero_padding = 0;
-    data_.v_int64 = 0;
-  }
-  /*!
-   * \brief Swap this AnyView with another AnyView
-   * \param other The other AnyView
-   */
-  TVM_FFI_INLINE void swap(AnyView& other) noexcept { std::swap(data_, other.data_); }
-  /*! \return the internal type index */
-  TVM_FFI_INLINE int32_t type_index() const noexcept { return data_.type_index; }
-  /*! \brief Default constructor */
-  AnyView() {
-    data_.type_index = TypeIndex::kTVMFFINone;
-    data_.zero_padding = 0;
-    data_.v_int64 = 0;
-  }
-  ~AnyView() = default;
-  // constructors from any view
-  /*! \brief Copy constructor */
-  AnyView(const AnyView&) = default;
-  /*! \brief Copy assignment operator */
-  AnyView& operator=(const AnyView&) = default;
-  /*! \brief Move constructor */
-  AnyView(AnyView&& other) : data_(other.data_) {
-    other.data_.type_index = TypeIndex::kTVMFFINone;
-    other.data_.zero_padding = 0;
-    other.data_.v_int64 = 0;
-  }
-  TVM_FFI_INLINE AnyView& operator=(AnyView&& other) {
-    // copy-and-swap idiom
-    AnyView(std::move(other)).swap(*this);  // NOLINT(*)
-    return *this;
-  }
-  /*!
-   * \brief Constructor from a general type.
-   * \tparam T The type to convert from.
-   * \param other The value to convert from.
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::convert_enabled>>
-  AnyView(const T& other) {  // NOLINT(*)
-    TypeTraits<T>::CopyToAnyView(other, &data_);
-  }
-  /*!
-   * \brief Assign from a general type.
-   * \tparam T The type to convert from.
-   * \param other The value to convert from.
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::convert_enabled>>
-  TVM_FFI_INLINE AnyView& operator=(const T& other) {  // NOLINT(*)
-    // copy-and-swap idiom
-    AnyView(other).swap(*this);  // NOLINT(*)
-    return *this;
-  }
-
-  /*!
-   * \brief Try to see if we can reinterpret the AnyView to as T object.
-   *
-   * \tparam T The type to cast to.
-   * \return The casted value, or std::nullopt if the cast is not possible.
-   * \note This function won't try run type conversion (use try_cast for that purpose).
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::convert_enabled>>
-  TVM_FFI_INLINE std::optional<T> as() const {
-    if (TypeTraits<T>::CheckAnyStrict(&data_)) {
-      return TypeTraits<T>::CopyFromAnyViewAfterCheck(&data_);
-    } else {
-      return std::optional<T>(std::nullopt);
-    }
-  }
-  /*!
-   * \brief Shortcut of as Object to cast to a const pointer when T is an Object.
-   *
-   * \tparam T The object type.
-   * \return The requested pointer, returns nullptr if type mismatches.
-   */
-  template <typename T, typename = std::enable_if_t<std::is_base_of_v<Object, T>>>
-  TVM_FFI_INLINE const T* as() const {
-    return this->as<const T*>().value_or(nullptr);
-  }
-
-  /*!
-   * \brief Cast to a type T.
-   *
-   * \tparam T The type to cast to.
-   * \return The casted value, or throws an exception if the cast is not possible.
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::convert_enabled>>
-  TVM_FFI_INLINE T cast() const {
-    std::optional<T> opt = TypeTraits<T>::TryCastFromAnyView(&data_);
-    if (!opt.has_value()) {
-      TVM_FFI_THROW(TypeError) << "Cannot convert from type `"
-                               << TypeTraits<T>::GetMismatchTypeInfo(&data_) << "` to `"
-                               << TypeTraits<T>::TypeStr() << "`";
-    }
-    return *std::move(opt);
-  }
-
-  /*!
-   * \brief Try to cast to a type T, return std::nullopt if the cast is not possible.
-   *
-   * \tparam T The type to cast to.
-   * \return The casted value, or std::nullopt if the cast is not possible.
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::convert_enabled>>
-  TVM_FFI_INLINE std::optional<T> try_cast() const {
-    return TypeTraits<T>::TryCastFromAnyView(&data_);
-  }
-
-  // comparison with nullptr
-  TVM_FFI_INLINE bool operator==(std::nullptr_t) const noexcept {
-    return data_.type_index == TypeIndex::kTVMFFINone;
-  }
-  TVM_FFI_INLINE bool operator!=(std::nullptr_t) const noexcept {
-    return data_.type_index != TypeIndex::kTVMFFINone;
-  }
-  /*!
-   * \brief Get the type key of the Any
-   * \return The type key of the Any
-   */
-  TVM_FFI_INLINE std::string GetTypeKey() const { return TypeIndexToTypeKey(data_.type_index); }
-  // The following functions are only used for testing purposes
-  /*!
-   * \return The underlying supporting data of any view
-   * \note This function is used only for testing purposes.
-   */
-  TVM_FFI_INLINE TVMFFIAny CopyToTVMFFIAny() const { return data_; }
-  /*!
-   * \return Create an AnyView from TVMFFIAny
-   * \param data the underlying ffi data.
-   */
-  TVM_FFI_INLINE static AnyView CopyFromTVMFFIAny(TVMFFIAny data) {
-    AnyView view;
-    view.data_ = data;
-    return view;
-  }
-};
-
-namespace details {
-/*!
- * \brief Helper function to inplace convert any view to any.
- * \param data The pointer that represents the format as any view.
- * \param extra_any_bytes Indicate that the data may contain extra bytes following
- *  the TVMFFIAny data structure. This is reserved for future possible optimizations
- *  of small-string and extended any object.
- */
-TVM_FFI_INLINE void InplaceConvertAnyViewToAny(TVMFFIAny* data,
-                                               [[maybe_unused]] size_t extra_any_bytes = 0) {
-  if (data->type_index >= TVMFFITypeIndex::kTVMFFIStaticObjectBegin) {
-    details::ObjectUnsafe::IncRefObjectHandle(data->v_obj);
-  } else if (data->type_index >= TypeIndex::kTVMFFIRawStr) {
-    if (data->type_index == TypeIndex::kTVMFFIRawStr) {
-      // convert raw string to owned string object
-      String temp(data->v_c_str);
-      TypeTraits<String>::MoveToAny(std::move(temp), data);
-    } else if (data->type_index == TypeIndex::kTVMFFIByteArrayPtr) {
-      // convert byte array to owned bytes object
-      Bytes temp(*static_cast<TVMFFIByteArray*>(data->v_ptr));
-      TypeTraits<Bytes>::MoveToAny(std::move(temp), data);
-    } else if (data->type_index == TypeIndex::kTVMFFIObjectRValueRef) {
-      // convert rvalue ref to owned object
-      Object** obj_addr = static_cast<Object**>(data->v_ptr);
-      TVM_FFI_ICHECK(obj_addr[0] != nullptr) << "RValueRef already moved";
-      ObjectRef temp(details::ObjectUnsafe::ObjectPtrFromOwned<Object>(obj_addr[0]));
-      // set the rvalue ref to nullptr to avoid double move
-      obj_addr[0] = nullptr;
-      TypeTraits<ObjectRef>::MoveToAny(std::move(temp), data);
-    }
-  }
-}
-}  // namespace details
-
-/*!
- * \brief Managed Any that takes strong reference to a value.
- *
- * \note Develooper invariance: the TVMFFIAny data_
- *       in the Any can be safely used in AnyView.
- */
-class Any {
- protected:
-  /*! \brief The underlying backing data of the any object */
-  TVMFFIAny data_;
-
- public:
-  /*!
-   * \brief Reset any to None
-   */
-  TVM_FFI_INLINE void reset() {
-    if (data_.type_index >= TVMFFITypeIndex::kTVMFFIStaticObjectBegin) {
-      details::ObjectUnsafe::DecRefObjectHandle(data_.v_obj);
-    }
-    data_.type_index = TVMFFITypeIndex::kTVMFFINone;
-    data_.zero_padding = 0;
-    data_.v_int64 = 0;
-  }
-  /*!
-   * \brief Swap this Any with another Any
-   * \param other The other Any
-   */
-  TVM_FFI_INLINE void swap(Any& other) noexcept { std::swap(data_, other.data_); }
-  /*! \return the internal type index */
-  TVM_FFI_INLINE int32_t type_index() const noexcept { return data_.type_index; }
-  /*!
-   * \brief Default constructor
-   */
-  Any() {
-    data_.type_index = TypeIndex::kTVMFFINone;
-    data_.zero_padding = 0;
-    data_.v_int64 = 0;
-  }
-  /*!
-   * \brief Destructor
-   */
-  ~Any() { this->reset(); }
-  /*!
-   * \brief Constructor from another Any
-   * \param other The other Any
-   */
-  Any(const Any& other) : data_(other.data_) {
-    if (data_.type_index >= TypeIndex::kTVMFFIStaticObjectBegin) {
-      details::ObjectUnsafe::IncRefObjectHandle(data_.v_obj);
-    }
-  }
-  /*!
-   * \brief Move constructor from another Any
-   * \param other The other Any
-   */
-  Any(Any&& other) : data_(other.data_) {
-    other.data_.type_index = TypeIndex::kTVMFFINone;
-    other.data_.zero_padding = 0;
-    other.data_.v_int64 = 0;
-  }
-  /*!
-   * \brief Assign from another Any
-   * \param other The other Any
-   */
-  TVM_FFI_INLINE Any& operator=(const Any& other) {
-    // copy-and-swap idiom
-    Any(other).swap(*this);  // NOLINT(*)
-    return *this;
-  }
-  /*!
-   * \brief Move assign from another Any
-   * \param other The other Any
-   */
-  TVM_FFI_INLINE Any& operator=(Any&& other) {
-    // copy-and-swap idiom
-    Any(std::move(other)).swap(*this);  // NOLINT(*)
-    return *this;
-  }
-  /*!
-   * \brief Constructor from another AnyView
-   * \param other The other AnyView
-   */
-  Any(const AnyView& other) : data_(other.data_) {  // NOLINT(*)
-    details::InplaceConvertAnyViewToAny(&data_);
-  }
-  /*!
-   * \brief Assign from another AnyView
-   * \param other The other AnyView
-   */
-  TVM_FFI_INLINE Any& operator=(const AnyView& other) {
-    // copy-and-swap idiom
-    Any(other).swap(*this);  // NOLINT(*)
-    return *this;
-  }
-  /*! \brief Any can be converted to AnyView in zero cost. */
-  operator AnyView() const { return AnyView::CopyFromTVMFFIAny(data_); }
-  /*!
-   * \brief Constructor from a general type
-   * \tparam T The value type of the other
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::convert_enabled>>
-  Any(T other) {  // NOLINT(*)
-    TypeTraits<T>::MoveToAny(std::move(other), &data_);
-  }
-  /*!
-   * \brief Assignment from a general type
-   * \tparam T The value type of the other
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::convert_enabled>>
-  TVM_FFI_INLINE Any& operator=(T other) {  // NOLINT(*)
-    // copy-and-swap idiom
-    Any(std::move(other)).swap(*this);  // NOLINT(*)
-    return *this;
-  }
-
-  /**
-   * \brief Try to reinterpret the Any as a type T, return std::nullopt if it is not possible.
-   *
-   * \tparam T The type to cast to.
-   * \return The casted value, or std::nullopt if the cast is not possible.
-   * \note This function won't try to run type conversion (use try_cast for that purpose).
-   */
-  template <typename T,
-            typename = std::enable_if_t<TypeTraits<T>::storage_enabled || std::is_same_v<T, Any>>>
-  TVM_FFI_INLINE std::optional<T> as() && {
-    if constexpr (std::is_same_v<T, Any>) {
-      return std::move(*this);
-    } else {
-      if (TypeTraits<T>::CheckAnyStrict(&data_)) {
-        return TypeTraits<T>::MoveFromAnyAfterCheck(&data_);
-      } else {
-        return std::optional<T>(std::nullopt);
-      }
-    }
-  }
-
-  /**
-   * \brief Try to reinterpret the Any as a type T, return std::nullopt if it is not possible.
-   *
-   * \tparam T The type to cast to.
-   * \return The casted value, or std::nullopt if the cast is not possible.
-   * \note This function won't try to run type conversion (use try_cast for that purpose).
-   */
-  template <typename T,
-            typename = std::enable_if_t<TypeTraits<T>::convert_enabled || std::is_same_v<T, Any>>>
-  TVM_FFI_INLINE std::optional<T> as() const& {
-    if constexpr (std::is_same_v<T, Any>) {
-      return *this;
-    } else {
-      if (TypeTraits<T>::CheckAnyStrict(&data_)) {
-        return TypeTraits<T>::CopyFromAnyViewAfterCheck(&data_);
-      } else {
-        return std::optional<T>(std::nullopt);
-      }
-    }
-  }
-
-  /*!
-   * \brief Shortcut of as Object to cast to a const pointer when T is an Object.
-   *
-   * \tparam T The object type.
-   * \return The requested pointer, returns nullptr if type mismatches.
-   */
-  template <typename T, typename = std::enable_if_t<std::is_base_of_v<Object, T>>>
-  TVM_FFI_INLINE const T* as() const& {
-    return this->as<const T*>().value_or(nullptr);
-  }
-
-  /**
-   * \brief Cast to a type T, throw an exception if the cast is not possible.
-   *
-   * \tparam T The type to cast to.
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::convert_enabled>>
-  TVM_FFI_INLINE T cast() const& {
-    std::optional<T> opt = TypeTraits<T>::TryCastFromAnyView(&data_);
-    if (!opt.has_value()) {
-      TVM_FFI_THROW(TypeError) << "Cannot convert from type `"
-                               << TypeTraits<T>::GetMismatchTypeInfo(&data_) << "` to `"
-                               << TypeTraits<T>::TypeStr() << "`";
-    }
-    return *std::move(opt);
-  }
-
-  /**
-   * \brief Cast to a type T, throw an exception if the cast is not possible.
-   *
-   * \tparam T The type to cast to.
-   */
-  template <typename T, typename = std::enable_if_t<TypeTraits<T>::storage_enabled>>
-  TVM_FFI_INLINE T cast() && {
-    if (TypeTraits<T>::CheckAnyStrict(&data_)) {
-      return TypeTraits<T>::MoveFromAnyAfterCheck(&data_);
-    }
-    // slow path, try to do fallback convert
-    std::optional<T> opt = TypeTraits<T>::TryCastFromAnyView(&data_);
-    if (!opt.has_value()) {
-      TVM_FFI_THROW(TypeError) << "Cannot convert from type `"
-                               << TypeTraits<T>::GetMismatchTypeInfo(&data_) << "` to `"
-                               << TypeTraits<T>::TypeStr() << "`";
-    }
-    return *std::move(opt);
-  }
-
-  /**
-   * \brief Try to cast to a type T.
-   *
-   * \tparam T The type to cast to.
-   * \return The casted value, or std::nullopt if the cast is not possible.
-   * \note use STL name since it to be more consistent with cast API.
-   */
-  template <typename T,
-            typename = std::enable_if_t<TypeTraits<T>::convert_enabled || std::is_same_v<T, Any>>>
-  TVM_FFI_INLINE std::optional<T> try_cast() const {
-    if constexpr (std::is_same_v<T, Any>) {
-      return *this;
-    } else {
-      return TypeTraits<T>::TryCastFromAnyView(&data_);
-    }
-  }
-  /*!
-   * \brief Check if the two Any are same type and value in shallow comparison.
-   * \param other The other Any
-   * \return True if the two Any are same type and value, false otherwise.
-   */
-  TVM_FFI_INLINE bool same_as(const Any& other) const noexcept {
-    return data_.type_index == other.data_.type_index &&
-           data_.zero_padding == other.data_.zero_padding && data_.v_int64 == other.data_.v_int64;
-  }
-
-  /*!
-   * \brief Check if any and ObjectRef are same type and value in shallow comparison.
-   * \param other The other ObjectRef
-   * \return True if the two Any are same type and value, false otherwise.
-   */
-  TVM_FFI_INLINE bool same_as(const ObjectRef& other) const noexcept {
-    if (other.get() != nullptr) {
-      return (data_.type_index == other->type_index() &&
-              reinterpret_cast<Object*>(data_.v_obj) == other.get());
-    } else {
-      return data_.type_index == TypeIndex::kTVMFFINone;
-    }
-  }
-
-  TVM_FFI_INLINE bool operator==(std::nullptr_t) const noexcept {
-    return data_.type_index == TypeIndex::kTVMFFINone;
-  }
-  TVM_FFI_INLINE bool operator!=(std::nullptr_t) const noexcept {
-    return data_.type_index != TypeIndex::kTVMFFINone;
-  }
-
-  /*!
-   * \brief Get the type key of the Any
-   * \return The type key of the Any
-   */
-  TVM_FFI_INLINE std::string GetTypeKey() const { return TypeIndexToTypeKey(data_.type_index); }
-
-  friend struct details::AnyUnsafe;
-  friend struct AnyHash;
-  friend struct AnyEqual;
-};
-
-// layout assert to ensure we can freely cast between the two types
-static_assert(sizeof(AnyView) == sizeof(TVMFFIAny));
-static_assert(sizeof(Any) == sizeof(TVMFFIAny));
-
-namespace details {
-
-template <typename Type>
-struct Type2Str {
-  static std::string v() { return TypeTraitsNoCR<Type>::TypeStr(); }
-};
-
-template <>
-struct Type2Str<Any> {
-  static std::string v() { return "Any"; }
-};
-
-template <>
-struct Type2Str<const Any&> {
-  static std::string v() { return "Any"; }
-};
-
-template <>
-struct Type2Str<AnyView> {
-  static std::string v() { return "AnyView"; }
-};
-
-template <>
-struct Type2Str<const AnyView&> {
-  static std::string v() { return "AnyView"; }
-};
-
-template <>
-struct Type2Str<void> {
-  static std::string v() { return "void"; }
-};
-
-// Extra unsafe method to help any manipulation
-struct AnyUnsafe : public ObjectUnsafe {
-  // FFI related operations
-  TVM_FFI_INLINE static TVMFFIAny MoveAnyToTVMFFIAny(Any&& any) {
-    TVMFFIAny result = any.data_;
-    any.data_.type_index = TypeIndex::kTVMFFINone;
-    any.data_.zero_padding = 0;
-    any.data_.v_int64 = 0;
-    return result;
-  }
-
-  TVM_FFI_INLINE static Any MoveTVMFFIAnyToAny(TVMFFIAny&& data) {
-    Any any;
-    any.data_ = data;
-    data.type_index = TypeIndex::kTVMFFINone;
-    data.zero_padding = 0;
-    data.v_int64 = 0;
-    return any;
-  }
-
-  template <typename T>
-  TVM_FFI_INLINE static bool CheckAnyStrict(const Any& ref) {
-    return TypeTraits<T>::CheckAnyStrict(&(ref.data_));
-  }
-
-  template <typename T>
-  TVM_FFI_INLINE static T CopyFromAnyViewAfterCheck(const Any& ref) {
-    if constexpr (!std::is_same_v<T, Any>) {
-      return TypeTraits<T>::CopyFromAnyViewAfterCheck(&(ref.data_));
-    } else {
-      return ref;
-    }
-  }
-
-  template <typename T>
-  TVM_FFI_INLINE static T MoveFromAnyAfterCheck(Any&& ref) {
-    if constexpr (!std::is_same_v<T, Any>) {
-      return TypeTraits<T>::MoveFromAnyAfterCheck(&(ref.data_));
-    } else {
-      return std::move(ref);
-    }
-  }
-
-  TVM_FFI_INLINE static Object* ObjectPtrFromAnyAfterCheck(const Any& ref) {
-    return reinterpret_cast<Object*>(ref.data_.v_obj);
-  }
-
-  TVM_FFI_INLINE static const TVMFFIAny* TVMFFIAnyPtrFromAny(const Any& ref) {
-    return &(ref.data_);
-  }
-
-  template <typename T>
-  TVM_FFI_INLINE static std::string GetMismatchTypeInfo(const Any& ref) {
-    return TypeTraits<T>::GetMismatchTypeInfo(&(ref.data_));
-  }
-};
-}  // namespace details
-
-/*! \brief String-aware Any equal functor */
-struct AnyHash {
-  /*!
-   * \brief Calculate the hash code of an Any
-   * \param a The given Any
-   * \return Hash code of a, string hash for strings and pointer address otherwise.
-   */
-  uint64_t operator()(const Any& src) const {
-    if (src.data_.type_index == TypeIndex::kTVMFFISmallStr) {
-      // for small string, we use the same type key hash as normal string
-      // so heap allocated string and on stack string will have the same hash
-      return details::StableHashCombine(TypeIndex::kTVMFFIStr,
-                                        details::StableHashSmallStrBytes(&src.data_));
-    } else if (src.data_.type_index == TypeIndex::kTVMFFISmallBytes) {
-      // use byte the same type key as bytes
-      return details::StableHashCombine(TypeIndex::kTVMFFIBytes,
-                                        details::StableHashSmallStrBytes(&src.data_));
-    } else if (src.data_.type_index == TypeIndex::kTVMFFIStr ||
-               src.data_.type_index == TypeIndex::kTVMFFIBytes) {
-      const details::BytesObjBase* src_str =
-          details::AnyUnsafe::CopyFromAnyViewAfterCheck<const details::BytesObjBase*>(src);
-      return details::StableHashCombine(src.data_.type_index,
-                                        details::StableHashBytes(src_str->data, src_str->size));
-    } else {
-      return details::StableHashCombine(src.data_.type_index, src.data_.v_uint64);
-    }
-  }
-};
-
-/*! \brief String-aware Any hash functor */
-struct AnyEqual {
-  /*!
-   * \brief Check if the two Any are equal
-   * \param lhs left operand.
-   * \param rhs right operand
-   * \return String equality if both are strings, pointer address equality otherwise.
-   */
-  bool operator()(const Any& lhs, const Any& rhs) const {
-    // header with type index
-    const int64_t* lhs_as_int64 = reinterpret_cast<const int64_t*>(&lhs.data_);
-    const int64_t* rhs_as_int64 = reinterpret_cast<const int64_t*>(&rhs.data_);
-    static_assert(sizeof(TVMFFIAny) == 16);
-    // fast path, check byte equality
-    if (lhs_as_int64[0] == rhs_as_int64[0] && lhs_as_int64[1] == rhs_as_int64[1]) {
-      return true;
-    }
-    // common false case type index match, in this case we only need to pay attention to string
-    // equality
-    if (lhs.data_.type_index == rhs.data_.type_index) {
-      // specialy handle string hash
-      if (lhs.data_.type_index == TypeIndex::kTVMFFIStr ||
-          lhs.data_.type_index == TypeIndex::kTVMFFIBytes) {
-        const details::BytesObjBase* lhs_str =
-            details::AnyUnsafe::CopyFromAnyViewAfterCheck<const details::BytesObjBase*>(lhs);
-        const details::BytesObjBase* rhs_str =
-            details::AnyUnsafe::CopyFromAnyViewAfterCheck<const details::BytesObjBase*>(rhs);
-        return Bytes::memequal(lhs_str->data, rhs_str->data, lhs_str->size, rhs_str->size);
-      }
-      return false;
-    } else {
-      // type_index mismatch, if index is not string, return false
-      if (lhs.data_.type_index != kTVMFFIStr && lhs.data_.type_index != kTVMFFISmallStr &&
-          lhs.data_.type_index != kTVMFFISmallBytes && lhs.data_.type_index != kTVMFFIBytes) {
-        return false;
-      }
-      // small string and normal string comparison
-      if (lhs.data_.type_index == kTVMFFIStr && rhs.data_.type_index == kTVMFFISmallStr) {
-        const details::BytesObjBase* lhs_str =
-            details::AnyUnsafe::CopyFromAnyViewAfterCheck<const details::BytesObjBase*>(lhs);
-        return Bytes::memequal(lhs_str->data, rhs.data_.v_bytes, lhs_str->size,
-                               rhs.data_.small_str_len);
-      }
-      if (lhs.data_.type_index == kTVMFFISmallStr && rhs.data_.type_index == kTVMFFIStr) {
-        const details::BytesObjBase* rhs_str =
-            details::AnyUnsafe::CopyFromAnyViewAfterCheck<const details::BytesObjBase*>(rhs);
-        return Bytes::memequal(lhs.data_.v_bytes, rhs_str->data, lhs.data_.small_str_len,
-                               rhs_str->size);
-      }
-      if (lhs.data_.type_index == kTVMFFIBytes && rhs.data_.type_index == kTVMFFISmallBytes) {
-        const details::BytesObjBase* lhs_bytes =
-            details::AnyUnsafe::CopyFromAnyViewAfterCheck<const details::BytesObjBase*>(lhs);
-        return Bytes::memequal(lhs_bytes->data, rhs.data_.v_bytes, lhs_bytes->size,
-                               rhs.data_.small_str_len);
-      }
-      if (lhs.data_.type_index == kTVMFFISmallBytes && rhs.data_.type_index == kTVMFFIBytes) {
-        const details::BytesObjBase* rhs_bytes =
-            details::AnyUnsafe::CopyFromAnyViewAfterCheck<const details::BytesObjBase*>(rhs);
-        return Bytes::memequal(lhs.data_.v_bytes, rhs_bytes->data, lhs.data_.small_str_len,
-                               rhs_bytes->size);
-      }
-      return false;
-    }
-  }
-};
-}  // namespace ffi
-
-// Expose to the tvm namespace for usability
-// Rationale: no ambiguity even in root
-using tvm::ffi::Any;
-using tvm::ffi::AnyView;
-
-}  // namespace tvm
-#endif  // TVM_FFI_ANY_H_
diff --git a/ffi/include/tvm/ffi/base_details.h b/ffi/include/tvm/ffi/base_details.h
deleted file mode 100644
index c20f0e5c05..0000000000
--- a/ffi/include/tvm/ffi/base_details.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * 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/base_details.h
- * \brief Internal detail utils that can be used by files in tvm/ffi.
- * \note details headers are for internal use only
- *       and not to be directly used by user.
- */
-#ifndef TVM_FFI_BASE_DETAILS_H_
-#define TVM_FFI_BASE_DETAILS_H_
-
-#include <tvm/ffi/c_api.h>
-#include <tvm/ffi/endian.h>
-
-#include <cstddef>
-#include <utility>
-
-#if defined(_MSC_VER)
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-
-#include <windows.h>
-
-#ifdef ERROR
-#undef ERROR
-#endif
-
-#endif
-/// \cond Doxygen_Suppress
-
-#if defined(_MSC_VER)
-#define TVM_FFI_INLINE [[msvc::forceinline]] inline
-#else
-#define TVM_FFI_INLINE [[gnu::always_inline]] inline
-#endif
-
-/*!
- * \brief Macro helper to force a function not to be inlined.
- * It is only used in places that we know not inlining is good,
- * e.g. some logging functions.
- */
-#if defined(_MSC_VER)
-#define TVM_FFI_NO_INLINE [[msvc::noinline]]
-#else
-#define TVM_FFI_NO_INLINE [[gnu::noinline]]
-#endif
-
-#if defined(_MSC_VER)
-#define TVM_FFI_UNREACHABLE() __assume(false)
-#else
-#define TVM_FFI_UNREACHABLE() __builtin_unreachable()
-#endif
-
-#define TVM_FFI_STR_CONCAT_(__x, __y) __x##__y
-#define TVM_FFI_STR_CONCAT(__x, __y) TVM_FFI_STR_CONCAT_(__x, __y)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define TVM_FFI_FUNC_SIG __PRETTY_FUNCTION__
-#elif defined(_MSC_VER)
-#define TVM_FFI_FUNC_SIG __FUNCSIG__
-#else
-#define TVM_FFI_FUNC_SIG __func__
-#endif
-
-#if defined(__GNUC__)
-// gcc and clang and attribute constructor
-/// \cond Doxygen_Suppress
-#define TVM_FFI_STATIC_INIT_BLOCK_DEF_(FnName) __attribute__((constructor)) static void FnName()
-/// \endcond
-/*
- * \brief Macro that defines a block that will be called during static initialization.
- *
- * \code
- * TVM_FFI_STATIC_INIT_BLOCK() {
- *   RegisterFunctions();
- * }
- * \endcode
- */
-#define TVM_FFI_STATIC_INIT_BLOCK() \
-  TVM_FFI_STATIC_INIT_BLOCK_DEF_(TVM_FFI_STR_CONCAT(__TVMFFIStaticInitFunc, __COUNTER__))
-
-#else
-/// \cond Doxygen_Suppress
-// for other compilers, use the variable trick
-#define TVM_FFI_STATIC_INIT_BLOCK_DEF_(FnName, RegVar) \
-  static void FnName();                                \
-  [[maybe_unused]] static inline int RegVar = []() {   \
-    FnName();                                          \
-    return 0;                                          \
-  }();                                                 \
-  static void FnName()
-
-#define TVM_FFI_STATIC_INIT_BLOCK()                                                       \
-  TVM_FFI_STATIC_INIT_BLOCK_DEF_(TVM_FFI_STR_CONCAT(__TVMFFIStaticInitFunc, __COUNTER__), \
-                                 TVM_FFI_STR_CONCAT(__TVMFFIStaticInitReg, __COUNTER__))
-/// \endcond
-#endif
-
-/*
- * \brief Define the default copy/move constructor and assign operator
- * \param TypeName The class typename.
- */
-#define TVM_FFI_DEFINE_DEFAULT_COPY_MOVE_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName& other) = default;                  \
-  TypeName(TypeName&& other) = default;                       \
-  TypeName& operator=(const TypeName& other) = default;       \
-  TypeName& operator=(TypeName&& other) = default;
-
-/**
- * \brief marks the begining of a C call that logs exception
- */
-#define TVM_FFI_LOG_EXCEPTION_CALL_BEGIN() \
-  try {                                    \
-  (void)0
-
-/*!
- * \brief Marks the end of a C call that logs exception
- */
-#define TVM_FFI_LOG_EXCEPTION_CALL_END(Name)                                              \
-  }                                                                                       \
-  catch (const std::exception& err) {                                                     \
-    std::cerr << "Exception caught during " << #Name << ":\n" << err.what() << std::endl; \
-    exit(-1);                                                                             \
-  }
-
-/*!
- * \brief Clear the padding parts so we can safely use v_int64 for hash
- *        and equality check even when the value stored is a pointer.
- *
- * This macro is used to clear the padding parts for hash and equality check
- * in 32bit platform.
- */
-#define TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result)                    \
-  if constexpr (sizeof((result)->v_obj) != sizeof((result)->v_int64)) { \
-    (result)->v_int64 = 0;                                              \
-  }
-
-namespace tvm {
-namespace ffi {
-namespace details {
-
-// for each iterator
-struct for_each_dispatcher {
-  template <typename F, typename... Args, size_t... I>
-  static void run(std::index_sequence<I...>, const F& f, Args&&... args) {  // NOLINT(*)
-    (f(I, std::forward<Args>(args)), ...);
-  }
-};
-
-template <typename F, typename... Args>
-void for_each(const F& f, Args&&... args) {  // NOLINT(*)
-  for_each_dispatcher::run(std::index_sequence_for<Args...>{}, f, std::forward<Args>(args)...);
-}
-
-/*!
- * \brief hash an object and combines uint64_t key with previous keys
- *
- * This hash function is stable across platforms.
- *
- * \param key The left operand.
- * \param value The right operand.
- * \return the combined result.
- */
-template <typename T, std::enable_if_t<std::is_convertible<T, uint64_t>::value, bool> = true>
-TVM_FFI_INLINE uint64_t StableHashCombine(uint64_t key, const T& value) {
-  // XXX: do not use std::hash in this function. This hash must be stable
-  // across different platforms and std::hash is implementation dependent.
-  return key ^ (uint64_t(value) + 0x9e3779b9 + (key << 6) + (key >> 2));
-}
-
-/*!
- * \brief Hash the binary bytes
- * \param data The data pointer
- * \param size The size of the bytes.
- * \return the hash value.
- */
-TVM_FFI_INLINE uint64_t StableHashBytes(const void* data_ptr, size_t size) {
-  const char* data = reinterpret_cast<const char*>(data_ptr);
-  const constexpr uint64_t kMultiplier = 1099511628211ULL;
-  const constexpr uint64_t kMod = 2147483647ULL;
-  union Union {
-    uint8_t a[8];
-    uint64_t b;
-  } u;
-  static_assert(sizeof(Union) == sizeof(uint64_t), "sizeof(Union) != sizeof(uint64_t)");
-  const char* it = data;
-  const char* end = it + size;
-  uint64_t result = 0;
-  if constexpr (TVM_FFI_IO_NO_ENDIAN_SWAP) {
-    // if alignment requirement is met, directly use load
-    if (reinterpret_cast<uintptr_t>(it) % 8 == 0) {
-      for (; it + 8 <= end; it += 8) {
-        u.b = *reinterpret_cast<const uint64_t*>(it);
-        result = (result * kMultiplier + u.b) % kMod;
-      }
-    } else {
-      // unaligned version
-      for (; it + 8 <= end; it += 8) {
-        u.a[0] = it[0];
-        u.a[1] = it[1];
-        u.a[2] = it[2];
-        u.a[3] = it[3];
-        u.a[4] = it[4];
-        u.a[5] = it[5];
-        u.a[6] = it[6];
-        u.a[7] = it[7];
-        result = (result * kMultiplier + u.b) % kMod;
-      }
-    }
-  } else {
-    // need endian swap
-    for (; it + 8 <= end; it += 8) {
-      u.a[0] = it[7];
-      u.a[1] = it[6];
-      u.a[2] = it[5];
-      u.a[3] = it[4];
-      u.a[4] = it[3];
-      u.a[5] = it[2];
-      u.a[6] = it[1];
-      u.a[7] = it[0];
-      result = (result * kMultiplier + u.b) % kMod;
-    }
-  }
-
-  if (it < end) {
-    u.b = 0;
-    uint8_t* a = u.a;
-    if (it + 4 <= end) {
-      a[0] = it[0];
-      a[1] = it[1];
-      a[2] = it[2];
-      a[3] = it[3];
-      it += 4;
-      a += 4;
-    }
-    if (it + 2 <= end) {
-      a[0] = it[0];
-      a[1] = it[1];
-      it += 2;
-      a += 2;
-    }
-    if (it + 1 <= end) {
-      a[0] = it[0];
-      it += 1;
-      a += 1;
-    }
-    if constexpr (!TVM_FFI_IO_NO_ENDIAN_SWAP) {
-      std::swap(u.a[0], u.a[7]);
-      std::swap(u.a[1], u.a[6]);
-      std::swap(u.a[2], u.a[5]);
-      std::swap(u.a[3], u.a[4]);
-    }
-    result = (result * kMultiplier + u.b) % kMod;
-  }
-  return result;
-}
-
-/*!
- *  \brief Same as StableHashBytes, but for small string data.
- *  \param data The data pointer
- *  \return the hash value.
- */
-TVM_FFI_INLINE uint64_t StableHashSmallStrBytes(const TVMFFIAny* data) {
-  if constexpr (TVM_FFI_IO_NO_ENDIAN_SWAP) {
-    // fast path, no endian swap, simply hash as uint64_t
-    const constexpr uint64_t kMod = 2147483647ULL;
-    return data->v_uint64 % kMod;
-  }
-  return StableHashBytes(reinterpret_cast<const void*>(data), sizeof(data->v_uint64));
-}
-
-}  // namespace details
-}  // namespace ffi
-}  // namespace tvm
-/// \endcond
-#endif  // TVM_FFI_BASE_DETAILS_H_
diff --git a/ffi/include/tvm/ffi/c_api.h b/ffi/include/tvm/ffi/c_api.h
deleted file mode 100644
index f13f820b7f..0000000000
--- a/ffi/include/tvm/ffi/c_api.h
+++ /dev/null
@@ -1,1097 +0,0 @@
-/*
- * 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>
-
-/*
- * \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)  //
-);
-
-// 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
-
-#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`
-  //
-  /*! \brief None/nullptr value */
-  kTVMFFINone = 0,
-  /*! \brief POD int value */
-  kTVMFFIInt = 1,
-  /*! \brief POD bool value */
-  kTVMFFIBool = 2,
-  /*! \brief POD float value */
-  kTVMFFIFloat = 3,
-  /*! \brief Opaque pointer object */
-  kTVMFFIOpaquePtr = 4,
-  /*! \brief DLDataType */
-  kTVMFFIDataType = 5,
-  /*! \brief DLDevice */
-  kTVMFFIDevice = 6,
-  /*! \brief DLTensor* */
-  kTVMFFIDLTensorPtr = 7,
-  /*! \brief const char* */
-  kTVMFFIRawStr = 8,
-  /*! \brief TVMFFIByteArray* */
-  kTVMFFIByteArrayPtr = 9,
-  /*! \brief R-value reference to ObjectRef */
-  kTVMFFIObjectRValueRef = 10,
-  /*! \brief Small string on stack */
-  kTVMFFISmallStr = 11,
-  /*! \brief Small bytes on stack */
-  kTVMFFISmallBytes = 12,
-  /*! \brief Start of statically defined objects. */
-  kTVMFFIStaticObjectBegin = 64,
-  /*!
-   * \brief Object, all objects starts with TVMFFIObject as its header.
-   * \note We will also add other fields
-   */
-  kTVMFFIObject = 64,
-  /*!
-   * \brief String object, layout = { TVMFFIObject, TVMFFIByteArray, ... }
-   */
-  kTVMFFIStr = 65,
-  /*!
-   * \brief Bytes object, layout = { TVMFFIObject, TVMFFIByteArray, ... }
-   */
-  kTVMFFIBytes = 66,
-  /*! \brief Error object. */
-  kTVMFFIError = 67,
-  /*! \brief Function object. */
-  kTVMFFIFunction = 68,
-  /*!
-   * \brief Shape object, layout = { TVMFFIObject, { const int64_t*, size_t }, ... }
-   */
-  kTVMFFIShape = 69,
-  /*!
-   * \brief Tensor object, layout = { TVMFFIObject, DLTensor, ... }
-   */
-  kTVMFFITensor = 70,
-  /*! \brief Array object. */
-  kTVMFFIArray = 71,
-  //----------------------------------------------------------------
-  // more complex objects
-  //----------------------------------------------------------------
-  /*! \brief Map object. */
-  kTVMFFIMap = 72,
-  /*! \brief Runtime dynamic loaded module object. */
-  kTVMFFIModule = 73,
-  /*!
-   * \brief Opaque python object.
-   *
-   * This is a special type index to indicate we are storing an opaque PyObject.
-   * Such object may interact with callback functions that are registered to support
-   * python-related operations.
-   *
-   * We only translate the objects that we do not recognize into this type index.
-   *
-   * \sa TVMFFIObjectCreateOpaque
-   */
-  kTVMFFIOpaquePyObject = 74,
-  kTVMFFIStaticObjectEnd,
-  // [Section] Dynamic Boxed: [kTVMFFIDynObjectBegin, +oo)
-  /*! \brief Start of type indices that are allocated at runtime. */
-  kTVMFFIDynObjectBegin = 128
-#ifdef __cplusplus
-};
-#else
-} TVMFFITypeIndex;
-#endif
-
-/*! \brief Handle to Object from C API's pov */
-typedef void* TVMFFIObjectHandle;
-
-/*!
- * \brief bitmask of the object deleter flag.
- */
-#ifdef __cplusplus
-enum TVMFFIObjectDeleterFlagBitMask : int32_t {
-#else
-typedef enum {
-#endif
-  /*!
-   * \brief deleter action when strong reference count becomes zero.
-   * Need to call destructor of the object but not free the memory block.
-   */
-  kTVMFFIObjectDeleterFlagBitMaskStrong = 1 << 0,
-  /*!
-   * \brief deleter action when weak reference count becomes zero.
-   * Need to free the memory block.
-   */
-  kTVMFFIObjectDeleterFlagBitMaskWeak = 1 << 1,
-  /*!
-   * \brief deleter action when both strong and weak reference counts become zero.
-   * \note This is the most common case.
-   */
-  kTVMFFIObjectDeleterFlagBitMaskBoth =
-      (kTVMFFIObjectDeleterFlagBitMaskStrong | kTVMFFIObjectDeleterFlagBitMaskWeak),
-#ifdef __cplusplus
-};
-#else
-} TVMFFIObjectDeleterFlagBitMask;
-#endif
-
-/*!
- * \brief C-based type of all FFI object header that allocates on heap.
- * \note TVMFFIObject and TVMFFIAny share the common type_index header
- */
-typedef struct {
-  /*!
-   * \brief type index of the object.
-   * \note The type index of Object and Any are shared in FFI.
-   */
-  int32_t type_index;
-  /*!
-   * \brief Weak reference counter of the object, for compatiblity with weak_ptr design.
-   * \note Use u32 to ensure that overall object stays within 24-byte boundary, usually
-   *       manipulation of weak counter is less common than strong counter.
-   */
-  uint32_t weak_ref_count;
-  /*! \brief Strong reference counter of the object. */
-  uint64_t strong_ref_count;
-  union {
-    /*!
-     * \brief Deleter to be invoked when strong reference counter goes to zero.
-     * \param self The self object handle.
-     * \param flags The flags to indicate deletion behavior.
-     * \sa TVMFFIObjectDeleterFlagBitMask
-     */
-    void (*deleter)(void* self, int flags);
-    /*!
-     * \brief auxilary field to TVMFFIObject is always 8 bytes aligned.
-     * \note This helps us to ensure cross platform compatibility.
-     */
-    int64_t __ensure_align;
-  };
-} TVMFFIObject;
-
-/*!
- * \brief C-based type of all on stack Any value.
- *
- * Any value can hold on stack values like int,
- * as well as reference counted pointers to object.
- */
-typedef struct {
-  /*!
-   * \brief type index of the object.
-   * \note The type index of Object and Any are shared in FFI.
-   */
-  int32_t type_index;
-  union {  // 4 bytes
-    /*! \brief padding, must set to zero for values other than small string. */
-    uint32_t zero_padding;
-    /*!
-     * \brief Length of small string, with a max value of 7.
-     *
-     * We keep small str to start at next 4 bytes to ensure alignment
-     * when accessing the small str content.
-     */
-    uint32_t small_str_len;
-  };
-  union {                  // 8 bytes
-    int64_t v_int64;       // integers
-    double v_float64;      // floating-point numbers
-    void* v_ptr;           // typeless pointers
-    const char* v_c_str;   // raw C-string
-    TVMFFIObject* v_obj;   // ref counted objects
-    DLDataType v_dtype;    // data type
-    DLDevice v_device;     // device
-    char v_bytes[8];       // small string
-    char32_t v_char32[2];  // small UCS4 string and Unicode
-    uint64_t v_uint64;     // uint64 repr mainly used for hashing
-  };
-} TVMFFIAny;
-
-/*!
- * \brief Byte array data structure used by String and Bytes.
- *
- * String and Bytes object layout = { TVMFFIObject, TVMFFIByteArray, ... }
- *
- * \note This byte array data structure layout differs in 32/64 bit platforms.
- *       as size_t equals to the size of the pointer, use this convetion to
- *       be consistent with std::string and also avoid need to calculate padding
- *       for the size field on 32-bit platforms.
- *       The FFI binding should be careful when treating this ABI.
- */
-typedef struct {
-  /*! \brief The data pointer. */
-  const char* data;
-  /*! \brief The size of the data. */
-  size_t size;
-} TVMFFIByteArray;
-
-/*!
- * \brief Shape cell used in shape object following header.
- */
-typedef struct {
-  /*! \brief The data pointer. */
-  const int64_t* data;
-  /*! \brief The size of the data. */
-  size_t size;
-} TVMFFIShapeCell;
-
-/*!
- * \brief Error cell used in error object following header.
- */
-typedef struct {
-  /*! \brief The kind of the error. */
-  TVMFFIByteArray kind;
-  /*! \brief The message of the error. */
-  TVMFFIByteArray message;
-  /*!
-   * \brief The traceback of the error.
-   */
-  TVMFFIByteArray traceback;
-  /*!
-   * \brief Function handle to update the traceback of the error.
-   * \param self The self object handle.
-   * \param traceback The traceback to update.
-   */
-  void (*update_traceback)(TVMFFIObjectHandle self, const TVMFFIByteArray* traceback);
-} TVMFFIErrorCell;
-
-/*!
- * \brief Type that defines C-style safe call convention
- *
- * Safe call explicitly catches exception on function boundary.
- *
- * \param handle The function handle
- * \param num_args Number of input arguments
- * \param args The input arguments to the call.
- * \param result Store output result.
- *
- * IMPORTANT: caller must initialize result->type_index to be kTVMFFINone,
- * or any other value smaller than kTVMFFIStaticObjectBegin.
- *
- * \return The call returns 0 if call is successful.
- *  It returns non-zero value if there is an error.
- *
- *  Possible return error of the API functions:
- *  * 0: success
- *  * -1: error happens, can be retrieved by TVMFFIErrorMoveFromRaised
- *  * -2: a frontend error occurred and recorded in the frontend.
- *
- * \note We decided to leverage TVMFFIErrorMoveFromRaised and TVMFFIErrorSetRaised
- *  for C function error propagation. This design choice, while
- *  introducing a dependency for TLS runtime, simplifies error
- *  propgation in chains of calls in compiler codegen.
- *  As we do not need to propagate error through argument but simply
- *  set them in the runtime environment.
- *
- * \sa TVMFFIErrorMoveFromRaised
- * \sa TVMFFIErrorSetRaised
- * \sa TVMFFIErrorSetRaisedFromCStr
- */
-typedef int (*TVMFFISafeCallType)(void* handle, const TVMFFIAny* args, int32_t num_args,
-                                  TVMFFIAny* result);
-
-/*!
- * \brief Object cell for function object following header.
- */
-typedef struct {
-  /*! \brief A C API compatible call with exception catching. */
-  TVMFFISafeCallType safe_call;
-} TVMFFIFunctionCell;
-
-/*!
- * \brief Object cell for opaque object following header.
- */
-typedef struct {
-  /*! \brief The handle of the opaque object, for python it is PyObject* */
-  void* handle;
-} TVMFFIOpaqueObjectCell;
-
-//------------------------------------------------------------
-// Section: Basic object API
-//------------------------------------------------------------
-/*!
- * \brief Increase the strong reference count of an object handle
- * \param obj The object handle.
- * \note Internally we increase the reference counter of the object.
- * \return 0 when success, nonzero when failure happens
- */
-TVM_FFI_DLL int TVMFFIObjectIncRef(TVMFFIObjectHandle obj);
-
-/*!
- * \brief Free an object handle by decreasing strong reference
- * \param obj The object handle.
- * \return 0 when success, nonzero when failure happens
- */
-TVM_FFI_DLL int TVMFFIObjectDecRef(TVMFFIObjectHandle obj);
-
-/*!
- * \brief Create an Opaque object by passing in handle, type_index and deleter.
- *
- * The opaque object's lifetime is managed as an Object, so it can be retained
- * and released like other objects.
- * When the opaque object is kTVMFFIOpaquePyObject, it can be converted back to
- * the python type when returned or passed as arguments to a python function.
- *
- * We can support ffi::Function that interacts with these objects,
- * most likely callback registered from python.
- *
- * For language bindings, we only convert types that we do not recognize into this type.
- * On the C++ side, the most common way to represent such OpaqueObject is to simply
- * use ffi::ObjectRef or ffi::Any.
- *
- * \param handle The resource handle of the opaque object.
- * \param type_index The type index of the object.
- * \param deleter deleter to recycle
- * \param out The output of the opaque object.
- * \return 0 when success, nonzero when failure happens
- *
- * \note The caller must ensure the type_index is a valid opaque object type index.
- * \sa kTVMFFIOpaquePyObject
- */
-TVM_FFI_DLL int TVMFFIObjectCreateOpaque(void* handle, int32_t type_index,
-                                         void (*deleter)(void* handle), TVMFFIObjectHandle* out);
-
-/*!
- * \brief Convert type key to type index.
- * \param type_key The key of the type.
- * \param out_tindex the corresponding type index.
- * \return 0 when success, nonzero when failure happens
- */
-TVM_FFI_DLL int TVMFFITypeKeyToIndex(const TVMFFIByteArray* type_key, int32_t* out_tindex);
-
-//-----------------------------------------------------------------------
-// Section: Basic function calling API for function implementation
-//-----------------------------------------------------------------------
-/*!
- * \brief Create a FFIFunc by passing in callbacks from a C callback.
- * The registered function can then be retrieved by the backend using its name.
- * \param self The resource handle of the C callback.
- * \param safe_call The C callback implementation.
- * \param deleter The deleter to recycle.
- * \param out The output of the function.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFIFunctionCreate(void* self, TVMFFISafeCallType safe_call,
-                                     void (*deleter)(void* self), TVMFFIObjectHandle* out);
-
-/*!
- * \brief Get a global function registered in the system.
- * \param name The name of the function.
- * \param out The result function pointer, NULL if it does not exist.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFIFunctionGetGlobal(const TVMFFIByteArray* name, TVMFFIObjectHandle* out);
-
-/*!
- * \brief Convert an AnyView to an owned Any.
- * \param any_view The AnyView to convert.
- * \param out The output Any, must be an empty object.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFIAnyViewToOwnedAny(const TVMFFIAny* any_view, TVMFFIAny* out);
-
-/*!
- * \brief Call a FFIFunc by passing in arguments.
- * \param func The resource handle of the C callback.
- * \param args The input arguments to the call.
- * \param num_args The number of input arguments.
- * \param result The output result, caller must ensure result->type_index is set to kTVMFFINone.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFIFunctionCall(TVMFFIObjectHandle func, TVMFFIAny* args, int32_t num_args,
-                                   TVMFFIAny* result);
-
-/*!
- * \brief Move the last error from the environment to the result.
- * \param result The result error.
- * \note This function clears the error stored in the TLS.
- */
-TVM_FFI_DLL void TVMFFIErrorMoveFromRaised(TVMFFIObjectHandle* result);
-
-/*!
- * \brief Set a raised error in TLS, which can be fetched by TVMFFIErrorMoveFromRaised.
- * \param error The error object handle
- */
-TVM_FFI_DLL void TVMFFIErrorSetRaised(TVMFFIObjectHandle error);
-
-/*!
- * \brief Set a raised error in TLS, which can be fetched by TVMFFIMoveFromRaised.
- * \param kind The kind of the error.
- * \param message The error message.
- * \note This is a convenient method for the C API side to set an error directly from a string.
- */
-TVM_FFI_DLL void TVMFFIErrorSetRaisedFromCStr(const char* kind, const char* message);
-
-/*!
- * \brief Create an initial error object.
- * \param kind The kind of the error.
- * \param message The error message.
- * \param traceback The traceback of the error.
- * \return The created error object handle.
- * \note This function is different from other functions as it is used in the error handling loop.
- * So we do not follow normal error handling patterns via returning an error code.
- */
-TVM_FFI_DLL TVMFFIObjectHandle TVMFFIErrorCreate(const TVMFFIByteArray* kind,
-                                                 const TVMFFIByteArray* message,
-                                                 const TVMFFIByteArray* traceback);
-
-//------------------------------------------------------------
-// Section: DLPack support APIs
-//------------------------------------------------------------
-/*!
- * \brief Produce a managed Tensor from a DLPack tensor.
- * \param from The source DLPack tensor.
- * \param require_alignment The minimum alignment required of the data + byte_offset.
- * \param require_contiguous Boolean flag indicating if we need to check for contiguity.
- * \param out The output Tensor handle.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFITensorFromDLPack(DLManagedTensor* from, int32_t require_alignment,
-                                       int32_t require_contiguous, TVMFFIObjectHandle* out);
-
-/*!
- * \brief Produce a DLManagedTensor from the array that shares data memory with the array.
- * \param from The source array.
- * \param out The DLManagedTensor handle.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFITensorToDLPack(TVMFFIObjectHandle from, DLManagedTensor** out);
-
-/*!
- * \brief Produce a managed Tensor from a DLPack tensor.
- * \param from The source DLPack tensor.
- * \param require_alignment The minimum alignment required of the data + byte_offset.
- * \param require_contiguous Boolean flag indicating if we need to check for contiguity.
- * \param out The output Tensor handle.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFITensorFromDLPackVersioned(DLManagedTensorVersioned* from,
-                                                int32_t require_alignment,
-                                                int32_t require_contiguous,
-                                                TVMFFIObjectHandle* out);
-
-/*!
- * \brief Produce a DLManagedTensor from the array that shares data memory with the array.
- * \param from The source array.
- * \param out The DLManagedTensor handle.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFITensorToDLPackVersioned(TVMFFIObjectHandle from,
-                                              DLManagedTensorVersioned** out);
-//---------------------------------------------------------------
-// Section: string/bytes support APIs.
-// These APIs are used to simplify the string/bytes construction
-//---------------------------------------------------------------
-/*!
- * \brief Reinterpret the content of TVMFFIByteArray to String.
- * \param input The TVMFFIByteArray to convert.
- * \param out The output String owned by the caller, maybe a SmallStr or a Str object.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFIStringFromByteArray(const TVMFFIByteArray* input, TVMFFIAny* out);
-
-/*!
- * \brief Reinterpret the content of TVMFFIByteArray to Bytes.
- * \param input The TVMFFIByteArray to convert.
- * \param out The output Bytes owned by the caller, maybe a SmallBytes or a Bytes object.
- * \return 0 on success, nonzero on failure.
- */
-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
-//---------------------------------------------------------------
-
-/*!
- * \brief Convert a string to a DLDataType.
- * \param str The string to convert.
- * \param out The output DLDataType.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFIDataTypeFromString(const TVMFFIByteArray* str, DLDataType* out);
-
-/*!
-* \brief Convert a DLDataType to a string.
-* \param dtype The DLDataType to convert.
-* \param out The output string.
-* \return 0 on success, nonzero on failure.
-* \note out is a String object that needs to be freed by the caller via TVMFFIObjectDecRef.
-The content of string can be accessed via TVMFFIObjectGetByteArrayPtr.
-
-* \note The input dtype is a pointer to the DLDataType to avoid ABI compatibility issues.
-*/
-TVM_FFI_DLL int TVMFFIDataTypeToString(const DLDataType* dtype, TVMFFIAny* out);
-
-//------------------------------------------------------------
-// Section: Type reflection support APIs
-//
-// The reflec
-//------------------------------------------------------------
-/*!
- * \brief Getter that can take the address of a field and set the result.
- * \param field The raw address of the field.
- * \param result Stores the result.
- * \return 0 on success, nonzero on failure.
- */
-typedef int (*TVMFFIFieldGetter)(void* field, TVMFFIAny* result);
-
-/*!
- * \brief Getter that can take the address of a field and set it to a value.
- * \param field The raw address of the field.
- * \param value The value to set.
- * \return 0 on success, nonzero on failure.
- */
-typedef int (*TVMFFIFieldSetter)(void* field, const TVMFFIAny* value);
-
-/*!
- * \brief Function that creates a new instance of the type.
- * \param result The new object handle
- * \return 0 on success, nonzero on failure.
- */
-typedef int (*TVMFFIObjectCreator)(TVMFFIObjectHandle* result);
-
-/*!
- * \brief bitmask of the field.
- */
-#ifdef __cplusplus
-enum TVMFFIFieldFlagBitMask : int32_t {
-#else
-typedef enum {
-#endif
-  /*! \brief The field is writable. */
-  kTVMFFIFieldFlagBitMaskWritable = 1 << 0,
-  /*! \brief The field has default value. */
-  kTVMFFIFieldFlagBitMaskHasDefault = 1 << 1,
-  /*! \brief The field is a static method. */
-  kTVMFFIFieldFlagBitMaskIsStaticMethod = 1 << 2,
-  /*!
-   * \brief The field should be ignored when performing structural eq/hash
-   *
-   * This is an optional meta-data for structural eq/hash.
-   */
-  kTVMFFIFieldFlagBitMaskSEqHashIgnore = 1 << 3,
-  /*!
-   * \brief The field enters a def region where var can be defined/matched.
-   *
-   * This is an optional meta-data for structural eq/hash.
-   */
-  kTVMFFIFieldFlagBitMaskSEqHashDef = 1 << 4,
-#ifdef __cplusplus
-};
-#else
-} TVMFFIFieldFlagBitMask;
-#endif
-
-/*!
- * \brief Optional meta-data for structural eq/hash.
- *
- * This meta-data is only useful when we want to leverage the information
- * to perform richer semantics aware structural comparison and hash.
- * It can be safely ignored if such information is not needed.
- *
- * The meta-data record comparison method in tree node and DAG node.
- *
- * \code
- * x = VarNode()
- * v0 = AddNode(x, 1)
- * v1 = AddNode(x, 1)
- * v2 = AddNode(v0, v0)
- * v3 = AddNode(v1, v0)
- * \endcode
- *
- * Consider the construct sequence of AddNode below,
- * if AddNode is treated as a tree node, then v2 and v3
- * structural equals to each other, but if AddNode is
- * treated as a DAG node, then v2 and v3 does not
- * structural equals to each other.
- */
-#ifdef __cplusplus
-enum TVMFFISEqHashKind : int32_t {
-#else
-typedef enum {
-#endif
-  /*! \brief Do not support structural eq/hash. */
-  kTVMFFISEqHashKindUnsupported = 0,
-  /*!
-   * \brief The object be compared as a tree node.
-   */
-  kTVMFFISEqHashKindTreeNode = 1,
-  /*!
-   * \brief The object is treated as a free variable that can be mapped
-   *        to another free variable in the definition region.
-   */
-  kTVMFFISEqHashKindFreeVar = 2,
-  /*!
-   * \brief The field should be compared as a DAG node.
-   */
-  kTVMFFISEqHashKindDAGNode = 3,
-  /*!
-   * \brief The object is treated as a constant tree node.
-   *
-   * Same as tree node, but the object does not contain free var
-   * as any of its nested children.
-   *
-   * That means we can use pointer equality for equality.
-   */
-  kTVMFFISEqHashKindConstTreeNode = 4,
-  /*!
-   * \brief One can simply use pointer equality for equality.
-   *
-   * This is useful for "singleton"-style object that can
-   * is only an unique copy of each value.
-   */
-  kTVMFFISEqHashKindUniqueInstance = 5,
-#ifdef __cplusplus
-};
-#else
-} TVMFFISEqHashKind;
-#endif
-
-/*!
- * \brief Information support for optional object reflection.
- */
-typedef struct {
-  /*! \brief The name of the field. */
-  TVMFFIByteArray name;
-  /*! \brief The docstring about the field. */
-  TVMFFIByteArray doc;
-  /*! \brief The type schema of the field in JSON string. */
-  TVMFFIByteArray type_schema;
-  /*!
-   * \brief bitmask flags of the field.
-   */
-  int64_t flags;
-  /*! \brief The size of the field. */
-  int64_t size;
-  /*! \brief The alignment of the field. */
-  int64_t alignment;
-  /*! \brief The offset of the field. */
-  int64_t offset;
-  /*! \brief The getter to access the field. */
-  TVMFFIFieldGetter getter;
-  /*!
-   * \brief The setter to access the field.
-   * \note The setter is set even if the field is readonly for serialization.
-   */
-  TVMFFIFieldSetter setter;
-  /*!
-   * \brief The default value of the field, this field hold AnyView,
-   *        valid when flags set kTVMFFIFieldFlagBitMaskHasDefault
-   */
-  TVMFFIAny default_value;
-  /*!
-   * \brief Records the static type kind of the field.
-   *
-   * Possible values:
-   *
-   * - TVMFFITypeIndex::kTVMFFIObject for general objects.
-   *   The value is nullable when kTVMFFIObject is chosen.
-   * - Static object type kinds such as Map, Dict, String
-   * - POD type index, note it does not give information about storage size of the field.
-   * - TVMFFITypeIndex::kTVMFFIAny if we don't have specialized info
-   *   about the field.
-   *
-   * When the value is a type index of Object type, the field is storaged as an ObjectRef.
-   *
-   * \note This information maybe helpful in designing serializer.
-   * As it helps to narrow down the field type so we don't have to
-   * print type_key for cases like POD types.
-   * It also helps to provide opportunities to enable short-cut getter to ObjectRef fields.
-   */
-  int32_t field_static_type_index;
-} TVMFFIFieldInfo;
-
-/*!
- * \brief Method information that can appear in reflection table.
- */
-typedef struct {
-  /*! \brief The name of the field. */
-  TVMFFIByteArray name;
-  /*! \brief The docstring about the method. */
-  TVMFFIByteArray doc;
-  /*! \brief Optional type schema of the method in JSON string. */
-  TVMFFIByteArray type_schema;
-  /*! \brief bitmask flags of the method. */
-  int64_t flags;
-  /*!
-   * \brief The method wrapped as ffi::Function, stored as AnyView.
-   * \note The first argument to the method is always the self for instance methods.
-   */
-  TVMFFIAny method;
-} TVMFFIMethodInfo;
-
-/*!
- * \brief Extra information of object type that can be used for reflection.
- *
- * \note This information is optional and can be used to enable reflection based
- *       creation of the object.
- */
-typedef struct {
-  /*! \brief The docstring about the object. */
-  TVMFFIByteArray doc;
-  /*!
-   * \brief An optional function that can create a new empty instance of the type.
-   *
-   * When known_fixed_size is non-zero, creator can be called
-   * with nullptr passed to optional_bytes.
-   *
-   * \note Caller must call setter for each field to initialize the object for
-   *       the final object to be in valid state.
-   *
-   * \note This field is optional to enable reflection based creation.
-   */
-  TVMFFIObjectCreator creator;
-  /*!
-   * \brief Total size of the object struct, if it is fixed and known.
-   *
-   * This field is set optional and set to 0 if not registered.
-   */
-  int32_t total_size;
-  /*!
-   * \brief Optional meta-data for structural eq/hash.
-   */
-  TVMFFISEqHashKind structural_eq_hash_kind;
-} TVMFFITypeMetadata;
-
-/*!
- * \brief Column array that stores extra attributes about types
- *
- * The attributes stored in a column array that can be looked up by type index.
- * Note that the TypeAttr behaves like type_traits so column[T] so not contain
- * attributes from base classes.
- *
- * \note
- * \sa TVMFFIRegisterTypeAttr
- */
-typedef struct {
-  /*! \brief The data of the column. */
-  const TVMFFIAny* data;
-  /*! \brief The size of the column. */
-  size_t size;
-} TVMFFITypeAttrColumn;
-
-/*!
- * \brief Runtime type information for object type checking.
- */
-#ifdef __cplusplus
-struct TVMFFITypeInfo {
-#else
-typedef struct TVMFFITypeInfo {
-#endif
-  /*!
-   *\brief The runtime type index,
-   * It can be allocated during runtime if the type is dynamic.
-   */
-  int32_t type_index;
-  /*! \brief number of parent types in the type hierachy. */
-  int32_t type_depth;
-  /*! \brief the unique type key to identify the type. */
-  TVMFFIByteArray type_key;
-  /*!
-   * \brief type_acenstors[depth] stores the type_index of the acenstors at depth level
-   * \note To keep things simple, we do not allow multiple inheritance so the
-   *       hieracy stays as a tree
-   */
-  const struct TVMFFITypeInfo** type_acenstors;
-  // The following fields are used for reflection
-  /*! \brief Cached hash value of the type key, used for consistent structural hashing. */
-  uint64_t type_key_hash;
-  /*! \brief number of reflection accessible fields. */
-  int32_t num_fields;
-  /*! \brief number of reflection acccesible methods. */
-  int32_t num_methods;
-  /*! \brief The reflection field information. */
-  const TVMFFIFieldInfo* fields;
-  /*! \brief The reflection method. */
-  const TVMFFIMethodInfo* methods;
-  /*! \brief The extra information of the type. */
-  const TVMFFITypeMetadata* metadata;
-#ifdef __cplusplus
-};
-#else
-} TVMFFITypeInfo;
-#endif
-
-/*!
- * \brief Register the function to runtime's global table.
- * The registered function can then be retrieved by the backend using its name.
- * \param name The name of the function.
- * \param f The function to be registered.
- * \param allow_override Whether to allow overriding an already registered function.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFIFunctionSetGlobal(const TVMFFIByteArray* name, TVMFFIObjectHandle f,
-                                        int allow_override);
-
-/*!
- * \brief Register the function to runtime's global table with method info.
- * This is the same as TVMFFIFunctionSetGlobal but with method info that can provide extra
- * metadata used in the runtime.
- * \param method_info The method info to be registered.
- * \param allow_override Whether to allow overriding an already registered function.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFIFunctionSetGlobalFromMethodInfo(const TVMFFIMethodInfo* method_info,
-                                                      int allow_override);
-
-/*!
- * \brief Register type field information for runtime reflection.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFITypeRegisterField(int32_t type_index, const TVMFFIFieldInfo* info);
-
-/*!
- * \brief Register type method information for runtime reflection.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFITypeRegisterMethod(int32_t type_index, const TVMFFIMethodInfo* info);
-
-/*!
- * \brief Register type creator information for runtime reflection.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFITypeRegisterMetadata(int32_t type_index, const TVMFFITypeMetadata* metadata);
-
-/*!
- * \brief Register extra type attributes that can be looked up during runtime.
- * \return 0 on success, nonzero on failure.
- */
-TVM_FFI_DLL int TVMFFITypeRegisterAttr(int32_t type_index, const TVMFFIByteArray* attr_name,
-                                       const TVMFFIAny* attr_value);
-
-/*!
- * \brief Get the type attribute column by name.
- * \return The pointer to the type attribute column.
- * \return NULL if the attribute was not registered in the system.
- */
-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
-//------------------------------------------------------------
-/*!
- * \brief Get stack traceback in a string.
- * \param filename The current file name.
- * \param lineno The current line number
- * \param func The current function
- * \param cross_ffi_boundary Whether the traceback is crossing the ffi boundary
- *                           or we should stop at the ffi boundary when detected
- * \return The traceback string
- *
- * \note filename/func can be nullptr, then this info is skipped, they are useful
- * for cases when debug symbols are not available.
- */
-TVM_FFI_DLL const TVMFFIByteArray* TVMFFITraceback(const char* filename, int lineno,
-                                                   const char* func, int cross_ffi_boundary);
-
-/*!
- * \brief Initialize the type info during runtime.
- *
- * When the function is first called for a type,
- * it will register the type to the type table in the runtime.
- * If the static_tindex is non-negative, the function will
- * allocate a runtime type index.
- * Otherwise, we will populate the type table and return the static index.
- *
- * \param type_key The type key.
- * \param type_depth The type depth.
- * \param static_type_index Static type index if any, can be -1, which means this is a dynamic index
- * \param num_child_slots Number of slots reserved for its children.
- * \param child_slots_can_overflow Whether to allow child to overflow the slots.
- * \param parent_type_index Parent type index, pass in -1 if it is root.
- *
- * \return The allocated type index.
- */
-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);
-
-/*!
- * \brief Get dynamic type info by type index.
- * \return The type info.
- */
-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
-/*!
- * \brief Get the type index of an object.
- * \param obj The object handle.
- * \return The type index.
- */
-inline int32_t TVMFFIObjectGetTypeIndex(TVMFFIObjectHandle obj) {
-  return static_cast<TVMFFIObject*>(obj)->type_index;
-}
-
-/*!
- * \brief Get the content of a small string in bytearray format.
- * \param value The value to get the content of the small string in bytearray format.
- * \return The content of the small string in bytearray format.
- */
-inline TVMFFIByteArray TVMFFISmallBytesGetContentByteArray(const TVMFFIAny* value) {
-  return TVMFFIByteArray{value->v_bytes, static_cast<size_t>(value->small_str_len)};
-}
-
-/*!
- * \brief Get the data pointer of a bytearray from a string or bytes object.
- * \param obj The object handle.
- * \return The data pointer.
- */
-inline TVMFFIByteArray* TVMFFIBytesGetByteArrayPtr(TVMFFIObjectHandle obj) {
-  return reinterpret_cast<TVMFFIByteArray*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
-}
-
-/*!
- * \brief Get the data pointer of a ErrorInfo from an Error object.
- * \param obj The object handle.
- * \return The cell pointer.
- */
-inline TVMFFIErrorCell* TVMFFIErrorGetCellPtr(TVMFFIObjectHandle obj) {
-  return reinterpret_cast<TVMFFIErrorCell*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
-}
-
-/*!
- * \brief Get the data pointer of a function cell from a function object.
- * \param obj The object handle.
- * \return The cell pointer.
- */
-inline TVMFFIFunctionCell* TVMFFIFunctionGetCellPtr(TVMFFIObjectHandle obj) {
-  return reinterpret_cast<TVMFFIFunctionCell*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
-}
-
-/*!
- * \brief Get the data pointer of a opaque object cell from a opaque object.
- * \param obj The object handle.
- * \return The cell pointer.
- */
-inline TVMFFIOpaqueObjectCell* TVMFFIOpaqueObjectGetCellPtr(TVMFFIObjectHandle obj) {
-  return reinterpret_cast<TVMFFIOpaqueObjectCell*>(reinterpret_cast<char*>(obj) +
-                                                   sizeof(TVMFFIObject));
-}
-
-/*!
- * \brief Get the data pointer of a shape array from a shape object.
- * \param obj The object handle.
- * \return The cell pointer.
- */
-inline TVMFFIShapeCell* TVMFFIShapeGetCellPtr(TVMFFIObjectHandle obj) {
-  return reinterpret_cast<TVMFFIShapeCell*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
-}
-
-/*!
- * \brief Get the DLTensor pointer from an Tensor object.
- * \param obj The object handle.
- * \return The DLTensor pointer.
- */
-inline DLTensor* TVMFFITensorGetDLTensorPtr(TVMFFIObjectHandle obj) {
-  return reinterpret_cast<DLTensor*>(reinterpret_cast<char*>(obj) + sizeof(TVMFFIObject));
-}
-
-/*!
- * \brief Create a DLDevice from a device type and device id.
- * \param device_type The device type.
- * \param device_id The device id.
- * \return The DLDevice.
- */
-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_
diff --git a/ffi/include/tvm/ffi/cast.h b/ffi/include/tvm/ffi/cast.h
deleted file mode 100644
index 398953ad65..0000000000
--- a/ffi/include/tvm/ffi/cast.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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/cast.h
- * \brief Extra value casting helpers
- */
-#ifndef TVM_FFI_CAST_H_
-#define TVM_FFI_CAST_H_
-
-#include <tvm/ffi/any.h>
-#include <tvm/ffi/object.h>
-#include <tvm/ffi/optional.h>
-
-namespace tvm {
-namespace ffi {
-
-/*!
- * \brief Get a reference type from a raw object ptr type
- *
- *  It is always important to get a reference type
- *  if we want to return a value as reference or keep
- *  the object alive beyond the scope of the function.
- *
- * \param ptr The object pointer
- * \tparam RefType The reference type
- * \tparam ObjectType The object type
- * \return The corresponding RefType
- */
-template <typename RefType, typename ObjectType>
-inline RefType GetRef(const ObjectType* ptr) {
-  using ContainerType = typename RefType::ContainerType;
-  static_assert(std::is_base_of_v<ContainerType, ObjectType>,
-                "Can only cast to the ref of same container type");
-
-  if constexpr (is_optional_type_v<RefType> || RefType::_type_is_nullable) {
-    if (ptr == nullptr) {
-      return details::ObjectUnsafe::ObjectRefFromObjectPtr<RefType>(nullptr);
-    }
-  } else {
-    TVM_FFI_ICHECK_NOTNULL(ptr);
-  }
-  return details::ObjectUnsafe::ObjectRefFromObjectPtr<RefType>(
-      details::ObjectUnsafe::ObjectPtrFromUnowned<Object>(
-          const_cast<Object*>(static_cast<const Object*>(ptr))));
-}
-
-/*!
- * \brief Get an object ptr type from a raw object ptr.
- *
- * \param ptr The object pointer
- * \tparam BaseType The reference type
- * \tparam ObjectType The object type
- * \return The corresponding RefType
- */
-template <typename BaseType, typename ObjectType>
-inline ObjectPtr<BaseType> GetObjectPtr(ObjectType* ptr) {
-  static_assert(std::is_base_of<BaseType, ObjectType>::value,
-                "Can only cast to the ref of same container type");
-  return details::ObjectUnsafe::ObjectPtrFromUnowned<BaseType>(ptr);
-}
-}  // namespace ffi
-}  // namespace tvm
-#endif  // TVM_FFI_CAST_H_
diff --git a/ffi/include/tvm/ffi/container/array.h b/ffi/include/tvm/ffi/container/array.h
deleted file mode 100644
index db025c02d8..0000000000
--- a/ffi/include/tvm/ffi/container/array.h
+++ /dev/null
@@ -1,1147 +0,0 @@
-/*
- * 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/container/array.h
- * \brief Array type.
- *
- * tvm::ffi::Array<Any> is an erased type that contains a list of content
- */
-#ifndef TVM_FFI_CONTAINER_ARRAY_H_
-#define TVM_FFI_CONTAINER_ARRAY_H_
-
-#include <tvm/ffi/any.h>
-#include <tvm/ffi/container/container_details.h>
-#include <tvm/ffi/memory.h>
-#include <tvm/ffi/object.h>
-#include <tvm/ffi/optional.h>
-
-#include <algorithm>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-namespace tvm {
-namespace ffi {
-
-/*! \brief Array node content in array */
-class ArrayObj : public Object, public details::InplaceArrayBase<ArrayObj, TVMFFIAny> {
- public:
-  ~ArrayObj() {
-    Any* begin = MutableBegin();
-    for (int64_t i = 0; i < size_; ++i) {
-      (begin + i)->Any::~Any();
-    }
-    if (data_deleter_ != nullptr) {
-      data_deleter_(data_);
-    }
-  }
-
-  /*! \return The size of the array */
-  size_t size() const { return this->size_; }
-
-  /*!
-   * \brief Read i-th element from array.
-   * \param i The index
-   * \return the i-th element.
-   */
-  const Any& at(int64_t i) const { return this->operator[](i); }
-
-  /*!
-   * \brief Read i-th element from array.
-   * \param i The index
-   * \return the i-th element.
-   */
-  const Any& operator[](int64_t i) const {
-    if (i >= size_) {
-      TVM_FFI_THROW(IndexError) << "Index " << i << " out of bounds " << size_;
-    }
-    return static_cast<Any*>(data_)[i];
-  }
-
-  /*! \return begin constant iterator */
-  const Any* begin() const { return static_cast<Any*>(data_); }
-
-  /*! \return end constant iterator */
-  const Any* end() const { return begin() + size_; }
-
-  /*! \brief Release reference to all the elements */
-  void clear() { ShrinkBy(size_); }
-
-  /*!
-   * \brief Set i-th element of the array in-place
-   * \param i The index
-   * \param item The value to be set
-   */
-  void SetItem(int64_t i, Any item) {
-    if (i >= size_) {
-      TVM_FFI_THROW(IndexError) << "Index " << i << " out of bounds " << size_;
-    }
-    static_cast<Any*>(data_)[i] = std::move(item);
-  }
-
-  /*!
-   * \brief Constructs a container and copy from another
-   * \param cap The capacity of the container
-   * \param from Source of the copy
-   * \return Ref-counted ArrayObj requested
-   */
-  static ObjectPtr<ArrayObj> CopyFrom(int64_t cap, ArrayObj* from) {
-    int64_t size = from->size_;
-    if (size > cap) {
-      TVM_FFI_THROW(ValueError) << "Not enough capacity";
-    }
-    ObjectPtr<ArrayObj> p = ArrayObj::Empty(cap);
-    Any* write = p->MutableBegin();
-    Any* read = from->MutableBegin();
-    // To ensure exception safety, size is only incremented after the initialization succeeds
-    for (int64_t& i = p->size_ = 0; i < size; ++i) {
-      new (write++) Any(*read++);
-    }
-    return p;
-  }
-
-  /*!
-   * \brief Constructs a container and move from another
-   * \param cap The capacity of the container
-   * \param from Source of the move
-   * \return Ref-counted ArrayObj requested
-   */
-  static ObjectPtr<ArrayObj> MoveFrom(int64_t cap, ArrayObj* from) {
-    int64_t size = from->size_;
-    if (size > cap) {
-      TVM_FFI_THROW(RuntimeError) << "Not enough capacity";
-    }
-    ObjectPtr<ArrayObj> p = ArrayObj::Empty(cap);
-    Any* write = p->MutableBegin();
-    Any* read = from->MutableBegin();
-    // To ensure exception safety, size is only incremented after the initialization succeeds
-    for (int64_t& i = p->size_ = 0; i < size; ++i) {
-      new (write++) Any(std::move(*read++));
-    }
-    from->size_ = 0;
-    return p;
-  }
-
-  /*!
-   * \brief Constructs a container with n elements. Each element is a copy of val
-   * \param n The size of the container
-   * \param val The init value
-   * \return Ref-counted ArrayObj requested
-   */
-  static ObjectPtr<ArrayObj> CreateRepeated(int64_t n, const Any& val) {
-    ObjectPtr<ArrayObj> p = ArrayObj::Empty(n);
-    Any* itr = p->MutableBegin();
-    for (int64_t& i = p->size_ = 0; i < n; ++i) {
-      new (itr++) Any(val);
-    }
-    return p;
-  }
-
-  /// \cond Doxygen_Suppress
-  static constexpr const int32_t _type_index = TypeIndex::kTVMFFIArray;
-  static const constexpr bool _type_final = true;
-  TVM_FFI_DECLARE_OBJECT_INFO_STATIC(StaticTypeKey::kTVMFFIArray, ArrayObj, Object);
-  /// \endcond
-
- private:
-  /*! \return Size of initialized memory, used by InplaceArrayBase. */
-  size_t GetSize() const { return this->size_; }
-
-  /*! \return begin mutable iterator */
-  Any* MutableBegin() const { return static_cast<Any*>(this->data_); }
-
-  /*! \return end mutable iterator */
-  Any* MutableEnd() const { return MutableBegin() + size_; }
-
-  /*!
-   * \brief Emplace a new element at the back of the array
-   * \param idx The index of the element.
-   * \param args The arguments to construct the new element
-   */
-  template <typename... Args>
-  void EmplaceInit(size_t idx, Args&&... args) {
-    Any* itr = MutableBegin() + idx;
-    new (itr) Any(std::forward<Args>(args)...);
-  }
-
-  /*!
-   * \brief Create an ArrayObj with the given capacity.
-   * \param n Required capacity
-   * \return Ref-counted ArrayObj requested
-   */
-  static ObjectPtr<ArrayObj> Empty(int64_t n = kInitSize) {
-    ObjectPtr<ArrayObj> p = make_inplace_array_object<ArrayObj, Any>(n);
-    p->capacity_ = n;
-    p->size_ = 0;
-    p->data_ = p->AddressOf(0);
-    return p;
-  }
-
-  /*!
-   * \brief Inplace-initialize the elements starting idx from [first, last)
-   * \param idx The starting point
-   * \param first Begin of iterator
-   * \param last End of iterator
-   * \tparam IterType The type of iterator
-   * \return Self
-   */
-  template <typename IterType>
-  ArrayObj* InitRange(int64_t idx, IterType first, IterType last) {
-    Any* itr = MutableBegin() + idx;
-    for (; first != last; ++first) {
-      Any ref = *first;
-      new (itr++) Any(std::move(ref));
-    }
-    return this;
-  }
-
-  /*!
-   * \brief Move elements from right to left, requires src_begin > dst
-   * \param dst Destination
-   * \param src_begin The start point of copy (inclusive)
-   * \param src_end The end point of copy (exclusive)
-   * \return Self
-   */
-  ArrayObj* MoveElementsLeft(int64_t dst, int64_t src_begin, int64_t src_end) {
-    Any* from = MutableBegin() + src_begin;
-    Any* to = MutableBegin() + dst;
-    while (src_begin++ != src_end) {
-      *to++ = std::move(*from++);
-    }
-    return this;
-  }
-
-  /*!
-   * \brief Move elements from left to right, requires src_begin < dst
-   * \param dst Destination
-   * \param src_begin The start point of move (inclusive)
-   * \param src_end The end point of move (exclusive)
-   * \return Self
-   */
-  ArrayObj* MoveElementsRight(int64_t dst, int64_t src_begin, int64_t src_end) {
-    Any* from = MutableBegin() + src_end;
-    Any* to = MutableBegin() + (src_end - src_begin + dst);
-    while (src_begin++ != src_end) {
-      *--to = std::move(*--from);
-    }
-    return this;
-  }
-
-  /*!
-   * \brief Enlarges the size of the array
-   * \param delta Size enlarged, should be positive
-   * \param val Default value
-   * \return Self
-   */
-  ArrayObj* EnlargeBy(int64_t delta, const Any& val = Any()) {
-    Any* itr = MutableEnd();
-    while (delta-- > 0) {
-      new (itr++) Any(val);
-      ++size_;
-    }
-    return this;
-  }
-
-  /*!
-   * \brief Shrinks the size of the array
-   * \param delta Size shrinked, should be positive
-   * \return Self
-   */
-  ArrayObj* ShrinkBy(int64_t delta) {
-    Any* itr = MutableEnd();
-    while (delta-- > 0) {
-      (--itr)->Any::~Any();
-      --size_;
-    }
-    return this;
-  }
-
-  /*! \brief Data pointer to the first element of the array */
-  void* data_;
-  /*! \brief Number of elements used */
-  int64_t size_;
-  /*! \brief Number of elements allocated */
-  int64_t capacity_;
-  /*!
-   * \brief Optional data deleter when data is allocated separately
-   *        and its deletion is not managed by ArrayObj::deleter_.
-   */
-  void (*data_deleter_)(void*) = nullptr;
-
-  /*! \brief Initial size of ArrayObj */
-  static constexpr int64_t kInitSize = 4;
-
-  /*! \brief Expansion factor of the Array */
-  static constexpr int64_t kIncFactor = 2;
-
-  // CRTP parent class
-  friend InplaceArrayBase<ArrayObj, Any>;
-
-  // Reference class
-  template <typename, typename>
-  friend class Array;
-
-  template <typename... Types>
-  friend class Tuple;
-
-  template <typename, typename>
-  friend struct TypeTraits;
-
-  // To specialize make_object<ArrayObj>
-  friend ObjectPtr<ArrayObj> make_object<>();
-};
-
-/*! \brief Helper struct for type-checking
- *
- * is_valid_iterator<T,IterType>::value will be true if IterType can
- * be dereferenced into a type that can be stored in an Array<T>, and
- * false otherwise.
- */
-template <typename T, typename IterType>
-struct is_valid_iterator
-    : std::bool_constant<
-          std::is_same_v<
-              T, std::remove_cv_t<std::remove_reference_t<decltype(*std::declval<IterType>())>>> ||
-          std::is_base_of_v<
-              T, std::remove_cv_t<std::remove_reference_t<decltype(*std::declval<IterType>())>>>> {
-};
-
-template <typename T, typename IterType>
-struct is_valid_iterator<Optional<T>, IterType> : is_valid_iterator<T, IterType> {};
-
-template <typename IterType>
-struct is_valid_iterator<Any, IterType> : std::true_type {};
-
-/*!
- * \brief Check whether IterType is valid iterator for T.
- * \tparam T The type.
- * \tparam IterType The type of iterator.
- */
-template <typename T, typename IterType>
-inline constexpr bool is_valid_iterator_v = is_valid_iterator<T, IterType>::value;
-
-/*!
- * \brief Array, container representing a contiguous sequence of ObjectRefs.
- *
- *  Array implements in-place copy-on-write semantics.
- *
- * As in typical copy-on-write, a method which would typically mutate the array
- * instead opaquely copies the underlying container, and then acts on its copy.
- *
- * If the array has reference count equal to one, we directly update the
- * container in place without copying. This is optimization is sound because
- * when the reference count is equal to one this reference is guranteed to be
- * the sole pointer to the container.
- *
- *
- * operator[] only provides const access, use Set to mutate the content.
- * \tparam T The content Value type, must be compatible with tvm::ffi::Any
- */
-template <typename T, typename = typename std::enable_if_t<details::storage_enabled_v<T>>>
-class Array : public ObjectRef {
- public:
-  /*! \brief The value type of the array */
-  using value_type = T;
-  // constructors
-  /*!
-   * \brief Construct an Array with UnsafeInit
-   */
-  explicit Array(UnsafeInit tag) : ObjectRef(tag) {}
-  /*!
-   * \brief default constructor
-   */
-  Array() { data_ = ArrayObj::Empty(); }
-  /*!
-   * \brief Move constructor
-   * \param other The other array
-   */
-  Array(Array<T>&& other) : ObjectRef(std::move(other.data_)) {}
-  /*!
-   * \brief Copy constructor
-   * \param other The other array
-   */
-  Array(const Array<T>& other) : ObjectRef(other.data_) {}
-  /*!
-   * \brief Constructor from another array
-   * \param other The other array
-   * \tparam U The value type of the other array
-   */
-  template <typename U, typename = std::enable_if_t<details::type_contains_v<T, U>>>
-  Array(Array<U>&& other) : ObjectRef(std::move(other.data_)) {}
-  /*!
-   * \brief Constructor from another array
-   * \param other The other array
-   * \tparam U The value type of the other array
-   */
-  template <typename U, typename = std::enable_if_t<details::type_contains_v<T, U>>>
-  Array(const Array<U>& other) : ObjectRef(other.data_) {}
-
-  /*!
-   * \brief Move assignment from another array
-   * \param other The other array
-   */
-  TVM_FFI_INLINE Array<T>& operator=(Array<T>&& other) {
-    data_ = std::move(other.data_);
-    return *this;
-  }
-  /*!
-   * \brief Assignment from another array
-   * \param other The other array
-   */
-  TVM_FFI_INLINE Array<T>& operator=(const Array<T>& other) {
-    data_ = other.data_;
-    return *this;
-  }
-  /*!
-   * \brief Move assignment from another array
-   * \param other The other array
-   * \tparam U The value type of the other array
-   */
-  template <typename U, typename = std::enable_if_t<details::type_contains_v<T, U>>>
-  TVM_FFI_INLINE Array<T>& operator=(Array<U>&& other) {
-    data_ = std::move(other.data_);
-    return *this;
-  }
-  /*!
-   * \brief Assignment from another array
-   * \param other The other array
-   * \tparam U The value type of the other array
-   */
-  template <typename U, typename = std::enable_if_t<details::type_contains_v<T, U>>>
-  TVM_FFI_INLINE Array<T>& operator=(const Array<U>& other) {
-    data_ = other.data_;
-    return *this;
-  }
-
-  /*!
-   * \brief Constructor from pointer
-   * \param n the container pointer
-   */
-  explicit Array(ObjectPtr<Object> n) : ObjectRef(n) {}
-
-  /*!
-   * \brief Constructor from iterator
-   * \param first begin of iterator
-   * \param last end of iterator
-   * \tparam IterType The type of iterator
-   */
-  template <typename IterType>
-  Array(IterType first, IterType last) {
-    static_assert(is_valid_iterator_v<T, IterType>,
-                  "IterType cannot be inserted into a tvm::Array<T>");
-    Assign(first, last);
-  }
-
-  /*!
-   * \brief constructor from initializer list
-   * \param init The initializer list
-   */
-  Array(std::initializer_list<T> init) {  // NOLINT(*)
-    Assign(init.begin(), init.end());
-  }
-
-  /*!
-   * \brief constructor from vector
-   * \param init The vector
-   */
-  Array(const std::vector<T>& init) {  // NOLINT(*)
-    Assign(init.begin(), init.end());
-  }
-
-  /*!
-   * \brief Constructs a container with n elements. Each element is a copy of val
-   * \param n The size of the container
-   * \param val The init value
-   */
-  explicit Array(const size_t n, const T& val) { data_ = ArrayObj::CreateRepeated(n, val); }
-
- public:
-  // iterators
-  /// \cond Doxygen_Suppress
-  struct ValueConverter {
-    using ResultType = T;
-    /*!
-     * \brief Convert any to T
-     * \param n The any value to convert
-     * \return The converted value
-     */
-    static T convert(const Any& n) { return details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(n); }
-  };
-  /// \endcond
-
-  /*! \brief The iterator type of the array */
-  using iterator = details::IterAdapter<ValueConverter, const Any*>;
-  /*! \brief The reverse iterator type of the array */
-  using reverse_iterator = details::ReverseIterAdapter<ValueConverter, const Any*>;
-
-  /*! \return begin iterator */
-  iterator begin() const { return iterator(GetArrayObj()->begin()); }
-
-  /*! \return end iterator */
-  iterator end() const { return iterator(GetArrayObj()->end()); }
-
-  /*! \return rbegin iterator */
-  reverse_iterator rbegin() const {
-    // ArrayObj::end() is never nullptr
-    return reverse_iterator(GetArrayObj()->end() - 1);
-  }
-
-  /*! \return rend iterator */
-  reverse_iterator rend() const {
-    // ArrayObj::begin() is never nullptr
-    return reverse_iterator(GetArrayObj()->begin() - 1);
-  }
-
- public:
-  // const methods in std::vector
-  /*!
-   * \brief Immutably read i-th element from array.
-   * \param i The index
-   * \return the i-th element.
-   */
-  const T operator[](int64_t i) const {
-    ArrayObj* p = GetArrayObj();
-    if (p == nullptr) {
-      TVM_FFI_THROW(IndexError) << "cannot index a null array";
-    }
-    if (i < 0 || i >= p->size_) {
-      TVM_FFI_THROW(IndexError) << "indexing " << i << " on an array of size " << p->size_;
-    }
-    return details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(*(p->begin() + i));
-  }
-
-  /*! \return The size of the array */
-  size_t size() const {
-    ArrayObj* p = GetArrayObj();
-    return p == nullptr ? 0 : GetArrayObj()->size_;
-  }
-
-  /*! \return The capacity of the array */
-  size_t capacity() const {
-    ArrayObj* p = GetArrayObj();
-    return p == nullptr ? 0 : GetArrayObj()->capacity_;
-  }
-
-  /*! \return Whether array is empty */
-  bool empty() const { return size() == 0; }
-
-  /*! \return The first element of the array */
-  const T front() const {
-    ArrayObj* p = GetArrayObj();
-    if (p == nullptr || p->size_ == 0) {
-      TVM_FFI_THROW(IndexError) << "cannot index a empty array";
-    }
-    return details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(*(p->begin()));
-  }
-
-  /*! \return The last element of the array */
-  const T back() const {
-    ArrayObj* p = GetArrayObj();
-    if (p == nullptr || p->size_ == 0) {
-      TVM_FFI_THROW(IndexError) << "cannot index a empty array";
-    }
-    return details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(*(p->end() - 1));
-  }
-
- public:
-  // mutation in std::vector, implements copy-on-write
-  /*!
-   * \brief push a new item to the back of the list
-   * \param item The item to be pushed.
-   */
-  void push_back(const T& item) {
-    ArrayObj* p = CopyOnWrite(1);
-    p->EmplaceInit(p->size_++, item);
-  }
-
-  /*!
-   * \brief Emplace a new element at the back of the array
-   * \param args The arguments to construct the new element
-   */
-  template <typename... Args>
-  void emplace_back(Args&&... args) {
-    ArrayObj* p = CopyOnWrite(1);
-    p->EmplaceInit(p->size_++, std::forward<Args>(args)...);
-  }
-
-  /*!
-   * \brief Insert an element into the given position
-   * \param position An iterator pointing to the insertion point
-   * \param val The element to insert
-   */
-  void insert(iterator position, const T& val) {
-    if (data_ == nullptr) {
-      TVM_FFI_THROW(RuntimeError) << "cannot insert a null array";
-    }
-    int64_t idx = std::distance(begin(), position);
-    int64_t size = GetArrayObj()->size_;
-    auto addr = CopyOnWrite(1)                               //
-                    ->EnlargeBy(1)                           //
-                    ->MoveElementsRight(idx + 1, idx, size)  //
-                    ->MutableBegin();
-    new (addr + idx) Any(val);
-  }
-
-  /*!
-   * \brief Insert a range of elements into the given position
-   * \param position An iterator pointing to the insertion point
-   * \param first The begin iterator of the range
-   * \param last The end iterator of the range
-   */
-  template <typename IterType>
-  void insert(iterator position, IterType first, IterType last) {
-    static_assert(is_valid_iterator_v<T, IterType>,
-                  "IterType cannot be inserted into a tvm::Array<T>");
-
-    if (first == last) {
-      return;
-    }
-    if (data_ == nullptr) {
-      TVM_FFI_THROW(RuntimeError) << "cannot insert a null array";
-    }
-    int64_t idx = std::distance(begin(), position);
-    int64_t size = GetArrayObj()->size_;
-    int64_t numel = std::distance(first, last);
-    CopyOnWrite(numel)
-        ->EnlargeBy(numel)
-        ->MoveElementsRight(idx + numel, idx, size)
-        ->InitRange(idx, first, last);
-  }
-
-  /*! \brief Remove the last item of the list */
-  void pop_back() {
-    if (data_ == nullptr) {
-      TVM_FFI_THROW(RuntimeError) << "cannot pop_back a null array";
-    }
-    int64_t size = GetArrayObj()->size_;
-    if (size == 0) {
-      TVM_FFI_THROW(RuntimeError) << "cannot pop_back an empty array";
-    }
-    CopyOnWrite()->ShrinkBy(1);
-  }
-
-  /*!
-   * \brief Erase an element on the given position
-   * \param position An iterator pointing to the element to be erased
-   */
-  void erase(iterator position) {
-    if (data_ == nullptr) {
-      TVM_FFI_THROW(RuntimeError) << "cannot erase a null array";
-    }
-    int64_t st = std::distance(begin(), position);
-    int64_t size = GetArrayObj()->size_;
-    if (st < 0 || st >= size) {
-      TVM_FFI_THROW(RuntimeError) << "cannot erase at index " << st << ", because Array size is "
-                                  << size;
-    }
-    CopyOnWrite()                             //
-        ->MoveElementsLeft(st, st + 1, size)  //
-        ->ShrinkBy(1);
-  }
-
-  /*!
-   * \brief Erase a given range of elements
-   * \param first The begin iterator of the range
-   * \param last The end iterator of the range
-   */
-  void erase(iterator first, iterator last) {
-    if (first == last) {
-      return;
-    }
-    if (data_ == nullptr) {
-      TVM_FFI_THROW(RuntimeError) << "cannot erase a null array";
-    }
-    int64_t size = GetArrayObj()->size_;
-    int64_t st = std::distance(begin(), first);
-    int64_t ed = std::distance(begin(), last);
-    if (st >= ed) {
-      TVM_FFI_THROW(IndexError) << "cannot erase array in range [" << st << ", " << ed << ")";
-    }
-    if (st < 0 || st > size || ed < 0 || ed > size) {
-      TVM_FFI_THROW(IndexError) << "cannot erase array in range [" << st << ", " << ed << ")"
-                                << ", because array size is " << size;
-    }
-    CopyOnWrite()                         //
-        ->MoveElementsLeft(st, ed, size)  //
-        ->ShrinkBy(ed - st);
-  }
-
-  /*!
-   * \brief Resize the array.
-   * \param n The new size.
-   */
-  void resize(int64_t n) {
-    if (n < 0) {
-      TVM_FFI_THROW(ValueError) << "cannot resize an Array to negative size";
-    }
-    if (data_ == nullptr) {
-      SwitchContainer(n);
-      return;
-    }
-    int64_t size = GetArrayObj()->size_;
-    if (size < n) {
-      CopyOnWrite(n - size)->EnlargeBy(n - size);
-    } else if (size > n) {
-      CopyOnWrite()->ShrinkBy(size - n);
-    }
-  }
-
-  /*!
-   * \brief Make sure the list has the capacity of at least n
-   * \param n lower bound of the capacity
-   */
-  void reserve(int64_t n) {
-    if (data_ == nullptr || n > GetArrayObj()->capacity_) {
-      SwitchContainer(n);
-    }
-  }
-
-  /*! \brief Release reference to all the elements */
-  void clear() {
-    if (data_ != nullptr) {
-      ArrayObj* p = CopyOnWrite();
-      p->clear();
-    }
-  }
-  /// \cond Doxygen_Suppress
-  template <typename... Args>
-  static size_t CalcCapacityImpl() {
-    return 0;
-  }
-
-  template <typename... Args>
-  static size_t CalcCapacityImpl(Array<T> value, Args... args) {
-    return value.size() + CalcCapacityImpl(args...);
-  }
-
-  template <typename... Args>
-  static size_t CalcCapacityImpl(T value, Args... args) {
-    return 1 + CalcCapacityImpl(args...);
-  }
-
-  template <typename... Args>
-  static void AgregateImpl(Array<T>& dest) {}  // NOLINT(*)
-
-  template <typename... Args>
-  static void AgregateImpl(Array<T>& dest, Array<T> value, Args... args) {  // NOLINT(*)
-    dest.insert(dest.end(), value.begin(), value.end());
-    AgregateImpl(dest, args...);
-  }
-
-  template <typename... Args>
-  static void AgregateImpl(Array<T>& dest, T value, Args... args) {  // NOLINT(*)
-    dest.push_back(value);
-    AgregateImpl(dest, args...);
-  }
-  /// \endcond
-
- public:
-  // Array's own methods
-
-  /*!
-   * \brief set i-th element of the array.
-   * \param i The index
-   * \param value The value to be setted.
-   */
-  void Set(int64_t i, T value) {
-    ArrayObj* p = this->CopyOnWrite();
-    if (i < 0 || i >= p->size_) {
-      TVM_FFI_THROW(IndexError) << "indexing " << i << " on an array of size " << p->size_;
-    }
-    *(p->MutableBegin() + i) = std::move(value);
-  }
-
-  /*! \return The underlying ArrayObj */
-  ArrayObj* GetArrayObj() const { return static_cast<ArrayObj*>(data_.get()); }
-
-  /*!
-   * \brief Helper function to apply a map function onto the array.
-   *
-   * \param fmap The transformation function T -> U.
-   *
-   * \tparam F The type of the mutation function.
-   *
-   * \tparam U The type of the returned array, inferred from the
-   * return type of F.  If overridden by the user, must be something
-   * that is convertible from the return type of F.
-   *
-   * \note This function performs copy on write optimization.  If
-   * `fmap` returns an object of type `T`, and all elements of the
-   * array are mapped to themselves, then the returned array will be
-   * the same as the original, and reference counts of the elements in
-   * the array will not be incremented.
-   *
-   * \return The transformed array.
-   */
-  template <typename F, typename U = std::invoke_result_t<F, T>>
-  Array<U> Map(F fmap) const {
-    return Array<U>(MapHelper(data_, fmap));
-  }
-
-  /*!
-   * \brief Helper function to apply fmutate to mutate an array.
-   * \param fmutate The transformation function T -> T.
-   * \tparam F the type of the mutation function.
-   * \note This function performs copy on write optimization.
-   */
-  template <typename F, typename = std::enable_if_t<std::is_same_v<T, std::invoke_result_t<F, T>>>>
-  void MutateByApply(F fmutate) {
-    data_ = MapHelper(std::move(data_), fmutate);
-  }
-
-  /*!
-   * \brief reset the array to content from iterator.
-   * \param first begin of iterator
-   * \param last end of iterator
-   * \tparam IterType The type of iterator
-   */
-  template <typename IterType>
-  void Assign(IterType first, IterType last) {
-    int64_t cap = std::distance(first, last);
-    if (cap < 0) {
-      TVM_FFI_THROW(ValueError) << "cannot construct an Array of negative size";
-    }
-    ArrayObj* p = GetArrayObj();
-    if (p != nullptr && data_.unique() && p->capacity_ >= cap) {
-      // do not have to make new space
-      p->clear();
-    } else {
-      // create new space
-      data_ = ArrayObj::Empty(cap);
-      p = GetArrayObj();
-    }
-    // To ensure exception safety, size is only incremented after the initialization succeeds
-    Any* itr = p->MutableBegin();
-    for (int64_t& i = p->size_ = 0; i < cap; ++i, ++first, ++itr) {
-      new (itr) Any(*first);
-    }
-  }
-
-  /*!
-   * \brief Copy on write semantics
-   *  Do nothing if current handle is the unique copy of the array.
-   *  Otherwise make a new copy of the array to ensure the current handle
-   *  hold a unique copy.
-   *
-   * \return Handle to the internal node container(which ganrantees to be unique)
-   */
-  ArrayObj* CopyOnWrite() {
-    if (data_ == nullptr) {
-      return SwitchContainer(ArrayObj::kInitSize);
-    }
-    if (!data_.unique()) {
-      return SwitchContainer(capacity());
-    }
-    return static_cast<ArrayObj*>(data_.get());
-  }
-
-  /*! \brief specify container node */
-  using ContainerType = ArrayObj;
-
-  /*!
-   * \brief Agregate arguments into a single Array<T>
-   * \param args sequence of T or Array<T> elements
-   * \return Agregated Array<T>
-   */
-  template <typename... Args>
-  static Array<T> Agregate(Args... args) {
-    Array<T> result;
-    result.reserve(CalcCapacityImpl(args...));
-    AgregateImpl(result, args...);
-    return result;
-  }
-
- private:
-  /*!
-   * \brief Implement copy-on-write semantics, and ensures capacity is enough for extra elements.
-   * \param reserve_extra Number of extra slots needed
-   * \return ArrayObj pointer to the unique copy
-   */
-  ArrayObj* CopyOnWrite(int64_t reserve_extra) {
-    ArrayObj* p = GetArrayObj();
-    if (p == nullptr) {
-      // necessary to get around the constexpr address issue before c++17
-      const int64_t kInitSize = ArrayObj::kInitSize;
-      return SwitchContainer(std::max(kInitSize, reserve_extra));
-    }
-    if (p->capacity_ >= p->size_ + reserve_extra) {
-      return CopyOnWrite();
-    }
-    int64_t cap = p->capacity_ * ArrayObj::kIncFactor;
-    cap = std::max(cap, p->size_ + reserve_extra);
-    return SwitchContainer(cap);
-  }
-
-  /*!
-   * \brief Move or copy the ArrayObj to new address with the given capacity
-   * \param capacity The capacity requirement of the new address
-   */
-  ArrayObj* SwitchContainer(int64_t capacity) {
-    if (data_ == nullptr) {
-      data_ = ArrayObj::Empty(capacity);
-    } else if (data_.unique()) {
-      data_ = ArrayObj::MoveFrom(capacity, GetArrayObj());
-    } else {
-      data_ = ArrayObj::CopyFrom(capacity, GetArrayObj());
-    }
-    return static_cast<ArrayObj*>(data_.get());
-  }
-
-  /*! \brief Helper method for mutate/map
-   *
-   * A helper function used internally by both `Array::Map` and
-   * `Array::MutateInPlace`.  Given an array of data, apply the
-   * mapping function to each element, returning the collected array.
-   * Applies both mutate-in-place and copy-on-write optimizations, if
-   * possible.
-   *
-   * \param data A pointer to the ArrayObj containing input data.
-   * Passed by value to allow for mutate-in-place optimizations.
-   *
-   * \param fmap The mapping function
-   *
-   * \tparam F The type of the mutation function.
-   *
-   * \tparam U The output type of the mutation function.  Inferred
-   * from the callable type given.  Must inherit from ObjectRef.
-   *
-   * \return The mapped array.  Depending on whether mutate-in-place
-   * or copy-on-write optimizations were applicable, may be the same
-   * underlying array as the `data` parameter.
-   */
-  template <typename F, typename U = std::invoke_result_t<F, T>>
-  static ObjectPtr<Object> MapHelper(ObjectPtr<Object> data, F fmap) {
-    if (data == nullptr) {
-      return nullptr;
-    }
-
-    TVM_FFI_ICHECK(data->IsInstance<ArrayObj>());
-
-    constexpr bool is_same_output_type = std::is_same_v<T, U>;
-
-    if constexpr (is_same_output_type) {
-      if (data.unique()) {
-        // Mutate-in-place path.  Only allowed if the output type U is
-        // the same as type T, we have a mutable this*, and there are
-        // no other shared copies of the array.
-        auto arr = static_cast<ArrayObj*>(data.get());
-        for (auto it = arr->MutableBegin(); it != arr->MutableEnd(); it++) {
-          T value = details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(*it);
-          // reset the original value to nullptr, to ensure unique ownership
-          it->reset();
-          T mapped = fmap(std::move(value));
-          *it = std::move(mapped);
-        }
-        return data;
-      }
-    }
-
-    constexpr bool compatible_types = is_valid_iterator_v<T, U*> || is_valid_iterator_v<U, T*>;
-
-    ObjectPtr<ArrayObj> output = nullptr;
-    auto arr = static_cast<ArrayObj*>(data.get());
-
-    auto it = arr->begin();
-    if constexpr (compatible_types) {
-      // Copy-on-write path, if the output Array<U> might be
-      // represented by the same underlying array as the existing
-      // Array<T>.  Typically, this is for functions that map `T` to
-      // `T`, but can also apply to functions that map `T` to
-      // `Optional<T>`, or that map `T` to a subclass or superclass of
-      // `T`.
-      bool all_identical = true;
-      for (; it != arr->end(); it++) {
-        U mapped = fmap(details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(*it));
-        if (!(*it).same_as(mapped)) {
-          // At least one mapped element is different than the
-          // original.  Therefore, prepare the output array,
-          // consisting of any previous elements that had mapped to
-          // themselves (if any), and the element that didn't map to
-          // itself.
-          //
-          // We cannot use `U()` as the default object, as `U` may be
-          // a non-nullable type.  Since the default `Any()`
-          // will be overwritten before returning, all objects will be
-          // of type `U` for the calling scope.
-          all_identical = false;
-          output = ArrayObj::CreateRepeated(arr->size(), Any());
-          output->InitRange(0, arr->begin(), it);
-          output->SetItem(it - arr->begin(), std::move(mapped));
-          it++;
-          break;
-        }
-      }
-      if (all_identical) {
-        return data;
-      }
-    } else {
-      // Path for incompatible types.  The constexpr check for
-      // compatible types isn't strictly necessary, as the first
-      // (*it).same_as(mapped) would return false, but we might as well
-      // avoid it altogether.
-      //
-      // We cannot use `U()` as the default object, as `U` may be a
-      // non-nullable type.  Since the default `Any()` will be
-      // overwritten before returning, all objects will be of type `U`
-      // for the calling scope.
-      output = ArrayObj::CreateRepeated(arr->size(), Any());
-    }
-
-    // Normal path for incompatible types, or post-copy path for
-    // copy-on-write instances.
-    //
-    // If the types are incompatible, then at this point `output` is
-    // empty, and `it` points to the first element of the input.
-    //
-    // If the types were compatible, then at this point `output`
-    // contains zero or more elements that mapped to themselves
-    // followed by the first element that does not map to itself, and
-    // `it` points to the element just after the first element that
-    // does not map to itself.  Because at least one element has been
-    // changed, we no longer have the opportunity to avoid a copy, so
-    // we don't need to check the result.
-    //
-    // In both cases, `it` points to the next element to be processed,
-    // so we can either start or resume the iteration from that point,
-    // with no further checks on the result.
-    for (; it != arr->end(); it++) {
-      U mapped = fmap(details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(*it));
-      output->SetItem(it - arr->begin(), std::move(mapped));
-    }
-
-    return output;
-  }
-  template <typename, typename>
-  friend class Array;
-};
-
-/*!
- * \brief Concat two Arrays.
- * \param lhs first Array to be concatenated.
- * \param rhs second Array to be concatenated.
- * \return The concatenated Array. Original Arrays are kept unchanged.
- */
-template <typename T, typename = typename std::enable_if_t<std::is_same_v<T, Any> ||
-                                                           TypeTraits<T>::convert_enabled>>
-inline Array<T> Concat(Array<T> lhs, const Array<T>& rhs) {
-  for (const auto& x : rhs) {
-    lhs.push_back(x);
-  }
-  return std::move(lhs);
-}
-
-/*!
- * \brief Specialize make_object<ArrayObj>
- * \return The empty array object.
- */
-template <>
-inline ObjectPtr<ArrayObj> make_object() {
-  return ArrayObj::Empty();
-}
-
-// Traits for Array
-template <typename T>
-inline constexpr bool use_default_type_traits_v<Array<T>> = false;
-
-template <typename T>
-struct TypeTraits<Array<T>> : public ObjectRefTypeTraitsBase<Array<T>> {
-  static constexpr int32_t field_static_type_index = TypeIndex::kTVMFFIArray;
-  using ObjectRefTypeTraitsBase<Array<T>>::CopyFromAnyViewAfterCheck;
-
-  TVM_FFI_INLINE static std::string GetMismatchTypeInfo(const TVMFFIAny* src) {
-    if (src->type_index != TypeIndex::kTVMFFIArray) {
-      return TypeTraitsBase::GetMismatchTypeInfo(src);
-    }
-    if constexpr (!std::is_same_v<T, Any>) {
-      const ArrayObj* n = reinterpret_cast<const ArrayObj*>(src->v_obj);
-      for (size_t i = 0; i < n->size(); i++) {
-        const Any& any_v = (*n)[i];
-        // CheckAnyStrict is cheaper than try_cast<T>
-        if (details::AnyUnsafe::CheckAnyStrict<T>(any_v)) continue;
-        // try see if p is convertible to T
-        if (any_v.try_cast<T>()) continue;
-        // now report the accurate mismatch information
-        return "Array[index " + std::to_string(i) + ": " +
-               details::AnyUnsafe::GetMismatchTypeInfo<T>(any_v) + "]";
-      }
-    }
-    TVM_FFI_THROW(InternalError) << "Cannot reach here";
-    TVM_FFI_UNREACHABLE();
-  }
-
-  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
-    if (src->type_index != TypeIndex::kTVMFFIArray) return false;
-    if constexpr (std::is_same_v<T, Any>) {
-      return true;
-    } else {
-      const ArrayObj* n = reinterpret_cast<const ArrayObj*>(src->v_obj);
-      for (size_t i = 0; i < n->size(); i++) {
-        const Any& any_v = (*n)[i];
-        if (!details::AnyUnsafe::CheckAnyStrict<T>(any_v)) return false;
-      }
-      return true;
-    }
-  }
-
-  TVM_FFI_INLINE static std::optional<Array<T>> TryCastFromAnyView(const TVMFFIAny* src) {
-    // try to run conversion.
-    if (src->type_index != TypeIndex::kTVMFFIArray) return std::nullopt;
-    if constexpr (!std::is_same_v<T, Any>) {
-      const ArrayObj* n = reinterpret_cast<const ArrayObj*>(src->v_obj);
-      bool storage_check = [&]() {
-        for (size_t i = 0; i < n->size(); i++) {
-          const Any& any_v = (*n)[i];
-          if (!details::AnyUnsafe::CheckAnyStrict<T>(any_v)) return false;
-        }
-        return true;
-      }();
-      // fast path, if storage check passes, we can return the array directly.
-      if (storage_check) {
-        return CopyFromAnyViewAfterCheck(src);
-      }
-      // slow path, try to run a conversion to Array<T>
-      Array<T> result;
-      result.reserve(n->size());
-      for (size_t i = 0; i < n->size(); i++) {
-        const Any& any_v = (*n)[i];
-        if (auto opt_v = any_v.try_cast<T>()) {
-          result.push_back(*std::move(opt_v));
-        } else {
-          return std::nullopt;
-        }
-      }
-      return result;
-    } else {
-      return CopyFromAnyViewAfterCheck(src);
-    }
-  }
-
-  TVM_FFI_INLINE static std::string TypeStr() { return "Array<" + details::Type2Str<T>::v() + ">"; }
-};
-
-namespace details {
-template <typename T, typename U>
-inline constexpr bool type_contains_v<Array<T>, Array<U>> = type_contains_v<T, U>;
-}  // namespace details
-
-}  // namespace ffi
-}  // namespace tvm
-#endif  // TVM_FFI_CONTAINER_ARRAY_H_
diff --git a/ffi/include/tvm/ffi/container/container_details.h b/ffi/include/tvm/ffi/container/container_details.h
deleted file mode 100644
index bb29a14f7c..0000000000
--- a/ffi/include/tvm/ffi/container/container_details.h
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * 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/container/container_details.h
- * \brief Common utilities for typed container types.
- */
-#ifndef TVM_FFI_CONTAINER_CONTAINER_DETAILS_H_
-#define TVM_FFI_CONTAINER_CONTAINER_DETAILS_H_
-
-#include <tvm/ffi/memory.h>
-#include <tvm/ffi/object.h>
-
-#include <sstream>
-#include <string>
-#include <type_traits>
-#include <utility>
-
-namespace tvm {
-namespace ffi {
-namespace details {
-/*!
- * \brief Base template for classes with array like memory layout.
- *
- *        It provides general methods to access the memory. The memory
- *        layout is ArrayType + [ElemType]. The alignment of ArrayType
- *        and ElemType is handled by the memory allocator.
- *
- * \tparam ArrayType The array header type, contains object specific metadata.
- * \tparam ElemType The type of objects stored in the array right after
- * ArrayType.
- *
- * \code
- * // Example usage of the template to define a simple array wrapper
- * class ArrayObj : public tvm::ffi::details::InplaceArrayBase<ArrayObj, Elem> {
- * public:
- *  // Wrap EmplaceInit to initialize the elements
- *  template <typename Iterator>
- *  void Init(Iterator begin, Iterator end) {
- *   size_t num_elems = std::distance(begin, end);
- *   auto it = begin;
- *   this->size = 0;
- *   for (size_t i = 0; i < num_elems; ++i) {
- *     InplaceArrayBase::EmplaceInit(i, *it++);
- *     this->size++;
- *   }
- *  }
- * }
- *
- * void test_function() {
- *   vector<Elem> fields;
- *   auto ptr = make_inplace_array_object<ArrayObj, Elem>(fields.size());
- *   ptr->Init(fields.begin(), fields.end());
- *
- *   // Access the 0th element in the array.
- *   assert(ptr->operator[](0) == fields[0]);
- * }
- *
- * \endcode
- */
-template <typename ArrayType, typename ElemType>
-class InplaceArrayBase {
- public:
-  /*!
-   * \brief Access element at index
-   * \param idx The index of the element.
-   * \return Const reference to ElemType at the index.
-   */
-  const ElemType& operator[](size_t idx) const {
-    size_t size = Self()->GetSize();
-    if (idx > size) {
-      TVM_FFI_THROW(IndexError) << "Index " << idx << " out of bounds " << size;
-    }
-    return *(reinterpret_cast<ElemType*>(AddressOf(idx)));
-  }
-
-  /*!
-   * \brief Access element at index
-   * \param idx The index of the element.
-   * \return Reference to ElemType at the index.
-   */
-  ElemType& operator[](size_t idx) {
-    size_t size = Self()->GetSize();
-    if (idx > size) {
-      TVM_FFI_THROW(IndexError) << "Index " << idx << " out of bounds " << size;
-    }
-    return *(reinterpret_cast<ElemType*>(AddressOf(idx)));
-  }
-
-  /*!
-   * \brief Destroy the Inplace Array Base object
-   */
-  ~InplaceArrayBase() {
-    if constexpr (!(std::is_standard_layout<ElemType>::value && std::is_trivial<ElemType>::value)) {
-      size_t size = Self()->GetSize();
-      for (size_t i = 0; i < size; ++i) {
-        ElemType* fp = reinterpret_cast<ElemType*>(AddressOf(i));
-        fp->ElemType::~ElemType();
-      }
-    }
-  }
-
- protected:
-  /*!
-   * \brief Construct a value in place with the arguments.
-   *
-   * \tparam Args Type parameters of the arguments.
-   * \param idx Index of the element.
-   * \param args Arguments to construct the new value.
-   *
-   * \note Please make sure ArrayType::GetSize returns 0 before first call of
-   * EmplaceInit, and increment GetSize by 1 each time EmplaceInit succeeds.
-   */
-  template <typename... Args>
-  void EmplaceInit(size_t idx, Args&&... args) {
-    void* field_ptr = AddressOf(idx);
-    new (field_ptr) ElemType(std::forward<Args>(args)...);
-  }
-
-  /*!
-   * \brief Return the self object for the array.
-   *
-   * \return Pointer to ArrayType.
-   */
-  inline ArrayType* Self() const {
-    return static_cast<ArrayType*>(const_cast<InplaceArrayBase*>(this));
-  }
-
-  /*!
-   * \brief Return the raw pointer to the element at idx.
-   *
-   * \param idx The index of the element.
-   * \return Raw pointer to the element.
-   */
-  void* AddressOf(size_t idx) const {
-    static_assert(
-        alignof(ArrayType) % alignof(ElemType) == 0 && sizeof(ArrayType) % alignof(ElemType) == 0,
-        "The size and alignment of ArrayType should respect "
-        "ElemType's alignment.");
-
-    size_t kDataStart = sizeof(ArrayType);
-    ArrayType* self = Self();
-    char* data_start = reinterpret_cast<char*>(self) + kDataStart;
-    return data_start + idx * sizeof(ElemType);
-  }
-};
-
-/*!
- * \brief iterator adapter that adapts TIter to return another type.
- * \tparam Converter a struct that contains converting function
- * \tparam TIter the content iterator type.
- */
-template <typename Converter, typename TIter>
-class IterAdapter {
- public:
-  using difference_type = typename std::iterator_traits<TIter>::difference_type;
-  using value_type = typename Converter::ResultType;
-  using pointer = typename Converter::ResultType*;
-  using reference = typename Converter::ResultType&;
-  using iterator_category = typename std::iterator_traits<TIter>::iterator_category;
-
-  explicit IterAdapter(TIter iter) : iter_(iter) {}
-  IterAdapter& operator++() {
-    ++iter_;
-    return *this;
-  }
-  IterAdapter& operator--() {
-    --iter_;
-    return *this;
-  }
-  IterAdapter operator++(int) {
-    IterAdapter copy = *this;
-    ++iter_;
-    return copy;
-  }
-  IterAdapter operator--(int) {
-    IterAdapter copy = *this;
-    --iter_;
-    return copy;
-  }
-
-  IterAdapter operator+(difference_type offset) const { return IterAdapter(iter_ + offset); }
-
-  IterAdapter operator-(difference_type offset) const { return IterAdapter(iter_ - offset); }
-
-  IterAdapter& operator+=(difference_type offset) {
-    iter_ += offset;
-    return *this;
-  }
-
-  IterAdapter& operator-=(difference_type offset) {
-    iter_ -= offset;
-    return *this;
-  }
-
-  template <typename T = IterAdapter>
-  typename std::enable_if<std::is_same<iterator_category, std::random_access_iterator_tag>::value,
-                          typename T::difference_type>::type inline
-  operator-(const IterAdapter& rhs) const {
-    return iter_ - rhs.iter_;
-  }
-
-  bool operator==(IterAdapter other) const { return iter_ == other.iter_; }
-  bool operator!=(IterAdapter other) const { return !(*this == other); }
-  const value_type operator*() const { return Converter::convert(*iter_); }
-
- private:
-  TIter iter_;
-};
-
-/*!
- * \brief iterator adapter that adapts TIter to return another type.
- * \tparam Converter a struct that contains converting function
- * \tparam TIter the content iterator type.
- */
-template <typename Converter, typename TIter>
-class ReverseIterAdapter {
- public:
-  using difference_type = typename std::iterator_traits<TIter>::difference_type;
-  using value_type = typename Converter::ResultType;
-  using pointer = typename Converter::ResultType*;
-  using reference = typename Converter::ResultType&;  // NOLINT(*)
-  using iterator_category = typename std::iterator_traits<TIter>::iterator_category;
-
-  explicit ReverseIterAdapter(TIter iter) : iter_(iter) {}
-  ReverseIterAdapter& operator++() {
-    --iter_;
-    return *this;
-  }
-  ReverseIterAdapter& operator--() {
-    ++iter_;
-    return *this;
-  }
-  ReverseIterAdapter operator++(int) {
-    ReverseIterAdapter copy = *this;
-    --iter_;
-    return copy;
-  }
-  ReverseIterAdapter operator--(int) {
-    ReverseIterAdapter copy = *this;
-    ++iter_;
-    return copy;
-  }
-  ReverseIterAdapter operator+(difference_type offset) const {
-    return ReverseIterAdapter(iter_ - offset);
-  }
-
-  template <typename T = ReverseIterAdapter>
-  typename std::enable_if<std::is_same<iterator_category, std::random_access_iterator_tag>::value,
-                          typename T::difference_type>::type inline
-  operator-(const ReverseIterAdapter& rhs) const {
-    return rhs.iter_ - iter_;
-  }
-
-  bool operator==(ReverseIterAdapter other) const { return iter_ == other.iter_; }
-  bool operator!=(ReverseIterAdapter other) const { return !(*this == other); }
-  const value_type operator*() const { return Converter::convert(*iter_); }
-
- private:
-  TIter iter_;
-};
-
-/*!
- * \brief Check if T is compatible with Any.
- *
- * \tparam T The type to check.
- * \return True if T is compatible with Any, false otherwise.
- */
-template <typename T>
-inline constexpr bool storage_enabled_v = std::is_same_v<T, Any> || TypeTraits<T>::storage_enabled;
-
-/*!
- * \brief Check if all T are compatible with Any.
- *
- * \tparam T The type to check.
- * \return True if T is compatible with Any, false otherwise.
- */
-template <typename... T>
-inline constexpr bool all_storage_enabled_v = (storage_enabled_v<T> && ...);
-
-/*!
- * \brief Check if all T are compatible with Any.
- *
- * \tparam T The type to check.
- * \return True if T is compatible with Any, false otherwise.
- */
-template <typename... T>
-inline constexpr bool all_object_ref_v = (std::is_base_of_v<ObjectRef, T> && ...);
-/**
- * \brief Check if Any storage of Derived can always be directly used as Base.
- *
- * \tparam Base The base type.
- * \tparam Derived The derived type.
- * \return True if Derived's storage can be used as Base's storage, false otherwise.
- */
-template <typename Base, typename Derived>
-inline constexpr bool type_contains_v =
-    std::is_base_of_v<Base, Derived> || std::is_same_v<Base, Derived>;
-// special case for Any
-template <typename Derived>
-inline constexpr bool type_contains_v<Any, Derived> = true;
-
-/*!
- * \brief Create a string of the container type.
- * \tparam V The types of the elements in the container.
- * \param name The name of the container type.
- * \return A string of the container type.
- */
-template <typename... V>
-std::string ContainerTypeStr(const char* name) {
-  std::stringstream ss;
-  // helper to construct concated string of TypeStr
-  class TypeStrHelper {
-   public:
-    TypeStrHelper(std::stringstream& stream) : stream_(stream) {}  // NOLINT(*)
-
-    TypeStrHelper& operator<<(const std::string& str) {
-      if (counter_ > 0) {
-        stream_ << ", ";
-      }
-      stream_ << str;
-      counter_++;
-      return *this;
-    }
-
-   private:
-    std::stringstream& stream_;  // NOLINT(*)
-    int counter_ = 0;
-  };
-  TypeStrHelper helper(ss);
-  ss << name << '<';
-  (helper << ... << Type2Str<V>::v());
-  ss << '>';
-  return ss.str();
-}
-
-}  // namespace details
-}  // namespace ffi
-}  // namespace tvm
-#endif  // TVM_FFI_CONTAINER_CONTAINER_DETAILS_H_
diff --git a/ffi/include/tvm/ffi/container/map.h b/ffi/include/tvm/ffi/container/map.h
deleted file mode 100644
index 471904502c..0000000000
--- a/ffi/include/tvm/ffi/container/map.h
+++ /dev/null
@@ -1,1762 +0,0 @@
-/*
- * 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/container/map.h
- * \brief Runtime Map container types.
- */
-#ifndef TVM_FFI_CONTAINER_MAP_H_
-#define TVM_FFI_CONTAINER_MAP_H_
-
-#include <tvm/ffi/any.h>
-#include <tvm/ffi/container/container_details.h>
-#include <tvm/ffi/memory.h>
-#include <tvm/ffi/object.h>
-#include <tvm/ffi/optional.h>
-
-#include <algorithm>
-#include <limits>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <utility>
-
-namespace tvm {
-namespace ffi {
-
-/// \cond Doxygen_Suppress
-#if TVM_FFI_DEBUG_WITH_ABI_CHANGE
-#define TVM_FFI_MAP_FAIL_IF_CHANGED() \
-  TVM_FFI_ICHECK(state_marker == self->state_marker) << "Concurrent modification of the Map";
-#else
-#define TVM_FFI_MAP_FAIL_IF_CHANGED()
-#endif  // TVM_FFI_DEBUG_WITH_ABI_CHANGE
-/// \endcond
-
-/*! \brief Shared content of all specializations of hash map */
-class MapObj : public Object {
- public:
-  /*! \brief Type of the keys in the hash map */
-  using key_type = Any;
-  /*! \brief Type of the values in the hash map */
-  using mapped_type = Any;
-  /*! \brief Type of value stored in the hash map */
-  using KVType = std::pair<Any, Any>;
-  /// \cond Doxygen_Suppress
-  /*! \brief Type of raw storage of the key-value pair in the hash map */
-  struct KVRawStorageType {
-    TVMFFIAny first;
-    TVMFFIAny second;
-  };
-  /// \endcond
-  /*! \brief Iterator class */
-  class iterator;
-
-  static_assert(std::is_standard_layout<KVType>::value, "KVType is not standard layout");
-  static_assert(sizeof(KVType) == 32, "sizeof(KVType) incorrect");
-
-  /// \cond Doxygen_Suppress
-  static constexpr const int32_t _type_index = TypeIndex::kTVMFFIMap;
-  static const constexpr bool _type_final = true;
-  TVM_FFI_DECLARE_OBJECT_INFO_STATIC(StaticTypeKey::kTVMFFIMap, MapObj, Object);
-  /// \endcond
-
-  /*!
-   * \brief Number of elements in the MapObj
-   * \return The result
-   */
-  size_t size() const { return size_; }
-  /*!
-   * \brief Count the number of times a key exists in the hash map
-   * \param key The indexing key
-   * \return The result, 0 or 1
-   */
-  size_t count(const key_type& key) const;
-  /*!
-   * \brief Index value associated with a key, throw exception if the key does not exist
-   * \param key The indexing key
-   * \return The const reference to the value
-   */
-  const mapped_type& at(const key_type& key) const;
-  /*!
-   * \brief Index value associated with a key, throw exception if the key does not exist
-   * \param key The indexing key
-   * \return The mutable reference to the value
-   */
-  mapped_type& at(const key_type& key);
-  /*! \return begin iterator */
-  iterator begin() const;
-  /*! \return end iterator */
-  iterator end() const;
-  /*!
-   * \brief Index value associated with a key
-   * \param key The indexing key
-   * \return The iterator of the entry associated with the key, end iterator if not exists
-   */
-  iterator find(const key_type& key) const;
-  /*!
-   * \brief Erase the entry associated with the iterator
-   * \param position The iterator
-   */
-  void erase(const iterator& position);
-  /*!
-   * \brief Erase the entry associated with the key, do nothing if not exists
-   * \param key The indexing key
-   */
-  void erase(const key_type& key) { erase(find(key)); }
-
-  /// \cond Doxygen_Suppress
-  class iterator {
-   public:
-    using iterator_category = std::forward_iterator_tag;
-    using difference_type = int64_t;
-    using value_type = KVType;
-    using pointer = KVType*;
-    using reference = KVType&;
-/*! \brief Default constructor */
-#if TVM_FFI_DEBUG_WITH_ABI_CHANGE
-    iterator() : state_marker(0), index(0), self(nullptr) {}
-#else
-    iterator() : index(0), self(nullptr) {}
-#endif  // TVM_FFI_DEBUG_WITH_ABI_CHANGE
-    /*! \brief Compare iterators */
-    bool operator==(const iterator& other) const {
-      TVM_FFI_MAP_FAIL_IF_CHANGED()
-      return index == other.index && self == other.self;
-    }
-    /*! \brief Compare iterators */
-    bool operator!=(const iterator& other) const { return !(*this == other); }
-    /*! \brief De-reference iterators */
-    pointer operator->() const;
-    /*! \brief De-reference iterators */
-    reference operator*() const {
-      TVM_FFI_MAP_FAIL_IF_CHANGED()
-      return *((*this).operator->());
-    }
-    /*! \brief Prefix self increment, e.g. ++iter */
-    iterator& operator++();
-    /*! \brief Prefix self decrement, e.g. --iter */
-    iterator& operator--();
-    /*! \brief Suffix self increment */
-    iterator operator++(int) {
-      TVM_FFI_MAP_FAIL_IF_CHANGED()
-      iterator copy = *this;
-      ++(*this);
-      return copy;
-    }
-    /*! \brief Suffix self decrement */
-    iterator operator--(int) {
-      TVM_FFI_MAP_FAIL_IF_CHANGED()
-      iterator copy = *this;
-      --(*this);
-      return copy;
-    }
-
-   protected:
-#if TVM_FFI_DEBUG_WITH_ABI_CHANGE
-    uint64_t state_marker;
-    /*! \brief Construct by value */
-    iterator(uint64_t index, const MapObj* self)
-        : state_marker(self->state_marker), index(index), self(self) {}
-
-#else
-    iterator(uint64_t index, const MapObj* self) : index(index), self(self) {}
-#endif  // TVM_FFI_DEBUG_WITH_ABI_CHANGE
-    /*! \brief The position on the array */
-    uint64_t index;
-    /*! \brief The container it points to */
-    const MapObj* self;
-
-    friend class DenseMapObj;
-    friend class SmallMapObj;
-  };
-  /// \endcond
-  /*!
-   * \brief Create an empty container
-   * \return The object created
-   */
-  static inline ObjectPtr<MapObj> Empty();
-
- protected:
-#if TVM_FFI_DEBUG_WITH_ABI_CHANGE
-  uint64_t state_marker;
-#endif  // TVM_FFI_DEBUG_WITH_ABI_CHANGE
-  /*!
-   * \brief Create the map using contents from the given iterators.
-   * \param first Begin of iterator
-   * \param last End of iterator
-   * \tparam IterType The type of iterator
-   * \return ObjectPtr to the map created
-   */
-  template <typename IterType>
-  static inline ObjectPtr<Object> CreateFromRange(IterType first, IterType last);
-  /*!
-   * \brief InsertMaybeReHash an entry into the given hash map
-   * \param kv The entry to be inserted
-   * \param map The pointer to the map, can be changed if re-hashing happens
-   */
-  static inline void InsertMaybeReHash(KVType&& kv, ObjectPtr<Object>* map);
-  /*!
-   * \brief Create an empty container with elements copying from another SmallMapObj
-   * \param from The source container
-   * \return The object created
-   */
-  static inline ObjectPtr<MapObj> CopyFrom(MapObj* from);
-  /*!
-   * \brief data pointer to the data region of the map.
-   * \note For immutable inplace small map we do not need data_,
-   *       but we keep it here for future compact with mutable container.
-   */
-  void* data_;
-  /*! \brief number of entries in the container */
-  uint64_t size_;
-  /*! \brief number of slots  */
-  uint64_t slots_;
-  /*!
-   * \brief Small layout tag mask
-   * \note The most significant bit is used to indicate the small map layout.
-   */
-  static constexpr uint64_t kSmallTagMask = static_cast<uint64_t>(1) << 63;
-  /*!
-   * \brief Check if the map is a small map
-   * \return True if the map is a small map
-   */
-  bool IsSmallMap() const { return (slots_ & kSmallTagMask) != 0ull; }
-  /*!
-   * \brief Optional data deleter when data is allocated separately
-   *        and its deletion is not managed by MapObj::deleter_.
-   */
-  void (*data_deleter_)(void*) = nullptr;
-  // Reference class
-  template <typename, typename, typename>
-  friend class Map;
-};
-
-/*! \brief A specialization of small-sized hash map */
-class SmallMapObj : public MapObj,
-                    public details::InplaceArrayBase<SmallMapObj, MapObj::KVRawStorageType> {
- private:
-  static constexpr uint64_t kInitSize = 2;
-  static constexpr uint64_t kMaxSize = 4;
-
- public:
-  using MapObj::iterator;
-  using MapObj::KVType;
-
-  // Return the number of usable slots for Small layout (mask off tag).
-  /*!
-   * \brief Return the number of usable slots for Small layout (mask off tag).
-   * \return The number of usable slots
-   */
-  uint64_t NumSlots() const { return slots_ & ~kSmallTagMask; }
-
-  ~SmallMapObj() {
-    KVType* begin = static_cast<KVType*>(data_);
-    for (uint64_t index = 0; index < size_; ++index) {
-      // call destructor to destroy the item in `begin + index`
-      // Explicit call Any::~Any() to destroy the Any object
-      // Favor this over ~KVType as MSVC may not support ~KVType (need the original name)
-      (begin + index)->first.Any::~Any();
-      (begin + index)->second.Any::~Any();
-    }
-    if (data_deleter_ != nullptr) {
-      data_deleter_(data_);
-    }
-  }
-  /*!
-   * \brief Count the number of times a key exists in the SmallMapObj
-   * \param key The indexing key
-   * \return The result, 0 or 1
-   */
-  size_t count(const key_type& key) const { return find(key).index < size_; }
-  /*!
-   * \brief Index value associated with a key, throw exception if the key does not exist
-   * \param key The indexing key
-   * \return The const reference to the value
-   */
-  const mapped_type& at(const key_type& key) const {
-    iterator itr = find(key);
-    if (itr.index >= size_) {
-      TVM_FFI_THROW(KeyError) << "key is not in Map";
-    }
-    return itr->second;
-  }
-  /*!
-   * \brief Index value associated with a key, throw exception if the key does not exist
-   * \param key The indexing key
-   * \return The mutable reference to the value
-   */
-  mapped_type& at(const key_type& key) {
-    iterator itr = find(key);
-    if (itr.index >= size_) {
-      TVM_FFI_THROW(KeyError) << "key is not in Map";
-    }
-    return itr->second;
-  }
-  /*! \return begin iterator */
-  iterator begin() const { return iterator(0, this); }
-  /*! \return end iterator */
-  iterator end() const { return iterator(size_, this); }
-  /*!
-   * \brief Index value associated with a key
-   * \param key The indexing key
-   * \return The iterator of the entry associated with the key, end iterator if not exists
-   */
-  iterator find(const key_type& key) const {
-    KVType* ptr = static_cast<KVType*>(data_);
-    for (uint64_t i = 0; i < size_; ++i, ++ptr) {
-      if (AnyEqual()(ptr->first, key)) {
-        return iterator(i, this);
-      }
-    }
-    return iterator(size_, this);
-  }
-  /*!
-   * \brief Erase the entry associated with the iterator
-   * \param position The iterator
-   */
-  void erase(const iterator& position) { Erase(position.index); }
-
- private:
-  /*!
-   * \brief Set the number of slots and attach tags bit.
-   * \param n The number of slots
-   */
-  void SetSlotsAndSmallLayoutTag(uint64_t n) { slots_ = (n & ~kSmallTagMask) | kSmallTagMask; }
-  /*!
-   * \brief Remove a position in SmallMapObj
-   * \param index The position to be removed
-   */
-  void Erase(const uint64_t index) {
-    if (index >= size_) {
-      return;
-    }
-    KVType* begin = static_cast<KVType*>(data_);
-    // call destructor to destroy the item in `begin + index`
-    // Explicit call Any::~Any() to destroy the Any object
-    // Favor this over ~KVType as MSVC may not support ~KVType (need the original name)
-    (begin + index)->first.Any::~Any();
-    (begin + index)->second.Any::~Any();
-    // IMPORTANT: We do direct raw memmove to bring later items to the current position
-    // to preserve the order of insertion.
-    // This works because direct memory copy preserves the Any's move semantics.
-    if (index + 1 < size_) {
-      std::memmove(reinterpret_cast<char*>(begin + index),
-                   reinterpret_cast<char*>(begin + index + 1),
-                   (size_ - index - 1) * sizeof(KVType));
-    }
-    size_ -= 1;
-  }
-  /*!
-   * \brief Create an empty container
-   * \param n Number of empty slots
-   * \return The object created
-   */
-  static ObjectPtr<SmallMapObj> Empty(uint64_t n = kInitSize) {
-    using ::tvm::ffi::make_inplace_array_object;
-    ObjectPtr<SmallMapObj> p = make_inplace_array_object<SmallMapObj, KVType>(n);
-    p->data_ = p->AddressOf(0);
-    p->size_ = 0;
-    p->SetSlotsAndSmallLayoutTag(n);
-    return p;
-  }
-  /*!
-   * \brief Create an empty container initialized with a given range
-   * \param n Number of empty slots
-   * \param first begin of iterator
-   * \param last end of iterator
-   * \tparam IterType The type of iterator
-   * \return The object created
-   */
-  template <typename IterType>
-  static ObjectPtr<SmallMapObj> CreateFromRange(uint64_t n, IterType first, IterType last) {
-    ObjectPtr<SmallMapObj> p = Empty(n);
-    KVType* ptr = static_cast<KVType*>(p->data_);
-    for (; first != last; ++first, ++p->size_) {
-      new (ptr++) KVType(*first);
-    }
-    return p;
-  }
-  /*!
-   * \brief Create an empty container with elements copying from another SmallMapObj
-   * \param from The source container
-   * \return The object created
-   */
-  static ObjectPtr<SmallMapObj> CopyFrom(SmallMapObj* from) {
-    KVType* first = static_cast<KVType*>(from->data_);
-    KVType* last = first + from->size_;
-    return CreateFromRange(from->size_, first, last);
-  }
-  /*!
-   * \brief InsertMaybeReHash an entry into the given hash map
-   * \param kv The entry to be inserted
-   * \param map The pointer to the map, can be changed if re-hashing happens
-   */
-  static void InsertMaybeReHash(KVType&& kv, ObjectPtr<Object>* map) {
-    SmallMapObj* map_node = static_cast<SmallMapObj*>(map->get());
-    iterator itr = map_node->find(kv.first);
-    if (itr.index < map_node->size_) {
-      itr->second = kv.second;
-      return;
-    }
-    if (map_node->size_ < map_node->NumSlots()) {
-      KVType* ptr = static_cast<KVType*>(map_node->data_) + map_node->size_;
-      new (ptr) KVType(std::move(kv));
-      ++map_node->size_;
-      return;
-    }
-    uint64_t next_size = std::max(map_node->NumSlots() * 2, uint64_t(kInitSize));
-    next_size = std::min(next_size, uint64_t(kMaxSize));
-    TVM_FFI_ICHECK_GT(next_size, map_node->NumSlots());
-    ObjectPtr<Object> new_map = CreateFromRange(next_size, map_node->begin(), map_node->end());
-    InsertMaybeReHash(std::move(kv), &new_map);
-    *map = std::move(new_map);
-  }
-  /*!
-   * \brief Increment the pointer
-   * \param index The pointer to be incremented
-   * \return The increased pointer
-   */
-  uint64_t IncItr(uint64_t index) const { return index + 1 < size_ ? index + 1 : size_; }
-  /*!
-   * \brief Decrement the pointer
-   * \param index The pointer to be decremented
-   * \return The decreased pointer
-   */
-  uint64_t DecItr(uint64_t index) const { return index > 0 ? index - 1 : size_; }
-  /*!
-   * \brief De-reference the pointer
-   * \param index The pointer to be dereferenced
-   * \return The result
-   */
-  KVType* DeRefItr(uint64_t index) const { return static_cast<KVType*>(data_) + index; }
-  /*! \brief A size function used by InplaceArrayBase */
-  uint64_t GetSize() const { return size_; }
-
- protected:
-  friend class MapObj;
-  friend class DenseMapObj;
-  friend class details::InplaceArrayBase<SmallMapObj, MapObj::KVType>;
-};
-
-/*! \brief A specialization of hash map that implements the idea of array-based hash map.
- * Another reference implementation can be found [1].
- *
- * A. Overview
- *
- * DenseMapObj did several improvements over traditional separate chaining hash,
- * in terms of cache locality, memory footprints and data organization.
- *
- * A1. Implicit linked list. For better cache locality, instead of using linked list
- * explicitly for each bucket, we store list data into a single array that spans contiguously
- * in memory, and then carefully design access patterns to make sure most of them fall into
- * a single cache line.
- *
- * A2. 1-byte metadata. There is only 1 byte overhead for each slot in the array to indexing and
- * traversal. This can be divided in 3 parts.
- * 1) Reserved code: (0b11111111)_2 indicates a slot is empty; (0b11111110)_2 indicates protected,
- * which means the slot is empty but not allowed to be written.
- * 2) If not empty or protected, the highest bit is used to indicate whether data in the slot is
- * head of a linked list.
- * 3) The rest 7 bits are used as the "next pointer" (i.e. pointer to the next element). On 64-bit
- * architecture, an ordinary pointer can take up to 8 bytes, which is not acceptable overhead when
- * dealing with 16-byte ObjectRef pairs. Based on a commonly noticed fact that the lists are
- * relatively short (length <= 3) in hash maps, we follow [1]'s idea that only allows the pointer to
- * be one of the 126 possible values, i.e. if the next element of i-th slot is (i + x)-th element,
- * then x must be one of the 126 pre-defined values.
- *
- * A3. Data blocking. We organize the array in the way that every 16 elements forms a data block.
- * The 16-byte metadata of those 16 elements are stored together, followed by the real data, i.e.
- * 16 key-value pairs.
- *
- * B. Implementation details
- *
- * B1. Power-of-2 table size and Fibonacci Hashing. We use power-of-two as table size to avoid
- * modulo for more efficient arithmetics. To make the hash-to-slot mapping distribute more evenly,
- * we use the Fibonacci Hashing [2] trick.
- *
- * B2. Traverse a linked list in the array.
- * 1) List head. Assume Fibonacci Hashing maps a given key to slot i, if metadata at slot i
- * indicates that it is list head, then we found the head; otherwise the list is empty. No probing
- * is done in this procedure. 2) Next element. To find the next element of a non-empty slot i, we
- * look at the last 7 bits of the metadata at slot i. If they are all zeros, then it is the end of
- * list; otherwise, we know that the next element is (i + candidates[the-last-7-bits]).
- *
- * B3. InsertMaybeReHash an element. Following B2, we first traverse the linked list to see if this
- * element is in the linked list, and if not, we put it at the end by probing the next empty
- * position in one of the 126 candidate positions. If the linked list does not even exist, but the
- * slot for list head has been occupied by another linked list, we should find this intruder another
- * place.
- *
- * B4. Quadratic probing with triangle numbers. In open address hashing, it is provable that probing
- * with triangle numbers can traverse power-of-2-sized table [3]. In our algorithm, we follow the
- * suggestion in [1] that also use triangle numbers for "next pointer" as well as sparing for list
- * head.
- *
- * [1] https://github.com/skarupke/flat_hash_map
- * [2] https://programmingpraxis.com/2018/06/19/fibonacci-hash/
- * [3] https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/
- */
-class DenseMapObj : public MapObj {
- private:
-  /*! \brief The number of elements in a memory block */
-  static constexpr int kBlockCap = 16;
-  /*! \brief Maximum load factor of the hash map */
-  static constexpr double kMaxLoadFactor = 0.99;
-  /*! \brief Binary representation of the metadata of an empty slot */
-  static constexpr uint8_t kEmptySlot = uint8_t(0b11111111);
-  /*! \brief Binary representation of the metadata of a protected slot */
-  static constexpr uint8_t kProtectedSlot = uint8_t(0b11111110);
-  /*! \brief Number of probing choices available */
-  static constexpr int kNumJumpDists = 126;
-  /*! \brief Index indicator to indicate an invalid index */
-  static constexpr uint64_t kInvalidIndex = std::numeric_limits<uint64_t>::max();
-  /*! \brief Head of the implicit linked list */
-  struct ListNode;
-  /*! \brief item type of the dense map, including a kv data and prev/next pointer */
-  struct ItemType {
-    KVType data;
-    uint64_t prev = kInvalidIndex;
-    uint64_t next = kInvalidIndex;
-
-    explicit ItemType(KVType&& data) : data(std::move(data)) {}
-    explicit ItemType(key_type key, mapped_type value) : data(key, value) {}
-  };
-  /*! \brief POD type of a block of memory */
-  struct Block {
-    uint8_t bytes[kBlockCap + kBlockCap * sizeof(ItemType)];
-  };
-  static_assert(sizeof(Block) == kBlockCap * (sizeof(ItemType) + 1), "sizeof(Block) incorrect");
-  static_assert(std::is_standard_layout<Block>::value, "Block is not standard layout");
-
-  /*!
-   * \brief Deleter for the Block
-   * \param data The pointer to the Block
-   */
-  static void BlockDeleter(void* data) { delete[] static_cast<Block*>(data); }
-
- public:
-  using MapObj::iterator;
-
-  /*!
-   * \brief Return the number of usable slots for Dense layout (MSB clear => identity).
-   * \return The number of usable slots
-   */
-  uint64_t NumSlots() const { return slots_; }
-
-  /*!
-   * \brief Destroy the DenseMapObj
-   */
-  ~DenseMapObj() { this->Reset(); }
-  /*! \return The number of elements of the key */
-  size_t count(const key_type& key) const { return !Search(key).IsNone(); }
-  /*!
-   * \brief Index value associated with a key, throw exception if the key does not exist
-   * \param key The indexing key
-   * \return The const reference to the value
-   */
-  const mapped_type& at(const key_type& key) const { return At(key); }
-  /*!
-   * \brief Index value associated with a key, throw exception if the key does not exist
-   * \param key The indexing key
-   * \return The mutable reference to the value
-   */
-  mapped_type& at(const key_type& key) { return At(key); }
-  /*!
-   * \brief Index value associated with a key
-   * \param key The indexing key
-   * \return The iterator of the entry associated with the key, end iterator if not exists
-   */
-  iterator find(const key_type& key) const {
-    ListNode node = Search(key);
-    return node.IsNone() ? end() : iterator(node.index, this);
-  }
-  /*!
-   * \brief Erase the entry associated with the iterator
-   * \param position The iterator
-   */
-  void erase(const iterator& position) {
-    uint64_t index = position.index;
-    if (position.self != nullptr && index <= this->NumSlots()) {
-      Erase(ListNode(index, this));
-    }
-  }
-  /*! \return begin iterator */
-  iterator begin() const { return iterator(iter_list_head_, this); }
-  /*! \return end iterator */
-  iterator end() const { return iterator(kInvalidIndex, this); }
-
- private:
-  Block* GetBlock(size_t index) const { return static_cast<Block*>(data_) + index; }
-  /*!
-   * \brief Unlink the entry from iterator list
-   * \param node The node to be unlinked
-   * \note This function is usually used before deletion,
-   *       and it does not change data content of the node.
-   */
-  void IterListUnlink(ListNode node) {
-    // update head and tail of iterator list if needed
-    if (node.Item().prev == kInvalidIndex) {
-      iter_list_head_ = node.Item().next;
-    } else {
-      ListNode prev_node(node.Item().prev, this);
-      prev_node.Item().next = node.Item().next;
-    }
-    if (node.Item().next == kInvalidIndex) {
-      iter_list_tail_ = node.Item().prev;
-    } else {
-      ListNode next_node(node.Item().next, this);
-      next_node.Item().prev = node.Item().prev;
-    }
-  }
-  /*!
-   * \brief Insert the entry into tail of iterator list
-   * \param node The node to be inserted
-   * \note this function does not change data content of the node.
-   */
-  void IterListPushBack(ListNode node) {
-    node.Item().prev = iter_list_tail_;
-    node.Item().next = kInvalidIndex;
-    if (iter_list_tail_ != kInvalidIndex) {
-      ListNode prev_node(iter_list_tail_, this);
-      prev_node.Item().next = node.index;
-    }
-    if (iter_list_head_ == kInvalidIndex) {
-      iter_list_head_ = node.index;
-    }
-    iter_list_tail_ = node.index;
-  }
-  /*!
-   * \brief Replace node src by dst in the iter list
-   * \param src The source node
-   * \param dst The destination node, must be empty
-   * \note This function does not change data content of the nodes,
-   *       which needs to be updated by the caller.
-   */
-  void IterListReplaceNodeBy(ListNode src, ListNode dst) {
-    // set link correctly on the dst
-    dst.Item().prev = src.Item().prev;
-    dst.Item().next = src.Item().next;
-    // update prev and next of dst
-    if (dst.Item().prev == kInvalidIndex) {
-      iter_list_head_ = dst.index;
-    } else {
-      ListNode prev_node(dst.Item().prev, this);
-      prev_node.Item().next = dst.index;
-    }
-    if (dst.Item().next == kInvalidIndex) {
-      iter_list_tail_ = dst.index;
-    } else {
-      ListNode next_node(dst.Item().next, this);
-      next_node.Item().prev = dst.index;
-    }
-  }
-  /*!
-   * \brief Search for the given key
-   * \param key The key
-   * \return ListNode that associated with the key
-   */
-  ListNode Search(const key_type& key) const {
-    if (this->size_ == 0) {
-      return ListNode();
-    }
-    for (ListNode iter = GetListHead(AnyHash()(key)); !iter.IsNone(); iter.MoveToNext(this)) {
-      if (AnyEqual()(key, iter.Key())) {
-        return iter;
-      }
-    }
-    return ListNode();
-  }
-  /*!
-   * \brief Search for the given key, throw exception if not exists
-   * \param key The key
-   * \return ListNode that associated with the key
-   */
-  mapped_type& At(const key_type& key) const {
-    ListNode iter = Search(key);
-    if (iter.IsNone()) {
-      TVM_FFI_THROW(IndexError) << "key is not in Map";
-    }
-    return iter.Val();
-  }
-  /*!
-   * \brief Try to insert a key, or do nothing if already exists
-   * \param key The indexing key
-   * \param result The linked-list entry found or just constructed
-   * \return A boolean, indicating if actual insertion happens
-   */
-  bool TryInsert(const key_type& key, ListNode* result) {
-    if (slots_ == 0) {
-      return false;
-    }
-    // required that `iter` to be the head of a linked list through which we can iterator
-    ListNode iter = IndexFromHash(AnyHash()(key));
-    // `iter` can be: 1) empty; 2) body of an irrelevant list; 3) head of the relevant list
-    // Case 1: empty
-    if (iter.IsEmpty()) {
-      iter.NewHead(ItemType(key, Any(nullptr)));
-      this->size_ += 1;
-      *result = iter;
-      return true;
-    }
-    // Case 2: body of an irrelevant list
-    if (!iter.IsHead()) {
-      // we move the elements around and construct the single-element linked list
-      return IsFull() ? false : TrySpareListHead(iter, key, result);
-    }
-    // Case 3: head of the relevant list
-    // we iterate through the linked list until the end
-    // make sure `iter` is the previous element of `next`
-    ListNode next = iter;
-    do {
-      // find equal item, do not insert
-      if (AnyEqual()(key, next.Key())) {
-        // we plan to take next, so we need to unlink it from iterator list
-        IterListUnlink(next);
-        *result = next;
-        return true;
-      }
-      // make sure `iter` is the previous element of `next`
-      iter = next;
-    } while (next.MoveToNext(this));
-    // `iter` is the tail of the linked list
-    // always check capacity before insertion
-    if (IsFull()) {
-      return false;
-    }
-    // find the next empty slot
-    uint8_t jump;
-    if (!iter.GetNextEmpty(this, &jump, result)) {
-      return false;
-    }
-    result->NewTail(ItemType(key, Any(nullptr)));
-    // link `iter` to `empty`, and move forward
-    iter.SetJump(jump);
-    this->size_ += 1;
-    return true;
-  }
-  /*!
-   * \brief Spare an entry to be the head of a linked list.
-   * As described in B3, during insertion, it is possible that the entire linked list does not
-   * exist, but the slot of its head has been occupied by other linked lists. In this case, we need
-   * to spare the slot by moving away the elements to another valid empty one to make insertion
-   * possible.
-   * \param target The given entry to be spared
-   * \param key The indexing key
-   * \param result The linked-list entry constructed as the head
-   * \return A boolean, if actual insertion happens
-   */
-  bool TrySpareListHead(ListNode target, const key_type& key, ListNode* result) {
-    // `target` is not the head of the linked list
-    // move the original item of `target` (if any)
-    // and construct new item on the position `target`
-    // To make `target` empty, we
-    // 1) find `w` the previous element of `target` in the linked list
-    // 2) copy the linked list starting from `r = target`
-    // 3) paste them after `w`
-    // read from the linked list after `r`
-    ListNode r = target;
-    // write to the tail of `w`
-    ListNode w = target.FindPrev(this);
-    // after `target` is moved, we disallow writing to the slot
-    bool is_first = true;
-    uint8_t r_meta, jump;
-    ListNode empty;
-    do {
-      // `jump` describes how `w` is jumped to `empty`
-      // rehash if there is no empty space after `w`
-      if (!w.GetNextEmpty(this, &jump, &empty)) {
-        return false;
-      }
-      // move `r` to `empty`
-      // first move the data over
-      empty.NewTail(ItemType(std::move(r.Data())));
-      // then move link list chain of r to empty
-      // this needs to happen after NewTail so empty's prev/next get updated
-      IterListReplaceNodeBy(r, empty);
-      // explicit call destructor to destroy the item in `r`
-      r.DestructData();
-      // clear the metadata of `r`
-      r_meta = r.Meta();
-      if (is_first) {
-        is_first = false;
-        r.SetProtected();
-      } else {
-        r.SetEmpty();
-      }
-      // link `w` to `empty`, and move forward
-      w.SetJump(jump);
-      w = empty;
-      // move `r` forward as well
-    } while (r.MoveToNext(this, r_meta));
-    // finally we have done moving the linked list
-    // fill data_ into `target`
-    target.NewHead(ItemType(key, Any(nullptr)));
-    this->size_ += 1;
-    *result = target;
-    return true;
-  }
-  /*!
-   * \brief Remove a ListNode
-   * \param iter The node to be removed
-   */
-  void Erase(const ListNode& iter) {
-    this->size_ -= 1;
-    if (!iter.HasNext()) {
-      // `iter` is the last
-      if (!iter.IsHead()) {
-        // cut the link if there is any
-        iter.FindPrev(this).SetJump(0);
-      }
-      // unlink the node from iterator list
-      IterListUnlink(iter);
-      // IMPORTANT: must explicit call destructor `iter` to avoid memory leak
-      // This is because we need to recycle iter's data
-      iter.DestructData();
-      // set the meta data to be empty
-      iter.SetEmpty();
-    } else {
-      ListNode last = iter, prev = iter;
-      for (last.MoveToNext(this); last.HasNext(); prev = last, last.MoveToNext(this)) {
-      }
-      // needs to first unlink iter from the list
-      IterListUnlink(iter);
-      // move data from last to iter
-      iter.Data() = std::move(last.Data());
-      // Move link chain of iter to last as we stores last node to the new iter loc.
-      IterListReplaceNodeBy(last, iter);
-      // IMPORTANT: must explicit call destructor `last` to avoid memory leak
-      // likely we don't need this in this particular case because Any move behavior
-      // keep it here to be safe so code do not depend on specific move behavior of KVType
-      last.DestructData();
-      // set the meta data to be empty
-      last.SetEmpty();
-      prev.SetJump(0);
-    }
-  }
-  /*! \brief Clear the container to empty, release all entries and memory acquired */
-  void Reset() {
-    uint64_t n_blocks = CalcNumBlocks(this->NumSlots());
-    for (uint64_t bi = 0; bi < n_blocks; ++bi) {
-      uint8_t* meta_ptr = GetBlock(bi)->bytes;
-      ItemType* data_ptr = reinterpret_cast<ItemType*>(GetBlock(bi)->bytes + kBlockCap);
-      for (int j = 0; j < kBlockCap; ++j, ++meta_ptr, ++data_ptr) {
-        uint8_t& meta = *meta_ptr;
-        if (meta != uint8_t(kProtectedSlot) && meta != uint8_t(kEmptySlot)) {
-          meta = uint8_t(kEmptySlot);
-          data_ptr->ItemType::~ItemType();
-        }
-      }
-    }
-    ReleaseMemory();
-  }
-  /*! \brief Release the memory acquired by the container without deleting its entries stored inside
-   */
-  void ReleaseMemory() {
-    if (data_ != nullptr) {
-      TVM_FFI_ICHECK(data_deleter_ != nullptr);
-      data_deleter_(data_);
-    }
-    data_ = nullptr;
-    data_deleter_ = nullptr;
-    slots_ = 0;
-    size_ = 0;
-    fib_shift_ = 63;
-  }
-  /*!
-   * \brief Create an empty container
-   * \param fib_shift The fib shift provided
-   * \param n_slots Number of slots required, should be power-of-two
-   * \return The object created
-   */
-  static ObjectPtr<DenseMapObj> Empty(uint32_t fib_shift, uint64_t n_slots) {
-    TVM_FFI_ICHECK_GT(n_slots, uint64_t(SmallMapObj::kMaxSize));
-    // Ensure even slot count (power-of-two expected by callers; this guard
-    // makes the method robust if a non-even value slips through).
-    ObjectPtr<DenseMapObj> p = make_object<DenseMapObj>();
-    uint64_t n_blocks = CalcNumBlocks(n_slots);
-    Block* block = new Block[n_blocks];
-    p->data_ = block;
-    // assign block deleter so even if we take re-alloc data
-    // in another shared-lib that may have different malloc/free behavior
-    // it will still be safe.
-    p->data_deleter_ = BlockDeleter;
-    p->SetSlotsAndDenseLayoutTag(n_slots);
-    p->size_ = 0;
-    p->fib_shift_ = fib_shift;
-    p->iter_list_head_ = kInvalidIndex;
-    p->iter_list_tail_ = kInvalidIndex;
-    for (uint64_t i = 0; i < n_blocks; ++i, ++block) {
-      std::fill(block->bytes, block->bytes + kBlockCap, uint8_t(kEmptySlot));
-    }
-    return p;
-  }
-  /*!
-   * \brief Create an empty container with elements copying from another DenseMapObj
-   * \param from The source container
-   * \return The object created
-   */
-  static ObjectPtr<DenseMapObj> CopyFrom(DenseMapObj* from) {
-    ObjectPtr<DenseMapObj> p = make_object<DenseMapObj>();
-    uint64_t n_blocks = CalcNumBlocks(from->NumSlots());
-    p->data_ = new Block[n_blocks];
-    // assign block deleter so even if we take re-alloc data
-    // in another shared-lib that may have different malloc/free behavior
-    // it will still be safe.
-    p->data_deleter_ = BlockDeleter;
-    p->SetSlotsAndDenseLayoutTag(from->NumSlots());
-    p->size_ = from->size_;
-    p->fib_shift_ = from->fib_shift_;
-    p->iter_list_head_ = from->iter_list_head_;
-    p->iter_list_tail_ = from->iter_list_tail_;
-    for (uint64_t bi = 0; bi < n_blocks; ++bi) {
-      uint8_t* meta_ptr_from = from->GetBlock(bi)->bytes;
-      ItemType* data_ptr_from = reinterpret_cast<ItemType*>(from->GetBlock(bi)->bytes + kBlockCap);
-      uint8_t* meta_ptr_to = p->GetBlock(bi)->bytes;
-      ItemType* data_ptr_to = reinterpret_cast<ItemType*>(p->GetBlock(bi)->bytes + kBlockCap);
-      for (int j = 0; j < kBlockCap;
-           ++j, ++meta_ptr_from, ++data_ptr_from, ++meta_ptr_to, ++data_ptr_to) {
-        uint8_t& meta = *meta_ptr_to = *meta_ptr_from;
-        TVM_FFI_ICHECK(meta != kProtectedSlot);
-        if (meta != uint8_t(kEmptySlot)) {
-          new (data_ptr_to) ItemType(*data_ptr_from);
-        }
-      }
-    }
-    return p;
-  }
-  /*!
-   * \brief InsertMaybeReHash an entry into the given hash map
-   * \param kv The entry to be inserted
-   * \param map The pointer to the map, can be changed if re-hashing happens
-   */
-  static void InsertMaybeReHash(KVType&& kv, ObjectPtr<Object>* map) {
-    DenseMapObj* map_node = static_cast<DenseMapObj*>(map->get());
-    ListNode iter;
-    // Try to insert. If succeed, we simply return
-    if (map_node->TryInsert(kv.first, &iter)) {
-      iter.Val() = std::move(kv.second);
-      // update the iter list relation
-      map_node->IterListPushBack(iter);
-      return;
-    }
-    TVM_FFI_ICHECK(!map_node->IsSmallMap());
-    // Otherwise, start rehash
-    ObjectPtr<Object> p = Empty(map_node->fib_shift_ - 1, map_node->NumSlots() * 2);
-
-    // need to insert in the same order as the original map
-    for (uint64_t index = map_node->iter_list_head_; index != kInvalidIndex;) {
-      ListNode node(index, map_node);
-      // now try move src_data into the new map, note that src may still not
-      // be fully consumed into the call, but destructor will be called.
-      InsertMaybeReHash(std::move(node.Data()), &p);
-      // Important, needs to explicit call destructor in case move did remove
-      // node's internal item
-      index = node.Item().next;
-      // IMPORTANT: must explicit call destructor `node` to avoid memory leak
-      // We must call node.DestructData() here.
-      // This is because std::move() arguments in IterMaybeReHash may or may not
-      // explicitly move out the node.Data()
-      // Remove this call will cause memory leak very likely.
-      node.DestructData();
-    }
-    InsertMaybeReHash(std::move(kv), &p);
-    map_node->ReleaseMemory();
-    *map = p;
-  }
-  /*!
-   * \brief Check whether the hash table is full
-   * \return A boolean indicating whether hash table is full
-   */
-  bool IsFull() const { return size_ + 1 > NumSlots() * kMaxLoadFactor; }
-  /*!
-   * \brief Increment the pointer
-   * \param index The pointer to be incremented
-   * \return The increased pointer
-   */
-  uint64_t IncItr(uint64_t index) const {
-    // keep at the end of iterator
-    if (index == kInvalidIndex) {
-      return index;
-    }
-    ListNode node(index, this);
-    return node.Item().next;
-  }
-  /*!
-   * \brief Decrement the pointer
-   * \param index The pointer to be decremented
-   * \return The decreased pointer
-   */
-  uint64_t DecItr(uint64_t index) const {
-    // this is the end iterator, we need to return tail.
-    if (index == kInvalidIndex) {
-      return iter_list_tail_;
-    }
-    // circle around the iterator list, which is OK
-    ListNode node(index, this);
-    return node.Item().prev;
-  }
-  /*!
-   * \brief De-reference the pointer
-   * \param index The pointer to be dereferenced
-   * \return The result
-   */
-  KVType* DeRefItr(uint64_t index) const { return &ListNode(index, this).Data(); }
-  /*! \brief Construct from hash code */
-  ListNode IndexFromHash(uint64_t hash_value) const {
-    return ListNode(FibHash(hash_value, fib_shift_), this);
-  }
-  /*! \brief Construct from hash code if the position is head of list */
-  ListNode GetListHead(uint64_t hash_value) const {
-    ListNode node = IndexFromHash(hash_value);
-    return node.IsHead() ? node : ListNode();
-  }
-  /*! \brief Construct the number of blocks in the hash table */
-  static uint64_t CalcNumBlocks(uint64_t n_slots) { return (n_slots + kBlockCap - 1) / kBlockCap; }
-  /*!
-   * \brief Calculate the power-of-2 table size given the lower-bound of required capacity.
-   * \param cap The lower-bound of the required capacity
-   * \param fib_shift The result shift for Fibonacci Hashing
-   * \param n_slots The result number of slots
-   */
-  static void CalcTableSize(uint64_t cap, uint32_t* fib_shift, uint64_t* n_slots) {
-    uint32_t shift = 64;
-    uint64_t slots = 1;
-    for (uint64_t c = cap; c; c >>= 1) {
-      shift -= 1;
-      slots <<= 1;
-    }
-    TVM_FFI_ICHECK_GT(slots, cap);
-    if (slots < cap * 2) {
-      *fib_shift = shift - 1;
-      *n_slots = slots << 1;
-    } else {
-      *fib_shift = shift;
-      *n_slots = slots;
-    }
-  }
-  /*!
-   * \brief Fibonacci Hashing, maps a hash code to an index in a power-of-2-sized table.
-   * See also: https://programmingpraxis.com/2018/06/19/fibonacci-hash/.
-   * \param hash_value The raw hash value
-   * \param fib_shift The shift in Fibonacci Hashing
-   * \return An index calculated using Fibonacci Hashing
-   */
-  static uint64_t FibHash(uint64_t hash_value, uint32_t fib_shift) {
-    constexpr uint64_t coeff = 11400714819323198485ull;
-    return (coeff * hash_value) >> fib_shift;
-  }
-  /*! \brief The implicit in-place linked list used to index a chain */
-  struct ListNode {
-    /*! \brief Construct None */
-    ListNode() : index(0), block(nullptr) {}
-    /*! \brief Construct from position */
-    ListNode(uint64_t index, const DenseMapObj* self)
-        : index(index), block(self->GetBlock(index / kBlockCap)) {}
-    /*! \brief Metadata on the entry */
-    uint8_t& Meta() const { return *(block->bytes + index % kBlockCap); }
-    /*! \brief Data on the entry */
-    ItemType& Item() const {
-      return *(reinterpret_cast<ItemType*>(block->bytes + kBlockCap +
-                                           (index % kBlockCap) * sizeof(ItemType)));
-    }
-    /*! \brief Data on the entry */
-    KVType& Data() const { return Item().data; }
-    /*! \brief Key on the entry */
-    key_type& Key() const { return Data().first; }
-    /*! \brief Value on the entry */
-    mapped_type& Val() const { return Data().second; }
-    /*! \brief If the entry is head of linked list */
-    bool IsHead() const { return (Meta() & 0b10000000) == 0b00000000; }
-    /*! \brief If the entry is none */
-    bool IsNone() const { return block == nullptr; }
-    /*! \brief If the entry is empty slot */
-    bool IsEmpty() const { return Meta() == uint8_t(kEmptySlot); }
-    /*! \brief If the entry is protected slot */
-    bool IsProtected() const { return Meta() == uint8_t(kProtectedSlot); }
-    /*! \brief Set the entry to be empty */
-    void SetEmpty() const { Meta() = uint8_t(kEmptySlot); }
-    /*! \brief Destruct the item in the entry */
-    void DestructData() const {
-      // explicit call destructor to destroy the item
-      // Favor this over ~KVType as MSVC may not support ~KVType (need the original name)
-      (&Data())->first.Any::~Any();
-      (&Data())->second.Any::~Any();
-    }
-    /*! \brief Set the entry to be protected */
-    void SetProtected() const { Meta() = uint8_t(kProtectedSlot); }
-    /*! \brief Set the entry's jump to its next entry */
-    void SetJump(uint8_t jump) const { (Meta() &= 0b10000000) |= jump; }
-    /*! \brief Construct a head of linked list in-place */
-    void NewHead(ItemType v) const {
-      Meta() = 0b00000000;
-      new (&Item()) ItemType(std::move(v));
-    }
-    /*! \brief Construct a tail of linked list in-place */
-    void NewTail(ItemType v) const {
-      Meta() = 0b10000000;
-      new (&Item()) ItemType(std::move(v));
-    }
-
-    /*! \brief If the entry has next entry on the linked list */
-    bool HasNext() const { return NextProbeLocation(Meta() & 0b01111111) != 0; }
-    /*! \brief Move the entry to the next entry on the linked list */
-    bool MoveToNext(const DenseMapObj* self, uint8_t meta) {
-      uint64_t offset = NextProbeLocation(meta & 0b01111111);
-      if (offset == 0) {
-        index = 0;
-        block = nullptr;
-        return false;
-      }
-      // the probing will go to next position and round back to stay within the
-      // correct range of the slots
-      index = (index + offset) % self->NumSlots();
-      block = self->GetBlock(index / kBlockCap);
-      return true;
-    }
-    /*! \brief Move the entry to the next entry on the linked list */
-    bool MoveToNext(const DenseMapObj* self) { return MoveToNext(self, Meta()); }
-    /*! \brief Get the previous entry on the linked list */
-    ListNode FindPrev(const DenseMapObj* self) const {
-      // start from the head of the linked list, which must exist
-      ListNode next = self->IndexFromHash(AnyHash()(Key()));
-      // `prev` is always the previous item of `next`
-      ListNode prev = next;
-      for (next.MoveToNext(self); index != next.index; prev = next, next.MoveToNext(self)) {
-      }
-      return prev;
-    }
-    /*! \brief Get the next empty jump */
-    bool GetNextEmpty(const DenseMapObj* self, uint8_t* jump, ListNode* result) const {
-      for (uint8_t idx = 1; idx < kNumJumpDists; ++idx) {
-        // the probing will go to next position and round back to stay within the
-        // correct range of the slots
-        ListNode candidate((index + NextProbeLocation(idx)) % self->NumSlots(), self);
-        if (candidate.IsEmpty()) {
-          *jump = idx;
-          *result = candidate;
-          return true;
-        }
-      }
-      return false;
-    }
-    /*! \brief Index on the real array */
-    uint64_t index;
-    /*! \brief Pointer to the actual block */
-    Block* block;
-  };
-
- protected:
-  /*! \brief fib shift in Fibonacci Hashing */
-  uint32_t fib_shift_;
-  /*! \brief the head of iterator list */
-  uint64_t iter_list_head_ = kInvalidIndex;
-  /*! \brief the tail of iterator list */
-  uint64_t iter_list_tail_ = kInvalidIndex;
-
-  static uint64_t NextProbeLocation(size_t index) {
-    /* clang-format off */
-    /*! \brief Candidates of probing distance */
-    static const uint64_t kNextProbeLocation[kNumJumpDists] {
-      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-      // Quadratic probing with triangle numbers. See also:
-      // 1) https://en.wikipedia.org/wiki/Quadratic_probing
-      // 2) https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/
-      // 3) https://github.com/skarupke/flat_hash_map
-      21, 28, 36, 45, 55, 66, 78, 91, 105, 120,
-      136, 153, 171, 190, 210, 231, 253, 276, 300, 325,
-      351, 378, 406, 435, 465, 496, 528, 561, 595, 630,
-      666, 703, 741, 780, 820, 861, 903, 946, 990, 1035,
-      1081, 1128, 1176, 1225, 1275, 1326, 1378, 1431, 1485, 1540,
-      1596, 1653, 1711, 1770, 1830, 1891, 1953, 2016, 2080, 2145,
-      2211, 2278, 2346, 2415, 2485, 2556, 2628,
-      // larger triangle numbers
-      8515, 19110, 42778, 96141, 216153,
-      486591, 1092981, 2458653, 5532801, 12442566,
-      27993903, 62983476, 141717030, 318844378, 717352503,
-      1614057336, 3631522476, 8170957530, 18384510628, 41364789378,
-      93070452520, 209408356380, 471168559170, 1060128894105, 2385289465695,
-      5366898840628, 12075518705635, 27169915244790, 61132312065111, 137547689707000,
-      309482283181501, 696335127828753, 1566753995631385, 3525196511162271, 7931691992677701,
-      17846306936293605, 40154190677507445, 90346928918121501, 203280589587557251,
-      457381325854679626, 1029107982097042876, 2315492959180353330, 5209859154120846435,
-    };
-    /* clang-format on */
-    return kNextProbeLocation[index];
-  }
-  friend class MapObj;
-
- private:
-  /*!
-   * \brief Set the number of slots and attach tags bit.
-   * \param n The number of slots
-   */
-  void SetSlotsAndDenseLayoutTag(uint64_t n) {
-    TVM_FFI_ICHECK(((n & kSmallTagMask) == 0ull)) << "DenseMap expects MSB clear";
-    slots_ = n;
-  }
-};
-
-/// \cond
-#define TVM_FFI_DISPATCH_MAP(base, var, body) \
-  {                                           \
-    using TSmall = SmallMapObj*;              \
-    using TDense = DenseMapObj*;              \
-    if (base->IsSmallMap()) {                 \
-      TSmall var = static_cast<TSmall>(base); \
-      body;                                   \
-    } else {                                  \
-      TDense var = static_cast<TDense>(base); \
-      body;                                   \
-    }                                         \
-  }
-
-#define TVM_FFI_DISPATCH_MAP_CONST(base, var, body) \
-  {                                                 \
-    using TSmall = const SmallMapObj*;              \
-    using TDense = const DenseMapObj*;              \
-    if (base->IsSmallMap()) {                       \
-      TSmall var = static_cast<TSmall>(base);       \
-      body;                                         \
-    } else {                                        \
-      TDense var = static_cast<TDense>(base);       \
-      body;                                         \
-    }                                               \
-  }
-
-inline MapObj::iterator::pointer MapObj::iterator::operator->() const {
-  TVM_FFI_MAP_FAIL_IF_CHANGED()
-  TVM_FFI_DISPATCH_MAP_CONST(self, p, { return p->DeRefItr(index); });
-}
-
-inline MapObj::iterator& MapObj::iterator::operator++() {
-  TVM_FFI_MAP_FAIL_IF_CHANGED()
-  TVM_FFI_DISPATCH_MAP_CONST(self, p, {
-    index = p->IncItr(index);
-    return *this;
-  });
-}
-
-inline MapObj::iterator& MapObj::iterator::operator--() {
-  TVM_FFI_MAP_FAIL_IF_CHANGED()
-  TVM_FFI_DISPATCH_MAP_CONST(self, p, {
-    index = p->DecItr(index);
-    return *this;
-  });
-}
-
-inline size_t MapObj::count(const key_type& key) const {
-  TVM_FFI_DISPATCH_MAP_CONST(this, p, { return p->count(key); });
-}
-
-inline const MapObj::mapped_type& MapObj::at(const MapObj::key_type& key) const {
-  TVM_FFI_DISPATCH_MAP_CONST(this, p, { return p->at(key); });
-}
-
-inline MapObj::mapped_type& MapObj::at(const MapObj::key_type& key) {
-  TVM_FFI_DISPATCH_MAP(this, p, { return p->at(key); });
-}
-
-inline MapObj::iterator MapObj::begin() const {
-  TVM_FFI_DISPATCH_MAP_CONST(this, p, { return p->begin(); });
-}
-
-inline MapObj::iterator MapObj::end() const {
-  TVM_FFI_DISPATCH_MAP_CONST(this, p, { return p->end(); });
-}
-
-inline MapObj::iterator MapObj::find(const MapObj::key_type& key) const {
-  TVM_FFI_DISPATCH_MAP_CONST(this, p, { return p->find(key); });
-}
-
-inline void MapObj::erase(const MapObj::iterator& position) {
-  TVM_FFI_DISPATCH_MAP(this, p, { return p->erase(position); });
-}
-/// \endcond
-
-#undef TVM_FFI_DISPATCH_MAP
-#undef TVM_FFI_DISPATCH_MAP_CONST
-
-inline ObjectPtr<MapObj> MapObj::Empty() { return SmallMapObj::Empty(); }
-
-inline ObjectPtr<MapObj> MapObj::CopyFrom(MapObj* from) {
-  if (from->IsSmallMap()) {
-    return SmallMapObj::CopyFrom(static_cast<SmallMapObj*>(from));
-  } else {
-    return DenseMapObj::CopyFrom(static_cast<DenseMapObj*>(from));
-  }
-}
-
-template <typename IterType>
-inline ObjectPtr<Object> MapObj::CreateFromRange(IterType first, IterType last) {
-  int64_t _cap = std::distance(first, last);
-  if (_cap < 0) {
-    return SmallMapObj::Empty();
-  }
-  uint64_t cap = static_cast<uint64_t>(_cap);
-  if (cap < SmallMapObj::kMaxSize) {
-    if (cap < 2) {
-      return SmallMapObj::CreateFromRange(cap, first, last);
-    }
-    // need to insert to avoid duplicate keys
-    ObjectPtr<Object> obj = SmallMapObj::Empty(cap);
-    for (; first != last; ++first) {
-      KVType kv(*first);
-      SmallMapObj::InsertMaybeReHash(std::move(kv), &obj);
-    }
-    return obj;
-  } else {
-    uint32_t fib_shift;
-    uint64_t n_slots;
-    DenseMapObj::CalcTableSize(cap, &fib_shift, &n_slots);
-    ObjectPtr<Object> obj = DenseMapObj::Empty(fib_shift, n_slots);
-    for (; first != last; ++first) {
-      KVType kv(*first);
-      DenseMapObj::InsertMaybeReHash(std::move(kv), &obj);
-    }
-    return obj;
-  }
-}
-
-inline void MapObj::InsertMaybeReHash(KVType&& kv, ObjectPtr<Object>* map) {
-  MapObj* base = static_cast<MapObj*>(map->get());
-#if TVM_FFI_DEBUG_WITH_ABI_CHANGE
-  base->state_marker++;
-#endif  // TVM_FFI_DEBUG_WITH_ABI_CHANGE
-  if (base->IsSmallMap()) {
-    SmallMapObj* sm = static_cast<SmallMapObj*>(base);
-    if (sm->NumSlots() < SmallMapObj::kMaxSize) {
-      SmallMapObj::InsertMaybeReHash(std::move(kv), map);
-    } else if (sm->NumSlots() == SmallMapObj::kMaxSize) {
-      if (base->size_ < sm->NumSlots()) {
-        SmallMapObj::InsertMaybeReHash(std::move(kv), map);
-      } else {
-        ObjectPtr<Object> new_map = MapObj::CreateFromRange(base->begin(), base->end());
-        DenseMapObj::InsertMaybeReHash(std::move(kv), &new_map);
-        *map = std::move(new_map);
-      }
-    }
-  } else {
-    DenseMapObj::InsertMaybeReHash(std::move(kv), map);
-  }
-}
-
-template <>
-inline ObjectPtr<MapObj> make_object<>() = delete;
-
-/*!
- * \brief 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.
- *
- * operator[] only provide const acces, use Set to mutate the content.
- * \tparam K The key NodeRef type.
- * \tparam V The value NodeRef type.
- */
-template <typename K, typename V,
-          typename = typename std::enable_if_t<details::storage_enabled_v<K> &&
-                                               details::storage_enabled_v<V>>>
-class Map : public ObjectRef {
- public:
-  /*! \brief The key type of the map */
-  using key_type = K;
-  /*! \brief The mapped type of the map */
-  using mapped_type = V;
-  /*! \brief The iterator type of the map */
-  class iterator;
-  /*!
-   * \brief Construct an Map with UnsafeInit
-   */
-  explicit Map(UnsafeInit tag) : ObjectRef(tag) {}
-  /*!
-   * \brief default constructor
-   */
-  Map() { data_ = MapObj::Empty(); }
-  /*!
-   * \brief move constructor
-   * \param other source
-   */
-  Map(Map<K, V>&& other) : ObjectRef(std::move(other.data_)) {}
-  /*!
-   * \brief copy constructor
-   * \param other source
-   */
-  Map(const Map<K, V>& other) : ObjectRef(other.data_) {}
-
-  /*!
-   * \brief Move constructor
-   * \param other The other map
-   * \tparam KU The key type of the other map
-   * \tparam VU The mapped type of the other map
-   */
-  template <typename KU, typename VU,
-            typename = std::enable_if_t<details::type_contains_v<K, KU> &&
-                                        details::type_contains_v<V, VU>>>
-  Map(Map<KU, VU>&& other) : ObjectRef(std::move(other.data_)) {}
-
-  /*!
-   * \brief Copy constructor
-   * \param other The other map
-   * \tparam KU The key type of the other map
-   * \tparam VU The mapped type of the other map
-   */
-  template <typename KU, typename VU,
-            typename = std::enable_if_t<details::type_contains_v<K, KU> &&
-                                        details::type_contains_v<V, VU>>>
-  Map(const Map<KU, VU>& other) : ObjectRef(other.data_) {}
-
-  /*!
-   * \brief Move assignment
-   * \param other The other map
-   */
-  Map<K, V>& operator=(Map<K, V>&& other) {
-    data_ = std::move(other.data_);
-    return *this;
-  }
-
-  /*!
-   * \brief Copy assignment
-   * \param other The other map
-   */
-  Map<K, V>& operator=(const Map<K, V>& other) {
-    data_ = other.data_;
-    return *this;
-  }
-
-  /*!
-   * \brief Move assignment
-   * \param other The other map
-   * \tparam KU The key type of the other map
-   * \tparam VU The mapped type of the other map
-   */
-  template <typename KU, typename VU,
-            typename = std::enable_if_t<details::type_contains_v<K, KU> &&
-                                        details::type_contains_v<V, VU>>>
-  Map<K, V>& operator=(Map<KU, VU>&& other) {
-    data_ = std::move(other.data_);
-    return *this;
-  }
-
-  /*!
-   * \brief Copy assignment
-   * \param other The other map
-   * \tparam KU The key type of the other map
-   * \tparam VU The mapped type of the other map
-   */
-  template <typename KU, typename VU,
-            typename = std::enable_if_t<details::type_contains_v<K, KU> &&
-                                        details::type_contains_v<V, VU>>>
-  Map<K, V>& operator=(const Map<KU, VU>& other) {
-    data_ = other.data_;
-    return *this;
-  }
-  /*!
-   * \brief constructor from pointer
-   * \param n the container pointer
-   */
-  explicit Map(ObjectPtr<Object> n) : ObjectRef(n) {}
-  /*!
-   * \brief constructor from iterator
-   * \param begin begin of iterator
-   * \param end end of iterator
-   * \tparam IterType The type of iterator
-   */
-  template <typename IterType>
-  Map(IterType begin, IterType end) {
-    data_ = MapObj::CreateFromRange(begin, end);
-  }
-  /*!
-   * \brief constructor from initializer list
-   * \param init The initalizer list
-   */
-  Map(std::initializer_list<std::pair<K, V>> init) {
-    data_ = MapObj::CreateFromRange(init.begin(), init.end());
-  }
-  /*!
-   * \brief constructor from unordered_map
-   * \param init The unordered_map
-   */
-  template <typename Hash, typename Equal>
-  Map(const std::unordered_map<K, V, Hash, Equal>& init) {  // NOLINT(*)
-    data_ = MapObj::CreateFromRange(init.begin(), init.end());
-  }
-  /*!
-   * \brief Read element from map.
-   * \param key The key
-   * \return the corresonding element.
-   */
-  const V at(const K& key) const {
-    return details::AnyUnsafe::CopyFromAnyViewAfterCheck<V>(GetMapObj()->at(key));
-  }
-  /*!
-   * \brief Read element from map.
-   * \param key The key
-   * \return the corresonding element.
-   */
-  const V operator[](const K& key) const { return this->at(key); }
-  /*! \return The size of the array */
-  size_t size() const {
-    MapObj* n = GetMapObj();
-    return n == nullptr ? 0 : n->size();
-  }
-  /*! \return The number of elements of the key */
-  size_t count(const K& key) const {
-    MapObj* n = GetMapObj();
-    return n == nullptr ? 0 : GetMapObj()->count(key);
-  }
-  /*! \return whether array is empty */
-  bool empty() const { return size() == 0; }
-  /*! \brief Release reference to all the elements */
-  void clear() {
-    MapObj* n = GetMapObj();
-    if (n != nullptr) {
-      data_ = MapObj::Empty();
-    }
-  }
-  /*!
-   * \brief set the Map.
-   * \param key The index key.
-   * \param value The value to be setted.
-   */
-  void Set(const K& key, const V& value) {
-    CopyOnWrite();
-    MapObj::InsertMaybeReHash(MapObj::KVType(key, value), &data_);
-  }
-  /*! \return begin iterator */
-  iterator begin() const { return iterator(GetMapObj()->begin()); }
-  /*! \return end iterator */
-  iterator end() const { return iterator(GetMapObj()->end()); }
-  /*! \return find the key and returns the associated iterator */
-  iterator find(const K& key) const { return iterator(GetMapObj()->find(key)); }
-  /*! \return The value associated with the key, std::nullopt if not found */
-  std::optional<V> Get(const K& key) const {
-    MapObj::iterator iter = GetMapObj()->find(key);
-    if (iter == GetMapObj()->end()) {
-      return std::nullopt;
-    }
-    return details::AnyUnsafe::CopyFromAnyViewAfterCheck<V>(iter->second);
-  }
-
-  /*!
-   * \brief Erase the entry associated with the key
-   * \param key The key
-   */
-  void erase(const K& key) { CopyOnWrite()->erase(key); }
-
-  /*!
-   * \brief copy on write semantics
-   *  Do nothing if current handle is the unique copy of the array.
-   *  Otherwise make a new copy of the array to ensure the current handle
-   *  hold a unique copy.
-   *
-   * \return Handle to the internal node container(which guarantees to be unique)
-   */
-  MapObj* CopyOnWrite() {
-    if (data_.get() == nullptr) {
-      data_ = MapObj::Empty();
-    } else if (!data_.unique()) {
-      data_ = MapObj::CopyFrom(GetMapObj());
-    }
-    return GetMapObj();
-  }
-  /*! \brief specify container node */
-  using ContainerType = MapObj;
-
-  /// \cond Doxygen_Suppress
-  /*! \brief Iterator of the hash map */
-  class iterator {
-   public:
-    using iterator_category = std::bidirectional_iterator_tag;
-    using difference_type = int64_t;
-    using value_type = const std::pair<K, V>;
-    using pointer = value_type*;
-    using reference = value_type;
-
-    iterator() : itr() {}
-
-    /*! \brief Compare iterators */
-    bool operator==(const iterator& other) const { return itr == other.itr; }
-    /*! \brief Compare iterators */
-    bool operator!=(const iterator& other) const { return itr != other.itr; }
-    /*! \brief De-reference iterators is not allowed */
-    pointer operator->() const = delete;
-    /*! \brief De-reference iterators */
-    reference operator*() const {
-      auto& kv = *itr;
-      return std::make_pair(details::AnyUnsafe::CopyFromAnyViewAfterCheck<K>(kv.first),
-                            details::AnyUnsafe::CopyFromAnyViewAfterCheck<V>(kv.second));
-    }
-    /*! \brief Prefix self increment, e.g. ++iter */
-    iterator& operator++() {
-      ++itr;
-      return *this;
-    }
-    /*! \brief Suffix self increment */
-    iterator operator++(int) {
-      iterator copy = *this;
-      ++(*this);
-      return copy;
-    }
-
-    /*! \brief Prefix self decrement, e.g. --iter */
-    iterator& operator--() {
-      --itr;
-      return *this;
-    }
-    /*! \brief Suffix self decrement */
-    iterator operator--(int) {
-      iterator copy = *this;
-      --(*this);
-      return copy;
-    }
-
-   private:
-    iterator(const MapObj::iterator& itr)  // NOLINT(*)
-        : itr(itr) {}
-
-    template <typename, typename, typename>
-    friend class Map;
-
-    MapObj::iterator itr;
-  };
-  /// \endcond
-
- private:
-  /*! \brief Return data_ as type of pointer of MapObj */
-  MapObj* GetMapObj() const { return static_cast<MapObj*>(data_.get()); }
-
-  template <typename, typename, typename>
-  friend class Map;
-};
-
-/*!
- * \brief Merge two Maps.
- * \param lhs the first Map to merge.
- * \param rhs the second Map to merge.
- * @return The merged Array. Original Maps are kept unchanged.
- */
-template <typename K, typename V,
-          typename = typename std::enable_if_t<details::storage_enabled_v<K> &&
-                                               details::storage_enabled_v<V>>>
-inline Map<K, V> Merge(Map<K, V> lhs, const Map<K, V>& rhs) {
-  for (const auto& p : rhs) {
-    lhs.Set(p.first, p.second);
-  }
-  return std::move(lhs);
-}
-
-// Traits for Map
-template <typename K, typename V>
-inline constexpr bool use_default_type_traits_v<Map<K, V>> = false;
-
-template <typename K, typename V>
-struct TypeTraits<Map<K, V>> : public ObjectRefTypeTraitsBase<Map<K, V>> {
-  static constexpr int32_t field_static_type_index = TypeIndex::kTVMFFIMap;
-  using ObjectRefTypeTraitsBase<Map<K, V>>::CopyFromAnyViewAfterCheck;
-
-  TVM_FFI_INLINE static std::string GetMismatchTypeInfo(const TVMFFIAny* src) {
-    if (src->type_index != TypeIndex::kTVMFFIMap) {
-      return TypeTraitsBase::GetMismatchTypeInfo(src);
-    }
-    if constexpr (!std::is_same_v<K, Any> || !std::is_same_v<V, Any>) {
-      const MapObj* n = reinterpret_cast<const MapObj*>(src->v_obj);
-      for (const auto& kv : *n) {
-        if constexpr (!std::is_same_v<K, Any>) {
-          if (!details::AnyUnsafe::CheckAnyStrict<K>(kv.first) &&
-              !kv.first.try_cast<K>().has_value()) {
-            return "Map[some key is " + details::AnyUnsafe::GetMismatchTypeInfo<K>(kv.first) +
-                   ", V]";
-          }
-        }
-        if constexpr (!std::is_same_v<V, Any>) {
-          if (!details::AnyUnsafe::CheckAnyStrict<V>(kv.second) &&
-              !kv.second.try_cast<V>().has_value()) {
-            return "Map[K, some value is " + details::AnyUnsafe::GetMismatchTypeInfo<V>(kv.second) +
-                   "]";
-          }
-        }
-      }
-    }
-    TVM_FFI_THROW(InternalError) << "Cannot reach here";
-    TVM_FFI_UNREACHABLE();
-  }
-
-  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
-    if (src->type_index != TypeIndex::kTVMFFIMap) return false;
-    if constexpr (std::is_same_v<K, Any> && std::is_same_v<V, Any>) {
-      return true;
-    } else {
-      const MapObj* n = reinterpret_cast<const MapObj*>(src->v_obj);
-      for (const auto& kv : *n) {
-        if constexpr (!std::is_same_v<K, Any>) {
-          if (!details::AnyUnsafe::CheckAnyStrict<K>(kv.first)) return false;
-        }
-        if constexpr (!std::is_same_v<V, Any>) {
-          if (!details::AnyUnsafe::CheckAnyStrict<V>(kv.second)) return false;
-        }
-      }
-      return true;
-    }
-  }
-
-  TVM_FFI_INLINE static std::optional<Map<K, V>> TryCastFromAnyView(const TVMFFIAny* src) {
-    if (src->type_index != TypeIndex::kTVMFFIMap) return std::nullopt;
-    if constexpr (!std::is_same_v<K, Any> || !std::is_same_v<V, Any>) {
-      const MapObj* n = reinterpret_cast<const MapObj*>(src->v_obj);
-      bool storage_check = [&]() {
-        for (const auto& kv : *n) {
-          if constexpr (!std::is_same_v<K, Any>) {
-            if (!details::AnyUnsafe::CheckAnyStrict<K>(kv.first)) return false;
-          }
-          if constexpr (!std::is_same_v<V, Any>) {
-            if (!details::AnyUnsafe::CheckAnyStrict<V>(kv.second)) return false;
-          }
-        }
-        return true;
-      }();
-      // fast path, if storage check passes, we can return the array directly.
-      if (storage_check) return CopyFromAnyViewAfterCheck(src);
-      // slow path, we need to create a new map and convert to the target type.
-      Map<K, V> ret;
-      for (const auto& kv : *n) {
-        auto k = kv.first.try_cast<K>();
-        auto v = kv.second.try_cast<V>();
-        if (!k.has_value() || !v.has_value()) return std::nullopt;
-        ret.Set(*std::move(k), *std::move(v));
-      }
-      return ret;
-    } else {
-      return CopyFromAnyViewAfterCheck(src);
-    }
-  }
-
-  TVM_FFI_INLINE static std::string TypeStr() {
-    return "Map<" + details::Type2Str<K>::v() + ", " + details::Type2Str<V>::v() + ">";
-  }
-};
-
-namespace details {
-template <typename K, typename V, typename KU, typename VU>
-inline constexpr bool type_contains_v<Map<K, V>, Map<KU, VU>> =
-    type_contains_v<K, KU> && type_contains_v<V, VU>;
-}  // namespace details
-
-}  // namespace ffi
-}  // namespace tvm
-#endif  // TVM_FFI_CONTAINER_MAP_H_
diff --git a/ffi/include/tvm/ffi/container/shape.h b/ffi/include/tvm/ffi/container/shape.h
deleted file mode 100644
index de24a44ded..0000000000
--- a/ffi/include/tvm/ffi/container/shape.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * 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/container/shape.h
- * \brief Container to store shape of an Tensor.
- */
-#ifndef TVM_FFI_CONTAINER_SHAPE_H_
-#define TVM_FFI_CONTAINER_SHAPE_H_
-
-#include <tvm/ffi/container/array.h>
-#include <tvm/ffi/error.h>
-#include <tvm/ffi/type_traits.h>
-
-#include <algorithm>
-#include <ostream>
-#include <utility>
-#include <vector>
-
-namespace tvm {
-namespace ffi {
-
... 29376 lines suppressed ...