This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb89b42b31c45: [tsan] Add tsan support for loongarch64 
(authored by tangyouling, committed by SixWeining).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D138489/new/

https://reviews.llvm.org/D138489

Files:
  clang/lib/Driver/ToolChains/Linux.cpp
  compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
  compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
  compiler-rt/lib/sanitizer_common/sanitizer_linux.h
  compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
  compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
  compiler-rt/lib/tsan/rtl/CMakeLists.txt
  compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
  compiler-rt/lib/tsan/rtl/tsan_platform.h
  compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
  compiler-rt/lib/tsan/rtl/tsan_rtl.h
  compiler-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S
  compiler-rt/test/sanitizer_common/print_address.h
  compiler-rt/test/tsan/map32bit.cpp
  compiler-rt/test/tsan/mmap_large.cpp

Index: compiler-rt/test/tsan/mmap_large.cpp
===================================================================
--- compiler-rt/test/tsan/mmap_large.cpp
+++ compiler-rt/test/tsan/mmap_large.cpp
@@ -17,7 +17,7 @@
 int main() {
 #ifdef __x86_64__
   const size_t kLog2Size = 39;
-#elif defined(__mips64) || defined(__aarch64__)
+#elif defined(__mips64) || defined(__aarch64__) || defined(__loongarch_lp64)
   const size_t kLog2Size = 32;
 #elif defined(__powerpc64__)
   const size_t kLog2Size = 39;
Index: compiler-rt/test/tsan/map32bit.cpp
===================================================================
--- compiler-rt/test/tsan/map32bit.cpp
+++ compiler-rt/test/tsan/map32bit.cpp
@@ -12,6 +12,7 @@
 // XFAIL: aarch64
 // XFAIL: powerpc64
 // XFAIL: s390x
+// XFAIL: loongarch64
 
 // MAP_32BIT doesn't exist on OS X and NetBSD.
 // UNSUPPORTED: darwin,netbsd
Index: compiler-rt/test/sanitizer_common/print_address.h
===================================================================
--- compiler-rt/test/sanitizer_common/print_address.h
+++ compiler-rt/test/sanitizer_common/print_address.h
@@ -7,8 +7,9 @@
   va_start(ap, n);
   while (n--) {
     void *p = va_arg(ap, void *);
-#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \
-    defined(__s390x__) || (defined(__riscv) && __riscv_xlen == 64)
+#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) ||   \
+    defined(__s390x__) || (defined(__riscv) && __riscv_xlen == 64) ||          \
+    defined(__loongarch_lp64)
     // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not
     // match to the format used in the diagnotic message.
     fprintf(stderr, "0x%012lx ", (unsigned long) p);
Index: compiler-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S
===================================================================
--- /dev/null
+++ compiler-rt/lib/tsan/rtl/tsan_rtl_loongarch64.S
@@ -0,0 +1,196 @@
+#include "sanitizer_common/sanitizer_asm.h"
+
+.section .text
+
+ASM_HIDDEN(__tsan_setjmp)
+.comm _ZN14__interception11real_setjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(setjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp))
+ASM_SYMBOL_INTERCEPTOR(setjmp):
+  CFI_STARTPROC
+
+  // Save frame pointer and return address register
+  addi.d $sp, $sp, -32
+  st.d $ra, $sp, 24
+  st.d $fp, $sp, 16
+  CFI_DEF_CFA_OFFSET (32)
+  CFI_OFFSET (1, -8)
+  CFI_OFFSET (22, -16)
+
+  // Adjust the SP for previous frame
+  addi.d $fp, $sp, 32
+  CFI_DEF_CFA_REGISTER (22)
+
+  // Save env parameter
+  st.d $a0, $sp, 8
+  CFI_OFFSET (4, -24)
+
+  // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+  addi.d  $a0, $fp, 0
+
+  // call tsan interceptor
+  bl      ASM_SYMBOL(__tsan_setjmp)
+
+  // Restore env parameter
+  ld.d $a0, $sp, 8
+  CFI_RESTORE (4)
+
+  // Restore frame/link register
+  ld.d $fp, $sp, 16
+  ld.d $ra, $sp, 24
+  addi.d $sp, $sp, 32
+  CFI_RESTORE (22)
+  CFI_RESTORE (1)
+  CFI_DEF_CFA (3, 0)
+
+  // tail jump to libc setjmp
+  la.local $a1, _ZN14__interception11real_setjmpE
+  ld.d $a1, $a1, 0
+  jr $a1
+
+  CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp))
+
+.comm _ZN14__interception12real__setjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(_setjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp))
+ASM_SYMBOL_INTERCEPTOR(_setjmp):
+  CFI_STARTPROC
+
+  // Save frame pointer and return address register
+  addi.d $sp, $sp, -32
+  st.d $ra, $sp, 24
+  st.d $fp, $sp, 16
+  CFI_DEF_CFA_OFFSET (32)
+  CFI_OFFSET (1, -8)
+  CFI_OFFSET (22, -16)
+
+  // Adjust the SP for previous frame
+  addi.d $fp, $sp, 32
+  CFI_DEF_CFA_REGISTER (22)
+
+  // Save env parameter
+  st.d $a0, $sp, 8
+  CFI_OFFSET (4, -24)
+
+  // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+  addi.d  $a0, $fp, 0
+
+  // call tsan interceptor
+  bl      ASM_SYMBOL(__tsan_setjmp)
+
+  // Restore env parameter
+  ld.d $a0, $sp, 8
+  CFI_RESTORE (4)
+
+  // Restore frame/link register
+  ld.d $fp, $sp, 16
+  ld.d $ra, $sp, 24
+  addi.d $sp, $sp, 32
+  CFI_RESTORE (22)
+  CFI_RESTORE (1)
+  CFI_DEF_CFA (3, 0)
+
+  // tail jump to libc setjmp
+  la.local $a1, _ZN14__interception12real__setjmpE
+  ld.d $a1, $a1, 0
+  jr $a1
+
+  CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp))
+
+.comm _ZN14__interception14real_sigsetjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(sigsetjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
+ASM_SYMBOL_INTERCEPTOR(sigsetjmp):
+  CFI_STARTPROC
+
+  // Save frame pointer and return address register
+  addi.d $sp, $sp, -32
+  st.d $ra, $sp, 24
+  st.d $fp, $sp, 16
+  CFI_DEF_CFA_OFFSET (32)
+  CFI_OFFSET (1, -8)
+  CFI_OFFSET (22, -16)
+
+  // Adjust the SP for previous frame
+  addi.d $fp, $sp, 32
+  CFI_DEF_CFA_REGISTER (22)
+
+  // Save env parameter
+  st.d $a0, $sp, 8
+  CFI_OFFSET (4, -24)
+
+  // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+  addi.d  $a0, $fp, 0
+
+  // call tsan interceptor
+  bl      ASM_SYMBOL(__tsan_setjmp)
+
+  // Restore env parameter
+  ld.d $a0, $sp, 8
+  CFI_RESTORE (4)
+
+  // Restore frame/link register
+  ld.d $fp, $sp, 16
+  ld.d $ra, $sp, 24
+  addi.d $sp, $sp, 32
+  CFI_RESTORE (22)
+  CFI_RESTORE (1)
+  CFI_DEF_CFA (3, 0)
+
+  // tail jump to libc setjmp
+  la.local $a1, _ZN14__interception14real_sigsetjmpE
+  ld.d $a1, $a1, 0
+  jr $a1
+
+  CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp))
+
+.comm _ZN14__interception16real___sigsetjmpE,8,8
+.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
+ASM_SYMBOL_INTERCEPTOR(__sigsetjmp):
+  CFI_STARTPROC
+
+  // Save frame pointer and return address register
+  addi.d $sp, $sp, -32
+  st.d $ra, $sp, 24
+  st.d $fp, $sp, 16
+  CFI_DEF_CFA_OFFSET (32)
+  CFI_OFFSET (1, -8)
+  CFI_OFFSET (22, -16)
+
+  // Adjust the SP for previous frame
+  addi.d $fp, $sp, 32
+  CFI_DEF_CFA_REGISTER (22)
+
+  // Save env parameter
+  st.d $a0, $sp, 8
+  CFI_OFFSET (4, -24)
+
+  // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)`
+  addi.d  $a0, $fp, 0
+
+  // call tsan interceptor
+  bl      ASM_SYMBOL(__tsan_setjmp)
+
+  // Restore env parameter
+  ld.d $a0, $sp, 8
+  CFI_RESTORE (4)
+
+  // Restore frame/link register
+  ld.d $fp, $sp, 16
+  ld.d $ra, $sp, 24
+  addi.d $sp, $sp, 32
+  CFI_RESTORE (22)
+  CFI_RESTORE (1)
+  CFI_DEF_CFA (3, 0)
+
+  // tail jump to libc setjmp
+  la.local $a1, _ZN14__interception16real___sigsetjmpE
+  ld.d $a1, $a1, 0
+  jr $a1
+
+  CFI_ENDPROC
+ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
Index: compiler-rt/lib/tsan/rtl/tsan_rtl.h
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -56,7 +56,8 @@
 
 #if !SANITIZER_GO
 struct MapUnmapCallback;
-#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__)
+#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
+    defined(__powerpc__)
 
 struct AP32 {
   static const uptr kSpaceBeg = 0;
Index: compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
+++ compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
@@ -230,6 +230,14 @@
     Die();
   }
 #endif
+#elif SANITIZER_LOONGARCH64
+# if !SANITIZER_GO
+  if (vmaSize != 47) {
+    Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
+    Printf("FATAL: Found %zd - Supported 47\n", vmaSize);
+    Die();
+  }
+# endif
 #elif defined(__powerpc64__)
 # if !SANITIZER_GO
   if (vmaSize != 44 && vmaSize != 46 && vmaSize != 47) {
@@ -375,6 +383,8 @@
 # else
   return mangled_sp;
 # endif
+#elif defined(__loongarch__)
+  return mangled_sp;
 #elif defined(__powerpc64__)
   // Reverse of:
   //   ld   r4, -28696(r13)
@@ -410,6 +420,8 @@
 #elif SANITIZER_LINUX
 # ifdef __aarch64__
 #  define LONG_JMP_SP_ENV_SLOT 13
+# elif defined(__loongarch__)
+#  define LONG_JMP_SP_ENV_SLOT 1
 # elif defined(__mips64)
 #  define LONG_JMP_SP_ENV_SLOT 1
 # elif defined(__s390x__)
Index: compiler-rt/lib/tsan/rtl/tsan_platform.h
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_platform.h
+++ compiler-rt/lib/tsan/rtl/tsan_platform.h
@@ -229,6 +229,38 @@
   static const uptr kVdsoBeg       = 0xffff000000000ull;
 };
 
+/* C/C++ on linux/loongarch64 (47-bit VMA)
+0000 0000 4000 - 0080 0000 0000: main binary
+0080 0000 0000 - 0100 0000 0000: -
+0100 0000 0000 - 1000 0000 0000: shadow memory
+1000 0000 0000 - 3000 0000 0000: -
+3000 0000 0000 - 3400 0000 0000: metainfo
+3400 0000 0000 - 5555 0000 0000: -
+5555 0000 0000 - 5556 0000 0000: main binary (PIE)
+5556 0000 0000 - 7ffe 0000 0000: -
+7ffe 0000 0000 - 7fff 0000 0000: heap
+7fff 0000 0000 - 7fff 8000 0000: -
+7fff 8000 0000 - 8000 0000 0000: modules and main thread stack
+*/
+struct MappingLoongArch64_47 {
+  static const uptr kMetaShadowBeg = 0x300000000000ull;
+  static const uptr kMetaShadowEnd = 0x340000000000ull;
+  static const uptr kShadowBeg     = 0x010000000000ull;
+  static const uptr kShadowEnd     = 0x100000000000ull;
+  static const uptr kHeapMemBeg    = 0x7ffe00000000ull;
+  static const uptr kHeapMemEnd    = 0x7fff00000000ull;
+  static const uptr kLoAppMemBeg   = 0x000000004000ull;
+  static const uptr kLoAppMemEnd   = 0x008000000000ull;
+  static const uptr kMidAppMemBeg  = 0x555500000000ull;
+  static const uptr kMidAppMemEnd  = 0x555600000000ull;
+  static const uptr kHiAppMemBeg   = 0x7fff80000000ull;
+  static const uptr kHiAppMemEnd   = 0x800000000000ull;
+  static const uptr kShadowMsk     = 0x780000000000ull;
+  static const uptr kShadowXor     = 0x040000000000ull;
+  static const uptr kShadowAdd     = 0x000000000000ull;
+  static const uptr kVdsoBeg       = 0x7fffffffc000ull;
+};
+
 /*
 C/C++ on linux/powerpc64 (44-bit VMA)
 0000 0000 0100 - 0001 0000 0000: main binary
@@ -599,6 +631,8 @@
     case 48:
       return Func::template Apply<MappingAarch64_48>(arg);
   }
+#  elif SANITIZER_LOONGARCH64
+  return Func::template Apply<MappingLoongArch64_47>(arg);
 #  elif defined(__powerpc64__)
   switch (vmaSize) {
     case 44:
@@ -627,6 +661,7 @@
   Func::template Apply<MappingAarch64_39>();
   Func::template Apply<MappingAarch64_42>();
   Func::template Apply<MappingAarch64_48>();
+  Func::template Apply<MappingLoongArch64_47>();
   Func::template Apply<MappingPPC64_44>();
   Func::template Apply<MappingPPC64_46>();
   Func::template Apply<MappingPPC64_47>();
Index: compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -76,6 +76,8 @@
 #define PTHREAD_ABI_BASE  "GLIBC_2.3.2"
 #elif defined(__aarch64__) || SANITIZER_PPC64V2
 #define PTHREAD_ABI_BASE  "GLIBC_2.17"
+#elif SANITIZER_LOONGARCH64
+#define PTHREAD_ABI_BASE  "GLIBC_2.36"
 #endif
 
 extern "C" int pthread_attr_init(void *attr);
Index: compiler-rt/lib/tsan/rtl/CMakeLists.txt
===================================================================
--- compiler-rt/lib/tsan/rtl/CMakeLists.txt
+++ compiler-rt/lib/tsan/rtl/CMakeLists.txt
@@ -211,6 +211,10 @@
 	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../go
 	COMMENT "Checking TSan Go runtime..."
 	VERBATIM)
+    elseif(arch MATCHES "loongarch64")
+      add_asm_sources(TSAN_ASM_SOURCES
+        tsan_rtl_loongarch64.S
+        )
     elseif(arch MATCHES "mips64|mips64le")
       add_asm_sources(TSAN_ASM_SOURCES
         tsan_rtl_mips64.S
Index: compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+++ compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
@@ -16,7 +16,7 @@
 #if SANITIZER_LINUX &&                                                   \
     (defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
      defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
-     defined(__arm__) || SANITIZER_RISCV64)
+     defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
 
 #include "sanitizer_stoptheworld.h"
 
@@ -31,7 +31,8 @@
 #include <sys/types.h> // for pid_t
 #include <sys/uio.h> // for iovec
 #include <elf.h> // for NT_PRSTATUS
-#if (defined(__aarch64__) || SANITIZER_RISCV64) && !SANITIZER_ANDROID
+#if (defined(__aarch64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64) && \
+     !SANITIZER_ANDROID
 // GLIBC 2.20+ sys/user does not include asm/ptrace.h
 # include <asm/ptrace.h>
 #endif
@@ -514,6 +515,12 @@
 static constexpr uptr kExtraRegs[] = {0};
 #define ARCH_IOVEC_FOR_GETREGSET
 
+#elif defined(__loongarch__)
+typedef struct user_pt_regs regs_struct;
+#define REG_SP regs[3]
+static constexpr uptr kExtraRegs[] = {0};
+#define ARCH_IOVEC_FOR_GETREGSET
+
 #elif SANITIZER_RISCV64
 typedef struct user_regs_struct regs_struct;
 // sys/ucontext.h already defines REG_SP as 2. Undefine it first.
@@ -621,3 +628,4 @@
 #endif  // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__)
         // || defined(__aarch64__) || defined(__powerpc64__)
         // || defined(__s390__) || defined(__i386__) || defined(__arm__)
+        // || SANITIZER_LOONGARCH64
Index: compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -205,7 +205,8 @@
   g_use_dlpi_tls_data =
       GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25;
 
-#if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__)
+#if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__) || \
+    defined(__loongarch__)
   void *get_tls_static_info = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
   size_t tls_align;
   ((void (*)(size_t *, size_t *))get_tls_static_info)(&g_tls_size, &tls_align);
@@ -265,6 +266,8 @@
 #elif defined(__mips__)
   // TODO(sagarthakur): add more values as per different glibc versions.
   val = FIRST_32_SECOND_64(1152, 1776);
+#elif SANITIZER_LOONGARCH64
+  val = 1856; // from glibc 2.36
 #elif SANITIZER_RISCV64
   int major;
   int minor;
@@ -304,7 +307,8 @@
   return val;
 }
 
-#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64
+#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
+    SANITIZER_LOONGARCH64
 // TlsPreTcbSize includes size of struct pthread_descr and size of tcb
 // head structure. It lies before the static tls blocks.
 static uptr TlsPreTcbSize() {
@@ -314,6 +318,8 @@
   const uptr kTcbHead = 88; // sizeof (tcbhead_t)
 #elif SANITIZER_RISCV64
   const uptr kTcbHead = 16;  // sizeof (tcbhead_t)
+#elif SANITIZER_LOONGARCH64
+  const uptr kTcbHead = 16;  // sizeof (tcbhead_t)
 #endif
   const uptr kTlsAlign = 16;
   const uptr kTlsPreTcbSize =
@@ -500,6 +506,10 @@
   *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
           ThreadDescriptorSize();
   *size = g_tls_size + ThreadDescriptorSize();
+#elif SANITIZER_GLIBC && defined(__loongarch__)
+  *addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
+          ThreadDescriptorSize();
+  *size = g_tls_size + ThreadDescriptorSize();
 #elif SANITIZER_GLIBC && defined(__powerpc64__)
   // Workaround for glibc<2.25(?). 2.27 is known to not need this.
   uptr tp;
Index: compiler-rt/lib/sanitizer_common/sanitizer_linux.h
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_linux.h
+++ compiler-rt/lib/sanitizer_common/sanitizer_linux.h
@@ -77,9 +77,9 @@
 // internal_sigaction instead.
 int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
 void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
-#if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
-    defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
-    defined(__arm__) || SANITIZER_RISCV64
+#    if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
+        defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
+        defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                     int *parent_tidptr, void *newtls, int *child_tidptr);
 #endif
Index: compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -1502,6 +1502,46 @@
                        : "x30", "memory");
   return res;
 }
+#elif SANITIZER_LOONGARCH64
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+                    int *parent_tidptr, void *newtls, int *child_tidptr) {
+  if (!fn || !child_stack)
+    return -EINVAL;
+
+  CHECK_EQ(0, (uptr)child_stack % 16);
+
+  register int res __asm__("$a0");
+  register int __flags __asm__("$a0") = flags;
+  register void *__stack __asm__("$a1") = child_stack;
+  register int *__ptid __asm__("$a2") = parent_tidptr;
+  register void *__tls __asm__("$a3") = newtls;
+  register int *__ctid __asm__("$a4") = child_tidptr;
+  register int (*__fn)(void *) __asm__("$a5") = fn;
+  register void *__arg __asm__("$a6") = arg;
+  register int nr_clone __asm__("$a7") = __NR_clone;
+
+  __asm__ __volatile__(
+      "syscall 0\n"
+
+      // if ($a0 != 0)
+      //   return $a0;
+      "bnez $a0, 1f\n"
+
+      // In the child, now. Call "fn(arg)".
+      "move $a0, $a6\n"
+      "jr $a5\n"
+
+      // Call _exit($a0).
+      "addi.d $a7, $zero, %9\n"
+      "syscall 0\n"
+      "1:\n"
+
+      : "=r"(res)
+      : "0"(__flags), "r"(__stack), "r"(__ptid), "r"(__tls), "r"(__ctid),
+        "r"(__fn), "r"(__arg), "r"(nr_clone), "i"(__NR_exit)
+      : "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8");
+  return res;
+}
 #elif defined(__powerpc64__)
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                    int *parent_tidptr, void *newtls, int *child_tidptr) {
Index: compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
===================================================================
--- compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
+++ compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
@@ -60,7 +60,8 @@
 set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64}
     ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
     ${RISCV32} ${RISCV64})
-set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X})
+set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}
+    ${LOONGARCH64})
 set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
     ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON})
 set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}
Index: clang/lib/Driver/ToolChains/Linux.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Linux.cpp
+++ clang/lib/Driver/ToolChains/Linux.cpp
@@ -768,7 +768,8 @@
   if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 ||
       IsRISCV64 || IsSystemZ || IsHexagon)
     Res |= SanitizerKind::Leak;
-  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ)
+  if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ ||
+      IsLoongArch64)
     Res |= SanitizerKind::Thread;
   if (IsX86_64)
     Res |= SanitizerKind::KernelMemory;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to