[compiler-rt] f4e8fbc - [compiler-rt][nsan] Add lit config for tests (#100286)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 23 22:48:09 PDT 2024


Author: Alexander Shaposhnikov
Date: 2024-07-23T22:48:05-07:00
New Revision: f4e8fbc5e90a4f2959a0eb6d7b01e7e279fb693b

URL: https://github.com/llvm/llvm-project/commit/f4e8fbc5e90a4f2959a0eb6d7b01e7e279fb693b
DIFF: https://github.com/llvm/llvm-project/commit/f4e8fbc5e90a4f2959a0eb6d7b01e7e279fb693b.diff

LOG: [compiler-rt][nsan] Add lit config for tests (#100286)

Initial setup for tests.

Test plan: ninja check-nsan

Added: 
    compiler-rt/test/nsan/alloca.cpp
    compiler-rt/test/nsan/helpers.h
    compiler-rt/test/nsan/sum.cpp

Modified: 
    compiler-rt/test/nsan/CMakeLists.txt
    compiler-rt/test/nsan/lit.cfg.py
    compiler-rt/test/nsan/lit.site.cfg.py.in

Removed: 
    


################################################################################
diff  --git a/compiler-rt/test/nsan/CMakeLists.txt b/compiler-rt/test/nsan/CMakeLists.txt
index d702e122a85ef..78a1f4baee116 100644
--- a/compiler-rt/test/nsan/CMakeLists.txt
+++ b/compiler-rt/test/nsan/CMakeLists.txt
@@ -3,6 +3,22 @@ set(NSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 set(NSAN_TESTSUITES)
 set(NSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} nsan)
 
+macro(add_nsan_testsuite arch)
+  set(NSAN_TEST_TARGET_ARCH ${arch})
+  get_test_cc_for_arch(${arch} NSAN_TEST_TARGET_CC NSAN_TEST_TARGET_CFLAGS)
+
+  string(TOUPPER ${arch} CONFIG_NAME)
+  configure_lit_site_cfg(
+    ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+    ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg.py)
+  list(APPEND NSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endmacro()
+
+set(NSAN_TEST_ARCH ${NSAN_SUPPORTED_ARCH})
+foreach(arch ${NSAN_TEST_ARCH})
+  add_nsan_testsuite(${arch})
+endforeach()
+
 if(COMPILER_RT_LIBCXX_PATH AND COMPILER_RT_LIBCXXABI_PATH)
   configure_lit_site_cfg(
     ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in

diff  --git a/compiler-rt/test/nsan/alloca.cpp b/compiler-rt/test/nsan/alloca.cpp
new file mode 100644
index 0000000000000..33f7c1364e664
--- /dev/null
+++ b/compiler-rt/test/nsan/alloca.cpp
@@ -0,0 +1,26 @@
+// RUN: %clangxx_nsan -O0 -g %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_nsan -O3 -g %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <cstddef>
+
+#include "helpers.h"
+
+extern "C" void __nsan_dump_shadow_mem(const char *addr, size_t size_bytes,
+                                       size_t bytes_per_line, size_t reserved);
+
+int main() {
+  int size = 3 * sizeof(float);
+  // Make sure we allocate dynamically: https://godbolt.org/z/T3h998.
+  DoNotOptimize(size);
+  float *array = reinterpret_cast<float *>(__builtin_alloca(size));
+  DoNotOptimize(array);
+  array[0] = 1.0;
+  array[1] = 2.0;
+  // The third float is uninitialized.
+  __nsan_dump_shadow_mem((const char *)array, 3 * sizeof(float), 16, 0);
+  // CHECK: {{.*}} f0 f1 f2 f3 f0 f1 f2 f3 __ __ __ __ (1.00000000000000000000) (2.00000000000000000000)
+  return 0;
+}

diff  --git a/compiler-rt/test/nsan/helpers.h b/compiler-rt/test/nsan/helpers.h
new file mode 100644
index 0000000000000..487707a0a8fa3
--- /dev/null
+++ b/compiler-rt/test/nsan/helpers.h
@@ -0,0 +1,4 @@
+// Prevents the compiler from optimizing everything away.
+template <class T> void DoNotOptimize(const T &var) {
+  asm volatile("" : "+m"(const_cast<T &>(var)));
+}

diff  --git a/compiler-rt/test/nsan/lit.cfg.py b/compiler-rt/test/nsan/lit.cfg.py
index 8b137891791fe..2d67911a7d5d8 100644
--- a/compiler-rt/test/nsan/lit.cfg.py
+++ b/compiler-rt/test/nsan/lit.cfg.py
@@ -1 +1,36 @@
+config.name = "NSan" + config.name_suffix
 
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+# Test suffixes.
+config.suffixes = [".c", ".cpp", ".test"]
+
+# C & CXX flags.
+c_flags = [config.target_cflags]
+
+# CXX flags
+cxx_flags = c_flags + config.cxx_mode_flags + ["-std=c++17"]
+
+nsan_flags = [
+    "-fsanitize=numerical",
+    "-g",
+    "-mno-omit-leaf-frame-pointer",
+    "-fno-omit-frame-pointer",
+]
+
+
+def build_invocation(compile_flags):
+    return " " + " ".join([config.clang] + compile_flags) + " "
+
+
+# Add substitutions.
+config.substitutions.append(("%clang ", build_invocation(c_flags)))
+config.substitutions.append(("%clang_nsan ", build_invocation(c_flags + nsan_flags)))
+config.substitutions.append(
+    ("%clangxx_nsan ", build_invocation(cxx_flags + nsan_flags))
+)
+
+# NSan tests are currently supported on Linux only.
+if config.host_os not in ["Linux"]:
+    config.unsupported = True

diff  --git a/compiler-rt/test/nsan/lit.site.cfg.py.in b/compiler-rt/test/nsan/lit.site.cfg.py.in
index 69fd057e75748..496a9d5277a06 100644
--- a/compiler-rt/test/nsan/lit.site.cfg.py.in
+++ b/compiler-rt/test/nsan/lit.site.cfg.py.in
@@ -4,8 +4,6 @@
 config.name_suffix = "- at CONFIG_NAME@"
 config.target_cflags = "@NSAN_TEST_TARGET_CFLAGS@"
 config.target_arch = "@NSAN_TEST_TARGET_ARCH@"
-config.use_lld = @NSAN_TEST_USE_LLD@
-config.use_thinlto = @NSAN_TEST_USE_THINLTO@
 
 # Load common config for all compiler-rt lit tests.
 lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")

diff  --git a/compiler-rt/test/nsan/sum.cpp b/compiler-rt/test/nsan/sum.cpp
new file mode 100644
index 0000000000000..31bd62e73966b
--- /dev/null
+++ b/compiler-rt/test/nsan/sum.cpp
@@ -0,0 +1,70 @@
+// RUN: %clangxx_nsan -O0 -mllvm -nsan-shadow-type-mapping=dqq -g -DSUM=NaiveSum -DFLT=float %s -o %t
+// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_nsan -O3 -mllvm -nsan-shadow-type-mapping=dqq -g -DSUM=NaiveSum -DFLT=float %s -o %t
+// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_nsan -O0 -mllvm -nsan-shadow-type-mapping=dqq -g -DSUM=KahanSum -DFLT=float %s -o %t
+// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t
+
+// RUN: %clangxx_nsan -O3 -mllvm -nsan-shadow-type-mapping=dqq -g -DSUM=KahanSum -DFLT=float %s -o %t
+// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t
+
+#include <chrono>
+#include <iostream>
+#include <random>
+#include <vector>
+
+// A naive, unstable summation.
+template <typename T>
+__attribute__((noinline))  // To check call stack reporting.
+T NaiveSum(const std::vector<T>& values) {
+  T sum = 0;
+  for (T v : values) {
+    sum += v;
+  }
+  return sum;
+  // CHECK: WARNING: NumericalStabilitySanitizer: inconsistent shadow results while checking return
+  // CHECK: float{{ *}}precision (native):
+  // CHECK: double{{ *}}precision (shadow):
+  // CHECK: {{#0 .*in .* NaiveSum}}
+}
+
+// Kahan's summation is a numerically stable sum.
+// https://en.wikipedia.org/wiki/Kahan_summation_algorithm
+template <typename T>
+__attribute__((noinline)) T KahanSum(const std::vector<T> &values) {
+  T sum = 0;
+  T c = 0;
+  for (T v : values) {
+    T y = v - c;
+    T t = sum + y;
+    c = (t - sum) - y;
+    sum = t;
+  }
+  return sum;
+}
+
+int main() {
+  std::vector<FLT> values;
+  constexpr int kNumValues = 1000000;
+  values.reserve(kNumValues);
+  // Using a seed to avoid flakiness.
+  constexpr uint32_t kSeed = 0x123456;
+  std::mt19937 gen(kSeed);
+  std::uniform_real_distribution<FLT> dis(0.0f, 1000.0f);
+  for (int i = 0; i < kNumValues; ++i) {
+    values.push_back(dis(gen));
+  }
+
+  const auto t1 = std::chrono::high_resolution_clock::now();
+  const auto sum = SUM(values);
+  const auto t2 = std::chrono::high_resolution_clock::now();
+  printf("sum: %.8f\n", sum);
+  std::cout << "runtime: "
+            << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1)
+                       .count() /
+                   1000.0
+            << "ms\n";
+  return 0;
+}


        


More information about the llvm-commits mailing list