diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -709,7 +709,7 @@ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 || IsRISCV64 || IsSystemZ) Res |= SanitizerKind::Leak; - if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64) + if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ) Res |= SanitizerKind::Thread; if (IsX86_64) Res |= SanitizerKind::KernelMemory; diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -329,7 +329,7 @@ set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64}) +set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -5303,6 +5303,12 @@ #define INIT_TIMES #endif +#if SANITIZER_S390 && (SANITIZER_INTERCEPT_TLS_GET_ADDR || \ + SANITIZER_INTERCEPT_TLS_GET_OFFSET) +extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg)); +DEFINE_REAL(uptr, __tls_get_offset, void *arg) +#endif + #if SANITIZER_INTERCEPT_TLS_GET_ADDR #if !SANITIZER_S390 #define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr) @@ -5342,11 +5348,7 @@ // descriptor offset as an argument instead of a pointer. GOT address // is passed in r12, so it's necessary to write it in assembly. This is // the function used by the compiler. -extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg)); #define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset) -DEFINE_REAL(uptr, __tls_get_offset, void *arg) -extern "C" uptr __tls_get_offset(void *arg); -extern "C" uptr __interceptor___tls_get_offset(void *arg); INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg); @@ -5362,6 +5364,15 @@ } return res; } +#endif // SANITIZER_S390 +#else +#define INIT_TLS_GET_ADDR +#endif + +#if SANITIZER_S390 && (SANITIZER_INTERCEPT_TLS_GET_ADDR || \ + SANITIZER_INTERCEPT_TLS_GET_OFFSET) +extern "C" uptr __tls_get_offset(void *arg); +extern "C" uptr __interceptor___tls_get_offset(void *arg); // We need a hidden symbol aliasing the above, so that we can jump // directly to it from the assembly below. extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"), @@ -5400,9 +5411,6 @@ "br %r3\n" ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n" ); -#endif // SANITIZER_S390 -#else -#define INIT_TLS_GET_ADDR #endif #if SANITIZER_INTERCEPT_LISTXATTR diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -884,7 +884,7 @@ __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); - k_set->sig[idx] &= ~(1 << bit); + k_set->sig[idx] &= ~((uptr)1 << bit); } bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { @@ -894,7 +894,7 @@ __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); - return k_set->sig[idx] & (1 << bit); + return k_set->sig[idx] & ((uptr)1 << bit); } #elif SANITIZER_FREEBSD void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -650,14 +650,14 @@ #endif // !SANITIZER_ANDROID #if defined(__mips__) -struct __sanitizer_kernel_sigset_t { - uptr sig[2]; -}; +#define __SANITIZER_KERNEL_NSIG 128 #else +#define __SANITIZER_KERNEL_NSIG 64 +#endif + struct __sanitizer_kernel_sigset_t { - u8 sig[8]; + uptr sig[__SANITIZER_KERNEL_NSIG / (sizeof(uptr) * 8)]; }; -#endif // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros. #if SANITIZER_MIPS diff --git a/compiler-rt/lib/tsan/CMakeLists.txt b/compiler-rt/lib/tsan/CMakeLists.txt --- a/compiler-rt/lib/tsan/CMakeLists.txt +++ b/compiler-rt/lib/tsan/CMakeLists.txt @@ -219,6 +219,10 @@ add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_mips64.S ) + elseif(arch MATCHES "s390x") + add_asm_sources(TSAN_ASM_SOURCES + rtl/tsan_rtl_s390x.S + ) else() set(TSAN_ASM_SOURCES) endif() diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -71,7 +71,8 @@ }; #endif -#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 +#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \ + defined(__s390x__) #define PTHREAD_ABI_BASE "GLIBC_2.3.2" #elif defined(__aarch64__) || SANITIZER_PPC64V2 #define PTHREAD_ABI_BASE "GLIBC_2.17" @@ -775,9 +776,11 @@ void *res = real_mmap(addr, sz, prot, flags, fd, off); if (res != MAP_FAILED) { if (!IsAppMem((uptr)res) || !IsAppMem((uptr)res + sz - 1)) { - Report("ThreadSanitizer: mmap at bad address: addr=%p size=%p res=%p\n", - addr, (void*)sz, res); - Die(); + // Application has attempted to map more memory than is supported by + // TSAN. Act as if we ran out of memory. + internal_munmap(res, sz); + errno = errno_ENOMEM; + return MAP_FAILED; } if (fd > 0) FdAccess(thr, pc, fd); MemoryRangeImitateWriteOrResetRange(thr, pc, (uptr)res, sz); @@ -2270,6 +2273,7 @@ #define NEED_TLS_GET_ADDR #endif #undef SANITIZER_INTERCEPT_TLS_GET_ADDR +#define SANITIZER_INTERCEPT_TLS_GET_OFFSET 1 #undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) @@ -2585,6 +2589,20 @@ #include "sanitizer_common/sanitizer_syscalls_netbsd.inc" #ifdef NEED_TLS_GET_ADDR + +static void handle_tls_addr(void *arg, void *res) { + ThreadState *thr = cur_thread(); + if (!thr) + return; + DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr, + thr->tls_addr + thr->tls_size); + if (!dtv) + return; + // New DTLS block has been allocated. + MemoryResetRange(thr, 0, dtv->beg, dtv->size); +} + +#if !SANITIZER_S390 // Define own interceptor instead of sanitizer_common's for three reasons: // 1. It must not process pending signals. // Signal handlers may contain MOVDQA instruction (see below). @@ -2597,18 +2615,18 @@ // execute MOVDQA with stack addresses. TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) { void *res = REAL(__tls_get_addr)(arg); - ThreadState *thr = cur_thread(); - if (!thr) - return res; - DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr, - thr->tls_addr + thr->tls_size); - if (!dtv) - return res; - // New DTLS block has been allocated. - MemoryResetRange(thr, 0, dtv->beg, dtv->size); + handle_tls_addr(arg, res); + return res; +} +#else // SANITIZER_S390 +TSAN_INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { + uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset)); + char *tp = static_cast(__builtin_thread_pointer()); + handle_tls_addr(arg, res + tp); return res; } #endif +#endif #if SANITIZER_NETBSD TSAN_INTERCEPTOR(void, _lwp_exit) { @@ -2830,7 +2848,12 @@ TSAN_INTERCEPT(_exit); #ifdef NEED_TLS_GET_ADDR +#if !SANITIZER_S390 TSAN_INTERCEPT(__tls_get_addr); +#else + TSAN_INTERCEPT(__tls_get_addr_internal); + TSAN_INTERCEPT(__tls_get_offset); +#endif #endif TSAN_MAYBE_INTERCEPT__LWP_EXIT; diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface.h b/compiler-rt/lib/tsan/rtl/tsan_interface.h --- a/compiler-rt/lib/tsan/rtl/tsan_interface.h +++ b/compiler-rt/lib/tsan/rtl/tsan_interface.h @@ -196,7 +196,8 @@ typedef unsigned int a32; typedef unsigned long long a64; #if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \ - || (__clang_major__ * 100 + __clang_minor__ >= 302)) && !defined(__mips64) + || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \ + !defined(__mips64) && !defined(__s390x__) __extension__ typedef __int128 a128; # define __TSAN_HAS_INT128 1 #else diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -365,6 +365,38 @@ // Indicates the runtime will define the memory regions at runtime. #define TSAN_RUNTIME_VMA 1 +#elif defined(__s390x__) +/* +C/C++ on linux/s390x +While the kernel provides a 64-bit address space, we have to restrict ourselves +to 48 bits due to how e.g. SyncVar::GetId() works. +0000 0000 1000 - 0e00 0000 0000: binary, modules, stacks - 14 TiB +0e00 0000 0000 - 4000 0000 0000: - +4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app) +8000 0000 0000 - 9000 0000 0000: - +9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app) +9800 0000 0000 - a000 0000 0000: - +a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads) +b000 0000 0000 - be00 0000 0000: - +be00 0000 0000 - c000 0000 0000: heap - 2TiB (max supported by the allocator) +*/ +struct Mapping { + static const uptr kMetaShadowBeg = 0x900000000000ull; + static const uptr kMetaShadowEnd = 0x980000000000ull; + static const uptr kTraceMemBeg = 0xa00000000000ull; + static const uptr kTraceMemEnd = 0xb00000000000ull; + static const uptr kShadowBeg = 0x400000000000ull; + static const uptr kShadowEnd = 0x800000000000ull; + static const uptr kHeapMemBeg = 0xbe0000000000ull; + static const uptr kHeapMemEnd = 0xc00000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x0e0000000000ull; + static const uptr kHiAppMemBeg = 0xc00000004000ull; + static const uptr kHiAppMemEnd = 0xc00000004000ull; + static const uptr kAppMemMsk = 0xb00000000000ull; + static const uptr kAppMemXor = 0x100000000000ull; + static const uptr kVdsoBeg = 0xfffffffff000ull; +}; #endif #elif SANITIZER_GO && !SANITIZER_WINDOWS && HAS_48_BIT_ADDRESS_SPACE diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp @@ -391,6 +391,10 @@ return mangled_sp ^ xor_key; #elif defined(__mips__) return mangled_sp; +#elif defined(__s390x__) + // tcbhead_t.stack_guard + uptr xor_key = ((uptr *)__builtin_thread_pointer())[5]; + return mangled_sp ^ xor_key; #else #error "Unknown platform" #endif @@ -411,6 +415,8 @@ # define LONG_JMP_SP_ENV_SLOT 13 # elif defined(__mips64) # define LONG_JMP_SP_ENV_SLOT 1 +# elif defined(__s390x__) +# define LONG_JMP_SP_ENV_SLOT 9 # else # define LONG_JMP_SP_ENV_SLOT 6 # endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S b/compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S @@ -0,0 +1,47 @@ +#include "sanitizer_common/sanitizer_asm.h" + +#define CFA_OFFSET 160 +#define R2_REL_OFFSET 16 +#define R3_REL_OFFSET 24 +#define R14_REL_OFFSET 112 +#define R15_REL_OFFSET 120 +#define FRAME_SIZE 160 + +.text + +ASM_HIDDEN(__tsan_setjmp) + +.macro intercept symbol, real +.comm \real, 8, 8 +.globl ASM_SYMBOL_INTERCEPTOR(\symbol) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(\symbol)) +ASM_SYMBOL_INTERCEPTOR(\symbol): + CFI_STARTPROC + stmg %r2, %r3, R2_REL_OFFSET(%r15) + CFI_REL_OFFSET(%r2, R2_REL_OFFSET) + CFI_REL_OFFSET(%r3, R3_REL_OFFSET) + stmg %r14, %r15, R14_REL_OFFSET(%r15) + CFI_REL_OFFSET(%r14, R14_REL_OFFSET) + CFI_REL_OFFSET(%r15, R15_REL_OFFSET) + aghi %r15, -FRAME_SIZE + CFI_ADJUST_CFA_OFFSET(FRAME_SIZE) + la %r2, FRAME_SIZE(%r15) + brasl %r14, ASM_SYMBOL(__tsan_setjmp) + lmg %r14, %r15, FRAME_SIZE + R14_REL_OFFSET(%r15) + CFI_RESTORE(%r14) + CFI_RESTORE(%r15) + CFI_DEF_CFA_OFFSET(CFA_OFFSET) + lmg %r2, %r3, R2_REL_OFFSET(%r15) + CFI_RESTORE(%r2) + CFI_RESTORE(%r3) + larl %r1, \real + lg %r1, 0(%r1) + br %r1 + CFI_ENDPROC + ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(\symbol)) +.endm + +intercept setjmp, _ZN14__interception11real_setjmpE +intercept _setjmp, _ZN14__interception12real__setjmpE +intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE +intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE diff --git a/compiler-rt/test/tsan/ignore_lib0.cpp b/compiler-rt/test/tsan/ignore_lib0.cpp --- a/compiler-rt/test/tsan/ignore_lib0.cpp +++ b/compiler-rt/test/tsan/ignore_lib0.cpp @@ -1,7 +1,7 @@ // RUN: rm -rf %t-dir // RUN: mkdir %t-dir -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib0.so +// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib0.so // RUN: %clangxx_tsan -O1 %s -L%t-dir -lignore_lib0 %link_libcxx_tsan -o %t // RUN: echo running w/o suppressions: // RUN: env LD_LIBRARY_PATH=%t-dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP diff --git a/compiler-rt/test/tsan/ignore_lib1.cpp b/compiler-rt/test/tsan/ignore_lib1.cpp --- a/compiler-rt/test/tsan/ignore_lib1.cpp +++ b/compiler-rt/test/tsan/ignore_lib1.cpp @@ -1,7 +1,7 @@ // RUN: rm -rf %t-dir // RUN: mkdir %t-dir -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so +// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so // RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t-dir/executable // RUN: echo running w/o suppressions: // RUN: %deflake %run %t-dir/executable | FileCheck %s --check-prefix=CHECK-NOSUPP diff --git a/compiler-rt/test/tsan/ignore_lib5.cpp b/compiler-rt/test/tsan/ignore_lib5.cpp --- a/compiler-rt/test/tsan/ignore_lib5.cpp +++ b/compiler-rt/test/tsan/ignore_lib5.cpp @@ -1,7 +1,7 @@ // RUN: rm -rf %t-dir // RUN: mkdir %t-dir -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so +// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so // RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t-dir/executable // RUN: echo running w/o suppressions: // RUN: %deflake %run %t-dir/executable | FileCheck %s --check-prefix=CHECK-NOSUPP diff --git a/compiler-rt/test/tsan/map32bit.cpp b/compiler-rt/test/tsan/map32bit.cpp --- a/compiler-rt/test/tsan/map32bit.cpp +++ b/compiler-rt/test/tsan/map32bit.cpp @@ -11,6 +11,7 @@ // XFAIL: mips // XFAIL: aarch64 // XFAIL: powerpc64 +// XFAIL: s390x // MAP_32BIT doesn't exist on OS X and NetBSD. // UNSUPPORTED: darwin,netbsd diff --git a/compiler-rt/test/tsan/mmap_large.cpp b/compiler-rt/test/tsan/mmap_large.cpp --- a/compiler-rt/test/tsan/mmap_large.cpp +++ b/compiler-rt/test/tsan/mmap_large.cpp @@ -21,6 +21,8 @@ const size_t kLog2Size = 32; #elif defined(__powerpc64__) const size_t kLog2Size = 39; +#elif defined(__s390x__) + const size_t kLog2Size = 43; #endif const uintptr_t kLocation = 0x40ULL << kLog2Size; void *p = mmap( diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -311,12 +311,21 @@ Type *Ty = Type::getIntNTy(M.getContext(), BitSize); Type *PtrTy = Ty->getPointerTo(); SmallString<32> AtomicLoadName("__tsan_atomic" + BitSizeStr + "_load"); - TsanAtomicLoad[i] = - M.getOrInsertFunction(AtomicLoadName, Attr, Ty, PtrTy, OrdTy); + { + AttributeList AL = Attr; + AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt); + TsanAtomicLoad[i] = + M.getOrInsertFunction(AtomicLoadName, AL, Ty, PtrTy, OrdTy); + } SmallString<32> AtomicStoreName("__tsan_atomic" + BitSizeStr + "_store"); - TsanAtomicStore[i] = M.getOrInsertFunction( - AtomicStoreName, Attr, IRB.getVoidTy(), PtrTy, Ty, OrdTy); + { + AttributeList AL = Attr; + AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt); + AL = AL.addParamAttribute(M.getContext(), 2, Attribute::ZExt); + TsanAtomicStore[i] = M.getOrInsertFunction( + AtomicStoreName, AL, IRB.getVoidTy(), PtrTy, Ty, OrdTy); + } for (unsigned Op = AtomicRMWInst::FIRST_BINOP; Op <= AtomicRMWInst::LAST_BINOP; ++Op) { @@ -339,24 +348,44 @@ else continue; SmallString<32> RMWName("__tsan_atomic" + itostr(BitSize) + NamePart); - TsanAtomicRMW[Op][i] = - M.getOrInsertFunction(RMWName, Attr, Ty, PtrTy, Ty, OrdTy); + { + AttributeList AL = Attr; + AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt); + AL = AL.addParamAttribute(M.getContext(), 2, Attribute::ZExt); + TsanAtomicRMW[Op][i] = + M.getOrInsertFunction(RMWName, AL, Ty, PtrTy, Ty, OrdTy); + } } SmallString<32> AtomicCASName("__tsan_atomic" + BitSizeStr + "_compare_exchange_val"); - TsanAtomicCAS[i] = M.getOrInsertFunction(AtomicCASName, Attr, Ty, PtrTy, Ty, - Ty, OrdTy, OrdTy); + { + AttributeList AL = Attr; + AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt); + AL = AL.addParamAttribute(M.getContext(), 2, Attribute::ZExt); + AL = AL.addParamAttribute(M.getContext(), 3, Attribute::ZExt); + AL = AL.addParamAttribute(M.getContext(), 4, Attribute::ZExt); + TsanAtomicCAS[i] = M.getOrInsertFunction(AtomicCASName, AL, Ty, PtrTy, Ty, + Ty, OrdTy, OrdTy); + } } TsanVptrUpdate = M.getOrInsertFunction("__tsan_vptr_update", Attr, IRB.getVoidTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy()); TsanVptrLoad = M.getOrInsertFunction("__tsan_vptr_read", Attr, IRB.getVoidTy(), IRB.getInt8PtrTy()); - TsanAtomicThreadFence = M.getOrInsertFunction("__tsan_atomic_thread_fence", - Attr, IRB.getVoidTy(), OrdTy); - TsanAtomicSignalFence = M.getOrInsertFunction("__tsan_atomic_signal_fence", - Attr, IRB.getVoidTy(), OrdTy); + { + AttributeList AL = Attr; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + TsanAtomicThreadFence = M.getOrInsertFunction("__tsan_atomic_thread_fence", + AL, IRB.getVoidTy(), OrdTy); + } + { + AttributeList AL = Attr; + AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt); + TsanAtomicSignalFence = M.getOrInsertFunction("__tsan_atomic_signal_fence", + AL, IRB.getVoidTy(), OrdTy); + } MemmoveFn = M.getOrInsertFunction("memmove", Attr, IRB.getInt8PtrTy(), diff --git a/llvm/utils/gn/secondary/compiler-rt/lib/tsan/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/lib/tsan/BUILD.gn --- a/llvm/utils/gn/secondary/compiler-rt/lib/tsan/BUILD.gn +++ b/llvm/utils/gn/secondary/compiler-rt/lib/tsan/BUILD.gn @@ -125,6 +125,8 @@ sources += [ "rtl/tsan_rtl_ppc64.S" ] } else if (target_cpu == "mips64") { sources += [ "rtl/tsan_rtl_mips64.S" ] + } else if (target_cpu == "s390x") { + sources += [ "rtl/tsan_rtl_s390x.S" ] } # To be able to include sanitizer_common.