From 37b00491c7550c4ed0d2a17d565e1f355cc41d67 Mon Sep 17 00:00:00 2001
From: herengui <herengui@kylinsec.com.cn>
Date: Thu, 31 Aug 2023 09:46:45 +0800
Subject: [PATCH 1000/1001] add loongarch64 support not upstream modified

Signed-off-by: herengui <herengui@kylinsec.com.cn>
---
 cmake/Modules/CompilerRTUtils.cmake           |   3 +
 cmake/base-config-ix.cmake                    |   2 +
 cmake/builtin-config-ix.cmake                 |   3 +-
 cmake/config-ix.cmake                         |  27 +-
 lib/asan/asan_interceptors.h                  |   9 +-
 lib/asan/asan_interceptors_vfork.S            |   1 +
 lib/asan/asan_malloc_linux.cpp                |   4 +
 lib/asan/asan_mapping.h                       |  14 +-
 lib/asan/scripts/asan_symbolize.py            |   2 +-
 lib/asan/tests/asan_test.cpp                  |  14 +-
 lib/builtins/CMakeLists.txt                   |   5 +
 lib/builtins/clear_cache.c                    |   2 +
 lib/crt/crtbegin.c                            |   8 +
 lib/dfsan/dfsan_platform.h                    |   7 +
 lib/fuzzer/FuzzerTracePC.cpp                  |   7 +-
 lib/fuzzer/FuzzerUtil.h                       |   3 +-
 lib/interception/tests/CMakeLists.txt         |   2 +-
 lib/lsan/lsan_allocator.cpp                   |   2 +-
 lib/lsan/lsan_allocator.h                     |   2 +-
 lib/lsan/lsan_common.cpp                      |   8 +-
 lib/lsan/lsan_common.h                        |   4 +-
 lib/msan/msan.h                               |  29 +-
 lib/msan/msan_allocator.cpp                   |   2 +-
 lib/msan/msan_interceptors.cpp                |   4 +
 lib/msan/tests/msan_test.cpp                  |  10 +-
 lib/safestack/safestack_platform.h            |   6 +
 lib/sanitizer_common/CMakeLists.txt           |   1 +
 lib/sanitizer_common/sanitizer_common.h       |   5 +-
 .../sanitizer_common_syscalls.inc             |   4 +-
 .../sanitizer_coverage_libcdep_new.cpp        |  14 +-
 lib/sanitizer_common/sanitizer_linux.cpp      | 514 +++++++++++-------
 lib/sanitizer_common/sanitizer_linux.h        |   2 +-
 .../sanitizer_linux_libcdep.cpp               |  31 +-
 lib/sanitizer_common/sanitizer_platform.h     |  42 +-
 .../sanitizer_platform_interceptors.h         |   7 +-
 .../sanitizer_platform_limits_linux.cpp       |   6 +-
 .../sanitizer_platform_limits_posix.cpp       |  71 +--
 .../sanitizer_platform_limits_posix.h         |  25 +-
 lib/sanitizer_common/sanitizer_ring_buffer.h  |   9 +-
 lib/sanitizer_common/sanitizer_stacktrace.cpp |   7 +-
 lib/sanitizer_common/sanitizer_stacktrace.h   |   7 +-
 .../sanitizer_stoptheworld_linux_libcdep.cpp  | 108 ++--
 .../sanitizer_symbolizer_libcdep.cpp          |   2 +
 .../sanitizer_tls_get_addr.cpp                |   8 +-
 lib/sanitizer_common/tests/CMakeLists.txt     |   2 +-
 .../tests/sanitizer_allocator_test.cpp        |   6 +-
 .../tests/sanitizer_ring_buffer_test.cpp      |   5 +-
 .../tests/sanitizer_stacktrace_test.cpp       |  16 +-
 lib/scudo/scudo_utils.cpp                     |   2 +
 lib/scudo/standalone/checksum.cpp             |   2 +
 lib/scudo/standalone/common.h                 |   4 +
 lib/tsan/CMakeLists.txt                       |   4 +-
 lib/tsan/rtl/tsan_interceptors_posix.cpp      |   2 +
 lib/tsan/rtl/tsan_platform.h                  |  47 +-
 lib/tsan/rtl/tsan_platform_linux.cpp          |  13 +-
 lib/tsan/rtl/tsan_rtl.cpp                     |   4 +-
 lib/tsan/rtl/tsan_rtl.h                       |   3 +-
 lib/xray/CMakeLists.txt                       |   6 +
 lib/xray/tests/CMakeLists.txt                 |   1 +
 lib/xray/xray_interface.cpp                   |   2 +
 lib/xray/xray_tsc.h                           |   3 +-
 test/asan/CMakeLists.txt                      |   2 +-
 test/asan/TestCases/Linux/ptrace.cpp          |   9 +-
 test/asan/TestCases/Linux/segv_read_write.c   |   2 +-
 .../Posix/unpoison-alternate-stack.cpp        |   4 +-
 test/builtins/Unit/addtf3_test.c              |   2 +-
 test/builtins/Unit/subtf3_test.c              |   2 +-
 test/fuzzer/disable-leaks.test                |   2 +-
 test/fuzzer/exit_on_src_pos.test              |   2 +
 test/fuzzer/fork-ubsan.test                   |   2 +-
 test/lit.common.cfg.py                        |   2 +-
 test/lsan/TestCases/strace_test.cpp           |   1 +
 test/lsan/TestCases/swapcontext.cpp           |   2 +-
 test/lsan/TestCases/use_registers.cpp         |   4 +
 test/lsan/lit.common.cfg.py                   |   2 +-
 test/msan/allocator_mapping.cpp               |   2 +-
 test/msan/fstat.cpp                           |   2 +-
 test/msan/lit.cfg.py                          |   2 +-
 test/msan/mmap.cpp                            |   6 +-
 test/msan/mmap_below_shadow.cpp               |   2 +-
 test/msan/param_tls_limit.cpp                 |   4 +-
 test/msan/preinit_array.cpp                   |   3 +
 test/msan/strlen_of_shadow.cpp                |   4 +-
 test/msan/vararg.cpp                          |   3 +-
 test/msan/vector_select.cpp                   |   2 +-
 test/msan/wcsncpy.cpp                         |   2 +-
 .../TestCases/Linux/pthread_mutex.cpp         |   3 +-
 .../TestCases/Linux/ptrace.cpp                |  22 +-
 .../Linux/sysconf_interceptor_bypass_test.cpp |   3 +-
 .../TestCases/Posix/lstat.cpp                 |   2 +-
 test/sanitizer_common/print_address.h         |   2 +-
 test/tsan/map32bit.cpp                        |   1 +
 test/tsan/mmap_large.cpp                      |   2 +
 test/tsan/test.h                              |   2 +
 .../TestCases/Posix/arg1-arg0-logging.cpp     |   2 +-
 test/xray/TestCases/Posix/arg1-logger.cpp     |   2 +-
 .../Posix/arg1-logging-implicit-this.cpp      |   2 +-
 .../TestCases/Posix/argv0-log-file-name.cpp   |   1 +
 test/xray/TestCases/Posix/coverage-sample.cpp |   1 +
 .../TestCases/Posix/fixedsize-logging.cpp     |   1 +
 test/xray/TestCases/Posix/func-id-utils.cpp   |   1 +
 test/xray/TestCases/Posix/logging-modes.cpp   |   1 +
 .../TestCases/Posix/optional-inmemory-log.cpp |   1 +
 .../TestCases/Posix/patching-unpatching.cpp   |   1 +
 test/xray/TestCases/Posix/pic_test.cpp        |   1 +
 105 files changed, 845 insertions(+), 441 deletions(-)

diff --git a/compiler-rt.orig/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt.new/cmake/Modules/CompilerRTUtils.cmake
index f61d487..49d0eac 100644
--- a/compiler-rt.orig/cmake/Modules/CompilerRTUtils.cmake
+++ b/compiler-rt.new/cmake/Modules/CompilerRTUtils.cmake
@@ -162,6 +162,7 @@ macro(detect_target_arch)
   check_symbol_exists(__powerpc64__ "" __PPC64)
   check_symbol_exists(__powerpc64le__ "" __PPC64LE)
   check_symbol_exists(__riscv "" __RISCV)
+  check_symbol_exists(__loongarch64 "" __LOONGARCH64)
   check_symbol_exists(__s390x__ "" __S390X)
   check_symbol_exists(__sparc "" __SPARC)
   check_symbol_exists(__sparcv9 "" __SPARCV9)
@@ -194,6 +195,8 @@ macro(detect_target_arch)
     else()
       message(FATAL_ERROR "Unsupport XLEN for RISC-V")
     endif()
+  elseif(__LOONGARCH64)
+    add_default_target_arch(loongarch64)
   elseif(__S390X)
     add_default_target_arch(s390x)
   elseif(__SPARCV9)
diff --git a/compiler-rt.orig/cmake/base-config-ix.cmake b/compiler-rt.new/cmake/base-config-ix.cmake
index 1edab43..5fdcdab 100644
--- a/compiler-rt.orig/cmake/base-config-ix.cmake
+++ b/compiler-rt.new/cmake/base-config-ix.cmake
@@ -224,6 +224,8 @@ macro(test_targets)
       test_target_arch(wasm64 "" "--target=wasm64-unknown-unknown")
     elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "ve")
       test_target_arch(ve "__ve__" "--target=ve-unknown-none")
+    elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "loongarch64")
+      test_target_arch(loongarch64 "" "")
     endif()
     set(COMPILER_RT_OS_SUFFIX "")
   endif()
diff --git a/compiler-rt.orig/cmake/builtin-config-ix.cmake b/compiler-rt.new/cmake/builtin-config-ix.cmake
index ad3b987..18b35f1 100644
--- a/compiler-rt.orig/cmake/builtin-config-ix.cmake
+++ b/compiler-rt.new/cmake/builtin-config-ix.cmake
@@ -52,6 +52,7 @@ set(SPARCV9 sparcv9)
 set(WASM32 wasm32)
 set(WASM64 wasm64)
 set(VE ve)
+set(LOONGARCH64 loongarch64)
 
 if(APPLE)
   set(ARM64 arm64 arm64e)
@@ -63,7 +64,7 @@ set(ALL_BUILTIN_SUPPORTED_ARCH
   ${X86} ${X86_64} ${ARM32} ${ARM64}
   ${HEXAGON} ${MIPS32} ${MIPS64} ${PPC32} ${PPC64}
   ${RISCV32} ${RISCV64} ${SPARC} ${SPARCV9}
-  ${WASM32} ${WASM64} ${VE})
+  ${WASM32} ${WASM64} ${VE} ${LOONGARCH64})
 
 include(CompilerRTUtils)
 include(CompilerRTDarwinUtils)
diff --git a/compiler-rt.orig/cmake/config-ix.cmake b/compiler-rt.new/cmake/config-ix.cmake
index f81b838..979e6c9 100644
--- a/compiler-rt.orig/cmake/config-ix.cmake
+++ b/compiler-rt.new/cmake/config-ix.cmake
@@ -288,6 +288,7 @@ set(SPARCV9 sparcv9)
 set(WASM32 wasm32)
 set(WASM64 wasm64)
 set(VE ve)
+set(LOONGARCH64 loongarch64)
 
 if(APPLE)
   set(ARM64 arm64)
@@ -296,11 +297,11 @@ if(APPLE)
 endif()
 
 set(ALL_SANITIZER_COMMON_SUPPORTED_ARCH ${X86} ${X86_64} ${PPC64} ${RISCV64}
-    ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9})
+    ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${LOONGARCH64})
 set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
-    ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9})
+    ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${LOONGARCH64})
 set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV32} ${RISCV64} ${VE})
-set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
+set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${LOONGARCH64})
 
 if(ANDROID)
   set(OS_NAME "Android")
@@ -309,7 +310,7 @@ else()
 endif()
 
 if(OS_NAME MATCHES "Linux")
-  set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${S390X})
+  set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${S390X} ${LOONGARCH64})
 elseif (OS_NAME MATCHES "Windows")
   set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64})
 elseif(OS_NAME MATCHES "Android")
@@ -322,24 +323,24 @@ set(ALL_GWP_ASAN_SUPPORTED_ARCH ${X86} ${X86_64})
 if(APPLE)
   set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64})
 else()
-  set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64} ${S390X})
+  set(ALL_LSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64} ${ARM64} ${ARM32} ${PPC64} ${S390X} ${LOONGARCH64})
 endif()
-set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X})
+set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X} ${LOONGARCH64})
 set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64})
 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})
+    ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${LOONGARCH64})
+set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${LOONGARCH64})
 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})
-set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64})
-set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64})
+    ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${LOONGARCH64})
+set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64} ${LOONGARCH64})
+set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64} ${LOONGARCH64})
+set(ALL_SCUDO_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64} ${LOONGARCH64})
 set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64})
 if(APPLE)
 set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})
 else()
-set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le)
+set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le ${LOONGARCH64})
 endif()
 set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
 
diff --git a/compiler-rt.orig/lib/asan/asan_interceptors.h b/compiler-rt.new/lib/asan/asan_interceptors.h
index 45cdb80..2c6d208 100644
--- a/compiler-rt.orig/lib/asan/asan_interceptors.h
+++ b/compiler-rt.new/lib/asan/asan_interceptors.h
@@ -112,10 +112,11 @@ void InitializePlatformInterceptors();
 # define ASAN_INTERCEPT___STRDUP 0
 #endif
 
-#if SANITIZER_LINUX &&                                                \
-    (defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \
-     defined(__x86_64__) || SANITIZER_RISCV64)
-# define ASAN_INTERCEPT_VFORK 1
+#if SANITIZER_LINUX &&                                                    \
+        (defined(__arm__) || defined(__aarch64__) || defined(__i386__) || \
+         defined(__x86_64__) || SANITIZER_RISCV64) ||                     \
+    SANITIZER_LOONGARCH64
+#define ASAN_INTERCEPT_VFORK 1
 #else
 # define ASAN_INTERCEPT_VFORK 0
 #endif
diff --git a/compiler-rt.orig/lib/asan/asan_interceptors_vfork.S b/compiler-rt.new/lib/asan/asan_interceptors_vfork.S
index 3ae5503..74cbf3c 100644
--- a/compiler-rt.orig/lib/asan/asan_interceptors_vfork.S
+++ b/compiler-rt.new/lib/asan/asan_interceptors_vfork.S
@@ -7,6 +7,7 @@
 #include "sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S"
 #include "sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S"
 #include "sanitizer_common/sanitizer_common_interceptors_vfork_riscv64.inc.S"
+#include "sanitizer_common/sanitizer_common_interceptors_vfork_loongarch64.inc.S"
 #include "sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S"
 #endif
 
diff --git a/compiler-rt.orig/lib/asan/asan_malloc_linux.cpp b/compiler-rt.new/lib/asan/asan_malloc_linux.cpp
index 9c3f0a5..88a68c0 100644
--- a/compiler-rt.orig/lib/asan/asan_malloc_linux.cpp
+++ b/compiler-rt.new/lib/asan/asan_malloc_linux.cpp
@@ -31,7 +31,11 @@ using namespace __asan;
 
 static uptr allocated_for_dlsym;
 static uptr last_dlsym_alloc_size_in_words;
+#if SANITIZER_LOONGARCH64
+static const uptr kDlsymAllocPoolSize = 4096 * 4;
+#else
 static const uptr kDlsymAllocPoolSize = SANITIZER_RTEMS ? 4096 : 1024;
+#endif
 static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize];
 
 static inline bool IsInDlsymAllocPool(const void *ptr) {
diff --git a/compiler-rt.orig/lib/asan/asan_mapping.h b/compiler-rt.new/lib/asan/asan_mapping.h
index f239c3e..0b81c62 100644
--- a/compiler-rt.orig/lib/asan/asan_mapping.h
+++ b/compiler-rt.new/lib/asan/asan_mapping.h
@@ -178,6 +178,8 @@ static const u64 kAArch64_ShadowOffset64 = 1ULL << 36;
 static const u64 kRiscv64_ShadowOffset64 = 0x20000000;
 static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000;
 static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37;
+static const u64 kLoongArch32_ShadowOffset32 = 0x0aaa0000;
+static const u64 kLoongArch64_ShadowOffset64 = 1ULL << 46;
 static const u64 kPPC64_ShadowOffset64 = 1ULL << 44;
 static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52;
 static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43;  // 0x80000000000
@@ -205,6 +207,8 @@ static const u64 kMyriadCacheBitMask32 = 0x40000000ULL;
 #    define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
 #  elif defined(__mips__)
 #    define SHADOW_OFFSET kMIPS32_ShadowOffset32
+#elif SANITIZER_LOONGARCH
+#    define SHADOW_OFFSET kLoongArch32_ShadowOffset32
 #  elif SANITIZER_FREEBSD
 #    define SHADOW_OFFSET kFreeBSD_ShadowOffset32
 #  elif SANITIZER_NETBSD
@@ -239,12 +243,14 @@ static const u64 kMyriadCacheBitMask32 = 0x40000000ULL;
 #   define SHADOW_OFFSET kDefaultShadowOffset64
 #  elif defined(__mips64)
 #   define SHADOW_OFFSET kMIPS64_ShadowOffset64
-#elif defined(__sparc__)
-#define SHADOW_OFFSET kSPARC64_ShadowOffset64
+#elif SANITIZER_LOONGARCH64
+#    define SHADOW_OFFSET kLoongArch64_ShadowOffset64
+#  elif defined(__sparc__)
+#    define SHADOW_OFFSET kSPARC64_ShadowOffset64
 #  elif SANITIZER_WINDOWS64
-#   define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
+#    define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
 #  else
-#   define SHADOW_OFFSET kDefaultShort64bitShadowOffset
+#    define SHADOW_OFFSET kDefaultShort64bitShadowOffset
 #  endif
 #endif
 
diff --git a/compiler-rt.orig/lib/asan/scripts/asan_symbolize.py b/compiler-rt.new/lib/asan/scripts/asan_symbolize.py
index 5c4001a..8e28462 100755
--- a/compiler-rt.orig/lib/asan/scripts/asan_symbolize.py
+++ b/compiler-rt.new/lib/asan/scripts/asan_symbolize.py
@@ -50,7 +50,7 @@ def fix_filename(file_name):
 def is_valid_arch(s):
   return s in ["i386", "x86_64", "x86_64h", "arm", "armv6", "armv7", "armv7s",
                "armv7k", "arm64", "powerpc64", "powerpc64le", "s390x", "s390",
-               "riscv64"]
+               "riscv64" "loongarch64"]
 
 def guess_arch(addr):
   # Guess which arch we're running. 10 = len('0x') + 8 hex digits.
diff --git a/compiler-rt.orig/lib/asan/tests/asan_test.cpp b/compiler-rt.new/lib/asan/tests/asan_test.cpp
index c0b79bb..a0e0f83 100644
--- a/compiler-rt.orig/lib/asan/tests/asan_test.cpp
+++ b/compiler-rt.new/lib/asan/tests/asan_test.cpp
@@ -621,9 +621,9 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) {
   siglongjmp(buf, 1);
 }
 
-#if !defined(__ANDROID__) && !defined(__arm__) && !defined(__aarch64__) && \
-    !defined(__mips__) && !defined(__mips64) && !defined(__s390__) &&      \
-    !defined(__riscv)
+#  if !defined(__ANDROID__) && !defined(__arm__) && !defined(__aarch64__) && \
+      !defined(__mips__) && !defined(__mips64) && !defined(__s390__) &&      \
+      !defined(__riscv) && !defined(__loongarch__)
 NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) {
   // create three red zones for these two stack objects.
   int a;
@@ -645,10 +645,10 @@ TEST(AddressSanitizer, BuiltinLongJmpTest) {
     TouchStackFunc();
   }
 }
-#endif  // !defined(__ANDROID__) && !defined(__arm__) &&
-        // !defined(__aarch64__) && !defined(__mips__)
-        // !defined(__mips64) && !defined(__s390__)
-        // !defined(__riscv)
+#  endif  // !defined(__ANDROID__) && !defined(__arm__) &&
+          // !defined(__aarch64__) && !defined(__mips__)
+          // !defined(__mips64) && !defined(__s390__)
+          // !defined(__riscv) && !defined(__loongarch__)
 
 TEST(AddressSanitizer, UnderscopeLongJmpTest) {
   static jmp_buf buf;
diff --git a/compiler-rt.orig/lib/builtins/CMakeLists.txt b/compiler-rt.new/lib/builtins/CMakeLists.txt
index 73b6bea..8c1274c 100644
--- a/compiler-rt.orig/lib/builtins/CMakeLists.txt
+++ b/compiler-rt.new/lib/builtins/CMakeLists.txt
@@ -599,6 +599,11 @@ set(mips64_SOURCES ${GENERIC_TF_SOURCES}
                    ${mips_SOURCES})
 set(mips64el_SOURCES ${GENERIC_TF_SOURCES}
                      ${mips_SOURCES})
+set(loongarch64_SOURCES
+   loongarch/fp_mode.c
+   ${GENERIC_TF_SOURCES}
+   ${GENERIC_SOURCES}
+)
 
 set(powerpc_SOURCES ${GENERIC_SOURCES})
 
diff --git a/compiler-rt.orig/lib/builtins/clear_cache.c b/compiler-rt.new/lib/builtins/clear_cache.c
index 5a443dd..bc0865b 100644
--- a/compiler-rt.orig/lib/builtins/clear_cache.c
+++ b/compiler-rt.new/lib/builtins/clear_cache.c
@@ -163,6 +163,8 @@ void __clear_cache(void *start, void *end) {
                    : "=r"(start_reg)
                    : "r"(start_reg), "r"(end_reg), "r"(flags), "r"(syscall_nr));
   assert(start_reg == 0 && "Cache flush syscall failed.");
+#elif defined(__linux__) && defined(__loongarch__)
+  __asm__ volatile("ibar 0");
 #else
 #if __APPLE__
   // On Darwin, sys_icache_invalidate() provides this functionality
diff --git a/compiler-rt.orig/lib/crt/crtbegin.c b/compiler-rt.new/lib/crt/crtbegin.c
index 481c158..bbdc711 100644
--- a/compiler-rt.orig/lib/crt/crtbegin.c
+++ b/compiler-rt.new/lib/crt/crtbegin.c
@@ -56,6 +56,10 @@ __asm__(".pushsection .init,\"ax\",@progbits\n\t"
 __asm__(".pushsection .init,\"ax\",%progbits\n\t"
         "call " __USER_LABEL_PREFIX__ "__do_init\n\t"
         ".popsection");
+#elif defined(__loongarch__)
+__asm__(".pushsection .init,\"ax\",%progbits\n\t"
+        "bl " __USER_LABEL_PREFIX__ "__do_init\n\t"
+        ".popsection");
 #elif defined(__arm__) || defined(__aarch64__)
 __asm__(".pushsection .init,\"ax\",%progbits\n\t"
     "bl " __USER_LABEL_PREFIX__ "__do_init\n\t"
@@ -118,6 +122,10 @@ __asm__(".pushsection .fini,\"ax\",@progbits\n\t"
 __asm__(".pushsection .fini,\"ax\",@progbits\n\t"
         "call " __USER_LABEL_PREFIX__ "__do_fini\n\t"
         ".popsection");
+#elif defined(__loongarch__)
+__asm__(".pushsection .fini,\"ax\",@progbits\n\t"
+        "bl " __USER_LABEL_PREFIX__ "__do_fini\n\t"
+        ".popsection");
 #elif defined(__sparc__)
 __asm__(".pushsection .fini,\"ax\",@progbits\n\t"
     "call " __USER_LABEL_PREFIX__ "__do_fini\n\t"
diff --git a/compiler-rt.orig/lib/dfsan/dfsan_platform.h b/compiler-rt.new/lib/dfsan/dfsan_platform.h
index 4ff68b9..43006d4 100644
--- a/compiler-rt.orig/lib/dfsan/dfsan_platform.h
+++ b/compiler-rt.new/lib/dfsan/dfsan_platform.h
@@ -54,6 +54,13 @@ struct Mapping48 {
 
 extern int vmaSize;
 # define DFSAN_RUNTIME_VMA 1
+#elif defined(__loongarch__)
+struct Mapping {
+  static const uptr kShadowAddr = 0x10000;
+  static const uptr kUnionTableAddr = 0x8000000000;
+  static const uptr kAppAddr = 0x7fff00008000;
+  static const uptr kShadowMask = ~0x7ffff0000000;
+};
 #else
 # error "DFSan not supported for this platform!"
 #endif
diff --git a/compiler-rt.orig/lib/fuzzer/FuzzerTracePC.cpp b/compiler-rt.new/lib/fuzzer/FuzzerTracePC.cpp
index 91e94d8..152780b 100644
--- a/compiler-rt.orig/lib/fuzzer/FuzzerTracePC.cpp
+++ b/compiler-rt.new/lib/fuzzer/FuzzerTracePC.cpp
@@ -124,7 +124,8 @@ inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
   // so we return (pc-2) in that case in order to be safe.
   // For A32 mode we return (pc-4) because all instructions are 32 bit long.
   return (PC - 3) & (~1);
-#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
+#elif defined(__powerpc__) || defined(__powerpc64__) ||                        \
+    defined(__aarch64__) || defined(__loongarch__)
   // PCs are always 4 byte aligned.
   return PC - 4;
 #elif defined(__sparc__) || defined(__mips__)
@@ -139,8 +140,8 @@ inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
 ALWAYS_INLINE uintptr_t TracePC::GetNextInstructionPc(uintptr_t PC) {
 #if defined(__mips__)
   return PC + 8;
-#elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \
-    defined(__aarch64__)
+#elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) ||        \
+    defined(__aarch64__) || defined(__loongarch__)
   return PC + 4;
 #else
   return PC + 1;
diff --git a/compiler-rt.orig/lib/fuzzer/FuzzerUtil.h b/compiler-rt.new/lib/fuzzer/FuzzerUtil.h
index e90be08..d7d0490 100644
--- a/compiler-rt.orig/lib/fuzzer/FuzzerUtil.h
+++ b/compiler-rt.new/lib/fuzzer/FuzzerUtil.h
@@ -15,6 +15,7 @@
 #include "FuzzerBuiltinsMsvc.h"
 #include "FuzzerCommand.h"
 #include "FuzzerDefs.h"
+#include <unistd.h>
 
 namespace fuzzer {
 
@@ -92,7 +93,7 @@ size_t SimpleFastHash(const uint8_t *Data, size_t Size);
 
 inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; }
 
-inline size_t PageSize() { return 4096; }
+inline size_t PageSize() { return getpagesize(); }
 inline uint8_t *RoundUpByPage(uint8_t *P) {
   uintptr_t X = reinterpret_cast<uintptr_t>(P);
   size_t Mask = PageSize() - 1;
diff --git a/compiler-rt.orig/lib/interception/tests/CMakeLists.txt b/compiler-rt.new/lib/interception/tests/CMakeLists.txt
index 06184ee..5525510 100644
--- a/compiler-rt.orig/lib/interception/tests/CMakeLists.txt
+++ b/compiler-rt.new/lib/interception/tests/CMakeLists.txt
@@ -1,6 +1,6 @@
 include(CompilerRTCompile)
 
-filter_available_targets(INTERCEPTION_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el)
+filter_available_targets(INTERCEPTION_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el loongarch64)
 
 set(INTERCEPTION_UNITTESTS
   interception_linux_test.cpp
diff --git a/compiler-rt.orig/lib/lsan/lsan_allocator.cpp b/compiler-rt.new/lib/lsan/lsan_allocator.cpp
index 7042295..ec90a62 100644
--- a/compiler-rt.orig/lib/lsan/lsan_allocator.cpp
+++ b/compiler-rt.new/lib/lsan/lsan_allocator.cpp
@@ -28,7 +28,7 @@ extern "C" void *memset(void *ptr, int value, uptr num);
 namespace __lsan {
 #if defined(__i386__) || defined(__arm__)
 static const uptr kMaxAllowedMallocSize = 1UL << 30;
-#elif defined(__mips64) || defined(__aarch64__)
+#elif defined(__mips64) || defined(__aarch64__) || defined(__loongarch64)
 static const uptr kMaxAllowedMallocSize = 4UL << 30;
 #else
 static const uptr kMaxAllowedMallocSize = 8UL << 30;
diff --git a/compiler-rt.orig/lib/lsan/lsan_allocator.h b/compiler-rt.new/lib/lsan/lsan_allocator.h
index 17e13cd..733d16f 100644
--- a/compiler-rt.orig/lib/lsan/lsan_allocator.h
+++ b/compiler-rt.new/lib/lsan/lsan_allocator.h
@@ -50,7 +50,7 @@ struct ChunkMetadata {
 };
 
 #if defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \
-    defined(__arm__)
+    defined(__arm__) || defined(__loongarch64)
 template <typename AddressSpaceViewTy>
 struct AP32 {
   static const uptr kSpaceBeg = 0;
diff --git a/compiler-rt.orig/lib/lsan/lsan_common.cpp b/compiler-rt.new/lib/lsan/lsan_common.cpp
index d5b4132..f147036 100644
--- a/compiler-rt.orig/lib/lsan/lsan_common.cpp
+++ b/compiler-rt.new/lib/lsan/lsan_common.cpp
@@ -167,13 +167,15 @@ static inline bool CanBeAHeapPointer(uptr p) {
   return ((p >> 47) == 0);
 #elif defined(__mips64)
   return ((p >> 40) == 0);
-#elif defined(__aarch64__)
+#  elif defined(__loongarch64)
+  return ((p >> 47) == 0);
+#  elif defined(__aarch64__)
   unsigned runtimeVMA =
     (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
   return ((p >> runtimeVMA) == 0);
-#else
+#  else
   return true;
-#endif
+#  endif
 }
 
 // Scans the memory range, looking for byte patterns that point into allocator
diff --git a/compiler-rt.orig/lib/lsan/lsan_common.h b/compiler-rt.new/lib/lsan/lsan_common.h
index b0ae6f0..9326471 100644
--- a/compiler-rt.orig/lib/lsan/lsan_common.h
+++ b/compiler-rt.new/lib/lsan/lsan_common.h
@@ -35,8 +35,8 @@
 #define CAN_SANITIZE_LEAKS 0
 #elif (SANITIZER_LINUX || SANITIZER_MAC) && (SANITIZER_WORDSIZE == 64) && \
     (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) ||  \
-     defined(__powerpc64__) || defined(__s390x__))
-#define CAN_SANITIZE_LEAKS 1
+     defined(__powerpc64__) || defined(__s390x__) || defined(__loongarch64))
+#  define CAN_SANITIZE_LEAKS 1
 #elif defined(__i386__) && (SANITIZER_LINUX || SANITIZER_MAC)
 #define CAN_SANITIZE_LEAKS 1
 #elif defined(__arm__) && SANITIZER_LINUX
diff --git a/compiler-rt.orig/lib/msan/msan.h b/compiler-rt.new/lib/msan/msan.h
index e794c7c..ccd53d0 100644
--- a/compiler-rt.orig/lib/msan/msan.h
+++ b/compiler-rt.new/lib/msan/msan.h
@@ -60,8 +60,33 @@ const MappingDesc kMemoryLayout[] = {
     {0x00c000000000ULL, 0x00e200000000ULL, MappingDesc::INVALID, "invalid"},
     {0x00e200000000ULL, 0x00ffffffffffULL, MappingDesc::APP, "app-3"}};
 
-#define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x8000000000ULL)
-#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x2000000000ULL)
+#  define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x8000000000ULL)
+#  define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x2000000000ULL)
+
+#elif SANITIZER_LINUX && defined(__loongarch64)
+
+// LOONGARCH64 maps:
+// - 0x000000000000-0x000200000000: Program own segments
+// - 0x555500000000-0x555600000000: PIE program segments
+// - 0x7fff00000000-0x7fffffffffff: libraries segments.
+const MappingDesc kMemoryLayout[] = {
+    {0x000000000000ULL, 0x000200000000ULL, MappingDesc::APP, "app-1"},
+    {0x000200000000ULL, 0x010000000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x010000000000ULL, 0x100000000000ULL, MappingDesc::SHADOW, "shadow-2"},
+    {0x100000000000ULL, 0x110000000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x110000000000ULL, 0x200000000000ULL, MappingDesc::ORIGIN, "origin-2"},
+    {0x200000000000ULL, 0x300000000000ULL, MappingDesc::SHADOW, "shadow-3"},
+    {0x300000000000ULL, 0x400000000000ULL, MappingDesc::ORIGIN, "origin-3"},
+    {0x400000000000ULL, 0x500000000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x500000000000ULL, 0x500200000000ULL, MappingDesc::SHADOW, "shadow-1"},
+    {0x500200000000ULL, 0x510000000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x510000000000ULL, 0x600000000000ULL, MappingDesc::APP, "app-2"},
+    {0x600000000000ULL, 0x600200000000ULL, MappingDesc::ORIGIN, "origin-1"},
+    {0x600200000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"},
+    {0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}};
+
+#define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x100000000000ULL)
 
 #elif SANITIZER_LINUX && defined(__aarch64__)
 
diff --git a/compiler-rt.orig/lib/msan/msan_allocator.cpp b/compiler-rt.new/lib/msan/msan_allocator.cpp
index 68be794..a9dcf12 100644
--- a/compiler-rt.orig/lib/msan/msan_allocator.cpp
+++ b/compiler-rt.new/lib/msan/msan_allocator.cpp
@@ -44,7 +44,7 @@ struct MsanMapUnmapCallback {
   }
 };
 
-#if defined(__mips64)
+#if defined(__mips64) || defined(__loongarch64)
 static const uptr kMaxAllowedMallocSize = 2UL << 30;
 
 struct AP32 {
diff --git a/compiler-rt.orig/lib/msan/msan_interceptors.cpp b/compiler-rt.new/lib/msan/msan_interceptors.cpp
index 4eea94f..fa42922 100644
--- a/compiler-rt.orig/lib/msan/msan_interceptors.cpp
+++ b/compiler-rt.new/lib/msan/msan_interceptors.cpp
@@ -74,7 +74,11 @@ bool IsInInterceptorScope() {
 }
 
 static uptr allocated_for_dlsym;
+#if SANITIZER_LOONGARCH64
+static const uptr kDlsymAllocPoolSize = 4096 * 4;
+#else
 static const uptr kDlsymAllocPoolSize = 1024;
+#endif
 static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize];
 
 static bool IsInDlsymAllocPool(const void *ptr) {
diff --git a/compiler-rt.orig/lib/msan/tests/msan_test.cpp b/compiler-rt.new/lib/msan/tests/msan_test.cpp
index 5dc9090..b8a08a1 100644
--- a/compiler-rt.orig/lib/msan/tests/msan_test.cpp
+++ b/compiler-rt.new/lib/msan/tests/msan_test.cpp
@@ -3159,13 +3159,15 @@ static void GetPathToLoadable(char *buf, size_t sz) {
   static const char basename[] = "libmsan_loadable.mips64.so";
 #elif defined(__mips64)
   static const char basename[] = "libmsan_loadable.mips64el.so";
-#elif defined(__aarch64__)
+#  elif defined(__loongarch64)
+  static const char basename[] = "libmsan_loadable.loongarch64.so";
+#  elif defined(__aarch64__)
   static const char basename[] = "libmsan_loadable.aarch64.so";
-#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
   static const char basename[] = "libmsan_loadable.powerpc64.so";
-#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#  elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
   static const char basename[] = "libmsan_loadable.powerpc64le.so";
-#endif
+#  endif
   int res = snprintf(buf, sz, "%.*s/%s",
                      (int)dir_len, program_path, basename);
   ASSERT_GE(res, 0);
diff --git a/compiler-rt.orig/lib/safestack/safestack_platform.h b/compiler-rt.new/lib/safestack/safestack_platform.h
index 81e4c26..7987bdc 100644
--- a/compiler-rt.orig/lib/safestack/safestack_platform.h
+++ b/compiler-rt.new/lib/safestack/safestack_platform.h
@@ -96,6 +96,8 @@ inline void *Mmap(void *addr, size_t length, int prot, int flags, int fd,
   return __mmap(addr, length, prot, flags, fd, 0, offset);
 #elif defined(__x86_64__) && (SANITIZER_FREEBSD)
   return (void *)__syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
+#elif SANITIZER_LOONGARCH64
+  return mmap(addr, length, prot, flags, fd, offset);
 #else
   return (void *)syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
 #endif
@@ -105,6 +107,8 @@ inline int Munmap(void *addr, size_t length) {
 #if SANITIZER_NETBSD
   DEFINE__REAL(int, munmap, void *a, size_t b);
   return _REAL(munmap, addr, length);
+#elif SANITIZER_LOONGARCH64
+  return munmap(addr, length);
 #else
   return syscall(SYS_munmap, addr, length);
 #endif
@@ -114,6 +118,8 @@ inline int Mprotect(void *addr, size_t length, int prot) {
 #if SANITIZER_NETBSD
   DEFINE__REAL(int, mprotect, void *a, size_t b, int c);
   return _REAL(mprotect, addr, length, prot);
+#elif SANITIZER_LOONGARCH64
+  return mprotect(addr, length, prot);
 #else
   return syscall(SYS_mprotect, addr, length, prot);
 #endif
diff --git a/compiler-rt.orig/lib/sanitizer_common/CMakeLists.txt b/compiler-rt.new/lib/sanitizer_common/CMakeLists.txt
index 674835a..82ab3c7 100644
--- a/compiler-rt.orig/lib/sanitizer_common/CMakeLists.txt
+++ b/compiler-rt.new/lib/sanitizer_common/CMakeLists.txt
@@ -184,6 +184,7 @@ set(SANITIZER_IMPL_HEADERS
   sanitizer_syscall_linux_arm.inc
   sanitizer_syscall_linux_x86_64.inc
   sanitizer_syscall_linux_riscv64.inc
+  sanitizer_syscall_linux_loongarch64.inc
   sanitizer_syscalls_netbsd.inc
   sanitizer_thread_registry.h
   sanitizer_tls_get_addr.h
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_common.h b/compiler-rt.new/lib/sanitizer_common/sanitizer_common.h
index a6532ee..877f120 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_common.h
@@ -679,7 +679,8 @@ enum ModuleArch {
   kModuleArchARMV7S,
   kModuleArchARMV7K,
   kModuleArchARM64,
-  kModuleArchRISCV64
+  kModuleArchRISCV64,
+  kModuleArchLOONGARCH64
 };
 
 // Sorts and removes duplicates from the container.
@@ -746,6 +747,8 @@ inline const char *ModuleArchToString(ModuleArch arch) {
       return "arm64";
     case kModuleArchRISCV64:
       return "riscv64";
+    case kModuleArchLOONGARCH64:
+      return "loongarch64";
   }
   CHECK(0 && "Invalid module arch");
   return "";
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt.new/lib/sanitizer_common/sanitizer_common_syscalls.inc
index 1b89d6e..4c64931 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_common_syscalls.inc
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_common_syscalls.inc
@@ -2297,7 +2297,7 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {
 #if !SANITIZER_ANDROID &&                                                   \
     (defined(__i386) || defined(__x86_64) || defined(__mips64) ||           \
      defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
-     SANITIZER_RISCV64)
+     SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
   if (data) {
     if (request == ptrace_setregs) {
       PRE_READ((void *)data, struct_user_regs_struct_sz);
@@ -2319,7 +2319,7 @@ POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {
 #if !SANITIZER_ANDROID &&                                                   \
     (defined(__i386) || defined(__x86_64) || defined(__mips64) ||           \
      defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \
-     SANITIZER_RISCV64)
+     SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
   if (res >= 0 && data) {
     // Note that this is different from the interceptor in
     // sanitizer_common_interceptors.inc.
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
index 73ebeb5..a280402 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_coverage_libcdep_new.cpp
@@ -10,11 +10,12 @@
 #include "sanitizer_platform.h"
 
 #if !SANITIZER_FUCHSIA
-#include "sancov_flags.h"
-#include "sanitizer_allocator_internal.h"
-#include "sanitizer_atomic.h"
-#include "sanitizer_common.h"
-#include "sanitizer_file.h"
+#  include "sancov_flags.h"
+#  include "sanitizer_allocator_internal.h"
+#  include "sanitizer_atomic.h"
+#  include "sanitizer_common.h"
+#  include "sanitizer_common/sanitizer_stacktrace.h"
+#  include "sanitizer_file.h"
 
 using namespace __sanitizer;
 
@@ -173,7 +174,8 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_dump_coverage(const uptr* pcs,
 
 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32* guard) {
   if (!*guard) return;
-  __sancov::pc_guard_controller.TracePcGuard(guard, GET_CALLER_PC() - 1);
+  __sancov::pc_guard_controller.TracePcGuard(
+      guard, StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()));
 }
 
 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init,
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_linux.cpp
index 379f6d9..faba5b3 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_linux.cpp
@@ -78,6 +78,10 @@
 #include <sys/personality.h>
 #endif
 
+#if SANITIZER_LINUX && defined(__loongarch__)
+#include <sys/sysmacros.h>
+#endif
+
 #if SANITIZER_FREEBSD
 #include <sys/exec.h>
 #include <sys/sysctl.h>
@@ -156,6 +160,8 @@ namespace __sanitizer {
 #include "sanitizer_syscall_linux_riscv64.inc"
 #elif SANITIZER_LINUX && defined(__aarch64__)
 #include "sanitizer_syscall_linux_aarch64.inc"
+#elif SANITIZER_LINUX && SANITIZER_LOONGARCH64
+#include "sanitizer_syscall_linux_loongarch64.inc"
 #elif SANITIZER_LINUX && defined(__arm__)
 #include "sanitizer_syscall_linux_arm.inc"
 #else
@@ -170,12 +176,17 @@ uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
 #if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
   return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
                           offset);
+#else
+#if SANITIZER_LOONGARCH64
+  return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
+                          offset);
 #else
   // mmap2 specifies file offset in 4096-byte units.
   CHECK(IsAligned(offset, 4096));
   return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
                           offset / 4096);
 #endif
+#endif
 }
 #endif // !SANITIZER_S390
 
@@ -252,6 +263,28 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) {
 }
 #endif
 
+#if SANITIZER_LINUX && SANITIZER_LOONGARCH64
+static void statx_to_stat(struct statx *in, struct stat *out) {
+  internal_memset(out, 0, sizeof(*out));
+  out->st_dev = makedev(in->stx_dev_major, in->stx_dev_minor);
+  out->st_ino = in->stx_ino;
+  out->st_mode = in->stx_mode;
+  out->st_nlink = in->stx_nlink;
+  out->st_uid = in->stx_uid;
+  out->st_gid = in->stx_gid;
+  out->st_rdev = makedev(in->stx_rdev_major, in->stx_rdev_minor);
+  out->st_size = in->stx_size;
+  out->st_blksize = in->stx_blksize;
+  out->st_blocks = in->stx_blocks;
+  out->st_atime = in->stx_atime.tv_sec;
+  out->st_atim.tv_nsec = in->stx_atime.tv_nsec;
+  out->st_mtime = in->stx_mtime.tv_sec;
+  out->st_mtim.tv_nsec = in->stx_mtime.tv_nsec;
+  out->st_ctime = in->stx_ctime.tv_sec;
+  out->st_ctim.tv_nsec = in->stx_ctime.tv_nsec;
+}
+#endif
+
 #if defined(__mips64)
 // Undefine compatibility macros from <sys/stat.h>
 // so that they would not clash with the kernel_stat
@@ -306,8 +339,16 @@ uptr internal_stat(const char *path, void *buf) {
 #if SANITIZER_FREEBSD
   return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0);
 #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+#if SANITIZER_LINUX && SANITIZER_LOONGARCH64
+  struct statx bufx;
+  int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,
+                             AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx);
+  statx_to_stat(&bufx, (struct stat *)buf);
+  return res;
+#else
   return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
                           0);
+#endif
 #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
 # if defined(__mips64)
   // For mips64, stat syscall fills buffer in the format of kernel_stat
@@ -331,8 +372,17 @@ uptr internal_lstat(const char *path, void *buf) {
   return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,
                           AT_SYMLINK_NOFOLLOW);
 #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+#if SANITIZER_LINUX && SANITIZER_LOONGARCH64
+  struct statx bufx;
+  int res = internal_syscall(SYSCALL(statx), AT_FDCWD, (uptr)path,
+                             AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT,
+                             STATX_BASIC_STATS, (uptr)&bufx);
+  statx_to_stat(&bufx, (struct stat *)buf);
+  return res;
+#else
   return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
                           AT_SYMLINK_NOFOLLOW);
+#endif
 #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
 # if SANITIZER_MIPS64
   // For mips64, lstat syscall fills buffer in the format of kernel_stat
@@ -359,6 +409,12 @@ uptr internal_fstat(fd_t fd, void *buf) {
   int res = internal_syscall(SYSCALL(fstat), fd, &kbuf);
   kernel_stat_to_stat(&kbuf, (struct stat *)buf);
   return res;
+#elif SANITIZER_LINUX && SANITIZER_LOONGARCH64
+  struct statx bufx;
+  int res = internal_syscall(SYSCALL(statx), fd, "", AT_EMPTY_PATH,
+                             STATX_BASIC_STATS, (uptr)&bufx);
+  statx_to_stat(&bufx, (struct stat *)buf);
+  return res;
 # else
   return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
 # endif
@@ -407,7 +463,7 @@ uptr internal_unlink(const char *path) {
 }
 
 uptr internal_rename(const char *oldpath, const char *newpath) {
-#if defined(__riscv)
+#if defined(__riscv) || defined(__loongarch__)
   return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
                           (uptr)newpath, 0);
 #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
@@ -455,7 +511,11 @@ bool FileExists(const char *filename) {
     return false;
   struct stat st;
 #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+#if SANITIZER_LINUX && SANITIZER_LOONGARCH64
+  if (internal_stat(filename, &st))
+#else
   if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
+#endif
 #else
   if (internal_stat(filename, &st))
 #endif
@@ -687,7 +747,8 @@ void BlockingMutex::CheckLocked() {
 // Not used
 #else
 struct linux_dirent {
-#if SANITIZER_X32 || defined(__aarch64__) || SANITIZER_RISCV64
+#if SANITIZER_X32 || defined(__aarch64__) || SANITIZER_RISCV64 || \
+    SANITIZER_LOONGARCH64
   u64 d_ino;
   u64 d_off;
 #else
@@ -695,9 +756,9 @@ struct linux_dirent {
   unsigned long      d_off;
 #endif
   unsigned short     d_reclen;
-#if defined(__aarch64__) || SANITIZER_RISCV64
+#if defined(__aarch64__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64
   unsigned char      d_type;
-#endif
+#    endif
   char               d_name[256];
 };
 #endif
@@ -1041,13 +1102,15 @@ uptr GetMaxVirtualAddress() {
   return (1ULL << 38) - 1;
 # elif defined(__mips64)
   return (1ULL << 40) - 1;  // 0x000000ffffffffffUL;
-# elif defined(__s390x__)
+#elif SANITIZER_LOONGARCH64
+  return (1ULL << 47) - 1;  // 0x00007fffffffffffUL;
+#    elif defined(__s390x__)
   return (1ULL << 53) - 1;  // 0x001fffffffffffffUL;
-#elif defined(__sparc__)
+#    elif defined(__sparc__)
   return ~(uptr)0;
-# else
+#    else
   return (1ULL << 47) - 1;  // 0x00007fffffffffffUL;
-# endif
+#    endif
 #else  // SANITIZER_WORDSIZE == 32
 # if defined(__s390__)
   return (1ULL << 31) - 1;  // 0x7fffffff;
@@ -1380,7 +1443,63 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
       : "ra", "memory");
   return res;
 }
-#elif defined(__aarch64__)
+#  elif defined(__loongarch__) && SANITIZER_LINUX
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+                    int *parent_tidptr, void *newtls, int *child_tidptr) {
+  long long res;
+  if (!fn || !child_stack)
+    return -EINVAL;
+  CHECK_EQ(0, (uptr)child_stack % 16);
+  child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
+  ((unsigned long long *)child_stack)[0] = (uptr)fn;
+  ((unsigned long long *)child_stack)[1] = (uptr)arg;
+
+  register int (*__fn)(void *) __asm__("$a0") = fn;
+  register void *__stack __asm__("$a1") = child_stack;
+  register int __flags __asm__("$a2") = flags;
+  register void *__arg __asm__("$a3") = arg;
+  register int *__ptid __asm__("$a4") = parent_tidptr;
+  register void *__tls __asm__("$a5") = newtls;
+  register int *__ctid __asm__("$a6") = child_tidptr;
+
+  __asm__ __volatile__(
+      /* $a0 = syscall($a7 = SYSCALL(clone),
+       *               $a0 = flags,
+       *               $a1 = child_stack,
+       *               $a2 = parent_tidptr,
+       *               $a3 = child_tyidptr,
+       *               $a4 = new_tls)
+       */
+
+      /* Do the system call */
+      "move $a0, $a2\n" /* flags */
+      "move $a2, $a4\n" /* parent_tidptr */
+      "move $a3, $a6\n" /* child_tidptr */
+      "move $a4, $a5\n" /* tls */
+      "addi.d $a7, $r0, %9\n"
+      "syscall 0\n"
+
+      "bne $a0, $r0, 1f\n"
+
+      /* In the child, now. Call "fn(arg)". */
+      "ld.d $a6, $sp, 0\n"
+      "ld.d $a0, $sp, 8\n"
+
+      "jirl $r1, $a6, 0\n"
+
+      /* Call _exit($v0) */
+      "addi.d $a7, $r0, %10\n"
+      "syscall 0\n"
+
+      "1:\n"
+      "move %0, $a0\n"
+      : "=r"(res)
+      : "i"(-EINVAL), "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg),
+        "r"(__ptid), "r"(__tls), "r"(__ctid), "i"(__NR_clone), "i"(__NR_exit)
+      : "$r1", "memory");
+  return res;
+}
+#  elif defined(__aarch64__)
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                     int *parent_tidptr, void *newtls, int *child_tidptr) {
   long long res;
@@ -1431,12 +1550,12 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                        : "x30", "memory");
   return res;
 }
-#elif defined(__powerpc64__)
+#  elif defined(__powerpc64__)
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                    int *parent_tidptr, void *newtls, int *child_tidptr) {
   long long res;
 // Stack frame structure.
-#if SANITIZER_PPC64V1
+#    if SANITIZER_PPC64V1
 //   Back chain == 0        (SP + 112)
 // Frame (112 bytes):
 //   Parameter save area    (SP + 48), 8 doublewords
@@ -1446,20 +1565,20 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
 //   LR save area           (SP + 16)
 //   CR save area           (SP + 8)
 //   Back chain             (SP + 0)
-# define FRAME_SIZE 112
-# define FRAME_TOC_SAVE_OFFSET 40
-#elif SANITIZER_PPC64V2
+#      define FRAME_SIZE 112
+#      define FRAME_TOC_SAVE_OFFSET 40
+#    elif SANITIZER_PPC64V2
 //   Back chain == 0        (SP + 32)
 // Frame (32 bytes):
 //   TOC save area          (SP + 24)
 //   LR save area           (SP + 16)
 //   CR save area           (SP + 8)
 //   Back chain             (SP + 0)
-# define FRAME_SIZE 32
-# define FRAME_TOC_SAVE_OFFSET 24
-#else
-# error "Unsupported PPC64 ABI"
-#endif
+#      define FRAME_SIZE 32
+#      define FRAME_TOC_SAVE_OFFSET 24
+#    else
+#      error "Unsupported PPC64 ABI"
+#    endif
   if (!fn || !child_stack)
     return -EINVAL;
   CHECK_EQ(0, (uptr)child_stack % 16);
@@ -1472,75 +1591,65 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
   register void *__newtls      __asm__("r8") = newtls;
   register int *__ctidptr      __asm__("r9") = child_tidptr;
 
- __asm__ __volatile__(
-           /* fn and arg are saved across the syscall */
-           "mr 28, %5\n\t"
-           "mr 27, %8\n\t"
-
-           /* syscall
-             r0 == __NR_clone
-             r3 == flags
-             r4 == child_stack
-             r5 == parent_tidptr
-             r6 == newtls
-             r7 == child_tidptr */
-           "mr 3, %7\n\t"
-           "mr 5, %9\n\t"
-           "mr 6, %10\n\t"
-           "mr 7, %11\n\t"
-           "li 0, %3\n\t"
-           "sc\n\t"
-
-           /* Test if syscall was successful */
-           "cmpdi  cr1, 3, 0\n\t"
-           "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
-           "bne-   cr1, 1f\n\t"
-
-           /* Set up stack frame */
-           "li    29, 0\n\t"
-           "stdu  29, -8(1)\n\t"
-           "stdu  1, -%12(1)\n\t"
-           /* Do the function call */
-           "std   2, %13(1)\n\t"
-#if SANITIZER_PPC64V1
-           "ld    0, 0(28)\n\t"
-           "ld    2, 8(28)\n\t"
-           "mtctr 0\n\t"
-#elif SANITIZER_PPC64V2
-           "mr    12, 28\n\t"
-           "mtctr 12\n\t"
-#else
-# error "Unsupported PPC64 ABI"
-#endif
-           "mr    3, 27\n\t"
-           "bctrl\n\t"
-           "ld    2, %13(1)\n\t"
-
-           /* Call _exit(r3) */
-           "li 0, %4\n\t"
-           "sc\n\t"
-
-           /* Return to parent */
-           "1:\n\t"
-           "mr %0, 3\n\t"
-             : "=r" (res)
-             : "0" (-1),
-               "i" (EINVAL),
-               "i" (__NR_clone),
-               "i" (__NR_exit),
-               "r" (__fn),
-               "r" (__cstack),
-               "r" (__flags),
-               "r" (__arg),
-               "r" (__ptidptr),
-               "r" (__newtls),
-               "r" (__ctidptr),
-               "i" (FRAME_SIZE),
-               "i" (FRAME_TOC_SAVE_OFFSET)
-             : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
+  __asm__ __volatile__(
+      /* fn and arg are saved across the syscall */
+      "mr 28, %5\n\t"
+      "mr 27, %8\n\t"
+
+      /* syscall
+        r0 == __NR_clone
+        r3 == flags
+        r4 == child_stack
+        r5 == parent_tidptr
+        r6 == newtls
+        r7 == child_tidptr */
+      "mr 3, %7\n\t"
+      "mr 5, %9\n\t"
+      "mr 6, %10\n\t"
+      "mr 7, %11\n\t"
+      "li 0, %3\n\t"
+      "sc\n\t"
+
+      /* Test if syscall was successful */
+      "cmpdi  cr1, 3, 0\n\t"
+      "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t"
+      "bne-   cr1, 1f\n\t"
+
+      /* Set up stack frame */
+      "li    29, 0\n\t"
+      "stdu  29, -8(1)\n\t"
+      "stdu  1, -%12(1)\n\t"
+      /* Do the function call */
+      "std   2, %13(1)\n\t"
+#    if SANITIZER_PPC64V1
+      "ld    0, 0(28)\n\t"
+      "ld    2, 8(28)\n\t"
+      "mtctr 0\n\t"
+#    elif SANITIZER_PPC64V2
+      "mr    12, 28\n\t"
+      "mtctr 12\n\t"
+#    else
+#      error "Unsupported PPC64 ABI"
+#    endif
+      "mr    3, 27\n\t"
+      "bctrl\n\t"
+      "ld    2, %13(1)\n\t"
+
+      /* Call _exit(r3) */
+      "li 0, %4\n\t"
+      "sc\n\t"
+
+      /* Return to parent */
+      "1:\n\t"
+      "mr %0, 3\n\t"
+      : "=r"(res)
+      : "0"(-1), "i"(EINVAL), "i"(__NR_clone), "i"(__NR_exit), "r"(__fn),
+        "r"(__cstack), "r"(__flags), "r"(__arg), "r"(__ptidptr), "r"(__newtls),
+        "r"(__ctidptr), "i"(FRAME_SIZE), "i"(FRAME_TOC_SAVE_OFFSET)
+      : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29");
   return res;
 }
-#elif defined(__i386__) && SANITIZER_LINUX
+#  elif defined(__i386__) && SANITIZER_LINUX
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                     int *parent_tidptr, void *newtls, int *child_tidptr) {
   int res;
@@ -1553,59 +1662,56 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
   ((unsigned int *)child_stack)[2] = (uptr)fn;
   ((unsigned int *)child_stack)[3] = (uptr)arg;
   __asm__ __volatile__(
-                       /* %eax = syscall(%eax = SYSCALL(clone),
-                        *                %ebx = flags,
-                        *                %ecx = child_stack,
-                        *                %edx = parent_tidptr,
-                        *                %esi  = new_tls,
-                        *                %edi = child_tidptr)
-                        */
+      /* %eax = syscall(%eax = SYSCALL(clone),
+       *                %ebx = flags,
+       *                %ecx = child_stack,
+       *                %edx = parent_tidptr,
+       *                %esi  = new_tls,
+       *                %edi = child_tidptr)
+       */
 
-                        /* Obtain flags */
-                        "movl    (%%ecx), %%ebx\n"
-                        /* Do the system call */
-                        "pushl   %%ebx\n"
-                        "pushl   %%esi\n"
-                        "pushl   %%edi\n"
-                        /* Remember the flag value.  */
-                        "movl    %%ebx, (%%ecx)\n"
-                        "int     $0x80\n"
-                        "popl    %%edi\n"
-                        "popl    %%esi\n"
-                        "popl    %%ebx\n"
-
-                        /* if (%eax != 0)
-                         *   return;
-                         */
-
-                        "test    %%eax,%%eax\n"
-                        "jnz    1f\n"
-
-                        /* terminate the stack frame */
-                        "xorl   %%ebp,%%ebp\n"
-                        /* Call FN. */
-                        "call    *%%ebx\n"
-#ifdef PIC
-                        "call    here\n"
-                        "here:\n"
-                        "popl    %%ebx\n"
-                        "addl    $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n"
-#endif
-                        /* Call exit */
-                        "movl    %%eax, %%ebx\n"
-                        "movl    %2, %%eax\n"
-                        "int     $0x80\n"
-                        "1:\n"
-                       : "=a" (res)
-                       : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
-                         "c"(child_stack),
-                         "d"(parent_tidptr),
-                         "S"(newtls),
-                         "D"(child_tidptr)
-                       : "memory");
+      /* Obtain flags */
+      "movl    (%%ecx), %%ebx\n"
+      /* Do the system call */
+      "pushl   %%ebx\n"
+      "pushl   %%esi\n"
+      "pushl   %%edi\n"
+      /* Remember the flag value.  */
+      "movl    %%ebx, (%%ecx)\n"
+      "int     $0x80\n"
+      "popl    %%edi\n"
+      "popl    %%esi\n"
+      "popl    %%ebx\n"
+
+      /* if (%eax != 0)
+       *   return;
+       */
+
+      "test    %%eax,%%eax\n"
+      "jnz    1f\n"
+
+      /* terminate the stack frame */
+      "xorl   %%ebp,%%ebp\n"
+      /* Call FN. */
+      "call    *%%ebx\n"
+#    ifdef PIC
+      "call    here\n"
+      "here:\n"
+      "popl    %%ebx\n"
+      "addl    $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n"
+#    endif
+      /* Call exit */
+      "movl    %%eax, %%ebx\n"
+      "movl    %2, %%eax\n"
+      "int     $0x80\n"
+      "1:\n"
+      : "=a"(res)
+      : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)), "c"(child_stack),
+        "d"(parent_tidptr), "S"(newtls), "D"(child_tidptr)
+      : "memory");
   return res;
 }
-#elif defined(__arm__) && SANITIZER_LINUX
+#  elif defined(__arm__) && SANITIZER_LINUX
 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                     int *parent_tidptr, void *newtls, int *child_tidptr) {
   unsigned int res;
@@ -1621,22 +1727,22 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
   register int *r4 __asm__("r4") = child_tidptr;
   register int r7 __asm__("r7") = __NR_clone;
 
-#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)
-# define ARCH_HAS_BX
-#endif
-#if __ARM_ARCH > 4
-# define ARCH_HAS_BLX
-#endif
-
-#ifdef ARCH_HAS_BX
-# ifdef ARCH_HAS_BLX
-#  define BLX(R) "blx "  #R "\n"
-# else
-#  define BLX(R) "mov lr, pc; bx " #R "\n"
-# endif
-#else
-# define BLX(R)  "mov lr, pc; mov pc," #R "\n"
-#endif
+#    if __ARM_ARCH > 4 || defined(__ARM_ARCH_4T__)
+#      define ARCH_HAS_BX
+#    endif
+#    if __ARM_ARCH > 4
+#      define ARCH_HAS_BLX
+#    endif
+
+#    ifdef ARCH_HAS_BX
+#      ifdef ARCH_HAS_BLX
+#        define BLX(R) "blx " #        R "\n"
+#      else
+#        define BLX(R) "mov lr, pc; bx " #        R "\n"
+#      endif
+#    else
+#      define BLX(R) "mov lr, pc; mov pc," #      R "\n"
+#    endif
 
   __asm__ __volatile__(
                        /* %r0 = syscall(%r7 = SYSCALL(clone),
@@ -1671,9 +1777,9 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
                        : "memory");
   return res;
 }
-#endif  // defined(__x86_64__) && SANITIZER_LINUX
+#  endif  // defined(__x86_64__) && SANITIZER_LINUX
 
-#if SANITIZER_LINUX
+#  if SANITIZER_LINUX
 int internal_uname(struct utsname *buf) {
   return internal_syscall(SYSCALL(uname), buf);
 }
@@ -1875,36 +1981,43 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
 #endif
   }
   return SignalContext::UNKNOWN;
-#elif defined(__arm__)
+#  elif defined(__loongarch__)
+  u32 flags = ucontext->uc_mcontext.__flags;
+  if (flags & SC_ADDRERR_RD)
+    return SignalContext::READ;
+  if (flags & SC_ADDRERR_WR)
+    return SignalContext::WRITE;
+  return SignalContext::UNKNOWN;
+#  elif defined(__arm__)
   static const uptr FSR_WRITE = 1U << 11;
   uptr fsr = ucontext->uc_mcontext.error_code;
   return fsr & FSR_WRITE ? WRITE : READ;
-#elif defined(__aarch64__)
+#  elif defined(__aarch64__)
   static const u64 ESR_ELx_WNR = 1U << 6;
   u64 esr;
   if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN;
   return esr & ESR_ELx_WNR ? WRITE : READ;
-#elif defined(__sparc__)
+#  elif defined(__sparc__)
   // Decode the instruction to determine the access type.
   // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype).
-#if SANITIZER_SOLARIS
+#    if SANITIZER_SOLARIS
   uptr pc = ucontext->uc_mcontext.gregs[REG_PC];
-#else
+#    else
   // Historical BSDism here.
   struct sigcontext *scontext = (struct sigcontext *)context;
-#if defined(__arch64__)
+#      if defined(__arch64__)
   uptr pc = scontext->sigc_regs.tpc;
-#else
+#      else
   uptr pc = scontext->si_regs.pc;
-#endif
-#endif
+#      endif
+#    endif
   u32 instr = *(u32 *)pc;
   return (instr >> 21) & 1 ? WRITE: READ;
-#elif defined(__riscv)
+#  elif defined(__riscv)
   unsigned long pc = ucontext->uc_mcontext.__gregs[REG_PC];
   unsigned faulty_instruction = *(uint16_t *)pc;
 
-#if defined(__riscv_compressed)
+#    if defined(__riscv_compressed)
   if ((faulty_instruction & 0x3) != 0x3) {  // it's a compressed instruction
     // set op_bits to the instruction bits [1, 0, 15, 14, 13]
     unsigned op_bits =
@@ -1912,38 +2025,38 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
     unsigned rd = faulty_instruction & 0xF80;  // bits 7-11, inclusive
     switch (op_bits) {
       case 0b10'010:  // c.lwsp (rd != x0)
-#if __riscv_xlen == 64
+#      if __riscv_xlen == 64
       case 0b10'011:  // c.ldsp (rd != x0)
-#endif
+#      endif
         return rd ? SignalContext::READ : SignalContext::UNKNOWN;
       case 0b00'010:  // c.lw
-#if __riscv_flen >= 32 && __riscv_xlen == 32
+#      if __riscv_flen >= 32 && __riscv_xlen == 32
       case 0b10'011:  // c.flwsp
-#endif
-#if __riscv_flen >= 32 || __riscv_xlen == 64
+#      endif
+#      if __riscv_flen >= 32 || __riscv_xlen == 64
       case 0b00'011:  // c.flw / c.ld
-#endif
-#if __riscv_flen == 64
+#      endif
+#      if __riscv_flen == 64
       case 0b00'001:  // c.fld
       case 0b10'001:  // c.fldsp
-#endif
+#      endif
         return SignalContext::READ;
       case 0b00'110:  // c.sw
       case 0b10'110:  // c.swsp
-#if __riscv_flen >= 32 || __riscv_xlen == 64
+#      if __riscv_flen >= 32 || __riscv_xlen == 64
       case 0b00'111:  // c.fsw / c.sd
       case 0b10'111:  // c.fswsp / c.sdsp
-#endif
-#if __riscv_flen == 64
+#      endif
+#      if __riscv_flen == 64
       case 0b00'101:  // c.fsd
       case 0b10'101:  // c.fsdsp
-#endif
+#      endif
         return SignalContext::WRITE;
       default:
         return SignalContext::UNKNOWN;
     }
   }
-#endif
+#    endif
 
   unsigned opcode = faulty_instruction & 0x7f;         // lower 7 bits
   unsigned funct3 = (faulty_instruction >> 12) & 0x7;  // bits 12-14, inclusive
@@ -1953,9 +2066,9 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
         case 0b000:  // lb
         case 0b001:  // lh
         case 0b010:  // lw
-#if __riscv_xlen == 64
+#    if __riscv_xlen == 64
         case 0b011:  // ld
-#endif
+#    endif
         case 0b100:  // lbu
         case 0b101:  // lhu
           return SignalContext::READ;
@@ -1967,20 +2080,20 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
         case 0b000:  // sb
         case 0b001:  // sh
         case 0b010:  // sw
-#if __riscv_xlen == 64
+#    if __riscv_xlen == 64
         case 0b011:  // sd
-#endif
+#    endif
           return SignalContext::WRITE;
         default:
           return SignalContext::UNKNOWN;
       }
-#if __riscv_flen >= 32
+#    if __riscv_flen >= 32
     case 0b0000111:  // floating-point loads
       switch (funct3) {
         case 0b010:  // flw
-#if __riscv_flen == 64
+#      if __riscv_flen == 64
         case 0b011:  // fld
-#endif
+#      endif
           return SignalContext::READ;
         default:
           return SignalContext::UNKNOWN;
@@ -1988,21 +2101,21 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
     case 0b0100111:  // floating-point stores
       switch (funct3) {
         case 0b010:  // fsw
-#if __riscv_flen == 64
+#      if __riscv_flen == 64
         case 0b011:  // fsd
-#endif
+#      endif
           return SignalContext::WRITE;
         default:
           return SignalContext::UNKNOWN;
       }
-#endif
+#    endif
     default:
       return SignalContext::UNKNOWN;
   }
-#else
+#  else
   (void)ucontext;
   return UNKNOWN;  // FIXME: Implement.
-#endif
+#  endif
 }
 
 bool SignalContext::IsTrueFaultingAddress() const {
@@ -2109,23 +2222,28 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
   *pc = ucontext->uc_mcontext.pc;
   *bp = ucontext->uc_mcontext.gregs[30];
   *sp = ucontext->uc_mcontext.gregs[29];
-#elif defined(__s390__)
+#elif defined(__loongarch__)
+  ucontext_t *ucontext = (ucontext_t *)context;
+  *pc = ucontext->uc_mcontext.__pc;
+  *bp = ucontext->uc_mcontext.__gregs[22];
+  *sp = ucontext->uc_mcontext.__gregs[3];
+#  elif defined(__s390__)
   ucontext_t *ucontext = (ucontext_t*)context;
-# if defined(__s390x__)
+#    if defined(__s390x__)
   *pc = ucontext->uc_mcontext.psw.addr;
-# else
+#    else
   *pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff;
-# endif
+#    endif
   *bp = ucontext->uc_mcontext.gregs[11];
   *sp = ucontext->uc_mcontext.gregs[15];
-#elif defined(__riscv)
+#  elif defined(__riscv)
   ucontext_t *ucontext = (ucontext_t*)context;
   *pc = ucontext->uc_mcontext.__gregs[REG_PC];
   *bp = ucontext->uc_mcontext.__gregs[REG_S0];
   *sp = ucontext->uc_mcontext.__gregs[REG_SP];
-#else
-# error "Unsupported arch"
-#endif
+#  else
+#    error "Unsupported arch"
+#  endif
 }
 
 void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); }
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt.new/lib/sanitizer_common/sanitizer_linux.h
index 24902d1..1ead3a1 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_linux.h
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_linux.h
@@ -61,7 +61,7 @@ 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
+    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
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
index f20b900..6a53b09 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -259,7 +259,7 @@ void InitTlsSize() { }
 
 #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) ||       \
      defined(__aarch64__) || defined(__powerpc64__) || defined(__s390__) || \
-     defined(__arm__) || SANITIZER_RISCV64) &&                              \
+     defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64) &&     \
     SANITIZER_LINUX && !SANITIZER_ANDROID
 // sizeof(struct pthread) from glibc.
 static atomic_uintptr_t thread_descriptor_size;
@@ -301,7 +301,10 @@ uptr ThreadDescriptorSize() {
 #elif defined(__mips__)
   // TODO(sagarthakur): add more values as per different glibc versions.
   val = FIRST_32_SECOND_64(1152, 1776);
-#elif SANITIZER_RISCV64
+#elif SANITIZER_LOONGARCH64
+  //  val = 1856;
+  val = 1984;  // get this from glibc 2.34
+#    elif SANITIZER_RISCV64
   int major;
   int minor;
   int patch;
@@ -316,10 +319,10 @@ uptr ThreadDescriptorSize() {
       val = 1936;  // tested against glibc 2.32
   }
 
-#elif defined(__aarch64__)
+#    elif defined(__aarch64__)
   // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
   val = 1776;
-#elif defined(__powerpc64__)
+#    elif defined(__powerpc64__)
   val = 1776; // from glibc.ppc64le 2.20-8.fc21
 #elif defined(__s390__)
   val = FIRST_32_SECOND_64(1152, 1776); // valid for glibc 2.22
@@ -336,17 +339,20 @@ uptr ThreadSelfOffset() {
   return kThreadSelfOffset;
 }
 
-#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() {
 #if defined(__mips__)
   const uptr kTcbHead = 16; // sizeof (tcbhead_t)
-#elif defined(__powerpc64__)
+#elif defined(__loongarch__)
+  const uptr kTcbHead = 16;  // sizeof (tcbhead_t)
+#      elif defined(__powerpc64__)
   const uptr kTcbHead = 88; // sizeof (tcbhead_t)
-#elif SANITIZER_RISCV64
+#      elif SANITIZER_RISCV64
   const uptr kTcbHead = 16;  // sizeof (tcbhead_t)
-#endif
+#      endif
   const uptr kTlsAlign = 16;
   const uptr kTlsPreTcbSize =
       RoundUpTo(ThreadDescriptorSize() + kTcbHead, kTlsAlign);
@@ -379,6 +385,10 @@ uptr ThreadSelf() {
   // https://github.com/riscv/riscv-elf-psabi-doc/issues/53
   uptr thread_pointer = reinterpret_cast<uptr>(__builtin_thread_pointer());
   descr_addr = thread_pointer - TlsPreTcbSize();
+#elif defined(__loongarch__)
+  uptr thread_pointer;
+  asm("or %0,$r2,$r0" : "=r"(thread_pointer));
+  descr_addr = thread_pointer - TlsPreTcbSize();
 #elif defined(__s390__)
   descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer());
 #elif defined(__powerpc64__)
@@ -473,7 +483,7 @@ static void GetTls(uptr *addr, uptr *size) {
   *addr -= *size;
   *addr += ThreadDescriptorSize();
 #elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) || \
-    defined(__arm__) || SANITIZER_RISCV64
+    defined(__arm__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64
   *addr = ThreadSelf();
   *size = GetTlsSize();
 #else
@@ -525,7 +535,8 @@ uptr GetTlsSize() {
   GetTls(&addr, &size);
   return size;
 #elif SANITIZER_GLIBC
-#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64
+#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
+    SANITIZER_LOONGARCH64
   return RoundUpTo(g_tls_size + TlsPreTcbSize(), 16);
 #else
   return g_tls_size;
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform.h
index 96c01ba..43a9d6d 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform.h
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform.h
@@ -232,6 +232,17 @@
 #define SANITIZER_RISCV64 0
 #endif
 
+#if defined(__loongarch__)
+#define SANITIZER_LOONGARCH 1
+#if defined(__loongarch64)
+#define SANITIZER_LOONGARCH32 0
+#define SANITIZER_LOONGARCH64 1
+#else
+#define SANITIZER_LOONGARCH32 1
+#define SANITIZER_LOONGARCH64 0
+#endif
+#endif
+
 // By default we allow to use SizeClassAllocator64 on 64-bit platform.
 // But in some cases (e.g. AArch64's 39-bit address space) SizeClassAllocator64
 // does not work well and we need to fallback to SizeClassAllocator32.
@@ -240,22 +251,22 @@
 #ifndef SANITIZER_CAN_USE_ALLOCATOR64
 # if (SANITIZER_ANDROID && defined(__aarch64__)) || SANITIZER_FUCHSIA
 #  define SANITIZER_CAN_USE_ALLOCATOR64 1
-# elif defined(__mips64) || defined(__aarch64__)
-#  define SANITIZER_CAN_USE_ALLOCATOR64 0
-# else
-#  define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
-# endif
+#elif defined(__mips64) || defined(__aarch64__)
+#    define SANITIZER_CAN_USE_ALLOCATOR64 0
+#  else
+#    define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
+#  endif
 #endif
 
 // The range of addresses which can be returned my mmap.
 // FIXME: this value should be different on different platforms.  Larger values
 // will still work but will consume more memory for TwoLevelByteMap.
 #if defined(__mips__)
-#if SANITIZER_GO && defined(__mips64)
-#define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
-#else
-# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
-#endif
+#  if SANITIZER_GO && defined(__mips64)
+#    define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
+#  else
+#    define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
+#  endif
 #elif SANITIZER_RISCV64
 #define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 38)
 #elif defined(__aarch64__)
@@ -284,11 +295,12 @@
 // mandated by the upstream linux community for all new ports. Other ports
 // may still use legacy syscalls.
 #ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
-# if (defined(__aarch64__) || defined(__riscv)) && SANITIZER_LINUX
-# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
-# else
-# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
-# endif
+#if (defined(__aarch64__) || defined(__riscv) || defined(__loongarch__)) && \
+    SANITIZER_LINUX
+#    define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
+#  else
+#    define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
+#  endif
 #endif
 
 // udi16 syscalls can only be used when the following conditions are
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 068fc98..643a8b6 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -274,8 +274,8 @@
 #if SI_LINUX_NOT_ANDROID &&                                                \
     (defined(__i386) || defined(__x86_64) || defined(__mips64) ||          \
      defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
-     defined(__s390__) || SANITIZER_RISCV64)
-#define SANITIZER_INTERCEPT_PTRACE 1
+     defined(__s390__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
+#  define SANITIZER_INTERCEPT_PTRACE 1
 #else
 #define SANITIZER_INTERCEPT_PTRACE 0
 #endif
@@ -486,7 +486,8 @@
   (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && SI_NOT_RTEMS)
 #define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC
 #define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID)
-#define SANITIZER_INTERCEPT_CFREE SI_GLIBC
+#define SANITIZER_INTERCEPT_CFREE \
+  (SI_GLIBC && !SANITIZER_LOONGARCH)
 #define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
 #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS)
 #define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp
index c51327e..c54b960 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp
@@ -63,9 +63,9 @@ namespace __sanitizer {
 #endif
 }  // namespace __sanitizer
 
-#if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\
-                            && !defined(__mips__) && !defined(__s390__)\
-                            && !defined(__sparc__) && !defined(__riscv)
+#  if !defined(__powerpc64__) && !defined(__x86_64__) &&                   \
+      !defined(__aarch64__) && !defined(__mips__) && !defined(__s390__) && \
+      !defined(__sparc__) && !defined(__riscv) && !defined(__loongarch__)
 COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
 #endif
 
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
index 7abaeb8..be80248 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -92,9 +92,9 @@
 # include <utime.h>
 # include <sys/ptrace.h>
 #if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
-    SANITIZER_RISCV64
-#  include <asm/ptrace.h>
-#  ifdef __arm__
+    SANITIZER_RISCV64 || SANITIZER_LOONGARCH64
+#      include <asm/ptrace.h>
+#      ifdef __arm__
 typedef struct user_fpregs elf_fpregset_t;
 #   define ARM_VFPREGS_SIZE_ASAN (32 * 8 /*fpregs*/ + 4 /*fpscr*/)
 #   if !defined(ARM_VFPREGS_SIZE)
@@ -139,20 +139,20 @@ typedef struct user_fpregs elf_fpregset_t;
 #include <sys/shm.h>
 #include <sys/statvfs.h>
 #include <sys/timex.h>
-#if defined(__mips64)
-# include <sys/procfs.h>
-#endif
-#include <sys/user.h>
-#include <linux/if_eql.h>
-#include <linux/if_plip.h>
-#include <linux/lp.h>
-#include <linux/mroute.h>
-#include <linux/mroute6.h>
-#include <linux/scc.h>
-#include <linux/serial.h>
-#include <sys/msg.h>
-#include <sys/ipc.h>
-#include <crypt.h>
+#      if defined(__mips64) || defined(__loongarch64)
+#        include <sys/procfs.h>
+#      endif
+#      include <crypt.h>
+#      include <linux/if_eql.h>
+#      include <linux/if_plip.h>
+#      include <linux/lp.h>
+#      include <linux/mroute.h>
+#      include <linux/mroute6.h>
+#      include <linux/scc.h>
+#      include <linux/serial.h>
+#      include <sys/ipc.h>
+#      include <sys/msg.h>
+#      include <sys/user.h>
 #endif  // SANITIZER_ANDROID
 
 #include <link.h>
@@ -240,13 +240,17 @@ namespace __sanitizer {
 #if defined(__aarch64__) || defined(__s390x__) || defined(__mips64) ||     \
     defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) || \
     defined(__x86_64__) || SANITIZER_RISCV64
-#define SIZEOF_STRUCT_USTAT 32
-#elif defined(__arm__) || defined(__i386__) || defined(__mips__) \
-  || defined(__powerpc__) || defined(__s390__) || defined(__sparc__)
-#define SIZEOF_STRUCT_USTAT 20
-#else
-#error Unknown size of struct ustat
-#endif
+#      define SIZEOF_STRUCT_USTAT 32
+#elif defined(__arm__) || defined(__i386__) || defined(__mips__) || \
+    defined(__powerpc__) || defined(__s390__) || defined(__sparc__)
+#      define SIZEOF_STRUCT_USTAT 20
+#elif defined(__loongarch__)
+  // Not used. The minimum Glibc version available for LoongArch is 2.36
+  // so ustat() wrapper is already gone.
+#define SIZEOF_STRUCT_USTAT 0
+#    else
+#      error Unknown size of struct ustat
+#    endif
   unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
   unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
   unsigned struct_statvfs64_sz = sizeof(struct statvfs64);
@@ -314,8 +318,8 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
 #if SANITIZER_LINUX && !SANITIZER_ANDROID &&                               \
     (defined(__i386) || defined(__x86_64) || defined(__mips64) ||          \
      defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
-     defined(__s390__) || SANITIZER_RISCV64)
-#if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)
+     defined(__s390__) || SANITIZER_RISCV64 || SANITIZER_LOONGARCH64)
+#    if defined(__mips64) || defined(__powerpc64__) || defined(__arm__)
   unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs);
   unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t);
 #elif SANITIZER_RISCV64
@@ -324,22 +328,25 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
 #elif defined(__aarch64__)
   unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs);
   unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpsimd_state);
-#elif defined(__s390__)
+#elif SANITIZER_LOONGARCH64
+  unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs);
+  unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fp_state);
+#    elif defined(__s390__)
   unsigned struct_user_regs_struct_sz = sizeof(struct _user_regs_struct);
   unsigned struct_user_fpregs_struct_sz = sizeof(struct _user_fpregs_struct);
-#else
+#    else
   unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
   unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);
-#endif // __mips64 || __powerpc64__ || __aarch64__
+#    endif  // __mips64 || __powerpc64__ || __aarch64__ || __loongarch64
 #if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \
     defined(__aarch64__) || defined(__arm__) || defined(__s390__) ||    \
-    SANITIZER_RISCV64
+    SANITIZER_RISCV64 || SANITIZER_LOONGARCH64
   unsigned struct_user_fpxregs_struct_sz = 0;
 #else
   unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct);
 #endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__
-// || __s390__
-#ifdef __arm__
+  // || __s390__ || __loongarch64
+#    ifdef __arm__
   unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE;
 #else
   unsigned struct_user_vfpregs_struct_sz = 0;
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 8a156b7..a7c745e 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -85,24 +85,27 @@ const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
                                            ? FIRST_32_SECOND_64(104, 128)
                                            : FIRST_32_SECOND_64(160, 216);
 const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__s390__) && !defined(__s390x__)
+#    elif defined(__loongarch__)
+const unsigned struct_kernel_stat_sz = 128;
+const unsigned struct_kernel_stat64_sz = 0;  // LoongArch does not use stat64
+#    elif defined(__s390__) && !defined(__s390x__)
 const unsigned struct_kernel_stat_sz = 64;
 const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__s390x__)
+#    elif defined(__s390x__)
 const unsigned struct_kernel_stat_sz = 144;
 const unsigned struct_kernel_stat64_sz = 0;
-#elif defined(__sparc__) && defined(__arch64__)
+#    elif defined(__sparc__) && defined(__arch64__)
 const unsigned struct___old_kernel_stat_sz = 0;
 const unsigned struct_kernel_stat_sz = 104;
 const unsigned struct_kernel_stat64_sz = 144;
-#elif defined(__sparc__) && !defined(__arch64__)
+#    elif defined(__sparc__) && !defined(__arch64__)
 const unsigned struct___old_kernel_stat_sz = 0;
 const unsigned struct_kernel_stat_sz = 64;
 const unsigned struct_kernel_stat64_sz = 104;
-#elif SANITIZER_RISCV64
+#    elif SANITIZER_RISCV64
 const unsigned struct_kernel_stat_sz = 128;
 const unsigned struct_kernel_stat64_sz = 0;  // RISCV64 does not use stat64
-#endif
+#    endif
 struct __sanitizer_perf_event_attr {
   unsigned type;
   unsigned size;
@@ -122,7 +125,7 @@ const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
 
 #if SANITIZER_LINUX
 
-#if defined(__powerpc64__) || defined(__s390__)
+#if defined(__powerpc64__) || defined(__s390__) || defined(__loongarch__)
 const unsigned struct___old_kernel_stat_sz = 0;
 #elif !defined(__sparc__)
 const unsigned struct___old_kernel_stat_sz = 32;
@@ -803,10 +806,10 @@ typedef void __sanitizer_FILE;
 # define SANITIZER_HAS_STRUCT_FILE 0
 #endif
 
-#if SANITIZER_LINUX && !SANITIZER_ANDROID &&                               \
-    (defined(__i386) || defined(__x86_64) || defined(__mips64) ||          \
-     defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
-     defined(__s390__) || SANITIZER_RISCV64)
+#  if SANITIZER_LINUX && !SANITIZER_ANDROID &&                               \
+      (defined(__i386) || defined(__x86_64) || defined(__mips64) ||          \
+       defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \
+       defined(__s390__) || SANITIZER_RISCV64 || defined(__loongarch64))
 extern unsigned struct_user_regs_struct_sz;
 extern unsigned struct_user_fpregs_struct_sz;
 extern unsigned struct_user_fpxregs_struct_sz;
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_ring_buffer.h b/compiler-rt.new/lib/sanitizer_common/sanitizer_ring_buffer.h
index 2a46e93..a154d4a 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_ring_buffer.h
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_ring_buffer.h
@@ -84,18 +84,21 @@ template <class T>
 class CompactRingBuffer {
   // Top byte of long_ stores the buffer size in pages.
   // Lower bytes store the address of the next buffer element.
-  static constexpr int kPageSizeBits = 12;
   static constexpr int kSizeShift = 56;
   static constexpr uptr kNextMask = (1ULL << kSizeShift) - 1;
 
-  uptr GetStorageSize() const { return (long_ >> kSizeShift) << kPageSizeBits; }
+  uptr GetStorageSize() const {
+    unsigned kPageSizeBits = Log2(GetPageSizeCached());
+    return (long_ >> kSizeShift) << kPageSizeBits;
+  }
 
   void Init(void *storage, uptr size) {
+    unsigned kPageSizeBits = Log2(GetPageSizeCached());
     CHECK_EQ(sizeof(CompactRingBuffer<T>), sizeof(void *));
     CHECK(IsPowerOfTwo(size));
     CHECK_GE(size, 1 << kPageSizeBits);
     CHECK_LE(size, 128 << kPageSizeBits);
-    CHECK_EQ(size % 4096, 0);
+    CHECK_EQ(size % GetPageSizeCached(), 0);
     CHECK_EQ(size % sizeof(T), 0);
     CHECK_EQ((uptr)storage % (size * 2), 0);
     long_ = (uptr)storage | ((size >> kPageSizeBits) << kSizeShift);
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_stacktrace.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_stacktrace.cpp
index b0487d8..451c966 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_stacktrace.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_stacktrace.cpp
@@ -21,7 +21,8 @@ namespace __sanitizer {
 uptr StackTrace::GetNextInstructionPc(uptr pc) {
 #if defined(__sparc__) || defined(__mips__)
   return pc + 8;
-#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__)
+#elif defined(__powerpc__) || defined(__arm__) || defined(__aarch64__) || \
+    defined(__loongarch__)
   return pc + 4;
 #elif SANITIZER_RISCV64
   // Current check order is 4 -> 2 -> 6 -> 8
@@ -118,7 +119,7 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
     uhwptr pc1 = caller_frame[2];
 #elif defined(__s390__)
     uhwptr pc1 = frame[14];
-#elif defined(__riscv)
+#elif defined(__riscv) || defined(__loongarch__)
     // frame[-1] contains the return address
     uhwptr pc1 = frame[-1];
 #else
@@ -133,7 +134,7 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top,
       trace_buffer[size++] = (uptr) pc1;
     }
     bottom = (uptr)frame;
-#if defined(__riscv)
+#if defined(__riscv) || defined(__loongarch__)
     // frame[-2] contain fp of the previous frame
     uptr new_bp = (uptr)frame[-2];
 #else
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt.new/lib/sanitizer_common/sanitizer_stacktrace.h
index 15616f8..e605c7e 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_stacktrace.h
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_stacktrace.h
@@ -21,8 +21,8 @@ struct BufferedStackTrace;
 
 static const u32 kStackTraceMax = 256;
 
-#if SANITIZER_LINUX && defined(__mips__)
-# define SANITIZER_CAN_FAST_UNWIND 0
+#if (SANITIZER_LINUX && defined(__mips__))
+#  define SANITIZER_CAN_FAST_UNWIND 0
 #elif SANITIZER_WINDOWS
 # define SANITIZER_CAN_FAST_UNWIND 0
 #else
@@ -77,7 +77,8 @@ uptr StackTrace::GetPreviousInstructionPc(uptr pc) {
   // so we return (pc-2) in that case in order to be safe.
   // For A32 mode we return (pc-4) because all instructions are 32 bit long.
   return (pc - 3) & (~1);
-#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
+#elif defined(__powerpc__) || defined(__powerpc64__) || \
+    defined(__aarch64__) || defined(__loongarch__)
   // PCs are always 4 byte aligned.
   return pc - 4;
 #elif defined(__sparc__) || defined(__mips__)
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
index 53cfddc..9e277b4 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp
@@ -16,45 +16,48 @@
 #if SANITIZER_LINUX &&                                                   \
     (defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \
      defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \
-     defined(__arm__) || SANITIZER_RISCV64)
-
-#include "sanitizer_stoptheworld.h"
-
-#include "sanitizer_platform_limits_posix.h"
-#include "sanitizer_atomic.h"
-
-#include <errno.h>
-#include <sched.h> // for CLONE_* definitions
-#include <stddef.h>
-#include <sys/prctl.h> // for PR_* definitions
-#include <sys/ptrace.h> // for PTRACE_* definitions
-#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
+     defined(__arm__) || SANITIZER_RISCV64 || defined(__loongarch__))
+
+#  include "sanitizer_atomic.h"
+#  include "sanitizer_platform_limits_posix.h"
+#  include "sanitizer_stoptheworld.h"
+
+#  if defined(__loongarch__)
+#    include <sys/ucontext.h>
+#  endif
+
+#  include <elf.h>  // for NT_PRSTATUS
+#  include <errno.h>
+#  include <sched.h>  // for CLONE_* definitions
+#  include <stddef.h>
+#  include <sys/prctl.h>   // for PR_* definitions
+#  include <sys/ptrace.h>  // for PTRACE_* definitions
+#  include <sys/types.h>   // for pid_t
+#  include <sys/uio.h>     // for iovec
+#  if (defined(__aarch64__) || SANITIZER_RISCV64) && !SANITIZER_ANDROID
 // GLIBC 2.20+ sys/user does not include asm/ptrace.h
 # include <asm/ptrace.h>
 #endif
 #include <sys/user.h>  // for user_regs_struct
-#if SANITIZER_ANDROID && SANITIZER_MIPS
-# include <asm/reg.h>  // for mips SP register in sys/user.h
-#endif
-#include <sys/wait.h> // for signal-related stuff
-
-#ifdef sa_handler
-# undef sa_handler
-#endif
-
-#ifdef sa_sigaction
-# undef sa_sigaction
-#endif
-
-#include "sanitizer_common.h"
-#include "sanitizer_flags.h"
-#include "sanitizer_libc.h"
-#include "sanitizer_linux.h"
-#include "sanitizer_mutex.h"
-#include "sanitizer_placement_new.h"
+#  if (SANITIZER_ANDROID && SANITIZER_MIPS) || SANITIZER_LOONGARCH
+#    include <asm/reg.h>  // for mips SP register in sys/user.h
+#  endif
+#  include <sys/wait.h>  // for signal-related stuff
+
+#  ifdef sa_handler
+#    undef sa_handler
+#  endif
+
+#  ifdef sa_sigaction
+#    undef sa_sigaction
+#  endif
+
+#  include "sanitizer_common.h"
+#  include "sanitizer_flags.h"
+#  include "sanitizer_libc.h"
+#  include "sanitizer_linux.h"
+#  include "sanitizer_mutex.h"
+#  include "sanitizer_placement_new.h"
 
 // Sufficiently old kernel headers don't provide this value, but we can still
 // call prctl with it. If the runtime kernel is new enough, the prctl call will
@@ -508,29 +511,38 @@ typedef struct user regs_struct;
 #  define REG_SP regs[EF_REG29]
 # endif
 
-#elif defined(__aarch64__)
+#  elif defined(__loongarch__)
+typedef struct user_regs_struct regs_struct;
+static constexpr uptr kExtraRegs[] = {0};
+#    define ARCH_IOVEC_FOR_GETREGSET
+
+#    if SANITIZER_LOONGARCH
+#define REG_SP regs[3]
+#    endif
+
+#  elif defined(__aarch64__)
 typedef struct user_pt_regs regs_struct;
-#define REG_SP sp
+#    define REG_SP sp
 static constexpr uptr kExtraRegs[] = {0};
-#define ARCH_IOVEC_FOR_GETREGSET
+#    define ARCH_IOVEC_FOR_GETREGSET
 
-#elif SANITIZER_RISCV64
+#  elif SANITIZER_RISCV64
 typedef struct user_regs_struct regs_struct;
 // sys/ucontext.h already defines REG_SP as 2. Undefine it first.
-#undef REG_SP
-#define REG_SP sp
+#    undef REG_SP
+#    define REG_SP sp
 static constexpr uptr kExtraRegs[] = {0};
-#define ARCH_IOVEC_FOR_GETREGSET
+#    define ARCH_IOVEC_FOR_GETREGSET
 
-#elif defined(__s390__)
+#  elif defined(__s390__)
 typedef _user_regs_struct regs_struct;
-#define REG_SP gprs[15]
+#    define REG_SP gprs[15]
 static constexpr uptr kExtraRegs[] = {0};
-#define ARCH_IOVEC_FOR_GETREGSET
+#    define ARCH_IOVEC_FOR_GETREGSET
 
-#else
-#error "Unsupported architecture"
-#endif // SANITIZER_ANDROID && defined(__arm__)
+#  else
+#    error "Unsupported architecture"
+#  endif  // SANITIZER_ANDROID && defined(__arm__)
 
 tid_t SuspendedThreadsListLinux::GetThreadID(uptr index) const {
   CHECK_LT(index, thread_ids_.size());
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
index 710da4c..ea9aae0 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
@@ -263,6 +263,8 @@ class LLVMSymbolizerProcess final : public SymbolizerProcess {
     const char *const kSymbolizerArch = "--default-arch=riscv64";
 #elif defined(__aarch64__)
     const char* const kSymbolizerArch = "--default-arch=arm64";
+#elif SANITIZER_LOONGARCH64
+    const char *const kSymbolizerArch = "--default-arch=loongarch64";
 #elif defined(__arm__)
     const char* const kSymbolizerArch = "--default-arch=arm";
 #elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
diff --git a/compiler-rt.orig/lib/sanitizer_common/sanitizer_tls_get_addr.cpp b/compiler-rt.new/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
index 1f664b6..25d3305 100644
--- a/compiler-rt.orig/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/sanitizer_tls_get_addr.cpp
@@ -98,14 +98,16 @@ void DTLS_Destroy() {
 // "Dynamic thread vector pointers point 0x8000 past the start of each
 //  TLS block." (sysdeps/<arch>/dl-tls.h)
 static const uptr kDtvOffset = 0x8000;
-#elif defined(__riscv)
+#  elif defined(__loongarch__)
+static const uptr kDtvOffset = 0;
+#  elif defined(__riscv)
 // This is glibc's TLS_DTV_OFFSET:
 // "Dynamic thread vector pointers point 0x800 past the start of each
 // TLS block." (sysdeps/riscv/dl-tls.h)
 static const uptr kDtvOffset = 0x800;
-#else
+#  else
 static const uptr kDtvOffset = 0;
-#endif
+#  endif
 
 DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
                                 uptr static_tls_begin, uptr static_tls_end) {
diff --git a/compiler-rt.orig/lib/sanitizer_common/tests/CMakeLists.txt b/compiler-rt.new/lib/sanitizer_common/tests/CMakeLists.txt
index abd73ca..a68058b 100644
--- a/compiler-rt.orig/lib/sanitizer_common/tests/CMakeLists.txt
+++ b/compiler-rt.new/lib/sanitizer_common/tests/CMakeLists.txt
@@ -3,7 +3,7 @@ include(CompilerRTCompile)
 clang_compiler_add_cxx_check()
 
 # FIXME: use SANITIZER_COMMON_SUPPORTED_ARCH here
-filter_available_targets(SANITIZER_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el riscv64)
+filter_available_targets(SANITIZER_UNITTEST_SUPPORTED_ARCH x86_64 i386 mips64 mips64el riscv64 loongarch64)
 if(APPLE)
   darwin_filter_host_archs(SANITIZER_UNITTEST_SUPPORTED_ARCH SANITIZER_UNITTEST_SUPPORTED_ARCH)
 endif()
diff --git a/compiler-rt.orig/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp b/compiler-rt.new/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp
index 26593c0..7a5a32d 100644
--- a/compiler-rt.orig/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp
@@ -146,9 +146,11 @@ static const u64 kAddressSpaceSize = 1ULL << 39;
 static const u64 kAddressSpaceSize = 1ULL << 53;
 #elif defined(__s390__)
 static const u64 kAddressSpaceSize = 1ULL << 31;
-#else
+#elif defined(__loongarch__)
+static const u64 kAddressSpaceSize = 1ULL << 47;
+#  else
 static const u64 kAddressSpaceSize = 1ULL << 32;
-#endif
+#  endif
 
 static const uptr kRegionSizeLog = FIRST_32_SECOND_64(20, 24);
 
diff --git a/compiler-rt.orig/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cpp b/compiler-rt.new/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cpp
index 91ec2f9..cbaefe1 100644
--- a/compiler-rt.orig/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/tests/sanitizer_ring_buffer_test.cpp
@@ -10,7 +10,9 @@
 //
 //===----------------------------------------------------------------------===//
 #include "sanitizer_common/sanitizer_ring_buffer.h"
+
 #include "gtest/gtest.h"
+#include "sanitizer_common/sanitizer_common.h"
 
 namespace __sanitizer {
 
@@ -84,9 +86,10 @@ CompactRingBuffer<T> *AllocCompactRingBuffer(size_t count) {
 
 TEST(CompactRingBuffer, int64) {
   const size_t page_sizes[] = {1, 2, 4, 128};
+  size_t page_size = GetPageSizeCached();
 
   for (size_t pages : page_sizes) {
-    size_t count = 4096 * pages / sizeof(int64_t);
+    size_t count = page_size * pages / sizeof(int64_t);
     auto R = AllocCompactRingBuffer<int64_t>(count);
     int64_t top = count * 3 + 13;
     for (int64_t i = 0; i < top; ++i) R->push(i);
diff --git a/compiler-rt.orig/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp b/compiler-rt.new/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp
index 9a47b4e..4f01054 100644
--- a/compiler-rt.orig/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp
+++ b/compiler-rt.new/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp
@@ -32,6 +32,14 @@ class FastUnwindTest : public ::testing::Test {
   uhwptr fake_top;
   uhwptr fake_bottom;
   BufferedStackTrace trace;
+
+#if defined(__loongarch__) || defined(__riscv)
+  const uptr kFpOffset = 4;
+  const uptr kBpOffset = 2;
+#else
+  const uptr kFpOffset = 2;
+  const uptr kBpOffset = 0;
+#endif
 };
 
 static uptr PC(uptr idx) {
@@ -49,17 +57,17 @@ void FastUnwindTest::SetUp() {
   // Fill an array of pointers with fake fp+retaddr pairs.  Frame pointers have
   // even indices.
   for (uptr i = 0; i + 1 < fake_stack_size; i += 2) {
-    fake_stack[i] = (uptr)&fake_stack[i+2];  // fp
+    fake_stack[i] = (uptr)&fake_stack[i + kFpOffset];  // fp
     fake_stack[i+1] = PC(i + 1); // retaddr
   }
   // Mark the last fp point back up to terminate the stack trace.
   fake_stack[RoundDownTo(fake_stack_size - 1, 2)] = (uhwptr)&fake_stack[0];
 
   // Top is two slots past the end because UnwindFast subtracts two.
-  fake_top = (uhwptr)&fake_stack[fake_stack_size + 2];
+  fake_top = (uhwptr)&fake_stack[fake_stack_size + kFpOffset];
   // Bottom is one slot before the start because UnwindFast uses >.
   fake_bottom = (uhwptr)mapping;
-  fake_bp = (uptr)&fake_stack[0];
+  fake_bp = (uptr)&fake_stack[kBpOffset];
   start_pc = PC(0);
 }
 
@@ -120,7 +128,7 @@ TEST_F(FastUnwindTest, OneFrameStackTrace) {
   trace.Unwind(start_pc, fake_bp, nullptr, true, 1);
   EXPECT_EQ(1U, trace.size);
   EXPECT_EQ(start_pc, trace.trace[0]);
-  EXPECT_EQ((uhwptr)&fake_stack[0], trace.top_frame_bp);
+  EXPECT_EQ((uhwptr)&fake_stack[kBpOffset], trace.top_frame_bp);
 }
 
 TEST_F(FastUnwindTest, ZeroFramesStackTrace) {
diff --git a/compiler-rt.orig/lib/scudo/scudo_utils.cpp b/compiler-rt.new/lib/scudo/scudo_utils.cpp
index b7ce8f9..fd31f6c 100644
--- a/compiler-rt.orig/lib/scudo/scudo_utils.cpp
+++ b/compiler-rt.new/lib/scudo/scudo_utils.cpp
@@ -138,6 +138,8 @@ bool hasHardwareCRC32() {
   return hasHardwareCRC32ARMPosix();
 #endif  // SANITIZER_FUCHSIA
 }
+#elif defined(__loongarch__)
+bool hasHardwareCRC32() { return true; }
 #else
 bool hasHardwareCRC32() { return false; }
 #endif  // defined(__x86_64__) || defined(__i386__)
diff --git a/compiler-rt.orig/lib/scudo/standalone/checksum.cpp b/compiler-rt.new/lib/scudo/standalone/checksum.cpp
index 05d4ba5..56c639f 100644
--- a/compiler-rt.orig/lib/scudo/standalone/checksum.cpp
+++ b/compiler-rt.new/lib/scudo/standalone/checksum.cpp
@@ -74,6 +74,8 @@ bool hasHardwareCRC32() {
   return !!(getauxval(AT_HWCAP) & HWCAP_CRC32);
 #endif // SCUDO_FUCHSIA
 }
+#elif defined(__loongarch__)
+bool hasHardwareCRC32() { return true; }
 #else
 // No hardware CRC32 implemented in Scudo for other architectures.
 bool hasHardwareCRC32() { return false; }
diff --git a/compiler-rt.orig/lib/scudo/standalone/common.h b/compiler-rt.new/lib/scudo/standalone/common.h
index 662b733..30162ee 100644
--- a/compiler-rt.orig/lib/scudo/standalone/common.h
+++ b/compiler-rt.new/lib/scudo/standalone/common.h
@@ -109,6 +109,10 @@ inline void yieldProcessor(u8 Count) {
   __asm__ __volatile__("" ::: "memory");
   for (u8 I = 0; I < Count; I++)
     __asm__ __volatile__("yield");
+#elif defined(__loongarch__)
+  __asm__ __volatile__("" ::: "memory");
+  for (u8 I = 0; I < Count; I++)
+    __asm__ __volatile__("dbar 0");
 #endif
   __asm__ __volatile__("" ::: "memory");
 }
diff --git a/compiler-rt.orig/lib/tsan/CMakeLists.txt b/compiler-rt.new/lib/tsan/CMakeLists.txt
index 88c6f09..8fc45af 100644
--- a/compiler-rt.orig/lib/tsan/CMakeLists.txt
+++ b/compiler-rt.new/lib/tsan/CMakeLists.txt
@@ -122,7 +122,7 @@ if(APPLE)
     message(FATAL_ERROR "Building the TSan runtime requires at least macOS SDK 10.12 (or aligned SDK on other platforms)")
   endif()
 
-  add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S rtl/tsan_rtl_aarch64.S)
+  add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_amd64.S rtl/tsan_rtl_aarch64.S rtl/tsan_rtl_loongarch64.S)
 
   set(TSAN_LINK_LIBS ${SANITIZER_COMMON_LINK_LIBS})
 
@@ -199,6 +199,8 @@ else()
 	VERBATIM)
     elseif(arch MATCHES "mips64|mips64le")
       add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_mips64.S)
+    elseif(arch MATCHES "loongarch64")
+	  add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_loongarch64.S)
     else()
       set(TSAN_ASM_SOURCES)
     endif()
diff --git a/compiler-rt.orig/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt.new/lib/tsan/rtl/tsan_interceptors_posix.cpp
index 6c49ccd..a596d74 100644
--- a/compiler-rt.orig/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt.new/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -75,6 +75,8 @@ struct ucontext_t {
 #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.34"
 #endif
 
 extern "C" int pthread_attr_init(void *attr);
diff --git a/compiler-rt.orig/lib/tsan/rtl/tsan_platform.h b/compiler-rt.new/lib/tsan/rtl/tsan_platform.h
index 81d345d..f2342b2 100644
--- a/compiler-rt.orig/lib/tsan/rtl/tsan_platform.h
+++ b/compiler-rt.new/lib/tsan/rtl/tsan_platform.h
@@ -113,6 +113,47 @@ struct Mapping {
   static const uptr kVdsoBeg       = 0xfffff00000ull;
 };
 
+#    define TSAN_RUNTIME_VMA 1
+#  elif defined(__loongarch64)
+// clang-format off
+/*
+C/C++ on linux/loongarch64 (48-bit VMA)
+0000 0000 0000 - 0001 0000 0000: -                                           (4 GB)
+0001 0000 0000 - 0002 0000 0000: main binary                                 (4 GB)
+0002 0000 0000 - 0020 0000 0000: -                                         (120 GB)
+0020 0000 0000 - 0040 0000 0000: shadow                                    (128 GB)
+0040 0000 0000 - 0050 0000 0000: metainfo (memory blocks and sync objects)  (64 GB)
+0050 0000 0000 - 5555 0000 0000: -                                         (360 GB)
+5555 0000 0000 - 5556 0000 0000: main binary (PIE)                           (4 GB)
+5556 0000 0000 - 7fb0 0000 0000: -                                          (20 GB)
+7fb0 0000 0000 - 7fb2 0000 0000: traces                                      (8 GB)
+7fb2 0000 0000 - 7ffe 0000 0000: -                                         (304 GB)
+7ffe 0000 0000 - 7fff 0000 0000: heap                                        (4 GB)
+7fff 0000 0000 - 7fff 8000 0000: -                                           (2 GB)
+7fff 8000 0000 - 7fff ffff ffff: modules and main thread stack              (<2 GB)
+*/
+
+struct Mapping {
+  static const uptr kLoAppMemBeg   = 0x000000004000ull;
+  static const uptr kLoAppMemEnd   = 0x000200000000ull;
+  static const uptr kShadowBeg     = 0x002000000000ull;
+  static const uptr kShadowEnd     = 0x004000000000ull;
+  static const uptr kMetaShadowBeg = 0x005000000000ull;
+  static const uptr kMetaShadowEnd = 0x555500000000ull;
+  static const uptr kMidAppMemBeg  = 0x555500000000ull;
+  static const uptr kMidAppMemEnd  = 0x555600000000ull;
+  static const uptr kTraceMemBeg   = 0x7fb000000000ull;
+  static const uptr kTraceMemEnd   = 0x7fb200000000ull;
+  static const uptr kHeapMemBeg    = 0x7ffe00000000ull;
+  static const uptr kHeapMemEnd    = 0x7fff00000000ull;
+  static const uptr kHiAppMemBeg   = 0x7fff80000000ull;
+  static const uptr kHiAppMemEnd   = 0x800000000000ull;
+  static const uptr kAppMemMsk     = 0x7ff800000000ull;
+  static const uptr kAppMemXor     = 0x000800000000ull;
+  static const uptr kVdsoBeg       = 0x7fffffffc000ull;
+};
+// clang-format on
+
 #define TSAN_MID_APP_RANGE 1
 #elif defined(__aarch64__) && defined(__APPLE__)
 /*
@@ -244,10 +285,10 @@ struct Mapping48 {
 };
 
 // Indicates the runtime will define the memory regions at runtime.
-#define TSAN_RUNTIME_VMA 1
+#    define TSAN_RUNTIME_VMA 1
 // Indicates that mapping defines a mid range memory segment.
-#define TSAN_MID_APP_RANGE 1
-#elif defined(__powerpc64__)
+#    define TSAN_MID_APP_RANGE 1
+#  elif defined(__powerpc64__)
 // PPC64 supports multiple VMA which leads to multiple address transformation
 // functions.  To support these multiple VMAS transformations and mappings TSAN
 // runtime for PPC64 uses an external memory read (vmaSize) to select which
diff --git a/compiler-rt.orig/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt.new/lib/tsan/rtl/tsan_platform_linux.cpp
index 5e8879d..60b0c77 100644
--- a/compiler-rt.orig/lib/tsan/rtl/tsan_platform_linux.cpp
+++ b/compiler-rt.new/lib/tsan/rtl/tsan_platform_linux.cpp
@@ -66,7 +66,8 @@ extern "C" void *__libc_stack_end;
 void *__libc_stack_end = 0;
 #endif
 
-#if SANITIZER_LINUX && defined(__aarch64__) && !SANITIZER_GO
+#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch__)) && \
+    !SANITIZER_GO
 # define INIT_LONGJMP_XOR_KEY 1
 #else
 # define INIT_LONGJMP_XOR_KEY 0
@@ -296,6 +297,8 @@ void InitializePlatform() {
       CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
       reexec = true;
     }
+#endif
+#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch__))
     // Initialize the xor key used in {sig}{set,long}jump.
     InitializeLongjmpXorKey();
 #endif
@@ -377,6 +380,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
   return mangled_sp ^ xor_key;
 #elif defined(__mips__)
   return mangled_sp;
+#    elif defined(__loongarch__)
+  return mangled_sp ^ longjmp_xor_key;
 #else
   #error "Unknown platform"
 #endif
@@ -395,7 +400,7 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
 #elif SANITIZER_LINUX
 # ifdef __aarch64__
 #  define LONG_JMP_SP_ENV_SLOT 13
-# elif defined(__mips64)
+#elif defined(__mips64) || defined(__loongarch__)
 #  define LONG_JMP_SP_ENV_SLOT 1
 # else
 #  define LONG_JMP_SP_ENV_SLOT 6
@@ -419,7 +424,11 @@ static void InitializeLongjmpXorKey() {
 
   // 2. Retrieve vanilla/mangled SP.
   uptr sp;
+#ifdef __aarch64__
   asm("mov  %0, sp" : "=r" (sp));
+#else  // loongarch
+  asm("move  %0, $sp" : "=r"(sp));
+#endif
   uptr mangled_sp = ((uptr *)&env)[LONG_JMP_SP_ENV_SLOT];
 
   // 3. xor SPs to obtain key.
diff --git a/compiler-rt.orig/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt.new/lib/tsan/rtl/tsan_rtl.cpp
index 3d721eb..3ef1a08 100644
--- a/compiler-rt.orig/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt.new/lib/tsan/rtl/tsan_rtl.cpp
@@ -227,7 +227,7 @@ static void StartBackgroundThread() {
   ctx->background_thread = internal_start_thread(&BackgroundThread, 0);
 }
 
-#ifndef __mips__
+#  if !(defined(__mips__) || defined(__loongarch__))
 static void StopBackgroundThread() {
   atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed);
   internal_join_thread(ctx->background_thread);
@@ -432,7 +432,7 @@ void MaybeSpawnBackgroundThread() {
   // On MIPS, TSan initialization is run before
   // __pthread_initialize_minimal_internal() is finished, so we can not spawn
   // new threads.
-#if !SANITIZER_GO && !defined(__mips__)
+#if !SANITIZER_GO && !(defined(__mips__) || defined(__loongarch__))
   static atomic_uint32_t bg_thread = {};
   if (atomic_load(&bg_thread, memory_order_relaxed) == 0 &&
       atomic_exchange(&bg_thread, 1, memory_order_relaxed) == 0) {
diff --git a/compiler-rt.orig/lib/tsan/rtl/tsan_rtl.h b/compiler-rt.new/lib/tsan/rtl/tsan_rtl.h
index 04d474e..cfa4746 100644
--- a/compiler-rt.orig/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt.new/lib/tsan/rtl/tsan_rtl.h
@@ -54,7 +54,8 @@ namespace __tsan {
 
 #if !SANITIZER_GO
 struct MapUnmapCallback;
-#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__)
+#  if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) || \
+      defined(__loongarch64)
 
 struct AP32 {
   static const uptr kSpaceBeg = 0;
diff --git a/compiler-rt.orig/lib/xray/CMakeLists.txt b/compiler-rt.new/lib/xray/CMakeLists.txt
index 54f2ad8..e8f64d5 100644
--- a/compiler-rt.orig/lib/xray/CMakeLists.txt
+++ b/compiler-rt.new/lib/xray/CMakeLists.txt
@@ -47,6 +47,11 @@ set(aarch64_SOURCES
   xray_trampoline_AArch64.S
   )
 
+set(loongarch64_SOURCES
+  xray_loongarch.cpp
+  xray_trampoline_loongarch.S
+  )
+
 set(mips_SOURCES
   xray_mips.cpp
   xray_trampoline_mips.S
@@ -111,6 +116,7 @@ set(XRAY_ALL_SOURCE_FILES
   ${x86_64_SOURCES}
   ${arm_SOURCES}
   ${armhf_SOURCES}
+  ${loongarch64_SOURCES}
   ${mips_SOURCES}
   ${mipsel_SOURCES}
   ${mips64_SOURCES}
diff --git a/compiler-rt.orig/lib/xray/tests/CMakeLists.txt b/compiler-rt.new/lib/xray/tests/CMakeLists.txt
index 96a9db1..0f034f9 100644
--- a/compiler-rt.orig/lib/xray/tests/CMakeLists.txt
+++ b/compiler-rt.new/lib/xray/tests/CMakeLists.txt
@@ -65,6 +65,7 @@ if (NOT APPLE)
       ${LLVM_TESTINGSUPPORT_LDFLAGS} XRAY_UNITTEST_LINK_FLAGS)
     append_list_if(COMPILER_RT_HAS_LLVMTESTINGSUPPORT
       ${LLVM_TESTINGSUPPORT_LIBLIST} XRAY_UNITTEST_LINK_FLAGS)
+    list(APPEND XRAY_UNITTEST_LINK_FLAGS -lLLVMXRay -lLLVMSupport -lLLVMDemangle -lLLVMTestingSupport)
   else()
     # We add the library directories one at a time in our CFLAGS.
     foreach (DIR ${LLVM_LIBRARY_DIR})
diff --git a/compiler-rt.orig/lib/xray/xray_interface.cpp b/compiler-rt.new/lib/xray/xray_interface.cpp
index 7669b9a..cc0e925 100644
--- a/compiler-rt.orig/lib/xray/xray_interface.cpp
+++ b/compiler-rt.new/lib/xray/xray_interface.cpp
@@ -50,6 +50,8 @@ static const int16_t cSledLength = 28;
 static const int16_t cSledLength = 48;
 #elif SANITIZER_MIPS64
 static const int16_t cSledLength = 64;
+#elif SANITIZER_LOONGARCH64
+static const int16_t cSledLength = 48;
 #elif defined(__powerpc64__)
 static const int16_t cSledLength = 8;
 #else
diff --git a/compiler-rt.orig/lib/xray/xray_tsc.h b/compiler-rt.new/lib/xray/xray_tsc.h
index bd7e191..d1c1d78 100644
--- a/compiler-rt.orig/lib/xray/xray_tsc.h
+++ b/compiler-rt.new/lib/xray/xray_tsc.h
@@ -42,7 +42,8 @@ inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
 #include "xray_x86_64.inc"
 #elif defined(__powerpc64__)
 #include "xray_powerpc64.inc"
-#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__)
+#elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) ||         \
+    defined(__loongarch__)
 // Emulated TSC.
 // There is no instruction like RDTSCP in user mode on ARM. ARM's CP15 does
 //   not have a constant frequency like TSC on x86(_64), it may go faster
diff --git a/compiler-rt.orig/test/asan/CMakeLists.txt b/compiler-rt.new/test/asan/CMakeLists.txt
index 855fac4..a7e1730 100644
--- a/compiler-rt.orig/test/asan/CMakeLists.txt
+++ b/compiler-rt.new/test/asan/CMakeLists.txt
@@ -14,7 +14,7 @@ if(OS_NAME MATCHES "Windows" AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND
 endif()
 
 macro(get_bits_for_arch arch bits)
-  if (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|arm64|mips64|mips64el|s390x|sparcv9|riscv64")
+  if (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|arm64|mips64|mips64el|s390x|sparcv9|riscv64|loongarch64")
     set(${bits} 64)
   elseif (${arch} MATCHES "i386|arm|mips|mipsel|sparc")
     set(${bits} 32)
diff --git a/compiler-rt.orig/test/asan/TestCases/Linux/ptrace.cpp b/compiler-rt.new/test/asan/TestCases/Linux/ptrace.cpp
index 21743cf..a39b7a0 100644
--- a/compiler-rt.orig/test/asan/TestCases/Linux/ptrace.cpp
+++ b/compiler-rt.new/test/asan/TestCases/Linux/ptrace.cpp
@@ -14,7 +14,7 @@
 #include <unistd.h>
 #include <sys/uio.h> // for iovec
 #include <elf.h> // for NT_PRSTATUS
-#ifdef __aarch64__
+#if defined(__aarch64__) || defined(__loongarch__)
 # include <asm/ptrace.h>
 #endif
 
@@ -37,6 +37,13 @@ typedef struct user_fpsimd_state fpregs_struct;
 #define PRINT_REG_FP(__fpregs)  printf ("%x\n", (unsigned) (__fpregs.fpsr))
 #define ARCH_IOVEC_FOR_GETREGSET
 
+#elif defined(__loongarch__)
+typedef struct user_pt_regs regs_struct;
+typedef struct user_fp_state fpregs_struct;
+#define PRINT_REG_PC(__regs) printf("%lx\n", (unsigned long)(__regs.csr_era))
+#define PRINT_REG_FP(__fpregs) printf("%x\n", (unsigned)(__fpregs.fcsr))
+#define ARCH_IOVEC_FOR_GETREGSET
+
 #elif defined(__powerpc64__)
 typedef struct pt_regs regs_struct;
 typedef elf_fpregset_t fpregs_struct;
diff --git a/compiler-rt.orig/test/asan/TestCases/Linux/segv_read_write.c b/compiler-rt.new/test/asan/TestCases/Linux/segv_read_write.c
index b137970..d6c4fb1 100644
--- a/compiler-rt.orig/test/asan/TestCases/Linux/segv_read_write.c
+++ b/compiler-rt.new/test/asan/TestCases/Linux/segv_read_write.c
@@ -1,7 +1,7 @@
 // RUN: %clangxx_asan -std=c++11 -O0 %s -o %t
 // RUN: not %run %t       2>&1 | FileCheck %s --check-prefix=READ
 // RUN: not %run %t write 2>&1 | FileCheck %s --check-prefix=WRITE
-// UNSUPPORTED: powerpc64,mips,s390
+// UNSUPPORTED: powerpc64,mips,s390,loongarch
 
 #include <sys/mman.h>
 
diff --git a/compiler-rt.orig/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp b/compiler-rt.new/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp
index 4774993..438d72f 100644
--- a/compiler-rt.orig/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp
+++ b/compiler-rt.new/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp
@@ -3,7 +3,7 @@
 
 // Don't optimize, otherwise the variables which create redzones might be
 // dropped.
-// RUN: %clangxx_asan -std=c++20 -fexceptions -O0 %s -o %t -pthread
+// RUN: %clangxx_asan -fexceptions -O0 %s -o %t -pthread
 // RUN: %run %t
 
 // XFAIL: ios && !iossim
@@ -140,7 +140,7 @@ void *threadFun(void *AltStack) {
 int main() {
   size_t const PageSize = sysconf(_SC_PAGESIZE);
   // The Solaris defaults of 4k (32-bit) and 8k (64-bit) are too small.
-  size_t const MinStackSize = std::max(PTHREAD_STACK_MIN, 16 * 1024);
+  size_t const MinStackSize = std::max<size_t>(PTHREAD_STACK_MIN, 16 * 1024);
   // To align the alternate stack, we round this up to page_size.
   size_t const DefaultStackSize =
       (MinStackSize - 1 + PageSize) & ~(PageSize - 1);
diff --git a/compiler-rt.orig/test/builtins/Unit/addtf3_test.c b/compiler-rt.new/test/builtins/Unit/addtf3_test.c
index 82a8020..e47821d 100644
--- a/compiler-rt.orig/test/builtins/Unit/addtf3_test.c
+++ b/compiler-rt.new/test/builtins/Unit/addtf3_test.c
@@ -66,7 +66,7 @@ int main()
         return 1;
 
 #if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) || \
-    defined(i386) || defined(__x86_64__)
+    defined(i386) || defined(__x86_64__) || (defined(__loongarch__) && __loongarch_frlen != 0)
     // Rounding mode tests on supported architectures
     const long double m = 1234.0L, n = 0.01L;
 
diff --git a/compiler-rt.orig/test/builtins/Unit/subtf3_test.c b/compiler-rt.new/test/builtins/Unit/subtf3_test.c
index c06a0ba..df5c393 100644
--- a/compiler-rt.orig/test/builtins/Unit/subtf3_test.c
+++ b/compiler-rt.new/test/builtins/Unit/subtf3_test.c
@@ -59,7 +59,7 @@ int main()
         return 1;
 
 #if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) || \
-    defined(i386) || defined(__x86_64__)
+    defined(i386) || defined(__x86_64__) || (defined(__loongarch__) && __loongarch_frlen != 0)
     // Rounding mode tests on supported architectures
     const long double m = 1234.02L, n = 0.01L;
 
diff --git a/compiler-rt.orig/test/fuzzer/disable-leaks.test b/compiler-rt.new/test/fuzzer/disable-leaks.test
index 1c65884..fc762d2 100644
--- a/compiler-rt.orig/test/fuzzer/disable-leaks.test
+++ b/compiler-rt.new/test/fuzzer/disable-leaks.test
@@ -1,5 +1,5 @@
 REQUIRES: lsan
-UNSUPPORTED: aarch64
+UNSUPPORTED: aarch64, loongarch
 RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest
 RUN: %run %t-AccumulateAllocationsTest -detect_leaks=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=ACCUMULATE_ALLOCS
 ACCUMULATE_ALLOCS: INFO: libFuzzer disabled leak detection after every mutation
diff --git a/compiler-rt.orig/test/fuzzer/exit_on_src_pos.test b/compiler-rt.new/test/fuzzer/exit_on_src_pos.test
index d8fb662..de4da32 100644
--- a/compiler-rt.orig/test/fuzzer/exit_on_src_pos.test
+++ b/compiler-rt.new/test/fuzzer/exit_on_src_pos.test
@@ -3,6 +3,8 @@
 # TODO: Find out why test fails on Darwin with -O2.
 # Binaries must end in .exe or else symbolization will break on Windows because of how periods
 # in expansion of %t cause the compiler to overwrite .lib and .exp files.
+UNSUPPORTED: loongarch
+
 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.orig/test/fuzzer/fork-ubsan.test b/compiler-rt.new/test/fuzzer/fork-ubsan.test
index 16be90d..09af1f9 100644
--- a/compiler-rt.orig/test/fuzzer/fork-ubsan.test
+++ b/compiler-rt.new/test/fuzzer/fork-ubsan.test
@@ -1,4 +1,4 @@
-# UNSUPPORTED: darwin, freebsd, aarch64
+# UNSUPPORTED: darwin, freebsd, aarch64, loongarch
 # Tests how the fork mode works together with ubsan.
 RUN: %cpp_compiler %S/IntegerOverflowTest.cpp -o %t-IntegerOverflowTest -fsanitize=signed-integer-overflow -fno-sanitize-recover=signed-integer-overflow
 RUN: not %run %t-IntegerOverflowTest -fork=1 -ignore_crashes=1  -runs=10000 2>&1 | FileCheck %s --check-prefix=UBSAN_FORK
diff --git a/compiler-rt.orig/test/lit.common.cfg.py b/compiler-rt.new/test/lit.common.cfg.py
index 30cfdbe..8a1b518 100644
--- a/compiler-rt.orig/test/lit.common.cfg.py
+++ b/compiler-rt.new/test/lit.common.cfg.py
@@ -390,7 +390,7 @@ if config.host_os == 'Linux':
   if not config.android and len(ver_lines) and ver_lines[0].startswith(b"ldd "):
     from distutils.version import LooseVersion
     ver = LooseVersion(ver_lines[0].split()[-1].decode())
-    for required in ["2.27", "2.30"]:
+    for required in ["2.27", "2.30", "2.34"]:
       if ver >= LooseVersion(required):
         config.available_features.add("glibc-" + required)
 
diff --git a/compiler-rt.orig/test/lsan/TestCases/strace_test.cpp b/compiler-rt.new/test/lsan/TestCases/strace_test.cpp
index 18c809c..2b4835d 100644
--- a/compiler-rt.orig/test/lsan/TestCases/strace_test.cpp
+++ b/compiler-rt.new/test/lsan/TestCases/strace_test.cpp
@@ -5,6 +5,7 @@
 // FIXME: This technically works in practice but cannot be tested because the
 // fatal-error caused adb to failed. Could not be captured to stderr to lit-check.
 // XFAIL: android
+// UNSUPPORTED : loongarch
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/compiler-rt.orig/test/lsan/TestCases/swapcontext.cpp b/compiler-rt.new/test/lsan/TestCases/swapcontext.cpp
index d099959..5f23cd3 100644
--- a/compiler-rt.orig/test/lsan/TestCases/swapcontext.cpp
+++ b/compiler-rt.new/test/lsan/TestCases/swapcontext.cpp
@@ -5,7 +5,7 @@
 // RUN: %env_lsan_opts= %run %t 2>&1
 // RUN: %env_lsan_opts= not %run %t foo 2>&1 | FileCheck %s
 // Missing 'getcontext' and 'makecontext' on Android.
-// UNSUPPORTED: arm,powerpc64,android
+// UNSUPPORTED: arm,powerpc64,android,loongarch
 
 #include "sanitizer_common/sanitizer_ucontext.h"
 #include <stdio.h>
diff --git a/compiler-rt.orig/test/lsan/TestCases/use_registers.cpp b/compiler-rt.new/test/lsan/TestCases/use_registers.cpp
index dcf3bb9..21a88a7 100644
--- a/compiler-rt.orig/test/lsan/TestCases/use_registers.cpp
+++ b/compiler-rt.new/test/lsan/TestCases/use_registers.cpp
@@ -32,6 +32,10 @@ extern "C" void *registers_thread_func(void *arg) {
   asm("move $16, %0"
       :
       : "r"(p));
+#elif defined(__loongarch__)
+  asm("move $r23, %0"
+      :
+      : "r"(p));
 #elif defined(__arm__)
   asm("mov r5, %0"
       :
diff --git a/compiler-rt.orig/test/lsan/lit.common.cfg.py b/compiler-rt.new/test/lsan/lit.common.cfg.py
index 5adeec3..9a3370a 100644
--- a/compiler-rt.orig/test/lsan/lit.common.cfg.py
+++ b/compiler-rt.new/test/lsan/lit.common.cfg.py
@@ -76,7 +76,7 @@ config.substitutions.append( ("%clangxx_lsan ", build_invocation(clang_lsan_cxxf
 # LeakSanitizer tests are currently supported on
 # Android{aarch64, x86, x86_64}, x86-64 Linux, PowerPC64 Linux, arm Linux, mips64 Linux, s390x Linux and x86_64 Darwin.
 supported_android = config.android and config.target_arch in ['x86_64', 'i386', 'aarch64'] and 'android-thread-properties-api' in config.available_features
-supported_linux = (not config.android) and config.host_os == 'Linux' and config.host_arch in ['x86_64', 'ppc64', 'ppc64le', 'mips64', 'arm', 'armhf', 'armv7l', 's390x']
+supported_linux = (not config.android) and config.host_os == 'Linux' and config.host_arch in ['x86_64', 'ppc64', 'ppc64le', 'mips64', 'arm', 'armhf', 'armv7l', 's390x', 'loongarch64']
 supported_darwin = config.host_os == 'Darwin' and config.target_arch in ['x86_64']
 supported_netbsd = config.host_os == 'NetBSD' and config.target_arch in ['x86_64', 'i386']
 if not (supported_android or supported_linux or supported_darwin or supported_netbsd):
diff --git a/compiler-rt.orig/test/msan/allocator_mapping.cpp b/compiler-rt.new/test/msan/allocator_mapping.cpp
index 533128f..6bc4db3 100644
--- a/compiler-rt.orig/test/msan/allocator_mapping.cpp
+++ b/compiler-rt.new/test/msan/allocator_mapping.cpp
@@ -8,7 +8,7 @@
 // This test only makes sense for the 64-bit allocator. The 32-bit allocator
 // does not have a fixed mapping. Exclude platforms that use the 32-bit
 // allocator.
-// UNSUPPORTED: target-is-mips64,target-is-mips64el,aarch64
+// UNSUPPORTED: target-is-mips64,target-is-mips64el,aarch64, loongarch
 
 #include <assert.h>
 #include <stdio.h>
diff --git a/compiler-rt.orig/test/msan/fstat.cpp b/compiler-rt.new/test/msan/fstat.cpp
index 83f9705..1338663 100644
--- a/compiler-rt.orig/test/msan/fstat.cpp
+++ b/compiler-rt.new/test/msan/fstat.cpp
@@ -4,7 +4,7 @@
 #include <stdlib.h>
 
 int main(void) {
-  struct stat st;
+  struct stat st = {};
   if (fstat(0, &st))
     exit(1);
 
diff --git a/compiler-rt.orig/test/msan/lit.cfg.py b/compiler-rt.new/test/msan/lit.cfg.py
index 8ec1614..2565fca 100644
--- a/compiler-rt.orig/test/msan/lit.cfg.py
+++ b/compiler-rt.new/test/msan/lit.cfg.py
@@ -44,7 +44,7 @@ if config.host_os not in ['Linux', 'NetBSD', 'FreeBSD']:
 # For mips64, mips64el we have forced store_context_size to 1 because these
 # archs use slow unwinder which is not async signal safe. Therefore we only
 # check the first frame since store_context size is 1.
-if config.host_arch in ['mips64', 'mips64el']:
+if config.host_arch in ['mips64', 'mips64el', 'loongarch64']:
   config.substitutions.append( ('CHECK-%short-stack', 'CHECK-SHORT-STACK'))
 else:
   config.substitutions.append( ('CHECK-%short-stack', 'CHECK-FULL-STACK'))
diff --git a/compiler-rt.orig/test/msan/mmap.cpp b/compiler-rt.new/test/msan/mmap.cpp
index 2e7e883..54cde8f 100644
--- a/compiler-rt.orig/test/msan/mmap.cpp
+++ b/compiler-rt.new/test/msan/mmap.cpp
@@ -22,6 +22,10 @@ bool AddrIsApp(void *p) {
   return (addr >= 0x0000000000ULL && addr <= 0x0200000000ULL) ||
          (addr >= 0xa200000000ULL && addr <= 0xc000000000ULL) ||
          addr >= 0xe200000000ULL;
+#elif defined(__loongarch64)
+  return (addr >= 0x000000000000ULL && addr < 0x000200000000ULL) ||
+         (addr >= 0x510000000000ULL && addr < 0x600000000000ULL) ||
+         (addr >= 0x700000000000ULL && addr < 0x800000000000ULL);
 #elif defined(__powerpc64__)
   return addr < 0x000100000000ULL || addr >= 0x300000000000ULL;
 #elif defined(__s390x__)
@@ -60,7 +64,7 @@ bool AddrIsApp(void *p) {
 
 int main() {
   // Large enough to quickly exhaust the entire address space.
-#if defined(__mips64) || defined(__aarch64__)
+#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch64)
   const size_t kMapSize = 0x100000000ULL;
 #else
   const size_t kMapSize = 0x1000000000ULL;
diff --git a/compiler-rt.orig/test/msan/mmap_below_shadow.cpp b/compiler-rt.new/test/msan/mmap_below_shadow.cpp
index 46d948c..97c416b 100644
--- a/compiler-rt.orig/test/msan/mmap_below_shadow.cpp
+++ b/compiler-rt.new/test/msan/mmap_below_shadow.cpp
@@ -21,7 +21,7 @@ int main(void) {
 #elif defined(__x86_64__)
   uintptr_t hint = 0x4f0000000000ULL;
   const uintptr_t app_start = 0x600000000000ULL;
-#elif defined (__mips64)
+#elif defined(__mips64) || defined(__loongarch64)
   uintptr_t hint = 0x4f00000000ULL;
   const uintptr_t app_start = 0x6000000000ULL;
 #elif defined (__powerpc64__)
diff --git a/compiler-rt.orig/test/msan/param_tls_limit.cpp b/compiler-rt.new/test/msan/param_tls_limit.cpp
index 43e6685..cd7ed31 100644
--- a/compiler-rt.orig/test/msan/param_tls_limit.cpp
+++ b/compiler-rt.new/test/msan/param_tls_limit.cpp
@@ -5,9 +5,9 @@
 // RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
 // RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && %run %t
 //
-// AArch64 fails with:
+// AArch64 and LoongArch fails with:
 // void f801(S<801>): Assertion `__msan_test_shadow(&s, sizeof(s)) == -1' failed
-// XFAIL: aarch64
+// XFAIL: aarch64 || loongarch
 // When passing huge structs by value, SystemZ uses pointers, therefore this
 // test in its present form is unfortunately not applicable.
 // ABI says: "A struct or union of any other size <snip>. Replace such an
diff --git a/compiler-rt.orig/test/msan/preinit_array.cpp b/compiler-rt.new/test/msan/preinit_array.cpp
index 6f877ba..c72004e 100644
--- a/compiler-rt.orig/test/msan/preinit_array.cpp
+++ b/compiler-rt.new/test/msan/preinit_array.cpp
@@ -1,5 +1,8 @@
 // RUN: %clangxx_msan -O0 %s -o %t && %run %t
 
+// FIXME: Something changed in glibc 2.34, maybe earier.
+// UNSUPPORTED: glibc-2.34
+
 #include <sanitizer/msan_interface.h>
 
 volatile int global;
diff --git a/compiler-rt.orig/test/msan/strlen_of_shadow.cpp b/compiler-rt.new/test/msan/strlen_of_shadow.cpp
index 5e7c89c..3b0365a 100644
--- a/compiler-rt.orig/test/msan/strlen_of_shadow.cpp
+++ b/compiler-rt.new/test/msan/strlen_of_shadow.cpp
@@ -13,9 +13,9 @@
 #include "test.h"
 
 const char *mem_to_shadow(const char *p) {
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__loongarch64)
   return (char *)((uintptr_t)p ^ 0x500000000000ULL);
-#elif defined (__mips64)
+#elif defined(__mips64)
   return (char *)((uintptr_t)p ^ 0x8000000000ULL);
 #elif defined(__powerpc64__)
 #define LINEARIZE_MEM(mem) \
diff --git a/compiler-rt.orig/test/msan/vararg.cpp b/compiler-rt.new/test/msan/vararg.cpp
index e1a7b12..ef4e40c 100644
--- a/compiler-rt.orig/test/msan/vararg.cpp
+++ b/compiler-rt.new/test/msan/vararg.cpp
@@ -16,10 +16,11 @@
 
 // Check that shadow and origin are passed through va_args.
 
-// Copying origins on AArch64, MIPS and PowerPC isn't supported yet.
+// Copying origins on AArch64, LoongArch, MIPS and PowerPC isn't supported yet.
 // XFAIL: aarch64
 // XFAIL: mips
 // XFAIL: powerpc64
+// XFAIL: loongarch
 
 #include <stdarg.h>
 #include <string.h>
diff --git a/compiler-rt.orig/test/msan/vector_select.cpp b/compiler-rt.new/test/msan/vector_select.cpp
index 0cf1164..8173b86 100644
--- a/compiler-rt.orig/test/msan/vector_select.cpp
+++ b/compiler-rt.new/test/msan/vector_select.cpp
@@ -11,7 +11,7 @@ __m128d select(bool b, __m128d c, __m128d d)
 {
   return b ? c : d;
 }
-#elif defined (__mips64) || defined (__powerpc64__)
+#elif defined(__mips64) || defined(__powerpc64__) || defined(__loongarch64)
 typedef double __w64d __attribute__ ((vector_size(16)));
 
 __w64d select(bool b, __w64d c, __w64d d)
diff --git a/compiler-rt.orig/test/msan/wcsncpy.cpp b/compiler-rt.new/test/msan/wcsncpy.cpp
index f448ab2..a5f31f4 100644
--- a/compiler-rt.orig/test/msan/wcsncpy.cpp
+++ b/compiler-rt.new/test/msan/wcsncpy.cpp
@@ -1,7 +1,7 @@
 // RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
 
-// XFAIL: mips
+// XFAIL: mips || loongarch
 
 #include <assert.h>
 #include <wchar.h>
diff --git a/compiler-rt.orig/test/sanitizer_common/TestCases/Linux/pthread_mutex.cpp b/compiler-rt.new/test/sanitizer_common/TestCases/Linux/pthread_mutex.cpp
index 6109581..45bff96 100644
--- a/compiler-rt.orig/test/sanitizer_common/TestCases/Linux/pthread_mutex.cpp
+++ b/compiler-rt.new/test/sanitizer_common/TestCases/Linux/pthread_mutex.cpp
@@ -4,7 +4,8 @@
 
 #include <pthread.h>
 
-#ifdef USE_GLIBC
+#if defined(USE_GLIBC) && !__GLIBC_PREREQ(2, 34)
+// They were removed from GLIBC 2.34
 extern "C" int __pthread_mutex_lock(pthread_mutex_t *__mutex);
 extern "C" int __pthread_mutex_unlock(pthread_mutex_t *__mutex);
 #define LOCK __pthread_mutex_lock
diff --git a/compiler-rt.orig/test/sanitizer_common/TestCases/Linux/ptrace.cpp b/compiler-rt.new/test/sanitizer_common/TestCases/Linux/ptrace.cpp
index 82532c3..a4645c0 100644
--- a/compiler-rt.orig/test/sanitizer_common/TestCases/Linux/ptrace.cpp
+++ b/compiler-rt.new/test/sanitizer_common/TestCases/Linux/ptrace.cpp
@@ -16,7 +16,7 @@
  #include <asm/ptrace.h>
  #include <sys/procfs.h>
 #endif
-#ifdef __aarch64__
+#if defined(__aarch64__) || defined(__loongarch__)
 // GLIBC 2.20+ sys/user does not include asm/ptrace.h
  #include <asm/ptrace.h>
 #endif
@@ -114,6 +114,26 @@ int main(void) {
       printf("%x\n", fpregs.fpc);
 #endif // (__s390__)
 
+#if (__loongarch64)
+    struct iovec regset_io;
+
+    struct user_pt_regs regs;
+    regset_io.iov_base = &regs;
+    regset_io.iov_len = sizeof(regs);
+    res = ptrace(PTRACE_GETREGSET, pid, (void *)NT_PRSTATUS, (void *)&regset_io);
+    assert(!res);
+    if (regs.csr_era)
+      printf("%lx\n", regs.csr_era);
+
+    struct user_fp_state fpregs;
+    regset_io.iov_base = &fpregs;
+    regset_io.iov_len = sizeof(fpregs);
+    res = ptrace(PTRACE_GETREGSET, pid, (void *)NT_FPREGSET, (void *)&regset_io);
+    assert(!res);
+    if (fpregs.fcsr)
+      printf("%lx\n", fpregs.fcsr);
+#endif // (__loongarch64)
+
     siginfo_t siginfo;
     res = ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo);
     assert(!res);
diff --git a/compiler-rt.orig/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cpp b/compiler-rt.new/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cpp
index 0ffb346..43e21e2 100644
--- a/compiler-rt.orig/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cpp
+++ b/compiler-rt.new/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cpp
@@ -8,7 +8,8 @@
 
 // getauxval() used instead of sysconf() in GetPageSize() is defined starting
 // glbc version 2.16.
-#if __GLIBC_PREREQ(2, 16)
+// Does not work with 2.31 and above at it calls sysconf for SIGSTKSZ.
+#if __GLIBC_PREREQ(2, 16) && !__GLIBC_PREREQ(2, 31)
 extern "C" long sysconf(int name) {
   fprintf(stderr, "sysconf wrapper called\n");
   return 0;
diff --git a/compiler-rt.orig/test/sanitizer_common/TestCases/Posix/lstat.cpp b/compiler-rt.new/test/sanitizer_common/TestCases/Posix/lstat.cpp
index 75b1961..f2ca240 100644
--- a/compiler-rt.orig/test/sanitizer_common/TestCases/Posix/lstat.cpp
+++ b/compiler-rt.new/test/sanitizer_common/TestCases/Posix/lstat.cpp
@@ -5,7 +5,7 @@
 #include <sys/stat.h>
 
 int main(void) {
-  struct stat st;
+  struct stat st = {};
 
   assert(!lstat("/dev/null", &st));
 #if defined(__sun__) && defined(__svr4__)
diff --git a/compiler-rt.orig/test/sanitizer_common/print_address.h b/compiler-rt.new/test/sanitizer_common/print_address.h
index e7bb1a3..7935f7b 100644
--- a/compiler-rt.orig/test/sanitizer_common/print_address.h
+++ b/compiler-rt.new/test/sanitizer_common/print_address.h
@@ -8,7 +8,7 @@ void print_address(const char *str, int n, ...) {
   while (n--) {
     void *p = va_arg(ap, void *);
 #if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \
-    defined(__s390x__)
+    defined(__s390x__) || defined(__loongarch__)
     // 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);
diff --git a/compiler-rt.orig/test/tsan/map32bit.cpp b/compiler-rt.new/test/tsan/map32bit.cpp
index 8aef27b..0629ae2 100644
--- a/compiler-rt.orig/test/tsan/map32bit.cpp
+++ b/compiler-rt.new/test/tsan/map32bit.cpp
@@ -11,6 +11,7 @@
 // XFAIL: mips
 // XFAIL: aarch64
 // XFAIL: powerpc64
+// XFAIL: loongarch
 
 // MAP_32BIT doesn't exist on OS X and NetBSD.
 // UNSUPPORTED: darwin,netbsd
diff --git a/compiler-rt.orig/test/tsan/mmap_large.cpp b/compiler-rt.new/test/tsan/mmap_large.cpp
index c8d258e..10ae9a0 100644
--- a/compiler-rt.orig/test/tsan/mmap_large.cpp
+++ b/compiler-rt.new/test/tsan/mmap_large.cpp
@@ -19,6 +19,8 @@ int main() {
   const size_t kLog2Size = 39;
 #elif defined(__mips64) || defined(__aarch64__)
   const size_t kLog2Size = 32;
+#elif defined(__loongarch64)
+  const size_t kLog2Size = 32;
 #elif defined(__powerpc64__)
   const size_t kLog2Size = 39;
 #endif
diff --git a/compiler-rt.orig/test/tsan/test.h b/compiler-rt.new/test/tsan/test.h
index 4c75572..4b2ddc0 100644
--- a/compiler-rt.orig/test/tsan/test.h
+++ b/compiler-rt.new/test/tsan/test.h
@@ -61,6 +61,8 @@ unsigned long long monotonic_clock_ns() {
 const int kPCInc = 4;
 #elif defined(__sparc__) || defined(__mips__)
 const int kPCInc = 8;
+#elif defined(__loongarch__)
+const int kPCInc = 4;
 #else
 const int kPCInc = 1;
 #endif
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/arg1-arg0-logging.cpp b/compiler-rt.new/test/xray/TestCases/Posix/arg1-arg0-logging.cpp
index 757f81a..a531622 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/arg1-arg0-logging.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/arg1-arg0-logging.cpp
@@ -6,7 +6,7 @@
 // RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg0-arg1-logging-" %run %t
 //
 // TODO: Support these in ARM and PPC
-// XFAIL: arm || aarch64 || mips
+// XFAIL: arm || aarch64 || mips || loongarch
 // UNSUPPORTED: powerpc64le
 
 #include "xray/xray_interface.h"
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/arg1-logger.cpp b/compiler-rt.new/test/xray/TestCases/Posix/arg1-logger.cpp
index 48544c3..0d7c9a2 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/arg1-logger.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/arg1-logger.cpp
@@ -11,7 +11,7 @@
 // RUN: rm -f arg1-logger-*
 //
 // At the time of writing, the ARM trampolines weren't written yet.
-// XFAIL: arm || aarch64 || mips
+// XFAIL: arm || aarch64 || mips || loongarch
 // See the mailing list discussion of r296998.
 // UNSUPPORTED: powerpc64le
 
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/arg1-logging-implicit-this.cpp b/compiler-rt.new/test/xray/TestCases/Posix/arg1-logging-implicit-this.cpp
index d8dd622..26129a8 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/arg1-logging-implicit-this.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/arg1-logging-implicit-this.cpp
@@ -4,7 +4,7 @@
 // RUN: rm -f log-args-this-*
 // RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=log-args-this-" %run %t
 //
-// XFAIL: FreeBSD || arm || aarch64 || mips
+// XFAIL: FreeBSD || arm || aarch64 || mips || loongarch
 // UNSUPPORTED: powerpc64le
 #include "xray/xray_interface.h"
 #include <cassert>
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/argv0-log-file-name.cpp b/compiler-rt.new/test/xray/TestCases/Posix/argv0-log-file-name.cpp
index bd48693..f364151 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/argv0-log-file-name.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/argv0-log-file-name.cpp
@@ -7,6 +7,7 @@
 // RUN: rm xray-log.argv0-log-file-name.* xray.log.file.name
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include <cstdio>
 #include <libgen.h>
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/coverage-sample.cpp b/compiler-rt.new/test/xray/TestCases/Posix/coverage-sample.cpp
index 1903ad6..70dfd46 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/coverage-sample.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/coverage-sample.cpp
@@ -6,6 +6,7 @@
 // RUN: XRAY_OPTIONS="patch_premain=false" %run %t | FileCheck %s
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include "xray/xray_interface.h"
 
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/fixedsize-logging.cpp b/compiler-rt.new/test/xray/TestCases/Posix/fixedsize-logging.cpp
index e4462c8..d9cdad5 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/fixedsize-logging.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/fixedsize-logging.cpp
@@ -8,6 +8,7 @@
 // RUN: rm fixedsize-logging-*
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include <cstdio>
 
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/func-id-utils.cpp b/compiler-rt.new/test/xray/TestCases/Posix/func-id-utils.cpp
index ab0c5b0..b2631f1 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/func-id-utils.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/func-id-utils.cpp
@@ -7,6 +7,7 @@
 // RUN: XRAY_OPTIONS="patch_premain=false" %run %t
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include "xray/xray_interface.h"
 #include <algorithm>
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/logging-modes.cpp b/compiler-rt.new/test/xray/TestCases/Posix/logging-modes.cpp
index f839ba5..2302995 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/logging-modes.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/logging-modes.cpp
@@ -5,6 +5,7 @@
 // RUN: %run %t | FileCheck %s
 //
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include "xray/xray_interface.h"
 #include "xray/xray_log_interface.h"
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/optional-inmemory-log.cpp b/compiler-rt.new/test/xray/TestCases/Posix/optional-inmemory-log.cpp
index a32c874..59d4c53 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/optional-inmemory-log.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/optional-inmemory-log.cpp
@@ -9,6 +9,7 @@
 // RUN: rm -f optional-inmemory-log.xray-*
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include <cstdio>
 
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/patching-unpatching.cpp b/compiler-rt.new/test/xray/TestCases/Posix/patching-unpatching.cpp
index 978a897..267c431 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/patching-unpatching.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/patching-unpatching.cpp
@@ -7,6 +7,7 @@
 // RUN: XRAY_OPTIONS="patch_premain=false" %run %t 2>&1 | FileCheck %s
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include "xray/xray_interface.h"
 
diff --git a/compiler-rt.orig/test/xray/TestCases/Posix/pic_test.cpp b/compiler-rt.new/test/xray/TestCases/Posix/pic_test.cpp
index fbf6bdc..161567b 100644
--- a/compiler-rt.orig/test/xray/TestCases/Posix/pic_test.cpp
+++ b/compiler-rt.new/test/xray/TestCases/Posix/pic_test.cpp
@@ -10,6 +10,7 @@
 // RUN: rm -f pic-test-logging-*
 
 // UNSUPPORTED: target-is-mips64,target-is-mips64el
+// UNSUPPORTED: target-is-loongarch64
 
 #include <cstdio>
 
-- 
2.41.0

