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 c84cb8ce5b [FIX] Repair shared C++ exports, OpenCL interfaces and 
compiler loading (#20722)
c84cb8ce5b is described below

commit c84cb8ce5b70bc03ec67b90f0e5fb0495e7d1992
Author: Tianqi Chen <[email protected]>
AuthorDate: Wed Oct 14 13:34:49 2026 -0400

    [FIX] Repair shared C++ exports, OpenCL interfaces and compiler loading 
(#20722)
    
    Expose an optional DeviceAPI query for borrowed host mappings so VM
    auxiliary copies no longer depend on private OpenCL runtime interfaces.
    Apply tensor and row offsets at the caller, retain the existing copy
    fallback, and clarify the host pointer arithmetic capability name.
    
    Export the native workspace methods consumed by CLML, with OpenCL
    visibility definitions and host-pointer configuration supplied through
    backend target usage requirements. Add missing TVM_TIRX_DLL annotations
    to existing shared analysis, IR and builder APIs. Give existing
    runtime-extra APIs an independent TVM_RUNTIME_EXTRA_DLL visibility
    policy and mark extra object producers separately from core runtime.
    
    Preflight compiler-library presence before using the existing loader,
    preserving runtime-only installations while allowing genuine compiler
    loading errors to propagate.
    
    Place the shared compiler texture helper alongside S-TIR Adreno
    lowering, with both Relax consumers using the same header and helper
    behavior preserved.
    
    Give Maven native-library assembly a configurable default heap through
    the existing JVM build script.
---
 CMakeLists.txt                                     |  7 +-
 cmake/modules/OpenCL.cmake                         | 21 ++++--
 cmake/modules/contrib/CLML.cmake                   |  3 -
 include/tvm/ir/location.h                          |  2 +-
 include/tvm/ir/stmt.h                              |  2 +-
 include/tvm/ir/transform.h                         |  2 +-
 include/tvm/ir/unique_name_supply.h                |  8 +--
 include/tvm/runtime/base.h                         | 27 ++++++--
 include/tvm/runtime/device_api.h                   | 14 +++-
 include/tvm/runtime/disco/builtin.h                | 36 +++++-----
 include/tvm/runtime/disco/cuda_ipc_memory.h        |  4 +-
 include/tvm/runtime/disco/disco_worker.h           |  2 +-
 include/tvm/runtime/disco/session.h                | 34 +++++-----
 include/tvm/runtime/tensor.h                       |  2 +-
 include/tvm/script/ir_builder/base.h               | 26 ++++----
 include/tvm/sym/bound.h                            |  6 +-
 include/tvm/sym/int_set.h                          | 77 +++++++++++-----------
 include/tvm/sym/iter_affine_map.h                  | 41 ++++++------
 include/tvm/sym/pattern.h                          |  3 +-
 include/tvm/tirx/analysis.h                        |  2 +-
 include/tvm/tirx/function.h                        |  3 +-
 include/tvm/tirx/index_map.h                       | 28 ++++----
 include/tvm/tirx/layout.h                          |  2 +-
 include/tvm/tirx/script/ir_builder/frame.h         |  2 +-
 include/tvm/tirx/type.h                            |  3 +-
 python/tvm/base.py                                 | 13 ++--
 src/backend/cuda/runtime/cuda_device_api.cc        |  2 +-
 src/backend/opencl/runtime/opencl_common.h         | 11 ++--
 src/backend/opencl/runtime/opencl_device_api.cc    | 14 ++--
 .../backend/adreno/fold_vdevice_scope_change.cc    |  2 +-
 src/relax/transform/static_plan_block_memory.cc    |  2 +-
 src/runtime/cpu_device_api.cc                      |  2 +-
 src/runtime/extra/contrib/clml/clml_runtime.h      |  3 +-
 src/runtime/extra/contrib/dnnl/dnnl_kernel.h       | 48 +++++++-------
 src/runtime/extra/disco/builtin.cc                 |  6 +-
 src/runtime/extra/disco/disco_worker.cc            |  2 +-
 src/runtime/vm/attn_utils.h                        | 31 +++------
 src/runtime/vm/builtin.cc                          |  2 +-
 src/s_tir/backend/adreno/inject_texture_alloc.cc   |  2 +-
 src/s_tir/backend/adreno/texture_flatten.cc        |  2 +-
 src/{ => s_tir/backend/adreno}/texture_utils.h     |  8 +--
 src/sym/bound_deducer.cc                           |  1 +
 src/sym/detect_linear_equation.cc                  |  1 +
 tests/scripts/task_jvm_build.sh                    |  2 +
 44 files changed, 281 insertions(+), 230 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d7ed0fef4e..2a7521545b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -132,13 +132,12 @@ add_library(tvm_runtime_extra SHARED)
 list(APPEND TVM_RUNTIME_BACKEND_LIBS tvm_runtime_extra)
 set_target_properties(tvm_runtime_extra PROPERTIES LINKER_LANGUAGE CXX)
 # INTERFACE target carrying compile definitions for OBJECT libs that build
-# into tvm_runtime_extra. On MSVC, TVM_RUNTIME_EXPORTS makes TVM_RUNTIME_DLL
-# expand to __declspec(dllexport) so that functions defined in extra modules
-# are properly exported from tvm_runtime_extra.dll.
+# into tvm_runtime_extra. On MSVC, TVM_RUNTIME_EXTRA_EXPORTS exports 
extra-owned
+# APIs while core-runtime APIs remain imports from tvm_runtime.dll.
 add_library(tvm_runtime_extra_defs INTERFACE)
 target_link_libraries(tvm_runtime_extra_defs INTERFACE tvm_ffi_header)
 target_compile_definitions(tvm_runtime_extra_defs
-  INTERFACE TVM_RUNTIME_EXPORTS TVM_FFI_EXPORTS)
+  INTERFACE TVM_RUNTIME_EXTRA_EXPORTS TVM_FFI_EXPORTS)
 
 
 # Check if this is being run on its own or as a subdirectory for another 
project
diff --git a/cmake/modules/OpenCL.cmake b/cmake/modules/OpenCL.cmake
index cabfc3173f..becbfa7a1d 100644
--- a/cmake/modules/OpenCL.cmake
+++ b/cmake/modules/OpenCL.cmake
@@ -24,14 +24,14 @@ if(USE_OPENCL)
     file_glob_append(RUNTIME_OPENCL_SRCS
       "src/backend/opencl/runtime/opencl_wrapper/opencl_wrapper.cc"
     )
-    include_directories(SYSTEM "3rdparty/OpenCL-Headers")
+    set(_opencl_include_dirs 
"${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/OpenCL-Headers")
   else()
     find_opencl(${USE_OPENCL})
     if(NOT OpenCL_FOUND)
       message(FATAL_ERROR "Error! Cannot find specified OpenCL library")
     endif()
     message(STATUS "Build with OpenCL support")
-    include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS})
+    set(_opencl_include_dirs ${OpenCL_INCLUDE_DIRS})
     list(APPEND _opencl_libs ${OpenCL_LIBRARIES})
   endif()
 
@@ -39,6 +39,15 @@ if(USE_OPENCL)
 
   add_library(tvm_runtime_opencl_objs OBJECT ${RUNTIME_OPENCL_SRCS})
   target_link_libraries(tvm_runtime_opencl_objs PUBLIC tvm_ffi_header)
+  target_include_directories(tvm_runtime_opencl_objs SYSTEM PRIVATE 
${_opencl_include_dirs})
+  if(WIN32)
+    set(_opencl_export "__declspec(dllexport)")
+    set(_opencl_import "__declspec(dllimport)")
+  else()
+    set(_opencl_export "__attribute__((visibility(\"default\")))")
+    set(_opencl_import "${_opencl_export}")
+  endif()
+  target_compile_definitions(tvm_runtime_opencl_objs PRIVATE 
"TVM_OPENCL_DLL=${_opencl_export}")
   set_target_properties(tvm_runtime_opencl_objs PROPERTIES 
POSITION_INDEPENDENT_CODE ON)
   if(TVM_VISIBILITY_FLAG)
     target_compile_options(tvm_runtime_opencl_objs PRIVATE 
"${TVM_VISIBILITY_FLAG}")
@@ -46,15 +55,19 @@ if(USE_OPENCL)
   add_library(tvm_runtime_opencl SHARED 
$<TARGET_OBJECTS:tvm_runtime_opencl_objs>)
   list(APPEND TVM_RUNTIME_BACKEND_LIBS tvm_runtime_opencl)
   target_link_libraries(tvm_runtime_opencl PUBLIC tvm_runtime PRIVATE 
${_opencl_libs})
+  target_compile_definitions(tvm_runtime_opencl INTERFACE 
"TVM_OPENCL_DLL=${_opencl_import}")
+  target_include_directories(tvm_runtime_opencl SYSTEM INTERFACE
+    "$<BUILD_INTERFACE:${_opencl_include_dirs}>")
   tvm_configure_target_library(tvm_runtime_opencl RUNTIME_MODULE)
 
-  if(USE_CLML OR USE_CLML_GRAPH_EXECUTOR)
+  if(USE_CLML_GRAPH_EXECUTOR)
     # CLML calls both OpenCL SDK and TVM OpenCL runtime APIs directly.
+    target_link_libraries(tvm_clml_objs PRIVATE tvm_runtime_opencl)
     target_link_libraries(tvm_runtime_extra PRIVATE tvm_runtime_opencl 
${_opencl_libs})
   endif()
 
   if(USE_OPENCL_ENABLE_HOST_PTR)
-    add_definitions(-DOPENCL_ENABLE_HOST_PTR)
+    target_compile_definitions(tvm_runtime_opencl_objs PRIVATE 
OPENCL_ENABLE_HOST_PTR)
   endif(USE_OPENCL_ENABLE_HOST_PTR)
   if(USE_OPENCL_EXTN_QCOM)
     add_definitions(-DUSE_OPENCL_EXTN_QCOM)
diff --git a/cmake/modules/contrib/CLML.cmake b/cmake/modules/contrib/CLML.cmake
index dbe383159c..edcb9b717b 100644
--- a/cmake/modules/contrib/CLML.cmake
+++ b/cmake/modules/contrib/CLML.cmake
@@ -81,7 +81,4 @@ if(USE_CLML_GRAPH_EXECUTOR)
 
     message(STATUS "Enable OpenCL as fallback to CLML")
     set(USE_OPENCL ${CLML_PATH})
-    if(USE_OPENCL_ENABLE_HOST_PTR)
-        add_definitions(-DOPENCL_ENABLE_HOST_PTR)
-    endif(USE_OPENCL_ENABLE_HOST_PTR)
 endif()
diff --git a/include/tvm/ir/location.h b/include/tvm/ir/location.h
index 2fb42aeec6..df862b12cc 100644
--- a/include/tvm/ir/location.h
+++ b/include/tvm/ir/location.h
@@ -234,7 +234,7 @@ class SourceMapObj : public ffi::Object {
 
 class SourceMap : public ffi::ObjectRef {
  public:
-  explicit SourceMap(ffi::Map<SourceName, Source> source_map);
+  TVM_TIRX_DLL explicit SourceMap(ffi::Map<SourceName, Source> source_map);
 
   explicit SourceMap(std::initializer_list<std::pair<SourceName, Source>> 
source_map)
       : SourceMap(ffi::Map<SourceName, Source>(source_map)) {}
diff --git a/include/tvm/ir/stmt.h b/include/tvm/ir/stmt.h
index 8167c3d8e8..d35cc2026e 100644
--- a/include/tvm/ir/stmt.h
+++ b/include/tvm/ir/stmt.h
@@ -484,7 +484,7 @@ class ForNode : public StmtNode {
   }
 
   /*! \brief Check it is a loop without nontrivial loop step. */
-  bool HasTrivialStep() const;
+  TVM_TIRX_DLL bool HasTrivialStep() const;
 
   TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.For", ForNode, StmtNode);
 };
diff --git a/include/tvm/ir/transform.h b/include/tvm/ir/transform.h
index a96c504537..d8d767c2f2 100644
--- a/include/tvm/ir/transform.h
+++ b/include/tvm/ir/transform.h
@@ -313,7 +313,7 @@ class Pass : public ffi::ObjectRef {
    *
    * \return The transformed module.
    */
-  IRModule operator()(IRModule mod) const;
+  TVM_TIRX_DLL IRModule operator()(IRModule mod) const;
 
   /*!
    * \brief Transform mod using a functor under a given pass context.
diff --git a/include/tvm/ir/unique_name_supply.h 
b/include/tvm/ir/unique_name_supply.h
index 9435fc87e4..b0cadde29c 100644
--- a/include/tvm/ir/unique_name_supply.h
+++ b/include/tvm/ir/unique_name_supply.h
@@ -59,8 +59,8 @@ class UniqueNameSupplyObj : public ffi::Object {
    * \param add_underscore If set to true, add '_' between prefix and a digit.
    * \return A unique name.
    */
-  ffi::String FreshName(const ffi::String& name, bool add_prefix = true,
-                        bool add_underscore = true);
+  TVM_TIRX_DLL ffi::String FreshName(const ffi::String& name, bool add_prefix 
= true,
+                                     bool add_underscore = true);
 
   /*!
    * \brief Reserves an existing name with this UniqueNameSupply.
@@ -69,7 +69,7 @@ class UniqueNameSupplyObj : public ffi::Object {
    * the name before reserving it. \return The name that was reserved with the 
UniqueNameSupply. It
    * can be different if a prefix is added.
    */
-  ffi::String ReserveName(const ffi::String& name, bool add_prefix = true);
+  TVM_TIRX_DLL ffi::String ReserveName(const ffi::String& name, bool 
add_prefix = true);
 
   /*!
    * \brief Checks if this UniqueNameSupply already generated a name.
@@ -78,7 +78,7 @@ class UniqueNameSupplyObj : public ffi::Object {
    * the name before checking for it. \return True if the name has already 
been generated. False
    * otherwise.
    */
-  bool ContainsName(const ffi::String& name, bool add_prefix = true);
+  TVM_TIRX_DLL bool ContainsName(const ffi::String& name, bool add_prefix = 
true);
 
   // Prefix for all GlobalVar names. It can be empty.
   std::string prefix_;
diff --git a/include/tvm/runtime/base.h b/include/tvm/runtime/base.h
index bc31b47f07..09ec0917f5 100644
--- a/include/tvm/runtime/base.h
+++ b/include/tvm/runtime/base.h
@@ -35,10 +35,8 @@
 #define TVM_VERSION "0.28.dev0"
 #endif
 
-// TVM ships two shared libraries: libtvm_compiler and libtvm_runtime.
-// Each exposes its own DLL macro pair.  The two families are defined
-// independently so that each can be overridden separately by downstream
-// embedders who need custom visibility on only one of the two libraries.
+// The compiler, core runtime and runtime-extra libraries expose independent
+// DLL policies so downstream embedders can override their visibility 
separately.
 //
 // TVM_DLL / TVM_DLL_EXPORT: symbols in libtvm_compiler.
 //   - TVM_DLL is dllexport when TVM_EXPORTS is defined (compiler build),
@@ -50,8 +48,12 @@
 //     (runtime build), dllimport otherwise.
 //   - TVM_RUNTIME_DLL_EXPORT is always dllexport.
 //
+// TVM_RUNTIME_EXTRA_DLL: symbols in libtvm_runtime_extra.
+//   - dllexport when TVM_RUNTIME_EXTRA_EXPORTS is defined (extra build),
+//     dllimport otherwise, including core-runtime and compiler builds.
+//
 // On non-MSVC platforms the import/export decision is made by the dynamic
-// loader, so all four macros expand to visibility("default"). Under
+// loader, so the macros expand to visibility("default"). Under
 // Emscripten they expand to EMSCRIPTEN_KEEPALIVE.
 #ifdef __EMSCRIPTEN__
 #include <emscripten/emscripten.h>
@@ -101,4 +103,19 @@
 #define TVM_RUNTIME_DLL_EXPORT __attribute__((visibility("default")))
 #endif
 
+// --- TVM_RUNTIME_EXTRA_DLL (libtvm_runtime_extra) ---
+#ifndef TVM_RUNTIME_EXTRA_DLL
+#if defined(__EMSCRIPTEN__)
+#define TVM_RUNTIME_EXTRA_DLL EMSCRIPTEN_KEEPALIVE
+#elif defined(_MSC_VER)
+#ifdef TVM_RUNTIME_EXTRA_EXPORTS
+#define TVM_RUNTIME_EXTRA_DLL __declspec(dllexport)
+#else
+#define TVM_RUNTIME_EXTRA_DLL __declspec(dllimport)
+#endif
+#else
+#define TVM_RUNTIME_EXTRA_DLL __attribute__((visibility("default")))
+#endif
+#endif
+
 #endif  // TVM_RUNTIME_BASE_H_
diff --git a/include/tvm/runtime/device_api.h b/include/tvm/runtime/device_api.h
index 637dce404c..0d54fe0b87 100644
--- a/include/tvm/runtime/device_api.h
+++ b/include/tvm/runtime/device_api.h
@@ -247,7 +247,19 @@ class TVM_RUNTIME_DLL DeviceAPI {
   /*!
    * \brief Whether pointer arithmetics on a device owned pointer may be 
performed on the host.
    */
-  virtual bool SupportsDevicePointerArithmeticsOnHost() { return false; }
+  virtual bool SupportsDevicePtrArithmeticOnHost() { return false; }
+
+  /*!
+   * \brief Query an existing host mapping of a device allocation, if 
available.
+   *
+   * The returned pointer is borrowed from the allocation and remains subject 
to
+   * its mapping lifetime and synchronization requirements. This query does not
+   * map, unmap, or synchronize memory, and does not apply a tensor byte 
offset.
+   *
+   * \param data The backend's device allocation handle.
+   * \return The base of the existing host mapping, or nullptr if unavailable.
+   */
+  virtual void* GetMappedHostPtrIfAvailable(void* data) { return nullptr; }
 
  protected:
   /*!
diff --git a/include/tvm/runtime/disco/builtin.h 
b/include/tvm/runtime/disco/builtin.h
index e2f61bde35..ff1a7f4e3b 100644
--- a/include/tvm/runtime/disco/builtin.h
+++ b/include/tvm/runtime/disco/builtin.h
@@ -62,7 +62,7 @@ inline std::string ReduceKind2String(ReduceKind kind) {
  * \param device The default device used to initialize the RelaxVM
  * \return The RelaxVM as a runtime Module
  */
-TVM_RUNTIME_DLL ffi::Module LoadVMModule(std::string path, 
ffi::Optional<Device> device);
+TVM_RUNTIME_EXTRA_DLL ffi::Module LoadVMModule(std::string path, 
ffi::Optional<Device> device);
 /*!
  * \brief Create an uninitialized empty Tensor
  * \param shape The shape of the Tensor
@@ -70,8 +70,8 @@ TVM_RUNTIME_DLL ffi::Module LoadVMModule(std::string path, 
ffi::Optional<Device>
  * \param device The device the Tensor is created on. If None, use the thread 
local default device
  * \return The Tensor created
  */
-TVM_RUNTIME_DLL ffi::Tensor DiscoEmptyTensor(ffi::Shape shape, DLDataType 
dtype,
-                                             ffi::Optional<Device> device);
+TVM_RUNTIME_EXTRA_DLL ffi::Tensor DiscoEmptyTensor(ffi::Shape shape, 
DLDataType dtype,
+                                                   ffi::Optional<Device> 
device);
 /*!
  * \brief Perform an allreduce operation using the underlying communication 
library
  * \param send The array send to perform allreduce on
@@ -79,22 +79,22 @@ TVM_RUNTIME_DLL ffi::Tensor DiscoEmptyTensor(ffi::Shape 
shape, DLDataType dtype,
  * \param in_group Whether the allreduce operation performs globally or in 
group as default.
  * \param recv The array receives the outcome of allreduce
  */
-TVM_RUNTIME_DLL void AllReduce(ffi::Tensor send, ReduceKind reduce_kind, bool 
in_group,
-                               ffi::Tensor recv);
+TVM_RUNTIME_EXTRA_DLL void AllReduce(ffi::Tensor send, ReduceKind reduce_kind, 
bool in_group,
+                                     ffi::Tensor recv);
 /*!
  * \brief Perform an allgather operation using the underlying communication 
library
  * \param send The array send to perform allgather on
  * \param in_group Whether the allgather operation performs globally or in 
group as default.
  * \param recv The array receives the outcome of allgather
  */
-TVM_RUNTIME_DLL void AllGather(ffi::Tensor send, bool in_group, ffi::Tensor 
recv);
+TVM_RUNTIME_EXTRA_DLL void AllGather(ffi::Tensor send, bool in_group, 
ffi::Tensor recv);
 /*!
  * \brief Perform a broadcast operation from worker-0
  * \param send The buffer to be broadcasted
  * \param in_group Whether the broadcast operation performs globally or in 
group as default.
  * \param recv The buffer receives the broadcasted array
  */
-TVM_RUNTIME_DLL void BroadcastFromWorker0(ffi::Tensor send, bool in_group, 
ffi::Tensor recv);
+TVM_RUNTIME_EXTRA_DLL void BroadcastFromWorker0(ffi::Tensor send, bool 
in_group, ffi::Tensor recv);
 /*!
  * \brief Perform a scatter operation from worker-0, chunking the given buffer 
into equal parts.
  * \param send For worker-0, it must be provided, and otherwise, the buffer 
must be None.
@@ -102,8 +102,8 @@ TVM_RUNTIME_DLL void BroadcastFromWorker0(ffi::Tensor send, 
bool in_group, ffi::
  * \param in_group Whether the scatter operation performs globally or in group 
as default.
  * \param recv The receiving buffer, which must not be None.
  */
-TVM_RUNTIME_DLL void ScatterFromWorker0(ffi::Optional<ffi::Tensor> send, bool 
in_group,
-                                        ffi::Tensor recv);
+TVM_RUNTIME_EXTRA_DLL void ScatterFromWorker0(ffi::Optional<ffi::Tensor> send, 
bool in_group,
+                                              ffi::Tensor recv);
 /*!
  * \brief Perform a gather operation to worker-0.
  * \param send The sending buffer, which must not be None.
@@ -111,45 +111,45 @@ TVM_RUNTIME_DLL void 
ScatterFromWorker0(ffi::Optional<ffi::Tensor> send, bool in
  * \param recv For worker-0, it must be provided, and otherwise, the buffer 
must be None. The
  * receiving buffer will be divided into equal parts and receive from each 
worker accordingly.
  */
-TVM_RUNTIME_DLL void GatherToWorker0(ffi::Tensor send, bool in_group,
-                                     ffi::Optional<ffi::Tensor> recv);
+TVM_RUNTIME_EXTRA_DLL void GatherToWorker0(ffi::Tensor send, bool in_group,
+                                           ffi::Optional<ffi::Tensor> recv);
 /*!
  * \brief Receive a buffer from worker-0. No-op if the current worker is 
worker-0.
  * \param buffer The buffer to be received
  */
-TVM_RUNTIME_DLL void RecvFromWorker0(ffi::Tensor buffer);
+TVM_RUNTIME_EXTRA_DLL void RecvFromWorker0(ffi::Tensor buffer);
 /*!
  * \brief Send a buffer to the corresponding worker in the next group.
  * An error is thrown if the worker is already in the last group.
  * \param buffer The sending buffer.
  */
-TVM_RUNTIME_DLL void SendToNextGroup(ffi::Tensor buffer);
+TVM_RUNTIME_EXTRA_DLL void SendToNextGroup(ffi::Tensor buffer);
 /*!
  * \brief Receive a buffer from the corresponding worker in the previous group.
  * An error is thrown if the worker is already in the first group.
  * \param buffer The receiving buffer.
  */
-TVM_RUNTIME_DLL void RecvFromPrevGroup(ffi::Tensor buffer);
+TVM_RUNTIME_EXTRA_DLL void RecvFromPrevGroup(ffi::Tensor buffer);
 /*!
  * \brief Send a buffer to the target receiver worker (globally across all 
groups).
  * \param buffer The sending buffer.
  * \param receiver_id The global receiver worker id.
  */
-TVM_RUNTIME_DLL void SendToWorker(ffi::Tensor buffer, int receiver_id);
+TVM_RUNTIME_EXTRA_DLL void SendToWorker(ffi::Tensor buffer, int receiver_id);
 /*!
  * \brief Receive a buffer from the target sender worker (globally across all 
groups).
  * \param buffer The receiving buffer.
  * \param sender_id The global sender worker id.
  */
-TVM_RUNTIME_DLL void RecvFromWorker(ffi::Tensor buffer, int sender_id);
+TVM_RUNTIME_EXTRA_DLL void RecvFromWorker(ffi::Tensor buffer, int sender_id);
 /*! \brief Get the local worker id */
-TVM_RUNTIME_DLL int WorkerId();
+TVM_RUNTIME_EXTRA_DLL int WorkerId();
 /*!
  * \brief Called by the worker thread. Waiting until the worker completes all 
its tasks.
  * As a specific example, on a CUDA worker, it blocks until all kernels are 
launched and
  * cudaStreamSynchronize is complete.
  */
-TVM_RUNTIME_DLL void SyncWorker();
+TVM_RUNTIME_EXTRA_DLL void SyncWorker();
 
 }  // namespace runtime
 }  // namespace tvm
diff --git a/include/tvm/runtime/disco/cuda_ipc_memory.h 
b/include/tvm/runtime/disco/cuda_ipc_memory.h
index 346fe09831..cc2b023421 100644
--- a/include/tvm/runtime/disco/cuda_ipc_memory.h
+++ b/include/tvm/runtime/disco/cuda_ipc_memory.h
@@ -80,14 +80,14 @@ class CUDAIPCMemoryObj : public ffi::Object {
 class CUDAIPCMemory : public ffi::ObjectRef {
  public:
   /*! \brief Get the global singleton CUDAIPCMemory pool. */
-  TVM_RUNTIME_DLL static TensorMemoryPool* GlobalMemoryPool();
+  TVM_RUNTIME_EXTRA_DLL static TensorMemoryPool* GlobalMemoryPool();
   /*!
    * \brief Given a local CUDA data pointer, return the CUDAIPCMemory object 
of the pointer.
    * \note The pointer's CUDAIPCMemory is expected to have been allocated
    * through global function "cuda_ipc.alloc_storage". Or otherwise this
    * function will raise exception.
    */
-  TVM_RUNTIME_DLL static CUDAIPCMemory GetIPCMemoryFromDevicePtr(void* ptr);
+  TVM_RUNTIME_EXTRA_DLL static CUDAIPCMemory GetIPCMemoryFromDevicePtr(void* 
ptr);
 
   explicit CUDAIPCMemory(ffi::UnsafeInit tag, ffi::ObjectPtr<CUDAIPCMemoryObj> 
n)
       : ffi::ObjectRef(tag) {
diff --git a/include/tvm/runtime/disco/disco_worker.h 
b/include/tvm/runtime/disco/disco_worker.h
index e5c88e0d21..4d5c8a3acc 100644
--- a/include/tvm/runtime/disco/disco_worker.h
+++ b/include/tvm/runtime/disco/disco_worker.h
@@ -63,7 +63,7 @@ class DiscoWorker {
   /*! \brief Main loop of the worker */
   void MainLoop();
   /*! \brief Get the worker instance on the current thread */
-  TVM_RUNTIME_DLL static DiscoWorker* ThreadLocal();
+  TVM_RUNTIME_EXTRA_DLL static DiscoWorker* ThreadLocal();
   /*! \brief Set the specific register to a specific value */
   void SetRegister(int reg_id, ffi::AnyView value);
 
diff --git a/include/tvm/runtime/disco/session.h 
b/include/tvm/runtime/disco/session.h
index 9d0494e65e..7b1bd192b3 100644
--- a/include/tvm/runtime/disco/session.h
+++ b/include/tvm/runtime/disco/session.h
@@ -221,25 +221,25 @@ class SessionObj : public ffi::Object {
    * The second element must be 0, which will later be updated by the session 
to return reg_id
    * The thirtd element is the function to be called.
    */
-  TVM_RUNTIME_DLL virtual DRef CallWithPacked(const ffi::PackedArgs& args) = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual DRef CallWithPacked(const ffi::PackedArgs& 
args) = 0;
   /*! \brief Get the number of workers in the session. */
-  TVM_RUNTIME_DLL virtual int64_t GetNumWorkers() = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual int64_t GetNumWorkers() = 0;
   /*! \brief Get a global functions on workers. */
-  TVM_RUNTIME_DLL virtual DRef GetGlobalFunc(const std::string& name) = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual DRef GetGlobalFunc(const std::string& name) = 
0;
   /*!
    * \brief Copy an Tensor from worker-0 to the controler-side Tensor
    * \param host_array The array to be copied to worker-0
    * \param remote_array The Tensor on worker-0
    */
-  TVM_RUNTIME_DLL virtual void CopyFromWorker0(const ffi::Tensor& host_array,
-                                               const DRef& remote_array) = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual void CopyFromWorker0(const ffi::Tensor& 
host_array,
+                                                     const DRef& remote_array) 
= 0;
   /*!
    * \brief Copy the controler-side Tensor to worker-0
    * \param host_array The array to be copied to worker-0
    * \param remote_array The Tensor on worker-0
    */
-  TVM_RUNTIME_DLL virtual void CopyToWorker0(const ffi::Tensor& host_array,
-                                             const DRef& remote_array) = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual void CopyToWorker0(const ffi::Tensor& 
host_array,
+                                                   const DRef& remote_array) = 
0;
   /*!
    * \brief Synchrnoize the controler with a worker, and it will wait until 
worker finishes
    * executing this instruction.
@@ -247,30 +247,30 @@ class SessionObj : public ffi::Object {
    * \note This function is usually used for worker-0, because it is the only 
worker that is
    * assumed to collocate with the controler. Syncing with other workers may 
not be supported.
    */
-  TVM_RUNTIME_DLL virtual void SyncWorker(int worker_id) = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual void SyncWorker(int worker_id) = 0;
   /*! \brief Signal all the workers to shutdown */
-  TVM_RUNTIME_DLL virtual void Shutdown() = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual void Shutdown() = 0;
   /*!
    * \brief Initialize the data plane between workers.
    * \param ccl The name of the communication backend, e.g., nccl, rccl, mpi.
    * \param device_ids The device ids of the workers.
    */
-  TVM_RUNTIME_DLL virtual void InitCCL(ffi::String ccl, ffi::Shape device_ids) 
= 0;
+  TVM_RUNTIME_EXTRA_DLL virtual void InitCCL(ffi::String ccl, ffi::Shape 
device_ids) = 0;
   /*!
    * \brief Get the value of a register from a remote worker.
    * \param reg_id The id of the register to be fetched.
    * \param worker_id The id of the worker to be fetched from.
    * \return The value of the register.
    */
-  TVM_RUNTIME_DLL virtual ffi::Any DebugGetFromRemote(int64_t reg_id, int 
worker_id) = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual ffi::Any DebugGetFromRemote(int64_t reg_id, 
int worker_id) = 0;
   /*!
    * \brief Set the value of a register on a remote worker.
    * \param reg_id The id of the register to be set.
    * \param value The value to be set.
    * \param worker_id The id of the worker to be set.
    */
-  TVM_RUNTIME_DLL virtual void DebugSetRegister(int64_t reg_id, ffi::AnyView 
value,
-                                                int worker_id) = 0;
+  TVM_RUNTIME_EXTRA_DLL virtual void DebugSetRegister(int64_t reg_id, 
ffi::AnyView value,
+                                                      int worker_id) = 0;
 
   struct FFI;
   friend struct SessionObj::FFI;
@@ -295,7 +295,7 @@ class Session : public ffi::ObjectRef {
    * \param num_workers The number of workers.
    * \param num_groups The number of worker groups.
    */
-  TVM_RUNTIME_DLL static Session ThreadedSession(int num_workers, int 
num_groups);
+  TVM_RUNTIME_EXTRA_DLL static Session ThreadedSession(int num_workers, int 
num_groups);
   /*!
    * \brief Create a session backed by pipe-based multiprocessing
    * \param num_workers The number of workers.
@@ -308,9 +308,9 @@ class Session : public ffi::ObjectRef {
    * \note Worker-0 is always co-located with the controler as a separate 
thread, and therefore
    * worker-0 does not exist in the process pool.
    */
-  TVM_RUNTIME_DLL static Session ProcessSession(int num_workers, int 
num_groups,
-                                                ffi::String 
process_pool_creator,
-                                                ffi::String entrypoint);
+  TVM_RUNTIME_EXTRA_DLL static Session ProcessSession(int num_workers, int 
num_groups,
+                                                      ffi::String 
process_pool_creator,
+                                                      ffi::String entrypoint);
 
   explicit Session(ffi::UnsafeInit tag, ffi::ObjectPtr<SessionObj> n) : 
ffi::ObjectRef(tag) {
     data_ = std::move(n);
diff --git a/include/tvm/runtime/tensor.h b/include/tvm/runtime/tensor.h
index 518f296317..dea5a1361a 100644
--- a/include/tvm/runtime/tensor.h
+++ b/include/tvm/runtime/tensor.h
@@ -246,7 +246,7 @@ class TensorMemoryPool : public ffi::Object {
     auto it = memory_pool_.find(size);
     if (it != memory_pool_.end()) {
       auto& pool = it->second;
-      bool addressable = 
DeviceAPI::Get(device)->SupportsDevicePointerArithmeticsOnHost();
+      bool addressable = 
DeviceAPI::Get(device)->SupportsDevicePtrArithmeticOnHost();
       auto candidate = std::find_if(pool.begin(), pool.end(), [&](const 
ffi::Tensor& tensor) {
         return tensor.device().device_type == device.device_type &&
                tensor.device().device_id == device.device_id &&
diff --git a/include/tvm/script/ir_builder/base.h 
b/include/tvm/script/ir_builder/base.h
index e3bfd29d89..7add479039 100644
--- a/include/tvm/script/ir_builder/base.h
+++ b/include/tvm/script/ir_builder/base.h
@@ -40,7 +40,7 @@ namespace ir_builder {
  * Frames capture construction context and nested scopes. Language variant 
builders define
  * concrete frame subclasses and decide how their contents contribute to the 
result.
  */
-class IRBuilderFrameObj : public ffi::Object {
+class TVM_TIRX_DLL IRBuilderFrameObj : public ffi::Object {
  public:
   /*! \brief Capture the source-call context when this frame is constructed. */
   IRBuilderFrameObj();
@@ -176,13 +176,13 @@ class IRBuilderObj : public ffi::Object {
   template <typename TObjectRef>
   inline TObjectRef Get() const;
   /*! \brief Push a frontend source location for IR constructed in the nested 
scope. */
-  void PushLoc(Location loc);
+  TVM_TIRX_DLL void PushLoc(Location loc);
   /*! \brief Pop the innermost frontend source location. */
-  void PopLoc();
+  TVM_TIRX_DLL void PopLoc();
   /*! \brief Normalize the full active source stack with an optional explicit 
location. */
-  Location ResolveLoc(Location location = UnknownLoc()) const;
+  TVM_TIRX_DLL Location ResolveLoc(Location location = UnknownLoc()) const;
   /*! \brief Compose active and explicit source context onto the same 
supported node or frame. */
-  ffi::ObjectRef AttachLoc(ffi::ObjectRef obj, Location loc = UnknownLoc()) 
const;
+  TVM_TIRX_DLL ffi::ObjectRef AttachLoc(ffi::ObjectRef obj, Location loc = 
UnknownLoc()) const;
 };
 
 /*!
@@ -192,7 +192,7 @@ class IRBuilderObj : public ffi::Object {
 class IRBuilder : public ffi::ObjectRef {
  public:
   /*! \brief Creates an IRBuilder. */
-  IRBuilder();
+  TVM_TIRX_DLL IRBuilder();
   TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(IRBuilder, ffi::ObjectRef, 
IRBuilderObj);
 
  public:
@@ -213,14 +213,14 @@ class IRBuilder : public ffi::ObjectRef {
    * \sa IRBuilder::ExitWithScope
    * \sa tvm::support::With
    */
-  void EnterWithScope();
+  TVM_TIRX_DLL void EnterWithScope();
   /*!
    * \brief Exit the RAII scope.
    * \sa IRBuilder::EnterWithScope
    * \sa IRBuilder::Current
    * \sa tvm::support::With
    */
-  void ExitWithScope();
+  TVM_TIRX_DLL void ExitWithScope();
   /*!
    * \brief Get the current IRBuilder in the current thread-local scope.
    * \return The current IRBuilder.
@@ -228,9 +228,9 @@ class IRBuilder : public ffi::ObjectRef {
    * \sa IRBuilder::ExitWithScope
    * \sa tvm::support::With
    */
-  static IRBuilder Current();
+  TVM_TIRX_DLL static IRBuilder Current();
   /*! \brief See if the current thread-local scope has an IRBuilder. */
-  static bool IsInScope();
+  TVM_TIRX_DLL static bool IsInScope();
   /*!
    * \brief Give a string name to the `obj`
    * \tparam TObjectRef The type of the object to name.
@@ -249,14 +249,14 @@ namespace details {
 class LocationAccessor {
  public:
   using FType = ObjectFunctor<Location*(const ffi::ObjectRef&)>;
-  static FType& vtable();
+  TVM_TIRX_DLL static FType& vtable();
 };
 
 class Namer {
  public:
   using FType = ObjectFunctor<void(const ffi::ObjectRef&, ffi::String)>;
-  static FType& vtable();
-  static void Name(ffi::ObjectRef node, ffi::String name);
+  TVM_TIRX_DLL static FType& vtable();
+  TVM_TIRX_DLL static void Name(ffi::ObjectRef node, ffi::String name);
 };
 
 }  // namespace details
diff --git a/include/tvm/sym/bound.h b/include/tvm/sym/bound.h
index 2c880a7152..e8deed0652 100644
--- a/include/tvm/sym/bound.h
+++ b/include/tvm/sym/bound.h
@@ -59,9 +59,9 @@ IntSet DeduceBound(PrimExpr v, PrimExpr cond, const 
ffi::Map<Var, IntSet>& hint_
  *        The deduce bound mush implies e for all value in relax_map
  * \return An integer set that always satisfies the condition.
  */
-IntSet DeduceBound(PrimExpr v, PrimExpr cond,
-                   const std::unordered_map<const VarNode*, IntSet>& hint_map,
-                   const std::unordered_map<const VarNode*, IntSet>& 
relax_map);
+TVM_TIRX_DLL IntSet DeduceBound(PrimExpr v, PrimExpr cond,
+                                const std::unordered_map<const VarNode*, 
IntSet>& hint_map,
+                                const std::unordered_map<const VarNode*, 
IntSet>& relax_map);
 
 }  // namespace sym
 }  // namespace tvm
diff --git a/include/tvm/sym/int_set.h b/include/tvm/sym/int_set.h
index 10132b4f9c..8758796b33 100644
--- a/include/tvm/sym/int_set.h
+++ b/include/tvm/sym/int_set.h
@@ -67,19 +67,19 @@ class IntSet : public ffi::ObjectRef {
    * \param max_range The range to be covered.
    * \return The covering range.
    */
-  ffi::Optional<Range> CoverRange(ffi::Optional<Range> max_range) const;
+  TVM_TIRX_DLL ffi::Optional<Range> CoverRange(ffi::Optional<Range> max_range) 
const;
   /*! \return Lower bound of the set */
-  PrimExpr min() const;
+  TVM_TIRX_DLL PrimExpr min() const;
   /*! \return upper bound of the set */
-  PrimExpr max() const;
+  TVM_TIRX_DLL PrimExpr max() const;
   /*! \return The sign of the elements in the integer set */
-  SignType GetSignType() const;
+  TVM_TIRX_DLL SignType GetSignType() const;
   /*! \return Whether the set represent nothing  */
-  bool IsNothing() const;
+  TVM_TIRX_DLL bool IsNothing() const;
   /*! \return Whether the set represent everything  */
-  bool IsEverything() const;
+  TVM_TIRX_DLL bool IsEverything() const;
   /*! \return Whether the set is a single point */
-  bool IsSinglePoint() const;
+  TVM_TIRX_DLL bool IsSinglePoint() const;
   /*!
    * \brief Check if we can prove it is a single point.
    *
@@ -93,70 +93,70 @@ class IntSet : public ffi::ObjectRef {
    * \param ana Analyzer used in the proof.
    * \return Whether we can prove it is a single point
    */
-  bool CanProveSinglePoint(const Analyzer& ana) const;
+  TVM_TIRX_DLL bool CanProveSinglePoint(const Analyzer& ana) const;
   // TODO(tvm-team): update all CanProve to explicitly take
   // analyzer to encourage more analyzer reuse
   /*! \return Whether the set is proved to be bigger than 0 */
-  bool CanProvePositive() const;
+  TVM_TIRX_DLL bool CanProvePositive() const;
   /*! \return Whether the set is proved to be smaller than 0 */
-  bool CanProveNegative() const;
+  TVM_TIRX_DLL bool CanProveNegative() const;
   /*! \return Whether the set is proved to be smaller than or equal to 0 */
-  bool CanProveNonPositive() const;
+  TVM_TIRX_DLL bool CanProveNonPositive() const;
   /*! \return Whether the set is proved to be larger than or equal to 0 */
-  bool CanProveNonNegative() const;
+  TVM_TIRX_DLL bool CanProveNonNegative() const;
   /*! \return Whether the set has upper bound. */
-  bool HasUpperBound() const;
+  TVM_TIRX_DLL bool HasUpperBound() const;
   /*! \return Whether the set has lower bound. */
-  bool HasLowerBound() const;
+  TVM_TIRX_DLL bool HasLowerBound() const;
 
   /*!
    * \brief The single point value, call only if IsSinglePoint is true
    * \return The point value.
    */
-  PrimExpr PointValue() const;
+  TVM_TIRX_DLL PrimExpr PointValue() const;
   /*!
    * \brief Try to match IntSet with range r.
    *
    * \note It is guanrateed that IntSet::FromRange(r).MatchRange(r) == true
    * \return true if we can prove they are the same.
    */
-  bool MatchRange(const tvm::Range& r) const;
+  TVM_TIRX_DLL bool MatchRange(const tvm::Range& r) const;
   /*! \return The set contains nothing */
-  static IntSet Nothing();
+  TVM_TIRX_DLL static IntSet Nothing();
   /*! \return The set contains everything */
-  static IntSet Everything();
+  TVM_TIRX_DLL static IntSet Everything();
   /*!
    * \brief construct a point set.
    * \param point The point in the set.
    * \return construct a single point set
    */
-  static IntSet SinglePoint(PrimExpr point);
+  TVM_TIRX_DLL static IntSet SinglePoint(PrimExpr point);
   /*!
    * \brief construct a integer set from vector expression.
    * \param vec The vector expression, can also be single point.
    * \return The result set containing the indices in the vector.
    */
-  static IntSet Vector(PrimExpr vec);
+  TVM_TIRX_DLL static IntSet Vector(PrimExpr vec);
   /*!
    * \brief Construct a set representing a range [min, min + extent).
    * \param min The minimum of the range range
    * \param extent The extent of the range.
    * \return The constructed set.
    */
-  static IntSet FromMinExtent(PrimExpr min, PrimExpr extent);
+  TVM_TIRX_DLL static IntSet FromMinExtent(PrimExpr min, PrimExpr extent);
   /*!
    * \brief Construct a set representing a range.
    * \param r The range
    * \return The constructed set.
    */
-  static IntSet FromRange(tvm::Range r);
+  TVM_TIRX_DLL static IntSet FromRange(tvm::Range r);
   /*!
    * \brief Construct a set representing a interval.
    * \param min The minimum value of the interval.
    * \param max The maximum value of the interval.
    * \return The constructed set.
    */
-  static IntSet Interval(PrimExpr min, PrimExpr max);
+  TVM_TIRX_DLL static IntSet Interval(PrimExpr min, PrimExpr max);
 
   TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(IntSet, ffi::ObjectRef, 
IntSetObj);
 };
@@ -170,7 +170,8 @@ class IntSet : public ffi::ObjectRef {
  * \param dom_map The domain map to convert.
  * \return The converted map.
  */
-ffi::Map<Var, IntSet> ConvertDomMap(const std::unordered_map<const VarNode*, 
IntSet>& dom_map);
+TVM_TIRX_DLL ffi::Map<Var, IntSet> ConvertDomMap(
+    const std::unordered_map<const VarNode*, IntSet>& dom_map);
 /*!
  * \brief Find an symbolic integer set that contains all possible values of
  *  e given the domain of each variables.
@@ -179,7 +180,7 @@ ffi::Map<Var, IntSet> ConvertDomMap(const 
std::unordered_map<const VarNode*, Int
  * \param dom_map The domain of each variable.
  * \return An integer set that can cover all the possible values of e.
  */
-IntSet EvalSet(PrimExpr e, const ffi::Map<Var, IntSet>& dom_map);
+TVM_TIRX_DLL IntSet EvalSet(PrimExpr e, const ffi::Map<Var, IntSet>& dom_map);
 /*!
  * \brief Same as EvalSet, but takes unordered_map
  *
@@ -187,7 +188,7 @@ IntSet EvalSet(PrimExpr e, const ffi::Map<Var, IntSet>& 
dom_map);
  * \param dom_map The domain of each variable.
  * \return An integer set that can cover all the possible values of e.
  */
-IntSet EvalSet(PrimExpr e, const std::unordered_map<const VarNode*, IntSet>& 
dom_map);
+TVM_TIRX_DLL IntSet EvalSet(PrimExpr e, const std::unordered_map<const 
VarNode*, IntSet>& dom_map);
 
 /*!
  * \brief Find an symbolic integer set that contains is union over
@@ -197,7 +198,7 @@ IntSet EvalSet(PrimExpr e, const std::unordered_map<const 
VarNode*, IntSet>& dom
  * \param dom_map The domain of each variable.
  * \return An integer set that can cover all the possible values.
  */
-IntSet EvalSet(IntSet s, const std::unordered_map<const VarNode*, IntSet>& 
dom_map);
+TVM_TIRX_DLL IntSet EvalSet(IntSet s, const std::unordered_map<const VarNode*, 
IntSet>& dom_map);
 /*!
  * \brief Same as EvalSet, but takes unordered_map
  *
@@ -205,7 +206,7 @@ IntSet EvalSet(IntSet s, const std::unordered_map<const 
VarNode*, IntSet>& dom_m
  * \param dom_map The domain of each variable.
  * \return An integer set that can cover all the possible values of e.
  */
-IntSet EvalSet(Range r, const std::unordered_map<const VarNode*, IntSet>& 
dom_map);
+TVM_TIRX_DLL IntSet EvalSet(Range r, const std::unordered_map<const VarNode*, 
IntSet>& dom_map);
 /*!
  * \brief Same as EvalSet, but takes ffi::Array<Range>
  *
@@ -213,7 +214,8 @@ IntSet EvalSet(Range r, const std::unordered_map<const 
VarNode*, IntSet>& dom_ma
  * \param dom_map The domain of each variable.
  * \return An array of integer sets that can cover all the possible values.
  */
-ffi::Array<IntSet> EvalSet(const ffi::Array<Range>& region, const 
ffi::Map<Var, IntSet>& dom_map);
+TVM_TIRX_DLL ffi::Array<IntSet> EvalSet(const ffi::Array<Range>& region,
+                                        const ffi::Map<Var, IntSet>& dom_map);
 /*! \brief Map from Expr to IntSet */
 using ExprIntSetMap = std::unordered_map<PrimExpr, IntSet, ffi::ObjectPtrHash, 
ffi::ObjectPtrEqual>;
 /*!
@@ -224,43 +226,44 @@ using ExprIntSetMap = std::unordered_map<PrimExpr, 
IntSet, ffi::ObjectPtrHash, f
  * \param dom_map The domain of each variable.
  * \return the map from the expression to its possible value.
  */
-ExprIntSetMap EvalSetForEachSubExpr(PrimExpr e,
-                                    const std::unordered_map<const VarNode*, 
IntSet>& dom_map);
+TVM_TIRX_DLL ExprIntSetMap
+EvalSetForEachSubExpr(PrimExpr e, const std::unordered_map<const VarNode*, 
IntSet>& dom_map);
 
 /*!
  * \brief Create a union set of all sets, possibly relaxed
  * \param sets The sets to be combined
  * \return the set after union
  */
-IntSet Union(const ffi::Array<IntSet>& sets);
+TVM_TIRX_DLL IntSet Union(const ffi::Array<IntSet>& sets);
 
 /*!
  * \brief The union of N-dimensional integer sets
  * \param nd_int_sets A list of N-dimensional integer sets
  * \return An N-dimensional integer set as the result of union
  */
-ffi::Array<IntSet> UnionRegion(const ffi::Array<ffi::Array<IntSet>>& 
nd_int_sets);
+TVM_TIRX_DLL ffi::Array<IntSet> UnionRegion(const 
ffi::Array<ffi::Array<IntSet>>& nd_int_sets);
 
 /*!
  * \brief Create a lower-bound of union set, where some of the segments may be 
dropped
  * \param sets The sets to be combined
  * \return the set after union
  */
-IntSet UnionLowerBound(const ffi::Array<IntSet>& sets);
+TVM_TIRX_DLL IntSet UnionLowerBound(const ffi::Array<IntSet>& sets);
 
 /*!
  * \brief The union of N-dimensional integer sets
  * \param nd_int_sets A list of N-dimensional integer sets
  * \return An N-dimensional integer set as the result of union
  */
-ffi::Array<IntSet> UnionRegionLowerBound(const ffi::Array<ffi::Array<IntSet>>& 
nd_int_sets);
+TVM_TIRX_DLL ffi::Array<IntSet> UnionRegionLowerBound(
+    const ffi::Array<ffi::Array<IntSet>>& nd_int_sets);
 
 /*!
  * \brief Create an intersected set of all sets
  * \param sets The sets to be intersected
  * \return the set after intersected
  */
-IntSet Intersect(const ffi::Array<IntSet>& sets);
+TVM_TIRX_DLL IntSet Intersect(const ffi::Array<IntSet>& sets);
 
 /*!
  * \brief Intersect two integer sets using the analyzer's bindings and 
constraints.
@@ -276,7 +279,7 @@ TVM_TIRX_DLL IntSet Intersect(const IntSet& lhs, const 
IntSet& rhs, const Analyz
  * \param var_dom The ranges of variables
  * \return The integer sets of the variables
  */
-ffi::Map<Var, sym::IntSet> AsIntSet(const ffi::Map<Var, Range>& var_dom);
+TVM_TIRX_DLL ffi::Map<Var, sym::IntSet> AsIntSet(const ffi::Map<Var, Range>& 
var_dom);
 
 /*!
  * \brief Analyze the region with affine map, given the domain of variables 
and their predicate.
diff --git a/include/tvm/sym/iter_affine_map.h 
b/include/tvm/sym/iter_affine_map.h
index 7b2880dc9e..cf6d127494 100644
--- a/include/tvm/sym/iter_affine_map.h
+++ b/include/tvm/sym/iter_affine_map.h
@@ -340,10 +340,11 @@ class IterMapResult : public ffi::ObjectRef {
  * \return The detected iteration result.
  * The return object's .indices is empty on failure.
  */
-IterMapResult DetectIterMap(const ffi::Array<PrimExpr>& indices,
-                            const ffi::Map<PrimVar, Range>& input_iters, const 
PrimExpr& predicate,
-                            IterMapLevel check_level, const sym::Analyzer& 
analyzer,
-                            bool simplify_trivial_iterators = true);
+TVM_TIRX_DLL IterMapResult DetectIterMap(const ffi::Array<PrimExpr>& indices,
+                                         const ffi::Map<PrimVar, Range>& 
input_iters,
+                                         const PrimExpr& predicate, 
IterMapLevel check_level,
+                                         const sym::Analyzer& analyzer,
+                                         bool simplify_trivial_iterators = 
true);
 
 /*!
  * \brief Use IterVarMap detector to rewrite and simplify the indices
@@ -356,11 +357,12 @@ IterMapResult DetectIterMap(const ffi::Array<PrimExpr>& 
indices,
  * \param simplify_trivial_iterators If true, iterators with unit extents are 
simplified
  * \return The indices after rewrite
  */
-ffi::Array<PrimExpr> IterMapSimplify(const ffi::Array<PrimExpr>& indices,
-                                     const ffi::Map<PrimVar, Range>& 
input_iters,
-                                     const PrimExpr& input_pred, IterMapLevel 
check_level,
-                                     const sym::Analyzer& analyzer,
-                                     bool simplify_trivial_iterators = true);
+TVM_TIRX_DLL ffi::Array<PrimExpr> IterMapSimplify(const ffi::Array<PrimExpr>& 
indices,
+                                                  const ffi::Map<PrimVar, 
Range>& input_iters,
+                                                  const PrimExpr& input_pred,
+                                                  IterMapLevel check_level,
+                                                  const sym::Analyzer& 
analyzer,
+                                                  bool 
simplify_trivial_iterators = true);
 
 /*!
  * \brief Apply the inverse of the affine transformation to the outputs.
@@ -382,8 +384,8 @@ ffi::Array<PrimExpr> IterMapSimplify(const 
ffi::Array<PrimExpr>& indices,
  *
  * \return The map from the input to the transformed result.
  */
-ffi::Map<Var, PrimExpr> InverseAffineIterMap(const ffi::Array<IterSumExpr>& 
iter_map,
-                                             const ffi::Array<PrimExpr> 
outputs);
+TVM_TIRX_DLL ffi::Map<Var, PrimExpr> InverseAffineIterMap(const 
ffi::Array<IterSumExpr>& iter_map,
+                                                          const 
ffi::Array<PrimExpr> outputs);
 
 /*!
  * \brief Detect if bindings can be written as
@@ -412,19 +414,17 @@ ffi::Map<Var, PrimExpr> InverseAffineIterMap(const 
ffi::Array<IterSumExpr>& iter
         len(bindings): the predicate of outer space and inner space
         Empty array if no match can be found.
  */
-ffi::Array<ffi::Array<IterMark>> SubspaceDivide(const ffi::Array<PrimExpr>& 
bindings,
-                                                const ffi::Map<PrimVar, 
Range>& input_iters,
-                                                const ffi::Array<PrimVar>& 
sub_iters,
-                                                const PrimExpr& predicate, 
IterMapLevel check_level,
-                                                const sym::Analyzer& analyzer,
-                                                bool 
simplify_trivial_iterators = true);
+TVM_TIRX_DLL ffi::Array<ffi::Array<IterMark>> SubspaceDivide(
+    const ffi::Array<PrimExpr>& bindings, const ffi::Map<PrimVar, Range>& 
input_iters,
+    const ffi::Array<PrimVar>& sub_iters, const PrimExpr& predicate, 
IterMapLevel check_level,
+    const sym::Analyzer& analyzer, bool simplify_trivial_iterators = true);
 
 /*!
  * \brief Given an expression that may contain IterMapExpr, transform it to 
normal PrimExpr.
  * \param expr The input expression, which may contain IterMapExpr.
  * \return The corresponding normal PrimExpr.
  */
-PrimExpr NormalizeIterMapToExpr(const PrimExpr& expr);
+TVM_TIRX_DLL PrimExpr NormalizeIterMapToExpr(const PrimExpr& expr);
 
 /*!
  * \brief Rewrite index as IterSumExpr
@@ -442,8 +442,9 @@ PrimExpr NormalizeIterMapToExpr(const PrimExpr& expr);
  * \param analyzer The input analyzer.
  * \note This function is useful to detect iterator stride patterns.
  */
-IterSumExpr NormalizeToIterSum(PrimExpr index, const ffi::Map<PrimVar, Range>& 
input_iters,
-                               const sym::Analyzer& analyzer);
+TVM_TIRX_DLL IterSumExpr NormalizeToIterSum(PrimExpr index,
+                                            const ffi::Map<PrimVar, Range>& 
input_iters,
+                                            const sym::Analyzer& analyzer);
 
 }  // namespace sym
 }  // namespace tvm
diff --git a/include/tvm/sym/pattern.h b/include/tvm/sym/pattern.h
index fbc4f7f33c..42fc25c8ee 100644
--- a/include/tvm/sym/pattern.h
+++ b/include/tvm/sym/pattern.h
@@ -36,7 +36,8 @@ namespace sym {
  * \param vars List of variables to be used in detection.
  * \return [coeff[i]] if it is possible, empty array if it is not.
  */
-ffi::Array<PrimExpr> DetectLinearEquation(const PrimExpr& e, const 
ffi::Array<PrimVar>& vars);
+TVM_TIRX_DLL ffi::Array<PrimExpr> DetectLinearEquation(const PrimExpr& e,
+                                                       const 
ffi::Array<PrimVar>& vars);
 
 /*!
  * \brief Detect if expression corresponds to clip bound of the vars
diff --git a/include/tvm/tirx/analysis.h b/include/tvm/tirx/analysis.h
index 1f97156b30..d976b3513e 100644
--- a/include/tvm/tirx/analysis.h
+++ b/include/tvm/tirx/analysis.h
@@ -113,7 +113,7 @@ TVM_TIRX_DLL bool VerifyWellFormed(const IRModule& mod, 
bool assert_mode = true)
  * \param result_g_var The result GlobalVar of the entry function.
  * \return The entry function.
  */
-const FunctionNode* FindEntryFunc(const IRModule& mod, GlobalVar* 
result_g_var);
+TVM_TIRX_DLL const FunctionNode* FindEntryFunc(const IRModule& mod, GlobalVar* 
result_g_var);
 
 // Pass variants of verification analysis
 // directly throws RuntimeError when verification fails.
diff --git a/include/tvm/tirx/function.h b/include/tvm/tirx/function.h
index c9e9a9e7b9..32202efa90 100644
--- a/include/tvm/tirx/function.h
+++ b/include/tvm/tirx/function.h
@@ -178,7 +178,8 @@ TVM_TIRX_DLL Function RenewDef(Function func);
  *              B[vi, vj] = A[vi, vj]
  * \endcode
  */
-Function Specialize(Function func, const ffi::Map<Var, ffi::Variant<TensorVar, 
Expr>>& param_map);
+TVM_TIRX_DLL Function Specialize(Function func,
+                                 const ffi::Map<Var, ffi::Variant<TensorVar, 
Expr>>& param_map);
 
 /*!
  * \brief Function specific attribute names.
diff --git a/include/tvm/tirx/index_map.h b/include/tvm/tirx/index_map.h
index fa4bf02f1d..8f0e45f6f2 100644
--- a/include/tvm/tirx/index_map.h
+++ b/include/tvm/tirx/index_map.h
@@ -107,8 +107,8 @@ class IndexMapNode : public ffi::Object {
    * \returns The indices in the output space.  Contains one value for
    * each expression in `final_indices`.
    */
-  ffi::Array<PrimExpr> MapIndices(const ffi::Array<PrimExpr>& indices,
-                                  const sym::Analyzer& analyzer) const;
+  TVM_TIRX_DLL ffi::Array<PrimExpr> MapIndices(const ffi::Array<PrimExpr>& 
indices,
+                                               const sym::Analyzer& analyzer) 
const;
 
   /*! \brief Map a memory range to the output space using a fresh analyzer.
    *
@@ -154,8 +154,8 @@ class IndexMapNode : public ffi::Object {
    * \returns The tensor shape in the output space.  Contains one
    * value for each expression in `final_indices`.
    */
-  ffi::Array<PrimExpr> MapShape(const ffi::Array<PrimExpr>& shape,
-                                const sym::Analyzer& analyzer) const;
+  TVM_TIRX_DLL ffi::Array<PrimExpr> MapShape(const ffi::Array<PrimExpr>& shape,
+                                             const sym::Analyzer& analyzer) 
const;
 
   /* \brief Map an Tensor according to this index map
    *
@@ -170,7 +170,7 @@ class IndexMapNode : public ffi::Object {
    * \param f_name_map Optional function to specify the stringified name of 
the variables.
    * \return The stringified lambda expression in Python.
    */
-  ffi::String ToPythonString(
+  TVM_TIRX_DLL ffi::String ToPythonString(
       const std::function<ffi::Optional<ffi::String>(const Var& var)>& 
f_name_map = nullptr) const;
 
   static void RegisterReflection() {
@@ -195,8 +195,8 @@ class IndexMap : public ffi::ObjectRef {
    * \param final_indices Expressions defining the indices after remapping.
    * \param inverse_index_map The optional pre-defined inverse index map
    */
-  IndexMap(ffi::Array<PrimVar> initial_indices, ffi::Array<PrimExpr> 
final_indices,
-           ffi::Optional<IndexMap> inverse_index_map = std::nullopt);
+  TVM_TIRX_DLL IndexMap(ffi::Array<PrimVar> initial_indices, 
ffi::Array<PrimExpr> final_indices,
+                        ffi::Optional<IndexMap> inverse_index_map = 
std::nullopt);
 
   /*!
    * \brief Create an index map from a packed function
@@ -205,8 +205,9 @@ class IndexMap : public ffi::ObjectRef {
    * \param inverse_index_map The optional pre-defined inverse index map
    * \return The created index map
    */
-  static IndexMap FromFunc(int ndim, 
ffi::TypedFunction<ffi::Array<PrimExpr>(ffi::Array<Var>)> func,
-                           ffi::Optional<IndexMap> inverse_index_map = 
std::nullopt);
+  TVM_TIRX_DLL static IndexMap FromFunc(
+      int ndim, ffi::TypedFunction<ffi::Array<PrimExpr>(ffi::Array<Var>)> func,
+      ffi::Optional<IndexMap> inverse_index_map = std::nullopt);
 
   /*! \brief Generate the inverse mapping using a fresh analyzer.
    *
@@ -229,7 +230,8 @@ class IndexMap : public ffi::ObjectRef {
    * \param analyzer An analyzer to be used while deriving and validating
    * the inverse.
    */
-  IndexMap Inverse(ffi::Array<Range> initial_ranges, const sym::Analyzer& 
analyzer) const;
+  TVM_TIRX_DLL IndexMap Inverse(ffi::Array<Range> initial_ranges,
+                                const sym::Analyzer& analyzer) const;
 
   /*! \brief Rename the variables in the index map and ensure the names are 
unique.
    *
@@ -239,7 +241,7 @@ class IndexMap : public ffi::ObjectRef {
    * \param f_name_map The optional name map to rename the variables.
    * \return The renamed index map.
    */
-  IndexMap RenameVariables(
+  TVM_TIRX_DLL IndexMap RenameVariables(
       const std::function<ffi::Optional<ffi::String>(const Var& var)>& 
f_name_map = nullptr) const;
 
   /*! \brief Generate the inverse mapping using a fresh analyzer.
@@ -265,8 +267,8 @@ class IndexMap : public ffi::ObjectRef {
    * \return The inverted index map, along with the predicate for
    * which the inverse maps to a valid range.
    */
-  std::pair<IndexMap, PrimExpr> NonSurjectiveInverse(ffi::Array<Range> 
initial_ranges,
-                                                     const sym::Analyzer& 
analyzer) const;
+  TVM_TIRX_DLL std::pair<IndexMap, PrimExpr> NonSurjectiveInverse(
+      ffi::Array<Range> initial_ranges, const sym::Analyzer& analyzer) const;
 
   TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(IndexMap, ffi::ObjectRef, 
IndexMapNode);
 };
diff --git a/include/tvm/tirx/layout.h b/include/tvm/tirx/layout.h
index d28e6ee338..ea8bb5bd7f 100644
--- a/include/tvm/tirx/layout.h
+++ b/include/tvm/tirx/layout.h
@@ -201,7 +201,7 @@ class TileLayoutNode : public LayoutNode {
   ffi::Optional<Tuple<ExecScope, ExecScope>> GetScope() const;
 
   /*! \brief Get the default layout for the shape */
-  static TileLayout DefaultLayout(ffi::Array<PrimExpr> shape);
+  TVM_TIRX_DLL static TileLayout DefaultLayout(ffi::Array<PrimExpr> shape);
 
   TVM_FFI_DECLARE_OBJECT_INFO_FINAL("tirx.TileLayout", TileLayoutNode, 
LayoutNode);
 };
diff --git a/include/tvm/tirx/script/ir_builder/frame.h 
b/include/tvm/tirx/script/ir_builder/frame.h
index 3c4e9069e1..c8c9c0d901 100644
--- a/include/tvm/tirx/script/ir_builder/frame.h
+++ b/include/tvm/tirx/script/ir_builder/frame.h
@@ -54,7 +54,7 @@ using ir::WhileFrameObj;
  *
  * \sa FunctionFrame
  */
-class FunctionFrameObj : public ir::StmtFrameObj {
+class TVM_TIRX_DLL FunctionFrameObj : public ir::StmtFrameObj {
  public:
   /*! \brief The name of the block. */
   ffi::Optional<ffi::String> name;
diff --git a/include/tvm/tirx/type.h b/include/tvm/tirx/type.h
index 7fc164e82f..57e6fc8515 100644
--- a/include/tvm/tirx/type.h
+++ b/include/tvm/tirx/type.h
@@ -128,7 +128,8 @@ class TensorTypeNode : public TypeNode {
    * \param index The index to be accessed.
    * \param inner Ignore the elem_offset, return inner offset only
    */
-  ffi::Array<PrimExpr> ElemOffset(ffi::Array<PrimExpr> index, bool inner = 
false) const;
+  TVM_TIRX_DLL ffi::Array<PrimExpr> ElemOffset(ffi::Array<PrimExpr> index,
+                                               bool inner = false) const;
 
   TVM_FFI_DECLARE_OBJECT_INFO_FINAL("tirx.TensorType", TensorTypeNode, 
TypeNode);
 };
diff --git a/python/tvm/base.py b/python/tvm/base.py
index e850f9c214..ca65863d5b 100644
--- a/python/tvm/base.py
+++ b/python/tvm/base.py
@@ -20,6 +20,7 @@
 
 import os
 
+from tvm_ffi import libinfo as tvm_ffi_libinfo
 from tvm_ffi.libinfo import load_lib_ctypes
 
 from . import libinfo
@@ -46,14 +47,16 @@ _LOADED_LIBS["tvm_runtime"] = load_lib_ctypes(
 )
 
 if not _RUNTIME_ONLY:
+    _lib_paths = libinfo.package_lib_paths()
     try:
+        tvm_ffi_libinfo._find_library_by_basename("tvm", "tvm_compiler", 
extra_lib_paths=_lib_paths)
+    except RuntimeError:
+        # A runtime-only installation need not contain the compiler library.
+        _RUNTIME_ONLY = True
+    else:
         _LOADED_LIBS["tvm_compiler"] = load_lib_ctypes(
-            "tvm", "tvm_compiler", "RTLD_LOCAL", 
extra_lib_paths=libinfo.package_lib_paths()
+            "tvm", "tvm_compiler", "RTLD_LOCAL", extra_lib_paths=_lib_paths
         )
-    except (RuntimeError, OSError):
-        # Compiler lib not present, or present but unloadable (missing LLVM
-        # deps / linker issues) — fall back to runtime-only mode.
-        _RUNTIME_ONLY = True
 
 if _RUNTIME_ONLY:
     from tvm_ffi import registry as _tvm_ffi_registry
diff --git a/src/backend/cuda/runtime/cuda_device_api.cc 
b/src/backend/cuda/runtime/cuda_device_api.cc
index 06bd168856..36caa14e8c 100644
--- a/src/backend/cuda/runtime/cuda_device_api.cc
+++ b/src/backend/cuda/runtime/cuda_device_api.cc
@@ -302,7 +302,7 @@ class CUDADeviceAPI final : public DeviceAPI {
     ThreadLocalWorkspacePool(dev.device_type)->FreeWorkspace(dev, data);
   }
 
-  bool SupportsDevicePointerArithmeticsOnHost() final { return true; }
+  bool SupportsDevicePtrArithmeticOnHost() final { return true; }
 
   static CUDADeviceAPI* Global() {
     // NOTE: explicitly use new to avoid exit-time destruction of global state
diff --git a/src/backend/opencl/runtime/opencl_common.h 
b/src/backend/opencl/runtime/opencl_common.h
index 0b2ac9494d..b89fb1ab3b 100644
--- a/src/backend/opencl/runtime/opencl_common.h
+++ b/src/backend/opencl/runtime/opencl_common.h
@@ -272,8 +272,9 @@ class OpenCLWorkspace : public DeviceAPI {
     }
   }
   // Initialize the device.
-  void Init(const std::string& type_key, const std::string& device_type,
-            const std::string& platform_name = "", cl_context_properties 
properties[] = nullptr);
+  TVM_OPENCL_DLL void Init(const std::string& type_key, const std::string& 
device_type,
+                           const std::string& platform_name = "",
+                           cl_context_properties properties[] = nullptr);
   virtual void Init() { Init(this->type_key, "gpu"); }
   virtual bool Init(cl_context_properties ctx_props[]) {
     if (!contexts.empty()) return false;
@@ -348,7 +349,7 @@ class OpenCLWorkspace : public DeviceAPI {
   void* AllocDataSpaceView(Device dev, void* data, ffi::Shape shape, 
DLDataType dtype,
                            ffi::Optional<runtime::MemoryScope> mem_scope = 
std::nullopt);
   void FreeDataSpaceView(Device dev, void* ptr);
-  cl_device_id GetCLDeviceID(int device_id);
+  TVM_OPENCL_DLL cl_device_id GetCLDeviceID(int device_id);
   // override device API
   void SetDevice(Device dev) final;
   ffi::Any GetAttr(Device dev, const ffi::String& name) final;
@@ -360,7 +361,7 @@ class OpenCLWorkspace : public DeviceAPI {
   void* AllocDataSpace(Device dev, size_t width, size_t height, size_t depth, 
DLDataType type_hint,
                        ffi::Optional<runtime::MemoryScope> mem_scope = 
std::nullopt,
                        TensorMemoryPool* pool = nullptr);
-  void* GetNativePtr(const tvm::ffi::Tensor& narr);
+  void* GetMappedHostPtrIfAvailable(void* data) final;
   void SetNativePtr(const tvm::ffi::Tensor& narr, void* host_ptr, size_t 
buf_size);
   void SetPerfHint(Device dev, cl_uint perf_hint);
   void FreeDataSpace(Device dev, void* ptr);
@@ -381,7 +382,7 @@ class OpenCLWorkspace : public DeviceAPI {
   virtual OpenCLThreadEntry* GetThreadEntry();
 
   // get the global workspace
-  static OpenCLWorkspace* Global();
+  TVM_OPENCL_DLL static OpenCLWorkspace* Global();
 
   void CopyDataFromTo(DLTensor* from, DLTensor* to, TVMStreamHandle stream) 
final;
 
diff --git a/src/backend/opencl/runtime/opencl_device_api.cc 
b/src/backend/opencl/runtime/opencl_device_api.cc
index c503a6d412..9d48a9bcdf 100644
--- a/src/backend/opencl/runtime/opencl_device_api.cc
+++ b/src/backend/opencl/runtime/opencl_device_api.cc
@@ -528,10 +528,16 @@ void OpenCLWorkspace::FreeDataSpaceView(Device dev, void* 
ptr) {
   }
 }
 
-void* OpenCLWorkspace::GetNativePtr(const tvm::ffi::Tensor& narr) {
-  TVM_FFI_ICHECK(narr.defined());
-  cl::BufferDescriptor* desc = 
static_cast<cl::BufferDescriptor*>(narr.GetDLTensorPtr()->data);
-  return desc->host_ptr;
+void* OpenCLWorkspace::GetMappedHostPtrIfAvailable(void* data) {
+#if defined(OPENCL_ENABLE_HOST_PTR)
+  if (data != nullptr) {
+    const auto* desc = static_cast<const cl::BufferDescriptor*>(data);
+    if (desc->layout == cl::BufferDescriptor::MemoryLayout::kBuffer1D) {
+      return desc->host_ptr;
+    }
+  }
+#endif
+  return nullptr;
 }
 
 void OpenCLWorkspace::SetNativePtr(const tvm::ffi::Tensor& narr, void* 
host_ptr, size_t buf_size) {
diff --git a/src/relax/backend/adreno/fold_vdevice_scope_change.cc 
b/src/relax/backend/adreno/fold_vdevice_scope_change.cc
index c86030e668..db147afa9a 100644
--- a/src/relax/backend/adreno/fold_vdevice_scope_change.cc
+++ b/src/relax/backend/adreno/fold_vdevice_scope_change.cc
@@ -34,7 +34,7 @@
 
 #include <tuple>
 
-#include "../../../texture_utils.h"
+#include "../../../s_tir/backend/adreno/texture_utils.h"
 #include "../../op/tensor/manipulate.h"
 #include "../../transform/infer_layout_utils.h"
 #include "../../transform/utils.h"
diff --git a/src/relax/transform/static_plan_block_memory.cc 
b/src/relax/transform/static_plan_block_memory.cc
index 5a2273b4a0..3705d9bf31 100644
--- a/src/relax/transform/static_plan_block_memory.cc
+++ b/src/relax/transform/static_plan_block_memory.cc
@@ -80,7 +80,7 @@
 #include <set>
 #include <vector>
 
-#include "../../texture_utils.h"
+#include "../../s_tir/backend/adreno/texture_utils.h"
 #include "utils.h"
 
 namespace tvm {
diff --git a/src/runtime/cpu_device_api.cc b/src/runtime/cpu_device_api.cc
index 9bccb53398..f22a0ea5aa 100644
--- a/src/runtime/cpu_device_api.cc
+++ b/src/runtime/cpu_device_api.cc
@@ -135,7 +135,7 @@ class CPUDeviceAPI final : public DeviceAPI {
   void* AllocWorkspace(Device dev, size_t size, DLDataType type_hint) final;
   void FreeWorkspace(Device dev, void* data) final;
 
-  bool SupportsDevicePointerArithmeticsOnHost() final { return true; }
+  bool SupportsDevicePtrArithmeticOnHost() final { return true; }
 
   static CPUDeviceAPI* Global() {
     // NOTE: explicitly use new to avoid exit-time destruction of global state
diff --git a/src/runtime/extra/contrib/clml/clml_runtime.h 
b/src/runtime/extra/contrib/clml/clml_runtime.h
index 1bb9962cf0..df0b19b276 100644
--- a/src/runtime/extra/contrib/clml/clml_runtime.h
+++ b/src/runtime/extra/contrib/clml/clml_runtime.h
@@ -44,13 +44,14 @@
 #include <utility>
 #include <vector>
 
-#include "../../../../backend/opencl/runtime/opencl_common.h"
 #include "../json/json_node.h"
 #include "../json/json_runtime.h"
 
 #ifdef TVM_GRAPH_EXECUTOR_CLML
 #include <CL/cl_qcom_ml_ops.h>
 
+#include "../../../../backend/opencl/runtime/opencl_common.h"
+
 #define CAT_I(a, b) a##b
 #define CAT(a, b) CAT_I(a, b)
 
diff --git a/src/runtime/extra/contrib/dnnl/dnnl_kernel.h 
b/src/runtime/extra/contrib/dnnl/dnnl_kernel.h
index b7a0ec0f73..edac82b51f 100644
--- a/src/runtime/extra/contrib/dnnl/dnnl_kernel.h
+++ b/src/runtime/extra/contrib/dnnl/dnnl_kernel.h
@@ -39,36 +39,36 @@ namespace contrib {
 
 using namespace dnnl;
 
-extern "C" TVM_RUNTIME_DLL void dnnl_conv2d(float* data, float* weights, 
float* out, int p_N_,
-                                            int p_C_, int p_H_, int p_W_, int 
p_O_, int p_G_,
-                                            int p_Ph0_, int p_Pw0_, int 
p_Ph1_, int p_Pw1_,
-                                            int p_Kh_, int p_Kw_, int p_Sh_, 
int p_Sw_);
+extern "C" TVM_RUNTIME_EXTRA_DLL void dnnl_conv2d(float* data, float* weights, 
float* out, int p_N_,
+                                                  int p_C_, int p_H_, int 
p_W_, int p_O_, int p_G_,
+                                                  int p_Ph0_, int p_Pw0_, int 
p_Ph1_, int p_Pw1_,
+                                                  int p_Kh_, int p_Kw_, int 
p_Sh_, int p_Sw_);
 
-extern "C" TVM_RUNTIME_DLL void dnnl_fused_conv2d_relu(float* data, float* 
weights, float* out,
-                                                       int p_N_, int p_C_, int 
p_H_, int p_W_,
-                                                       int p_O_, int p_G_, int 
p_Ph0_, int p_Pw0_,
-                                                       int p_Ph1_, int p_Pw1_, 
int p_Kh_, int p_Kw_,
-                                                       int p_Sh_, int p_Sw_);
+extern "C" TVM_RUNTIME_EXTRA_DLL void dnnl_fused_conv2d_relu(float* data, 
float* weights,
+                                                             float* out, int 
p_N_, int p_C_,
+                                                             int p_H_, int 
p_W_, int p_O_, int p_G_,
+                                                             int p_Ph0_, int 
p_Pw0_, int p_Ph1_,
+                                                             int p_Pw1_, int 
p_Kh_, int p_Kw_,
+                                                             int p_Sh_, int 
p_Sw_);
 
-extern "C" TVM_RUNTIME_DLL void dnnl_fused_conv2d_bias_relu(float* data, 
float* weights,
-                                                            float* bias, 
float* out, int p_N_,
-                                                            int p_C_, int 
p_H_, int p_W_, int p_O_,
-                                                            int p_G_, int 
p_Ph0_, int p_Pw0_,
-                                                            int p_Ph1_, int 
p_Pw1_, int p_Kh_,
-                                                            int p_Kw_, int 
p_Sh_, int p_Sw_);
+extern "C" TVM_RUNTIME_EXTRA_DLL void dnnl_fused_conv2d_bias_relu(
+    float* data, float* weights, float* bias, float* out, int p_N_, int p_C_, 
int p_H_, int p_W_,
+    int p_O_, int p_G_, int p_Ph0_, int p_Pw0_, int p_Ph1_, int p_Pw1_, int 
p_Kh_, int p_Kw_,
+    int p_Sh_, int p_Sw_);
 
-extern "C" TVM_RUNTIME_DLL void dnnl_dense(float* data, float* weight, float* 
out, int p_B_,
-                                           int p_I_, int p_O_);
+extern "C" TVM_RUNTIME_EXTRA_DLL void dnnl_dense(float* data, float* weight, 
float* out, int p_B_,
+                                                 int p_I_, int p_O_);
 
-extern "C" TVM_RUNTIME_DLL void dnnl_relu(float* data, float* out, 
std::vector<int64_t> shape);
+extern "C" TVM_RUNTIME_EXTRA_DLL void dnnl_relu(float* data, float* out,
+                                                std::vector<int64_t> shape);
 
-extern "C" TVM_RUNTIME_DLL void dnnl_bn(float* data, float* gamma, float* 
beta, float* mean,
-                                        float* variance, float* out, float* 
new_mean,
-                                        float* new_variance, int p_n_, int 
p_c_, int p_h_, int p_w_,
-                                        int p_e_);
+extern "C" TVM_RUNTIME_EXTRA_DLL void dnnl_bn(float* data, float* gamma, 
float* beta, float* mean,
+                                              float* variance, float* out, 
float* new_mean,
+                                              float* new_variance, int p_n_, 
int p_c_, int p_h_,
+                                              int p_w_, int p_e_);
 
-extern "C" TVM_RUNTIME_DLL void dnnl_binary_op(float* data, float* weight, 
float* out,
-                                               int binary_algo, 
std::vector<int64_t> shape);
+extern "C" TVM_RUNTIME_EXTRA_DLL void dnnl_binary_op(float* data, float* 
weight, float* out,
+                                                     int binary_algo, 
std::vector<int64_t> shape);
 
 }  // namespace contrib
 }  // namespace runtime
diff --git a/src/runtime/extra/disco/builtin.cc 
b/src/runtime/extra/disco/builtin.cc
index 1651441e24..46b968e77d 100644
--- a/src/runtime/extra/disco/builtin.cc
+++ b/src/runtime/extra/disco/builtin.cc
@@ -94,14 +94,14 @@ void AllGather(ffi::Tensor send, bool in_group, ffi::Tensor 
recv) {
   GetCCLFunc("allgather")(send, in_group, recv);
 }
 
-TVM_RUNTIME_DLL void BroadcastFromWorker0(ffi::Tensor send, bool in_group, 
ffi::Tensor recv) {
+TVM_RUNTIME_EXTRA_DLL void BroadcastFromWorker0(ffi::Tensor send, bool 
in_group, ffi::Tensor recv) {
   TVM_FFI_ICHECK(send.defined());
   TVM_FFI_ICHECK(recv.defined());
   GetCCLFunc("broadcast_from_worker0")(send, in_group, recv);
 }
 
-TVM_RUNTIME_DLL void ScatterFromWorker0(ffi::Optional<ffi::Tensor> send, bool 
in_group,
-                                        ffi::Tensor recv) {
+TVM_RUNTIME_EXTRA_DLL void ScatterFromWorker0(ffi::Optional<ffi::Tensor> send, 
bool in_group,
+                                              ffi::Tensor recv) {
   TVM_FFI_ICHECK(recv.defined());
   GetCCLFunc("scatter_from_worker0")(send, in_group, recv);
 }
diff --git a/src/runtime/extra/disco/disco_worker.cc 
b/src/runtime/extra/disco/disco_worker.cc
index 799f577283..5e3a8b6668 100644
--- a/src/runtime/extra/disco/disco_worker.cc
+++ b/src/runtime/extra/disco/disco_worker.cc
@@ -27,7 +27,7 @@
 namespace tvm {
 namespace runtime {
 
-TVM_RUNTIME_DLL DiscoWorker* DiscoWorker::ThreadLocal() {
+TVM_RUNTIME_EXTRA_DLL DiscoWorker* DiscoWorker::ThreadLocal() {
   DiscoWorker* ret = ThreadLocalDiscoWorker::Get()->worker;
   TVM_FFI_CHECK(ret, ValueError) << "The current thread is not a DiscoWorker 
thread";
   return ret;
diff --git a/src/runtime/vm/attn_utils.h b/src/runtime/vm/attn_utils.h
index a3e9223313..899e3d34d7 100644
--- a/src/runtime/vm/attn_utils.h
+++ b/src/runtime/vm/attn_utils.h
@@ -26,19 +26,17 @@
 
 #include <tvm/ffi/container/map.h>
 #include <tvm/ffi/container/shape.h>
+#include <tvm/runtime/device_api.h>
 #include <tvm/runtime/logging.h>
 #include <tvm/runtime/tensor.h>
 #include <tvm/support/cuda/nvtx.h>
 
 #include <algorithm>
+#include <cstring>
 #include <limits>
 #include <utility>
 #include <vector>
 
-#if defined(OPENCL_ENABLE_HOST_PTR)
-#include "../../backend/opencl/runtime/opencl_common.h"
-#endif
-
 namespace tvm {
 namespace runtime {
 namespace vm {
@@ -761,22 +759,6 @@ class PlainPagedKVCacheAuxDataManager : public 
PagedKVCacheAuxDataManager {
       return;
     }
     DLTensor copy_dst = *array.GetDLTensorPtr();
-#if defined(OPENCL_ENABLE_HOST_PTR)
-    tvm::runtime::cl::OpenCLWorkspace* workspace = 
tvm::runtime::cl::OpenCLWorkspace::Global();
-    if (workspace->IsOpenCLDevice(copy_dst.device)) {
-      void* nptr = workspace->GetNativePtr(array);
-      uint64_t copy_size;
-      if (shape.has_value()) {
-        TVM_FFI_ICHECK_EQ(shape.value().size(), 1);
-        copy_size = shape.value()->data[0] * sizeof(int32_t);
-      } else {
-        copy_size = ffi::GetDataSize(*array.GetDLTensorPtr());
-      }
-      memcpy(static_cast<char*>(nptr) + dst_elem_offset * sizeof(int32_t), 
vec_data, copy_size);
-      return;
-    }
-#endif
-
     if (shape.has_value()) {
       TVM_FFI_ICHECK_EQ(shape.value().size(), 1);
       copy_dst.ndim = 1;
@@ -784,7 +766,14 @@ class PlainPagedKVCacheAuxDataManager : public 
PagedKVCacheAuxDataManager {
       // The strides still describe the multi-row view this copies one row of.
       copy_dst.strides = nullptr;
     }
-    copy_dst.byte_offset = dst_elem_offset * sizeof(int32_t);
+    copy_dst.byte_offset += dst_elem_offset * sizeof(int32_t);
+
+    if (void* host_ptr =
+            
DeviceAPI::Get(copy_dst.device)->GetMappedHostPtrIfAvailable(copy_dst.data)) {
+      std::memcpy(static_cast<char*>(host_ptr) + copy_dst.byte_offset, 
vec_data,
+                  ffi::GetDataSize(copy_dst));
+      return;
+    }
 
     DLTensor copy_src;
     copy_src.data = vec_data;
diff --git a/src/runtime/vm/builtin.cc b/src/runtime/vm/builtin.cc
index 39d3db03b0..ec1bd91aa1 100644
--- a/src/runtime/vm/builtin.cc
+++ b/src/runtime/vm/builtin.cc
@@ -774,7 +774,7 @@ TVM_FFI_STATIC_INIT_BLOCK() {
           return data;
         }
         auto* device_api = DeviceAPI::Get(data.device());
-        if (device_api->SupportsDevicePointerArithmeticsOnHost() &&
+        if (device_api->SupportsDevicePtrArithmeticOnHost() &&
             data.byte_offset() % tvm::runtime::kAllocAlignment == 0) {
           DLManagedTensor* dl_tensor = data.ToDLPack();
           dl_tensor->dl_tensor.data =
diff --git a/src/s_tir/backend/adreno/inject_texture_alloc.cc 
b/src/s_tir/backend/adreno/inject_texture_alloc.cc
index 6f5aedc0fa..a09afd3bfe 100644
--- a/src/s_tir/backend/adreno/inject_texture_alloc.cc
+++ b/src/s_tir/backend/adreno/inject_texture_alloc.cc
@@ -33,7 +33,7 @@
 #include <tvm/tirx/op/abi.h>
 #include <tvm/tirx/op/memory.h>
 
-#include "../../../texture_utils.h"
+#include "texture_utils.h"
 
 namespace tvm {
 namespace s_tir {
diff --git a/src/s_tir/backend/adreno/texture_flatten.cc 
b/src/s_tir/backend/adreno/texture_flatten.cc
index ca855c4265..ec774ad78a 100644
--- a/src/s_tir/backend/adreno/texture_flatten.cc
+++ b/src/s_tir/backend/adreno/texture_flatten.cc
@@ -36,7 +36,7 @@
 
 #include <unordered_map>
 
-#include "../../../texture_utils.h"
+#include "texture_utils.h"
 
 namespace tvm {
 namespace s_tir {
diff --git a/src/texture_utils.h b/src/s_tir/backend/adreno/texture_utils.h
similarity index 95%
rename from src/texture_utils.h
rename to src/s_tir/backend/adreno/texture_utils.h
index cbe256a824..64ba9acea2 100644
--- a/src/texture_utils.h
+++ b/src/s_tir/backend/adreno/texture_utils.h
@@ -18,11 +18,11 @@
  */
 
 /*!
- * \file texture_utils.h
+ * \file src/s_tir/backend/adreno/texture_utils.h
  * \brief Texture utilities
  */
-#ifndef TVM_TEXTURE_UTILS_H_
-#define TVM_TEXTURE_UTILS_H_
+#ifndef TVM_S_TIR_BACKEND_ADRENO_TEXTURE_UTILS_H_
+#define TVM_S_TIR_BACKEND_ADRENO_TEXTURE_UTILS_H_
 
 #include <tvm/ffi/error.h>
 #include <tvm/ir/prim/op.h>
@@ -129,4 +129,4 @@ size_t GetTextureMemorySize(T shape, int bits, int lanes, 
runtime::MemoryScope m
 
 }  // namespace texture
 }  // namespace tvm
-#endif  // TVM_TEXTURE_UTILS_H_
+#endif  // TVM_S_TIR_BACKEND_ADRENO_TEXTURE_UTILS_H_
diff --git a/src/sym/bound_deducer.cc b/src/sym/bound_deducer.cc
index a7e3a9aa06..6afbeaca1e 100644
--- a/src/sym/bound_deducer.cc
+++ b/src/sym/bound_deducer.cc
@@ -27,6 +27,7 @@
 #include <tvm/ir/expr_functor.h>
 #include <tvm/ir/prim/expr.h>
 #include <tvm/sym/analyzer.h>
+#include <tvm/sym/bound.h>
 
 #include <unordered_map>
 #include <unordered_set>
diff --git a/src/sym/detect_linear_equation.cc 
b/src/sym/detect_linear_equation.cc
index bf7292fc35..2199de96e8 100644
--- a/src/sym/detect_linear_equation.cc
+++ b/src/sym/detect_linear_equation.cc
@@ -28,6 +28,7 @@
 #include <tvm/ir/prim/expr.h>
 #include <tvm/ir/prim/op.h>
 #include <tvm/sym/analyzer.h>
+#include <tvm/sym/pattern.h>
 
 #include <unordered_set>
 
diff --git a/tests/scripts/task_jvm_build.sh b/tests/scripts/task_jvm_build.sh
index a38ea564be..468fea4ec6 100755
--- a/tests/scripts/task_jvm_build.sh
+++ b/tests/scripts/task_jvm_build.sh
@@ -53,6 +53,8 @@ else
 fi
 
 JVM_TEST_ARGS="${JVM_TEST_ARGS:--DskipTests -Dcheckstyle.skip=true}"
+# Native-library assembly needs more heap than some container JVM defaults 
provide.
+export MAVEN_OPTS="${MAVEN_OPTS:--Xmx1g}"
 
 cd "${ROOTDIR}/jvm"
 # shellcheck disable=SC2086

Reply via email to