diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 0146d8af35498631d2ecf6bf1cdd4c52f44814a6..69811c09559426216471b9280ccbdd79f0b9fb8f 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1273,7 +1273,8 @@ SanitizerMask ToolChain::getSupportedSanitizers() const { if (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64 || getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() || - getTriple().isAArch64() || getTriple().isRISCV()) + getTriple().isAArch64() || getTriple().isRISCV() || + getTriple().isLoongArch64()) Res |= SanitizerKind::CFIICall; if (getTriple().getArch() == llvm::Triple::x86_64 || getTriple().isAArch64(64) || getTriple().isRISCV()) diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 9442f6b91471f6a5b0e1e65f03e4196a2ffea234..4a525d75ea117f12abb0fbd3bc111d2304ca7b8e 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -600,6 +600,7 @@ // RUN: %clang --target=aarch64_be -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI // RUN: %clang --target=riscv32 -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI // RUN: %clang --target=riscv64 -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI +// RUN: %clang --target=loongarch64 -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI // CHECK-CFI: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-mfcall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall // CHECK-CFI-NOMFCALL: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall // CHECK-CFI-DCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index d14745ef9d138fede590c366c8c0dd63f8b65f35..9b0a4655cd6536c738b25b1c91cbe10344bc3b80 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -73,7 +73,7 @@ set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64} ${HEXAGON} ${LOONGARCH64}) set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64} - ${HEXAGON}) + ${HEXAGON} ${LOONGARCH64}) set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64} ${HEXAGON} ${LOONGARCH64} ${RISCV64}) if(APPLE) diff --git a/compiler-rt/lib/cfi/cfi.cpp b/compiler-rt/lib/cfi/cfi.cpp index 22f0b175dd87d9a86d7c18b163042d7a354d27aa..ad1c91623514e8fdf70072d4ed59f53dc545059b 100644 --- a/compiler-rt/lib/cfi/cfi.cpp +++ b/compiler-rt/lib/cfi/cfi.cpp @@ -51,7 +51,11 @@ using namespace __sanitizer; namespace __cfi { +#if SANITIZER_LOONGARCH64 +#define kCfiShadowLimitsStorageSize 16384 // 16KiB on loongarch64 per page +#else #define kCfiShadowLimitsStorageSize 4096 // 1 page +#endif // Lets hope that the data segment is mapped with 4K pages. // The pointer to the cfi shadow region is stored at the start of this page. // The rest of the page is unused and re-mapped read-only. diff --git a/compiler-rt/lib/tsan/go/buildgo.sh b/compiler-rt/lib/tsan/go/buildgo.sh index 0bd59368cc4673682858e36b52e80faf0074aaa0..78ba41a0bdc6d612a9035fbcd86ff2da9a356f61 100755 --- a/compiler-rt/lib/tsan/go/buildgo.sh +++ b/compiler-rt/lib/tsan/go/buildgo.sh @@ -10,6 +10,8 @@ if [ "`uname -a | grep Linux`" != "" ]; then HOST_GOARCH="amd64" elif [ "`uname -a | grep aarch64`" != "" ]; then HOST_GOARCH="arm64" + elif [ "`uname -a | grep loongarch64`" != "" ]; then + HOST_GOARCH="loong64" elif [ "`uname -a | grep -i mips64`" != "" ]; then if [ "`lscpu | grep -i Little`" != "" ]; then HOST_GOARCH="mips64le" diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 177e338bf28288b493d99c28b8a1f9dd843cd1bb..622afc90a57761e982d41de5af28168931e69642 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -14,6 +14,7 @@ #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_errno.h" +#include "sanitizer_common/sanitizer_glibc_version.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" @@ -1595,47 +1596,40 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { FdAccess(thr, pc, fd); return REAL(__fxstat)(version, fd, buf); } -#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat) + +TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { + SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); + if (fd > 0) + FdAccess(thr, pc, fd); + return REAL(__fxstat64)(version, fd, buf); +} +#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat); TSAN_INTERCEPT(__fxstat64) #else #define TSAN_MAYBE_INTERCEPT___FXSTAT #endif +#if !SANITIZER_GLIBC || __GLIBC_PREREQ(2, 33) TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_GLIBC - SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf); - if (fd > 0) - FdAccess(thr, pc, fd); - return REAL(__fxstat)(0, fd, buf); -#else SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); return REAL(fstat)(fd, buf); -#endif -} - -#if SANITIZER_GLIBC -TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { - SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); - if (fd > 0) - FdAccess(thr, pc, fd); - return REAL(__fxstat64)(version, fd, buf); } -#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64) +# define TSAN_MAYBE_INTERCEPT_FSTAT TSAN_INTERCEPT(fstat) #else -#define TSAN_MAYBE_INTERCEPT___FXSTAT64 +# define TSAN_MAYBE_INTERCEPT_FSTAT #endif -#if SANITIZER_GLIBC +#if __GLIBC_PREREQ(2, 33) TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { - SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); + SCOPED_TSAN_INTERCEPTOR(fstat64, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); - return REAL(__fxstat64)(0, fd, buf); + return REAL(fstat64)(fd, buf); } -#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64) +# define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64) #else -#define TSAN_MAYBE_INTERCEPT_FSTAT64 +# define TSAN_MAYBE_INTERCEPT_FSTAT64 #endif TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) { @@ -2929,10 +2923,9 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pthread_once); - TSAN_INTERCEPT(fstat); TSAN_MAYBE_INTERCEPT___FXSTAT; + TSAN_MAYBE_INTERCEPT_FSTAT; TSAN_MAYBE_INTERCEPT_FSTAT64; - TSAN_MAYBE_INTERCEPT___FXSTAT64; TSAN_INTERCEPT(open); TSAN_MAYBE_INTERCEPT_OPEN64; TSAN_INTERCEPT(creat); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h index f0cdaf48eaa3102e669e366ae431af998dc364f0..48dd56d1575142aae77a9f2c0c7e0b687ea532bc 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -558,6 +558,35 @@ struct MappingGoAarch64 { static const uptr kShadowAdd = 0x200000000000ull; }; +/* Go on linux/loongarch64 (47-bit VMA) +0000 0000 1000 - 0000 1000 0000: executable +0000 1000 0000 - 00c0 0000 0000: - +00c0 0000 0000 - 00e0 0000 0000: heap +00e0 0000 0000 - 2000 0000 0000: - +2000 0000 0000 - 2800 0000 0000: shadow +2800 0000 0000 - 3000 0000 0000: - +3000 0000 0000 - 3200 0000 0000: metainfo (memory blocks and sync objects) +3200 0000 0000 - 8000 0000 0000: - +*/ +struct MappingGoLoongArch64_47 { + static const uptr kMetaShadowBeg = 0x300000000000ull; + static const uptr kMetaShadowEnd = 0x320000000000ull; + static const uptr kShadowBeg = 0x200000000000ull; + static const uptr kShadowEnd = 0x280000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x00e000000000ull; + static const uptr kMidAppMemBeg = 0; + static const uptr kMidAppMemEnd = 0; + static const uptr kHiAppMemBeg = 0; + static const uptr kHiAppMemEnd = 0; + static const uptr kHeapMemBeg = 0; + static const uptr kHeapMemEnd = 0; + static const uptr kVdsoBeg = 0; + static const uptr kShadowMsk = 0; + static const uptr kShadowXor = 0; + static const uptr kShadowAdd = 0x200000000000ull; +}; + /* Go on linux/mips64 (47-bit VMA) 0000 0000 1000 - 0000 1000 0000: executable @@ -633,6 +662,8 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) { return Func::template Apply(arg); # elif defined(__aarch64__) return Func::template Apply(arg); +# elif defined(__loongarch_lp64) + return Func::template Apply(arg); # elif SANITIZER_WINDOWS return Func::template Apply(arg); # else @@ -692,6 +723,7 @@ void ForEachMapping() { Func::template Apply(); Func::template Apply(); Func::template Apply(); + Func::template Apply(); Func::template Apply(); Func::template Apply(); } diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp index 384a443c16b0b2e7c0733c085c41c130ddeeabe8..3f4a3760794fc8c94c2ae9dd91709934b7080ef2 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp @@ -238,7 +238,13 @@ void InitializePlatformEarly() { Printf("FATAL: Found %zd - Supported 47\n", vmaSize); Die(); } -# endif +# else + 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) { diff --git a/compiler-rt/test/cfi/cross-dso/icall/dlopen.cpp b/compiler-rt/test/cfi/cross-dso/icall/dlopen.cpp index c9674c3fb412a2a4fb44710fd764b0e6b792dd9e..d04f7ba5dd0e06c5667eb525c86b25919be30622 100644 --- a/compiler-rt/test/cfi/cross-dso/icall/dlopen.cpp +++ b/compiler-rt/test/cfi/cross-dso/icall/dlopen.cpp @@ -53,6 +53,13 @@ struct A { virtual void f(); }; +// The page size of LoongArch is 16KiB, aligned to the memory page size. +#ifdef __loongarch__ +# define PAGESIZE 16384 +#else +# define PAGESIZE 4096 +#endif + #ifdef SHARED_LIB #include "../../utils.h" @@ -66,13 +73,13 @@ extern "C" void *create_B() { return (void *)(new B()); } -extern "C" __attribute__((aligned(4096))) void do_nothing() {} +extern "C" __attribute__((aligned(PAGESIZE))) void do_nothing() {} #else void A::f() {} -static const int kCodeAlign = 4096; +static const int kCodeAlign = PAGESIZE; static const int kCodeSize = 4096; static char saved_code[kCodeSize]; static char *real_start; diff --git a/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg.py b/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg.py index 749c265bbf1c0c00472acea55a1b4bc8bc45c8dd..6e64199ed5c5043258be8a8bd929e420be220383 100644 --- a/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg.py +++ b/compiler-rt/test/cfi/cross-dso/icall/lit.local.cfg.py @@ -1,3 +1,3 @@ # The cfi-icall checker is only supported on x86 and x86_64 for now. -if config.root.host_arch not in ["x86", "x86_64"]: +if config.root.host_arch not in ["x86", "x86_64", "loongarch64"]: config.unsupported = True diff --git a/compiler-rt/test/cfi/icall/lit.local.cfg.py b/compiler-rt/test/cfi/icall/lit.local.cfg.py index 749c265bbf1c0c00472acea55a1b4bc8bc45c8dd..6e64199ed5c5043258be8a8bd929e420be220383 100644 --- a/compiler-rt/test/cfi/icall/lit.local.cfg.py +++ b/compiler-rt/test/cfi/icall/lit.local.cfg.py @@ -1,3 +1,3 @@ # The cfi-icall checker is only supported on x86 and x86_64 for now. -if config.root.host_arch not in ["x86", "x86_64"]: +if config.root.host_arch not in ["x86", "x86_64", "loongarch64"]: config.unsupported = True diff --git a/compiler-rt/test/fuzzer/exit_on_src_pos.test b/compiler-rt/test/fuzzer/exit_on_src_pos.test index 541e0c4c6e4248c6c6bb615264546d2f8fd913d9..020424e2d9fddea9dccd61972829e9c5aa0946a3 100644 --- a/compiler-rt/test/fuzzer/exit_on_src_pos.test +++ b/compiler-rt/test/fuzzer/exit_on_src_pos.test @@ -6,6 +6,8 @@ # Test does not complete on Armv7 Thumb build bot UNSUPPORTED: target=thumb{{.*}} +# Timeout on loongarch64 machine +UNSUPPORTED: target=loongarch64{{.*}} RUN: %cpp_compiler -O0 %S/SimpleTest.cpp -o %t-SimpleTest.exe -mllvm -use-unknown-locations=Disable RUN: %cpp_compiler -O0 %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest.exe diff --git a/compiler-rt/test/msan/signal_stress_test.cpp b/compiler-rt/test/msan/signal_stress_test.cpp index aade0f1f4051e0a8a0459d94f5fcdf7facda901a..043393fce6defc4552347c4379240201b5f781c3 100644 --- a/compiler-rt/test/msan/signal_stress_test.cpp +++ b/compiler-rt/test/msan/signal_stress_test.cpp @@ -5,9 +5,6 @@ // Reported deadly signal due to stack-overflow // XFAIL: target={{.*netbsd.*}} -// VarArg implementation on LoongArch isn't supported yet. -// UNSUPPORTED: target=loongarch{{.*}} - #include #include #include diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/odd_stack_size.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/odd_stack_size.cpp index fc31212b7f18b23f651cd295530329d2c5c3e225..9d7d46b462a88cafd10cfeb75365a845554067e0 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/odd_stack_size.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/odd_stack_size.cpp @@ -5,6 +5,8 @@ // AddressSanitizer: CHECK failed: asan_thread.cpp:315 "((AddrIsInStack((uptr)&local))) != (0)" // https://lab.llvm.org/buildbot/#/builders/18/builds/8162 // UNSUPPORTED: target=powerpc64{{.*}} +/// Occasionally fail on loongarch64 machine +// UNSUPPORTED: target=loongarch64{{.*}} #include #include diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp index 67351a9164412df59eb07f1c5dcf691b4af86412..0fa77200bf1cc0d14ba439c7b0d973df49d50d58 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp @@ -3,7 +3,7 @@ // Temporarily disable test // UNSUPPORTED: tsan -// UNSUPPORTED: target=powerpc64{{.*}} +// UNSUPPORTED: target={{(powerpc64|loongarch64).*}} // Not needed, no allocator. // UNSUPPORTED: ubsan diff --git a/compiler-rt/test/xray/TestCases/Posix/fdr-mode.cpp b/compiler-rt/test/xray/TestCases/Posix/fdr-mode.cpp index 3065981a2c9a733e8684ece8be2a95d5c7e9d2c8..0ee8aaa755d5a4167975a6af16caa3fdb3cecceb 100644 --- a/compiler-rt/test/xray/TestCases/Posix/fdr-mode.cpp +++ b/compiler-rt/test/xray/TestCases/Posix/fdr-mode.cpp @@ -19,6 +19,8 @@ // RUN: rm fdr-logging-test-* // RUN: rm fdr-unwrite-test-* // UNSUPPORTED: target=powerpc64le-{{.*}} +/// TODO: FDR logging arg1 handler(__xray_ArgLoggerEntry) hasn't implemented yet on LoongArch +// UNSUPPORTED: target=loongarch64{{.*}} // REQUIRES: built-in-llvm-tree #include "xray/xray_log_interface.h" diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp index 9b4b3efd7283e574cd05b41928eb0451f6ae31cd..a89d57d12615d2c7f45ec0b9839da1c6e429faeb 100644 --- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -1196,6 +1196,7 @@ static const unsigned kARMJumpTableEntrySize = 4; static const unsigned kARMBTIJumpTableEntrySize = 8; static const unsigned kARMv6MJumpTableEntrySize = 16; static const unsigned kRISCVJumpTableEntrySize = 8; +static const unsigned kLOONGARCH64JumpTableEntrySize = 8; unsigned LowerTypeTestsModule::getJumpTableEntrySize() { switch (JumpTableArch) { @@ -1222,6 +1223,8 @@ unsigned LowerTypeTestsModule::getJumpTableEntrySize() { case Triple::riscv32: case Triple::riscv64: return kRISCVJumpTableEntrySize; + case Triple::loongarch64: + return kLOONGARCH64JumpTableEntrySize; default: report_fatal_error("Unsupported architecture for jump tables"); } @@ -1286,6 +1289,9 @@ void LowerTypeTestsModule::createJumpTableEntry( } else if (JumpTableArch == Triple::riscv32 || JumpTableArch == Triple::riscv64) { AsmOS << "tail $" << ArgIndex << "@plt\n"; + } else if (JumpTableArch == Triple::loongarch64) { + AsmOS << "pcalau12i $$t0, %pc_hi20($" << ArgIndex << ")\n" + << "jirl $$r0, $$t0, %pc_lo12($" << ArgIndex << ")\n"; } else { report_fatal_error("Unsupported architecture for jump tables"); } @@ -1304,7 +1310,8 @@ void LowerTypeTestsModule::buildBitSetsFromFunctions( ArrayRef TypeIds, ArrayRef Functions) { if (Arch == Triple::x86 || Arch == Triple::x86_64 || Arch == Triple::arm || Arch == Triple::thumb || Arch == Triple::aarch64 || - Arch == Triple::riscv32 || Arch == Triple::riscv64) + Arch == Triple::riscv32 || Arch == Triple::riscv64 || + Arch == Triple::loongarch64) buildBitSetsFromFunctionsNative(TypeIds, Functions); else if (Arch == Triple::wasm32 || Arch == Triple::wasm64) buildBitSetsFromFunctionsWASM(TypeIds, Functions); diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 83d90049abc39e0965a03dbbe738d580a52db183..362fd6e4151f921be6372a0f5b1c91839a424cda 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -4945,6 +4945,7 @@ struct VarArgAMD64Helper : public VarArgHelper { }; /// MIPS64-specific implementation of VarArgHelper. +/// NOTE: This is also used for LoongArch64. struct VarArgMIPS64Helper : public VarArgHelper { Function &F; MemorySanitizer &MS; @@ -5836,6 +5837,10 @@ struct VarArgSystemZHelper : public VarArgHelper { } }; +// Loongarch64 is not a MIPS, but the current vargs calling convention matches +// the MIPS. +using VarArgLoongArch64Helper = VarArgMIPS64Helper; + /// A no-op implementation of VarArgHelper. struct VarArgNoOpHelper : public VarArgHelper { VarArgNoOpHelper(Function &F, MemorySanitizer &MS, @@ -5868,6 +5873,8 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan, return new VarArgPowerPC64Helper(Func, Msan, Visitor); else if (TargetTriple.getArch() == Triple::systemz) return new VarArgSystemZHelper(Func, Msan, Visitor); + else if (TargetTriple.isLoongArch64()) + return new VarArgLoongArch64Helper(Func, Msan, Visitor); else return new VarArgNoOpHelper(Func, Msan, Visitor); } diff --git a/llvm/test/Instrumentation/MemorySanitizer/LoongArch/vararg-loongarch64.ll b/llvm/test/Instrumentation/MemorySanitizer/LoongArch/vararg-loongarch64.ll new file mode 100644 index 0000000000000000000000000000000000000000..8a4ab59588adb6086557310f7de1102a046eb1fc --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/LoongArch/vararg-loongarch64.ll @@ -0,0 +1,78 @@ +; RUN: opt < %s -S -passes=msan 2>&1 | FileCheck %s + +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" +target triple = "loongarch64-unknown-linux-gnu" + +;; First, check allocation of the save area. +declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #1 +declare void @llvm.va_start(ptr) #2 +declare void @llvm.va_end(ptr) #2 +declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #1 +define i32 @foo(i32 %guard, ...) { +; CHECK-LABEL: @foo +; CHECK: [[TMP1:%.*]] = load {{.*}} @__msan_va_arg_overflow_size_tls +; CHECK: [[TMP2:%.*]] = add i64 0, [[TMP1]] +; CHECK: [[TMP3:%.*]] = alloca {{.*}} [[TMP2]] +; CHECK: call void @llvm.memset.p0.i64(ptr align 8 [[TMP3]], i8 0, i64 [[TMP2]], i1 false) +; CHECK: [[TMP4:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 800) +; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP3]], ptr align 8 @__msan_va_arg_tls, i64 [[TMP4]], i1 false) +; + %vl = alloca ptr, align 8 + call void @llvm.lifetime.start.p0(i64 32, ptr %vl) + call void @llvm.va_start(ptr %vl) + call void @llvm.va_end(ptr %vl) + call void @llvm.lifetime.end.p0(i64 32, ptr %vl) + ret i32 0 +} + +;; Save the incoming shadow value from the arguments in the __msan_va_arg_tls +;; array. +define i32 @bar() { +; CHECK-LABEL: @bar +; CHECK: store i32 0, ptr @__msan_va_arg_tls, align 8 +; CHECK: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 8) to ptr), align 8 +; CHECK: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 16) to ptr), align 8 +; CHECK: store {{.*}} 24, {{.*}} @__msan_va_arg_overflow_size_tls +; + %1 = call i32 (i32, ...) @foo(i32 0, i32 1, i64 2, double 3.000000e+00) + ret i32 %1 +} + +;; Check multiple fixed arguments. +declare i32 @foo2(i32 %g1, i32 %g2, ...) +define i32 @bar2() { +; CHECK-LABEL: @bar2 +; CHECK: store i64 0, ptr @__msan_va_arg_tls, align 8 +; CHECK: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 8) to ptr), align 8 +; CHECK: store {{.*}} 16, {{.*}} @__msan_va_arg_overflow_size_tls +; + %1 = call i32 (i32, i32, ...) @foo2(i32 0, i32 1, i64 2, double 3.000000e+00) + ret i32 %1 +} + +;; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are +;; passed to a variadic function. +declare i64 @sum(i64 %n, ...) +define dso_local i64 @many_args() { +;; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed. +; CHECK-LABEL: @many_args +; CHECK: i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 792) +; CHECK-NOT: i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 800) +; +entry: + %ret = call i64 (i64, ...) @sum(i64 120, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, + i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1 + ) + ret i64 %ret +} diff --git a/llvm/test/Transforms/LowerTypeTests/function-weak.ll b/llvm/test/Transforms/LowerTypeTests/function-weak.ll index ff69abacc8e93af8a15e07fdf066b19684484cde..c765937f19913404e79e048f3906ba45792a0a3c 100644 --- a/llvm/test/Transforms/LowerTypeTests/function-weak.ll +++ b/llvm/test/Transforms/LowerTypeTests/function-weak.ll @@ -4,6 +4,7 @@ ; RUN: opt -S -passes=lowertypetests -mtriple=aarch64-unknown-linux-gnu %s | FileCheck --check-prefixes=CHECK,ARM %s ; RUN: opt -S -passes=lowertypetests -mtriple=riscv32-unknown-linux-gnu %s | FileCheck --check-prefixes=CHECK,RISCV %s ; RUN: opt -S -passes=lowertypetests -mtriple=riscv64-unknown-linux-gnu %s | FileCheck --check-prefixes=CHECK,RISCV %s +; RUN: opt -S -passes=lowertypetests -mtriple=loongarch64-unknown-linux-gnu %s | FileCheck --check-prefixes=CHECK,LOONGARCH64 %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -116,6 +117,7 @@ define i1 @foo(ptr %p) { ; X86: define private void @[[JT]]() #{{.*}} align 8 { ; ARM: define private void @[[JT]]() #{{.*}} align 4 { ; RISCV: define private void @[[JT]]() #{{.*}} align 8 { +; LOONGARCH64: define private void @[[JT]]() #{{.*}} align 8 { ; CHECK: define internal void @__cfi_global_var_init() section ".text.startup" { ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/LowerTypeTests/function.ll b/llvm/test/Transforms/LowerTypeTests/function.ll index 968c9d434eb2f604e0628aa22fe1a50a55f1caa3..802b88d92977fee623bf76405476ff4c551ee2e8 100644 --- a/llvm/test/Transforms/LowerTypeTests/function.ll +++ b/llvm/test/Transforms/LowerTypeTests/function.ll @@ -5,6 +5,7 @@ ; RUN: opt -S -passes=lowertypetests -mtriple=riscv32-unknown-linux-gnu %s | FileCheck --check-prefixes=RISCV,NATIVE %s ; RUN: opt -S -passes=lowertypetests -mtriple=riscv64-unknown-linux-gnu %s | FileCheck --check-prefixes=RISCV,NATIVE %s ; RUN: opt -S -passes=lowertypetests -mtriple=wasm32-unknown-unknown %s | FileCheck --check-prefix=WASM32 %s +; RUN: opt -S -passes=lowertypetests -mtriple=loongarch64-unknown-linux-gnu %s | FileCheck --check-prefixes=LOONGARCH64,NATIVE %s ; The right format for Arm jump tables depends on the selected ; subtarget, so we can't get these tests right without the Arm target @@ -34,6 +35,7 @@ target datalayout = "e-p:64:64" ; THUMB: @g = internal alias void (), getelementptr inbounds ([2 x [4 x i8]], ptr @[[JT]], i64 0, i64 1) ; THUMBV6M: @g = internal alias void (), getelementptr inbounds ([2 x [16 x i8]], ptr @[[JT]], i64 0, i64 1) ; RISCV: @g = internal alias void (), getelementptr inbounds ([2 x [8 x i8]], ptr @[[JT]], i64 0, i64 1) +; LOONGARCH64: @g = internal alias void (), getelementptr inbounds ([2 x [8 x i8]], ptr @[[JT]], i64 0, i64 1) ; NATIVE: define hidden void @f.cfi() ; WASM32: define void @f() !type !{{[0-9]+}} !wasm.index ![[I0:[0-9]+]] @@ -65,6 +67,7 @@ define i1 @foo(ptr %p) { ; THUMB: define private void @[[JT]]() #[[ATTR:.*]] align 4 { ; THUMBV6M: define private void @[[JT]]() #[[ATTR:.*]] align 16 { ; RISCV: define private void @[[JT]]() #[[ATTR:.*]] align 8 { +; LOONGARCH64: define private void @[[JT]]() #[[ATTR:.*]] align 8 { ; X86: jmp ${0:c}@plt ; X86-SAME: int3 @@ -99,6 +102,11 @@ define i1 @foo(ptr %p) { ; RISCV: tail $0@plt ; RISCV-SAME: tail $1@plt +; LOONGARCH64: pcalau12i $$t0, %pc_hi20($0) +; LOONGARCH64-SAME: jirl $$r0, $$t0, %pc_lo12($0) +; LOONGARCH64-SAME: pcalau12i $$t0, %pc_hi20($1) +; LOONGARCH64-SAME: jirl $$r0, $$t0, %pc_lo12($1) + ; NATIVE-SAME: "s,s"(ptr @f.cfi, ptr @g.cfi) ; X86-LINUX: attributes #[[ATTR]] = { naked nocf_check nounwind } @@ -107,6 +115,7 @@ define i1 @foo(ptr %p) { ; THUMB: attributes #[[ATTR]] = { naked nounwind "target-cpu"="cortex-a8" "target-features"="+thumb-mode" } ; THUMBV6M: attributes #[[ATTR]] = { naked nounwind "target-features"="+thumb-mode" } ; RISCV: attributes #[[ATTR]] = { naked nounwind "target-features"="-c,-relax" } +; LOONGARCH64: attributes #[[ATTR]] = { naked nounwind } ; WASM32: ![[I0]] = !{i64 1} ; WASM32: ![[I1]] = !{i64 2}