[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