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

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 23 17:15:07 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Alexander Shaposhnikov (alexander-shaposhnikov)

<details>
<summary>Changes</summary>

Add a lit config for tests (and first tests as well).

Test plan: ninja check-nsan


---
Full diff: https://github.com/llvm/llvm-project/pull/100286.diff


6 Files Affected:

- (modified) compiler-rt/test/nsan/CMakeLists.txt (+16) 
- (added) compiler-rt/test/nsan/alloca.cpp (+26) 
- (added) compiler-rt/test/nsan/helpers.h (+15) 
- (modified) compiler-rt/test/nsan/lit.cfg.py (+28) 
- (modified) compiler-rt/test/nsan/lit.site.cfg.py.in (-2) 
- (added) compiler-rt/test/nsan/sum.cpp (+70) 


``````````diff
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..f0a95a23a33be
--- /dev/null
+++ b/compiler-rt/test/nsan/helpers.h
@@ -0,0 +1,15 @@
+// Prevents the compiler from optimizing everything away.
+template <class T> void DoNotOptimize(const T &var) {
+  asm volatile("" : "+m"(const_cast<T &>(var)));
+}
+
+// Writes a single double with inconsistent shadow to v.
+void CreateInconsistency(double *data) {
+  double num = 0.6;
+  double denom = 0.2;
+  // Prevent the compiler from constant-folding this.
+  DoNotOptimize(num);
+  DoNotOptimize(denom);
+  // Both values are very close to 0.0, but shadow value is closer.
+  *data = 1.0 / (num / denom - 3.0);
+}
diff --git a/compiler-rt/test/nsan/lit.cfg.py b/compiler-rt/test/nsan/lit.cfg.py
index 8b137891791fe..a625412559e75 100644
--- a/compiler-rt/test/nsan/lit.cfg.py
+++ b/compiler-rt/test/nsan/lit.cfg.py
@@ -1 +1,29 @@
+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;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/100286


More information about the llvm-commits mailing list