[compiler-rt] [tsan][go]: add a128 store, load, compare_exchange (PR #196833)

Mauri de Souza Meneguzzo via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 16 06:29:41 PDT 2026


https://github.com/mauri870 updated https://github.com/llvm/llvm-project/pull/196833

>From a80da2a8c7bc0e2ffa60a135014fe52f38c574c0 Mon Sep 17 00:00:00 2001
From: Mauri de Souza Meneguzzo <mauri870 at gmail.com>
Date: Sat, 9 May 2026 20:34:03 -0300
Subject: [PATCH] [tsan][go]: add a128 load, store, compare_exchange

---
 compiler-rt/lib/tsan/rtl/tsan_interface.h     | 16 +++++++--
 .../lib/tsan/rtl/tsan_interface_atomic.cpp    | 34 ++++++++++++++++---
 2 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface.h b/compiler-rt/lib/tsan/rtl/tsan_interface.h
index db94cf48f9c2d..1e2c4b36284e4 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface.h
@@ -207,8 +207,7 @@ typedef unsigned char a8;
 typedef unsigned short a16;
 typedef unsigned int a32;
 typedef unsigned long long a64;
-#if !SANITIZER_GO &&                                      \
-    (defined(__SIZEOF_INT128__) ||                        \
+#if (defined(__SIZEOF_INT128__) ||                        \
      (__clang_major__ * 100 + __clang_minor__ >= 302)) && \
     !defined(__mips64) && !defined(__s390x__)
 __extension__ typedef __int128 a128;
@@ -411,10 +410,18 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_go_atomic32_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
 SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic128_load(ThreadState* thr, uptr cpc, uptr pc, u8* a);
+#endif
 SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
 SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic128_store(ThreadState* thr, uptr cpc, uptr pc, u8* a);
+#endif
 SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a);
 SANITIZER_INTERFACE_ATTRIBUTE
@@ -437,6 +444,11 @@ void __tsan_go_atomic32_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
 SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
                                          u8 *a);
+#if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic128_compare_exchange(ThreadState* thr, uptr cpc, uptr pc,
+                                          u8* a);
+#endif
 
 }  // extern "C"
 
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
index 5c2461634d2d4..5dd86e05c96b9 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp
@@ -28,7 +28,7 @@
 
 using namespace __tsan;
 
-#if !SANITIZER_GO && __TSAN_HAS_INT128
+#if __TSAN_HAS_INT128
 // Protects emulation of 128-bit atomic operations.
 static StaticSpinMutex mutex128;
 #endif
@@ -112,8 +112,7 @@ T func_cas(volatile T *v, T cmp, T xch) {
 // Atomic ops are executed under tsan internal mutex,
 // here we assume that the atomic variables are not accessed
 // from non-instrumented code.
-#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && !SANITIZER_GO && \
-    __TSAN_HAS_INT128
+#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && __TSAN_HAS_INT128
 a128 func_xchg(volatile a128 *v, a128 op) {
   SpinMutexLock lock(&mutex128);
   a128 cmp = *v;
@@ -253,7 +252,7 @@ struct OpLoad {
     return atomic_load(to_atomic(a), to_mo(mo));
   }
 
-#if __TSAN_HAS_INT128 && !SANITIZER_GO
+#if __TSAN_HAS_INT128
   static a128 NoTsanAtomic(morder mo, const volatile a128 *a) {
     SpinMutexLock lock(&mutex128);
     return *a;
@@ -294,7 +293,7 @@ struct OpStore {
     atomic_store(to_atomic(a), v, to_mo(mo));
   }
 
-#if __TSAN_HAS_INT128 && !SANITIZER_GO
+#if __TSAN_HAS_INT128
   static void NoTsanAtomic(morder mo, volatile a128 *a, a128 v) {
     SpinMutexLock lock(&mutex128);
     *a = v;
@@ -928,6 +927,13 @@ void __tsan_go_atomic64_load(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
   *(a64 *)(a + 8) = AtomicGoRet<OpLoad>(thr, cpc, pc, mo_acquire, *(a64 **)a);
 }
 
+#  if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic128_load(ThreadState* thr, uptr cpc, uptr pc, u8* a) {
+  *(a128*)(a + 8) = AtomicGoRet<OpLoad>(thr, cpc, pc, mo_acquire, *(a128**)a);
+}
+#  endif
+
 SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_go_atomic32_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
   AtomicGo<OpStore>(thr, cpc, pc, mo_release, *(a32 **)a, *(a32 *)(a + 8));
@@ -938,6 +944,13 @@ void __tsan_go_atomic64_store(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
   AtomicGo<OpStore>(thr, cpc, pc, mo_release, *(a64 **)a, *(a64 *)(a + 8));
 }
 
+#  if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic128_store(ThreadState* thr, uptr cpc, uptr pc, u8* a) {
+  AtomicGo<OpStore>(thr, cpc, pc, mo_release, *(a128**)a, *(a128*)(a + 8));
+}
+#  endif
+
 SANITIZER_INTERFACE_ATTRIBUTE
 void __tsan_go_atomic32_fetch_add(ThreadState *thr, uptr cpc, uptr pc, u8 *a) {
   *(a32 *)(a + 16) = AtomicGoRet<OpFetchAdd>(thr, cpc, pc, mo_acq_rel,
@@ -1003,5 +1016,16 @@ void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
                                cmp, *(a64 *)(a + 16));
   *(bool *)(a + 24) = (cur == cmp);
 }
+
+#  if __TSAN_HAS_INT128
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_go_atomic128_compare_exchange(ThreadState* thr, uptr cpc, uptr pc,
+                                          u8* a) {
+  a128 cmp = *(a128*)(a + 8);
+  a128 cur = AtomicGoRet<OpCAS>(thr, cpc, pc, mo_acq_rel, mo_acquire,
+                                *(a128**)a, cmp, *(a128*)(a + 24));
+  *(bool*)(a + 40) = (cur == cmp);
+}
+#  endif
 }  // extern "C"
 #endif  // #if !SANITIZER_GO



More information about the llvm-commits mailing list