[compiler-rt] [compiler-rt] Enable ubsan_minimal runtime for SPIR-V (PR #196149)

Victor Mustya via llvm-commits llvm-commits at lists.llvm.org
Wed May 6 11:48:36 PDT 2026


https://github.com/vmustya created https://github.com/llvm/llvm-project/pull/196149

The SPIR-V target support for UBSan Minimal Runtime is added to provide
basic undefined behavior detection capabilities for SPIR-V based devices.

Currently, only the `spirv64` target is supported.

>From 70666190001d15c9d568ab3fac7b23c536b90e7b Mon Sep 17 00:00:00 2001
From: Victor Mustya <victor.mustya at intel.com>
Date: Wed, 6 May 2026 11:41:23 -0700
Subject: [PATCH] [compiler-rt] Enable ubsan_minimal runtime for SPIR-V

The SPIR-V target support for UBSan Minimal Runtime is added to provide
basic undefined behavior detection capabilities for SPIR-V based devices.

Currently, only the `spirv64` target is supported.
---
 compiler-rt/CMakeLists.txt                    |  4 ++--
 .../cmake/Modules/AllSupportedArchDefs.cmake  |  3 ++-
 compiler-rt/cmake/base-config-ix.cmake        |  2 ++
 compiler-rt/cmake/config-ix.cmake             |  2 +-
 .../lib/sanitizer_common/sanitizer_platform.h |  9 +++++++-
 .../ubsan_minimal/ubsan_minimal_handlers.cpp  | 21 ++++++++++++++++++-
 6 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index 6e8045631b218..e88321d822f84 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -370,7 +370,7 @@ if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "hexagon")
   list(APPEND SANITIZER_COMMON_CFLAGS -fno-emulated-tls)
   string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " -fno-emulated-tls")
 endif()
-if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "amdgcn|nvptx")
+if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "amdgcn|nvptx|spirv64")
   append_list_if(UBSAN_COMMON_SUPPORTED_ARCH -ffreestanding SANITIZER_COMMON_CFLAGS)
   append_list_if(COMPILER_RT_HAS_NOGPULIB_FLAG -nogpulib SANITIZER_COMMON_CFLAGS)
   append_list_if(COMPILER_RT_HAS_FLTO_FLAG -flto SANITIZER_COMMON_CFLAGS)
@@ -395,7 +395,7 @@ append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANIT
 if(NOT COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG)
   append_list_if(COMPILER_RT_HAS_FVISIBILITY_INLINES_HIDDEN_FLAG -fvisibility-inlines-hidden SANITIZER_COMMON_CFLAGS)
 endif()
-if(NOT "${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "amdgcn|nvptx")
+if(NOT "${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "amdgcn|nvptx|spirv64")
   append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SANITIZER_COMMON_CFLAGS)
 endif()
 
diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
index 761e26ce3e7d8..0cc4165c8dbd5 100644
--- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
+++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
@@ -15,6 +15,7 @@ set(RISCV64 riscv64)
 set(S390X s390x)
 set(SPARC sparc)
 set(SPARCV9 sparcv9)
+set(SPIRV64 spirv64)
 set(WASM32 wasm32)
 set(WASM64 wasm64)
 set(VE ve)
@@ -105,7 +106,7 @@ endif()
 set(ALL_TYSAN_SUPPORTED_ARCH ${X86_64} ${ARM64} ${S390X} ${HEXAGON})
 set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
     ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
-    ${LOONGARCH64} ${AMDGPU} ${NVPTX})
+    ${LOONGARCH64} ${AMDGPU} ${NVPTX} ${SPIRV64})
 if (OS_NAME MATCHES "FreeBSD")
   set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64})
 else()
diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake
index 4898e3428ebb0..72f7b94f02603 100644
--- a/compiler-rt/cmake/base-config-ix.cmake
+++ b/compiler-rt/cmake/base-config-ix.cmake
@@ -290,6 +290,8 @@ macro(test_targets)
       endif()
     elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "nvptx")
       test_target_arch(nvptx64 "" "--nvptx64-nvidia-cuda" "-nogpulib" "-flto" "-c")
+    elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "spirv64")
+      test_target_arch(spirv64 "" "--spirv64-unknown-unknown" "-nogpulib" "-flto" "-c")
     elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "arm")
       if(WIN32)
         test_target_arch(arm "" "" "")
diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index 9909783d7bb57..ad5497ba81b5b 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -894,7 +894,7 @@ endif()
 
 if (UBSAN_SUPPORTED_ARCH AND
     (OS_NAME MATCHES "Linux|FreeBSD|NetBSD|Android|Darwin|SunOS" OR
-     "${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "amdgcn|nvptx"))
+     "${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "amdgcn|nvptx|spirv64"))
   set(COMPILER_RT_HAS_UBSAN_MINIMAL TRUE)
 else()
   set(COMPILER_RT_HAS_UBSAN_MINIMAL FALSE)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
index a1f3cf799e344..2c70fb7712597 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
@@ -15,7 +15,8 @@
 #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) &&     \
     !(defined(__sun__) && defined(__svr4__)) && !defined(__HAIKU__) &&      \
-    !defined(__wasi__) && !defined(__NVPTX__) && !defined(__AMDGPU__)
+    !defined(__wasi__) && !defined(__NVPTX__) && !defined(__AMDGPU__) &&    \
+    !defined(__SPIRV__)
 #  error "This operating system is not supported"
 #endif
 
@@ -314,6 +315,12 @@
 #  define SANITIZER_NVPTX 0
 #endif
 
+#if defined(__SPIRV__)
+#  define SANITIZER_SPIRV 1
+#else
+#  define SANITIZER_SPIRV 0
+#endif
+
 // By default we allow to use SizeClassAllocator64 on 64-bit platform.
 // But in some cases SizeClassAllocator64 does not work well and we need to
 // fallback to SizeClassAllocator32.
diff --git a/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp b/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
index 6d6638c26ce19..9a6cca3796729 100644
--- a/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
+++ b/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
@@ -13,6 +13,12 @@ template <typename... Args>
 static void message(const char *msg, Args &&...args) {
   fprintf(stderr, msg, args...);
 }
+#elif SANITIZER_SPIRV
+extern "C" int printf(const char *fmt, ...);
+template <typename... Args>
+static void message(const char *msg, Args &&...args) {
+  printf(msg, args...);
+}
 #else
 #include <unistd.h>
 static void message(const char *msg) { (void)write(2, msg, strlen(msg)); }
@@ -69,7 +75,7 @@ static void format_msg(const char *kind, uintptr_t caller, char *buf,
 }
 
 static void format(const char *kind, uintptr_t caller) {
-#if SANITIZER_AMDGPU || SANITIZER_NVPTX
+#if SANITIZER_AMDGPU || SANITIZER_NVPTX || SANITIZER_SPIRV
   (void)format_msg;
   message("ubsan: %s by %p\n", kind, reinterpret_cast<void *>(caller));
 #else
@@ -151,6 +157,19 @@ static void abort_with_message(const char *kind, uintptr_t caller) {
 static void abort_with_message(const char *kind, uintptr_t caller) {
   __builtin_verbose_trap("ubsan", "unrecoverable error");
 }
+#elif SANITIZER_SPIRV
+struct __ubsan_abort_info_t {
+  const char *fmt;
+  const char *kind;
+  const void *caller;
+};
+[[noreturn]] void __spirv_AbortKHR(__ubsan_abort_info_t info);
+[[noreturn]] static void abort_with_message(const char *kind,
+                                            uintptr_t caller) {
+  __ubsan_abort_info_t info = {"ubsan: %s by %p\n", kind,
+                               reinterpret_cast<void *>(caller)};
+  __spirv_AbortKHR(info);
+}
 #else
 static void abort_with_message(const char *kind, uintptr_t caller) { abort(); }
 #endif



More information about the llvm-commits mailing list