From 6f69e03d93e82865abcf44544df412080466572a Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 4 Aug 2022 11:29:09 -0700 Subject: [PATCH 01/14] asan toolchain --- apps/CMakeLists.txt | 6 +- apps/fft/CMakeLists.txt | 2 +- cmake/HalideGeneratorHelpers.cmake | 6 +- cmake/HalideTestHelpers.cmake | 2 +- .../test/correctness/CMakeLists.txt | 2 +- python_bindings/tutorial/CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- src/Target.cpp | 11 ++- src/Util.cpp | 15 +++- src/Util.h | 26 ++++++ src/autoschedulers/adams2019/CMakeLists.txt | 2 +- src/autoschedulers/li2018/CMakeLists.txt | 2 +- src/runtime/CMakeLists.txt | 10 +-- test/correctness/tracing_stack.cpp | 7 ++ test/correctness/unroll_huge_mux.cpp | 5 ++ test/performance/CMakeLists.txt | 87 ++++++++++--------- tutorial/CMakeLists.txt | 13 ++- 17 files changed, 129 insertions(+), 71 deletions(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index ace6f8e89d42..b42acfe8acf8 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -19,7 +19,11 @@ enable_testing() # add_subdirectory(HelloWasm) # TODO(#5374): missing CMake build # add_subdirectory(HelloiOS) # TODO(#5374): missing CMake build # add_subdirectory(auto_viz) # TODO(#5374): missing CMake build -add_subdirectory(bgu) +if (Halide_ENABLE_ASAN) + message(STATUS "Skipping apps/bgu under ASAN") +else() + add_subdirectory(bgu) # Requires too much stack space for ASAN +endif() add_subdirectory(bilateral_grid) add_subdirectory(blur) add_subdirectory(c_backend) diff --git a/apps/fft/CMakeLists.txt b/apps/fft/CMakeLists.txt index d126c60b6647..98bac09a8275 100644 --- a/apps/fft/CMakeLists.txt +++ b/apps/fft/CMakeLists.txt @@ -48,5 +48,5 @@ foreach (i IN ITEMS 8 12 16 24 32 48) set_tests_properties(bench${i}x${i} PROPERTIES LABELS fft - ENVIRONMENT "PATH=$>") + ENVIRONMENT "PATH=$>;${SANITIZER_ENV_VARS}") endforeach () diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index a0329ee6396f..57fc9ac7aa1f 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -325,7 +325,8 @@ function(add_halide_library TARGET) endif () add_custom_command(OUTPUT ${generator_output_files} - COMMAND ${ARG_FROM} + COMMAND ${CMAKE_COMMAND} -E ${SANITIZER_SET_ENV_VARS} + $ -n "${TARGET}" -d "${gradient_descent}" -g "${ARG_GENERATOR}" @@ -400,7 +401,8 @@ function(_Halide_add_halide_runtime RT) endif () add_custom_command(OUTPUT ${GEN_OUTS} - COMMAND ${ARG_FROM} -r "${TARGET}.runtime" -o . ${GEN_ARGS} + COMMAND ${CMAKE_COMMAND} -E ${SANITIZER_SET_ENV_VARS} + $ -r "${TARGET}.runtime" -o . ${GEN_ARGS} # Defers reading the list of targets for which to generate a common runtime to CMake _generation_ time. # This prevents issues where a lower GCD is required by a later Halide library linking to this runtime. target=$,$> diff --git a/cmake/HalideTestHelpers.cmake b/cmake/HalideTestHelpers.cmake index 3ec36a1851a9..86283a3185f5 100644 --- a/cmake/HalideTestHelpers.cmake +++ b/cmake/HalideTestHelpers.cmake @@ -51,7 +51,7 @@ function(add_halide_test TARGET) set_tests_properties(${TARGET} PROPERTIES LABELS "${args_GROUPS}" - ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET}" + ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET};${SANITIZER_ENV_VARS}" PASS_REGULAR_EXPRESSION "Success!" SKIP_REGULAR_EXPRESSION "\\[SKIP\\]" WILL_FAIL ${args_EXPECT_FAILURE}) diff --git a/python_bindings/test/correctness/CMakeLists.txt b/python_bindings/test/correctness/CMakeLists.txt index 205256e4d2f7..ef754d35d25f 100644 --- a/python_bindings/test/correctness/CMakeLists.txt +++ b/python_bindings/test/correctness/CMakeLists.txt @@ -41,5 +41,5 @@ foreach (TEST IN LISTS TESTS) COMMAND Python3::Interpreter "$") set_tests_properties(python_correctness_${TEST_NAME} PROPERTIES LABELS "python" - ENVIRONMENT "PYTHONPATH=${PYTHONPATH};HL_TARGET=${Halide_TARGET}") + ENVIRONMENT "PYTHONPATH=${PYTHONPATH};HL_TARGET=${Halide_TARGET};${SANITIZER_ENV_VARS}") endforeach () diff --git a/python_bindings/tutorial/CMakeLists.txt b/python_bindings/tutorial/CMakeLists.txt index 09f2759a9e82..20450071e410 100644 --- a/python_bindings/tutorial/CMakeLists.txt +++ b/python_bindings/tutorial/CMakeLists.txt @@ -30,7 +30,7 @@ foreach (TEST IN LISTS TESTS) set_tests_properties(python_tutorial_${TEST_NAME} PROPERTIES LABELS python - ENVIRONMENT "PYTHONPATH=${PYTHONPATH};HL_TARGET=${Halide_TARGET}") + ENVIRONMENT "PYTHONPATH=${PYTHONPATH};HL_TARGET=${Halide_TARGET};${SANITIZER_ENV_VARS}") endforeach () ## Add some hacks for getting CMake to delay compiling lesson_10_halide until after the test has run. The "better" way diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c31e37c32a20..dd86add7a13e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -360,7 +360,7 @@ set(HALIDE_H "${Halide_BINARY_DIR}/include/Halide.h") set(LICENSE_PATH "${Halide_SOURCE_DIR}/LICENSE.txt") add_custom_command(OUTPUT "${Halide_BINARY_DIR}/include/Halide.h" COMMAND ${CMAKE_COMMAND} -E make_directory "$" - COMMAND build_halide_h "$" ${HEADER_FILES} > "$" + COMMAND $ "$" ${HEADER_FILES} > "$" DEPENDS build_halide_h "${LICENSE_PATH}" ${HEADER_FILES} WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" VERBATIM) diff --git a/src/Target.cpp b/src/Target.cpp index dd0e0d5ab416..7c6dbc64f5e0 100644 --- a/src/Target.cpp +++ b/src/Target.cpp @@ -567,19 +567,18 @@ Target get_target_from_environment() { Target get_jit_target_from_environment() { Target host = get_host_target(); host.set_feature(Target::JIT); -#if defined(__has_feature) -#if __has_feature(address_sanitizer) +// Note, we must include Util.h for these to be defined properly (or not) +#ifdef HALIDE_INTERNAL_USING_ASAN host.set_feature(Target::ASAN); #endif -#if __has_feature(memory_sanitizer) +#ifdef HALIDE_INTERNAL_USING_MSAN host.set_feature(Target::MSAN); #endif -#if __has_feature(thread_sanitizer) +#ifdef HALIDE_INTERNAL_USING_TSAN host.set_feature(Target::TSAN); #endif -#if __has_feature(coverage_sanitizer) +#ifdef HALIDE_INTERNAL_USING_COVSAN host.set_feature(Target::SanitizerCoverage); -#endif #endif string target = Internal::get_env_variable("HL_JIT_TARGET"); if (target.empty()) { diff --git a/src/Util.cpp b/src/Util.cpp index d99d5eb4a3a0..954f1378f726 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -661,6 +661,9 @@ size_t get_compiler_stack_size() { namespace Internal { +#ifdef HALIDE_INTERNAL_USING_ASAN +// nothing +#else namespace { // We can't reliably pass arguments through makecontext, because // the calling convention involves an invalid function pointer @@ -668,6 +671,7 @@ namespace { // platforms, so we use a thread local to pass arguments. thread_local void *run_with_large_stack_arg = nullptr; } // namespace +#endif void run_with_large_stack(const std::function &action) { if (stack_size.size == 0) { @@ -677,7 +681,6 @@ void run_with_large_stack(const std::function &action) { } #if _WIN32 - // Only exists for its address, which is used to compute remaining stack space. ULONG_PTR approx_stack_pos; @@ -719,6 +722,14 @@ void run_with_large_stack(const std::function &action) { #else // On posixy systems we have makecontext / swapcontext +#ifdef HALIDE_INTERNAL_USING_ASAN + // ... unless we are compiling under ASAN, in which case we + // will get a zillion warnings about ASAN not supporting makecontext/swapcontext + // and the possibility of false positives. Just skip the extra stack space, I guess? + action(); + return; +#else + #ifdef HALIDE_WITH_EXCEPTIONS struct Args { const std::function &run; @@ -783,6 +794,8 @@ void run_with_large_stack(const std::function &action) { } #endif +#endif // not ADDRESS_SANITIZER + #endif } diff --git a/src/Util.h b/src/Util.h index 71228eb0da3b..00489b1b3f34 100644 --- a/src/Util.h +++ b/src/Util.h @@ -45,6 +45,32 @@ #define HALIDE_NO_USER_CODE_INLINE HALIDE_NEVER_INLINE #endif +// Clang uses __has_feature() for sanitizers... +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define HALIDE_INTERNAL_USING_ASAN +#endif +#if __has_feature(memory_sanitizer) +#define HALIDE_INTERNAL_USING_MSAN +#endif +#if __has_feature(thread_sanitizer) +#define HALIDE_INTERNAL_USING_TSAN +#endif +#if __has_feature(coverage_sanitizer) +#define HALIDE_INTERNAL_USING_COVSAN +#endif +#if __has_feature(undefined_behavior_sanitizer) +#define HALIDE_INTERNAL_USING_UBSAN +#endif +#endif + +// ...but GCC/MSVC don't like __has_feature, so handle them separately. +// (Only AddressSanitizer for now, not sure if any others are well-supported +// outside of Clang. +#if defined(__SANITIZE_ADDRESS__) && !defined(HALIDE_INTERNAL_USING_ASAN) +#define HALIDE_INTERNAL_USING_ASAN +#endif + namespace Halide { /** Load a plugin in the form of a dynamic library (e.g. for custom autoschedulers). diff --git a/src/autoschedulers/adams2019/CMakeLists.txt b/src/autoschedulers/adams2019/CMakeLists.txt index 5b4547de7143..4f93f504351c 100644 --- a/src/autoschedulers/adams2019/CMakeLists.txt +++ b/src/autoschedulers/adams2019/CMakeLists.txt @@ -6,7 +6,7 @@ set(WF_CPP baseline.cpp) configure_file(baseline.weights baseline.weights COPYONLY) add_custom_command(OUTPUT ${WF_CPP} - COMMAND binary2cpp baseline_weights < baseline.weights > ${WF_CPP} + COMMAND $ baseline_weights < baseline.weights > ${WF_CPP} DEPENDS baseline.weights binary2cpp VERBATIM) diff --git a/src/autoschedulers/li2018/CMakeLists.txt b/src/autoschedulers/li2018/CMakeLists.txt index 31a1fb2f8eab..fe2c00434034 100644 --- a/src/autoschedulers/li2018/CMakeLists.txt +++ b/src/autoschedulers/li2018/CMakeLists.txt @@ -61,6 +61,6 @@ if (WITH_PYTHON_BINDINGS) string(REPLACE ";" "${SEP}" _PATH "${_PATH}") set_tests_properties(gradient_autoscheduler_test_py PROPERTIES LABELS "Li2018;auto_schedule" - ENVIRONMENT "PYTHONPATH=${PYTHONPATH};PATH=${_PATH}") + ENVIRONMENT "PYTHONPATH=${PYTHONPATH};PATH=${_PATH};${SANITIZER_ENV_VARS}") endif () endif () diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index 1d1832be504f..b59339617fc6 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -279,7 +279,7 @@ foreach (i IN LISTS RUNTIME_CPP) VERBATIM) add_custom_command(OUTPUT "${INITMOD}" - COMMAND binary2cpp ${SYMBOL} < "${BC}" > "${INITMOD}" + COMMAND $ ${SYMBOL} < "${BC}" > "${INITMOD}" DEPENDS "${BC}" binary2cpp VERBATIM) @@ -322,7 +322,7 @@ foreach (i IN LISTS RUNTIME_LL) DEPENDS "${LL_TRANSFORMED}" VERBATIM) add_custom_command(OUTPUT "${INITMOD}" - COMMAND binary2cpp "halide_internal_initmod_${i}_ll" < "${BC}" > "${INITMOD}" + COMMAND $ "halide_internal_initmod_${i}_ll" < "${BC}" > "${INITMOD}" DEPENDS "${BC}" binary2cpp VERBATIM) target_sources(Halide_initmod PRIVATE ${INITMOD}) @@ -333,14 +333,14 @@ foreach (i IN LISTS RUNTIME_BC) set(RT_BC "${CMAKE_CURRENT_SOURCE_DIR}/nvidia_libdevice_bitcode/libdevice.${i}.10.bc") add_custom_command(OUTPUT "${INITMOD}" - COMMAND binary2cpp "halide_internal_initmod_ptx_${i}_ll" < "$" > "${INITMOD}" + COMMAND $ "halide_internal_initmod_ptx_${i}_ll" < "$" > "${INITMOD}" DEPENDS binary2cpp "${RT_BC}" VERBATIM) target_sources(Halide_initmod PRIVATE ${INITMOD}) endforeach () add_custom_command(OUTPUT "_initmod_inlined_c.cpp" - COMMAND binary2cpp "halide_internal_initmod_inlined_c" < "$" > "_initmod_inlined_c.cpp" + COMMAND $ "halide_internal_initmod_inlined_c" < "$" > "_initmod_inlined_c.cpp" DEPENDS "halide_buffer_t.cpp" binary2cpp VERBATIM) target_sources(Halide_initmod PRIVATE "_initmod_inlined_c.cpp") @@ -348,7 +348,7 @@ target_sources(Halide_initmod PRIVATE "_initmod_inlined_c.cpp") foreach (i IN LISTS RUNTIME_HEADER_FILES) string(REPLACE "." "_" SYM_NAME "${i}") add_custom_command(OUTPUT "_initmod_${SYM_NAME}.cpp" - COMMAND binary2cpp "halide_internal_runtime_header_${SYM_NAME}" < "$" > "_initmod_${SYM_NAME}.cpp" + COMMAND $ "halide_internal_runtime_header_${SYM_NAME}" < "$" > "_initmod_${SYM_NAME}.cpp" DEPENDS "${i}" binary2cpp VERBATIM) target_sources(Halide_initmod PRIVATE "_initmod_${SYM_NAME}.cpp") diff --git a/test/correctness/tracing_stack.cpp b/test/correctness/tracing_stack.cpp index d3fe04d548b5..6ea21e48ce57 100644 --- a/test/correctness/tracing_stack.cpp +++ b/test/correctness/tracing_stack.cpp @@ -64,6 +64,13 @@ void signal_handler(int signum) { } // namespace int main(int argc, char **argv) { +#ifdef HALIDE_INTERNAL_USING_ASAN + // ASAN also needs to intercept the SIGSEGV signal handler; + // we could probably make these work together, but it's + // also probably not worth the effort. + printf("[SKIP] tracing_stack does not run under ASAN.\n"); + return 0; +#endif signal(SIGSEGV, signal_handler); signal(SIGBUS, signal_handler); diff --git a/test/correctness/unroll_huge_mux.cpp b/test/correctness/unroll_huge_mux.cpp index 9a6307d68414..233ee038c4e8 100644 --- a/test/correctness/unroll_huge_mux.cpp +++ b/test/correctness/unroll_huge_mux.cpp @@ -3,6 +3,11 @@ using namespace Halide; int main(int argc, char **argv) { +#ifdef HALIDE_INTERNAL_USING_ASAN + printf("[SKIP] unroll_huge_mux requires set_compiler_stack_size() to work properly, which is disabled under ASAN.\n"); + return 0; +#endif + Func f; Var x; diff --git a/test/performance/CMakeLists.txt b/test/performance/CMakeLists.txt index 0e462530ff9b..80290b496de0 100644 --- a/test/performance/CMakeLists.txt +++ b/test/performance/CMakeLists.txt @@ -1,44 +1,49 @@ -tests(GROUPS performance - SOURCES - async_gpu.cpp - block_transpose.cpp - boundary_conditions.cpp - clamped_vector_load.cpp - const_division.cpp - fast_inverse.cpp - fast_pow.cpp - fast_sine_cosine.cpp - gpu_half_throughput.cpp - jit_stress.cpp - lots_of_inputs.cpp - memcpy.cpp - nested_vectorization_gemm.cpp - packed_planar_fusion.cpp - realize_overhead.cpp - rgb_interleaved.cpp - tiled_matmul.cpp - vectorize.cpp - wrap.cpp - ) +if (Halide_ANY_SANITIZERS_ENABLED) + # All sanitizers impact performance, so don't even bother with this test suite + message(STATUS "Skipping all performance testing because at least one Sanitizer is enabled.") +else() + tests(GROUPS performance + SOURCES + async_gpu.cpp + block_transpose.cpp + boundary_conditions.cpp + clamped_vector_load.cpp + const_division.cpp + fast_inverse.cpp + fast_pow.cpp + fast_sine_cosine.cpp + gpu_half_throughput.cpp + jit_stress.cpp + lots_of_inputs.cpp + memcpy.cpp + nested_vectorization_gemm.cpp + packed_planar_fusion.cpp + realize_overhead.cpp + rgb_interleaved.cpp + tiled_matmul.cpp + vectorize.cpp + wrap.cpp + ) -tests(GROUPS performance multithreaded - SOURCES - fan_in.cpp - inner_loop_parallel.cpp - lots_of_small_allocations.cpp - matrix_multiplication.cpp - memory_profiler.cpp - parallel_performance.cpp - profiler.cpp - rfactor.cpp - sort.cpp - stack_vs_heap.cpp - thread_safe_jit.cpp - ) + tests(GROUPS performance multithreaded + SOURCES + fan_in.cpp + inner_loop_parallel.cpp + lots_of_small_allocations.cpp + matrix_multiplication.cpp + memory_profiler.cpp + parallel_performance.cpp + profiler.cpp + rfactor.cpp + sort.cpp + stack_vs_heap.cpp + thread_safe_jit.cpp + ) -# Make sure that performance tests do not run in parallel with other tests, -# since doing so might make them flaky. -set_tests_properties(${TEST_NAMES} PROPERTIES RUN_SERIAL TRUE) + # Make sure that performance tests do not run in parallel with other tests, + # since doing so might make them flaky. + set_tests_properties(${TEST_NAMES} PROPERTIES RUN_SERIAL TRUE) -# This test needs rdynamic or equivalent -set_target_properties(performance_fast_pow PROPERTIES ENABLE_EXPORTS TRUE) + # This test needs rdynamic or equivalent + set_target_properties(performance_fast_pow PROPERTIES ENABLE_EXPORTS TRUE) +endif() diff --git a/tutorial/CMakeLists.txt b/tutorial/CMakeLists.txt index 2db06c7d0dfa..61f8cc516468 100644 --- a/tutorial/CMakeLists.txt +++ b/tutorial/CMakeLists.txt @@ -16,7 +16,7 @@ function(add_tutorial source_file) add_test(NAME tutorial_${name} COMMAND ${name}) set_tests_properties(tutorial_${name} PROPERTIES - ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET}" + ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET};${SANITIZER_ENV_VARS}" LABELS "tutorial;${args_GROUPS}") if (args_WITH_IMAGE_IO) @@ -56,13 +56,10 @@ if (TARGET_NVPTX) # so we can build the final executable. add_tutorial(lesson_10_aot_compilation_generate.cpp) - # LLVM may leak memory during Halide compilation. If projects are built with address sanitizer enabled, - # this may cause generators to fail, making it hard to use Halide and address sanitizer at the same time. - # To work around this, we execute generators with an environment setting to disable leak checking. set(FILTER_LIB "lesson_10_halide${CMAKE_STATIC_LIBRARY_SUFFIX}") add_custom_command(OUTPUT lesson_10_halide.h "${FILTER_LIB}" DEPENDS lesson_10_aot_compilation_generate - COMMAND ${CMAKE_COMMAND} -E env "ASAN_OPTIONS=detect_leaks=0" $ + COMMAND ${CMAKE_COMMAND} -E ${SANITIZER_SET_ENV_VARS} $ VERBATIM) add_custom_target(exec_lesson_10_aot_compilation_generate DEPENDS lesson_10_halide.h "${FILTER_LIB}") @@ -84,7 +81,7 @@ if (TARGET_NVPTX) target_include_directories(lesson_10_aot_compilation_run PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") - add_test(NAME tutorial_lesson_10_aot_compilation_run COMMAND lesson_10_aot_compilation_run) + add_test(NAME tutorial_lesson_10_aot_compilation_run COMMAND $) set_tests_properties(tutorial_lesson_10_aot_compilation_run PROPERTIES LABELS "tutorial;multithreaded") endif () endif () @@ -177,7 +174,7 @@ else () Halide::ImageIO Halide::Tools) - add_test(NAME tutorial_lesson_16_rgb_run COMMAND lesson_16_rgb_run) + add_test(NAME tutorial_lesson_16_rgb_run COMMAND $) set_tests_properties(tutorial_lesson_16_rgb_run PROPERTIES LABELS tutorial) endif () @@ -207,6 +204,6 @@ if (TARGET Halide::Mullapudi2016) target_link_libraries(lesson_21_auto_scheduler_run PRIVATE auto_schedule_false auto_schedule_true Halide::Tools) - add_test(NAME tutorial_lesson_21_auto_scheduler_run COMMAND lesson_21_auto_scheduler_run) + add_test(NAME tutorial_lesson_21_auto_scheduler_run COMMAND $) set_tests_properties(tutorial_lesson_21_auto_scheduler_run PROPERTIES LABELS "tutorial;multithreaded") endif () From 3cc350a4ead54d17484bb24d744e9b07c25cc172 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 4 Aug 2022 13:19:36 -0700 Subject: [PATCH 02/14] wip --- python_bindings/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python_bindings/CMakeLists.txt b/python_bindings/CMakeLists.txt index 979a3594b534..0ccdbc27bc2a 100644 --- a/python_bindings/CMakeLists.txt +++ b/python_bindings/CMakeLists.txt @@ -56,6 +56,15 @@ endif () add_subdirectory(src/halide) add_subdirectory(stub) +if (Halide_ASAN_ENABLED) + # Getting asan to work in shared mode requires some LD_PRELOAD hackery + # in a lot of places; just skipping them for now. + if (WITH_TEST_PYTHON OR WITH_TUTORIALS) + message(STATUS "Python tests/tutorials are not yet supported under ASAN.") + endif() + return() +endif() + if (WITH_TEST_PYTHON) add_subdirectory(test) endif () From baa23bcc2cdaa8e778a13559bd5712257c66dac9 Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 4 Aug 2022 13:19:53 -0700 Subject: [PATCH 03/14] wip --- cmake/toolchain.linux-x64-asan.cmake | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 cmake/toolchain.linux-x64-asan.cmake diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake new file mode 100644 index 000000000000..0c6c75120ee8 --- /dev/null +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -0,0 +1,55 @@ +# Toolchain for compiling with ASAN enabled on a Linux-x86-64 host. +# This is done as a "crosscompile" because we must use our LLVM version +# of clang for *all* compilation (rather than using it just for bitcode +# and letting the host compiler, eg gcc, handle everything else); ASAN +# essentially requires everything to be compiled with matching versions +# of the same compiler. +# +# Note: requires LLVM to be built with -DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi;libunwind" +# +# Note: only tested with LLVM/Clang 16 as of this comment. Earlier versions +# may likely work but are not tested. + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR i686) + +set(LLVM_INSTALL_DIR ${LLVM_DIR}/../../../) + +set(CMAKE_C_COMPILER ${LLVM_INSTALL_DIR}/bin/clang) +set(CMAKE_CXX_COMPILER ${LLVM_INSTALL_DIR}/bin/clang++) + +set(_ASAN_FLAGS "-fsanitize=address") +# set(_ASAN_FLAGS "-fsanitize=address -shared-libasan") + +set(CMAKE_CXX_FLAGS_INIT ${_ASAN_FLAGS}) +set(CMAKE_C_FLAGS_INIT ${_ASAN_FLAGS}) + +set(CMAKE_EXE_LINKER_FLAGS_INIT ${_ASAN_FLAGS}) +set(CMAKE_SHARED_LINKER_FLAGS_INIT ${_ASAN_FLAGS}) +set(CMAKE_MODULE_LINKER_FLAGS_INIT ${_ASAN_FLAGS}) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Set to empty string to indicate the resulting binaries can be natively executed +set(CMAKE_CROSSCOMPILING_EMULATOR) + +# A few downstream build rules need to be able to sniff these: +# - ASAN means we can't run with large stacks, so some things will overflow +set(Halide_ASAN_ENABLED ON) +# - Pretty much every sanitizer affects performance, so skip benchmarks +set(Halide_ANY_SANITIZERS_ENABLED ON) + +# If running under ASAN, we need to suppress some errors: +# - detect_leaks, because circular Expr chains in Halide can indeed leak, +# but we don't care here +# - detect_container_overflow, because this is a known false-positive +# if compiling with a non-ASAN build of LLVM (which is usually the case) +set(SANITIZER_ENV_VARS "ASAN_OPTIONS=detect_leaks=0:detect_container_overflow=0") +# set(SANITIZER_ENV_VARS "ASAN_OPTIONS=detect_leaks=0:detect_container_overflow=0;LD_PRELOAD=${LLVM_INSTALL_DIR}/lib/clang/16.0.0/lib/x86_64-unknown-linux-gnu/libclang_rt.asan.so") + +# Work around bug where "cmake -E env $FOO" gives error if FOO is empty +set(SANITIZER_SET_ENV_VARS env ${SANITIZER_ENV_VARS}) + From 352e05a4eaea32f1ccf5346ab0b65e0b303e72af Mon Sep 17 00:00:00 2001 From: Steven Johnson Date: Thu, 4 Aug 2022 16:11:43 -0700 Subject: [PATCH 04/14] address some comments --- apps/CMakeLists.txt | 2 +- python_bindings/CMakeLists.txt | 2 +- test/performance/CMakeLists.txt | 87 +++++++++++++++++---------------- 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index b42acfe8acf8..91237561b8fb 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -19,7 +19,7 @@ enable_testing() # add_subdirectory(HelloWasm) # TODO(#5374): missing CMake build # add_subdirectory(HelloiOS) # TODO(#5374): missing CMake build # add_subdirectory(auto_viz) # TODO(#5374): missing CMake build -if (Halide_ENABLE_ASAN) +if (Halide_ASAN_ENABLED) message(STATUS "Skipping apps/bgu under ASAN") else() add_subdirectory(bgu) # Requires too much stack space for ASAN diff --git a/python_bindings/CMakeLists.txt b/python_bindings/CMakeLists.txt index 0ccdbc27bc2a..aa8a880021c3 100644 --- a/python_bindings/CMakeLists.txt +++ b/python_bindings/CMakeLists.txt @@ -60,7 +60,7 @@ if (Halide_ASAN_ENABLED) # Getting asan to work in shared mode requires some LD_PRELOAD hackery # in a lot of places; just skipping them for now. if (WITH_TEST_PYTHON OR WITH_TUTORIALS) - message(STATUS "Python tests/tutorials are not yet supported under ASAN.") + message(WARNING "Python tests/tutorials are not yet supported under ASAN.") endif() return() endif() diff --git a/test/performance/CMakeLists.txt b/test/performance/CMakeLists.txt index 80290b496de0..d1e869d97f07 100644 --- a/test/performance/CMakeLists.txt +++ b/test/performance/CMakeLists.txt @@ -1,49 +1,50 @@ if (Halide_ANY_SANITIZERS_ENABLED) # All sanitizers impact performance, so don't even bother with this test suite message(STATUS "Skipping all performance testing because at least one Sanitizer is enabled.") -else() - tests(GROUPS performance - SOURCES - async_gpu.cpp - block_transpose.cpp - boundary_conditions.cpp - clamped_vector_load.cpp - const_division.cpp - fast_inverse.cpp - fast_pow.cpp - fast_sine_cosine.cpp - gpu_half_throughput.cpp - jit_stress.cpp - lots_of_inputs.cpp - memcpy.cpp - nested_vectorization_gemm.cpp - packed_planar_fusion.cpp - realize_overhead.cpp - rgb_interleaved.cpp - tiled_matmul.cpp - vectorize.cpp - wrap.cpp - ) + return() +endif() - tests(GROUPS performance multithreaded - SOURCES - fan_in.cpp - inner_loop_parallel.cpp - lots_of_small_allocations.cpp - matrix_multiplication.cpp - memory_profiler.cpp - parallel_performance.cpp - profiler.cpp - rfactor.cpp - sort.cpp - stack_vs_heap.cpp - thread_safe_jit.cpp - ) +tests(GROUPS performance + SOURCES + async_gpu.cpp + block_transpose.cpp + boundary_conditions.cpp + clamped_vector_load.cpp + const_division.cpp + fast_inverse.cpp + fast_pow.cpp + fast_sine_cosine.cpp + gpu_half_throughput.cpp + jit_stress.cpp + lots_of_inputs.cpp + memcpy.cpp + nested_vectorization_gemm.cpp + packed_planar_fusion.cpp + realize_overhead.cpp + rgb_interleaved.cpp + tiled_matmul.cpp + vectorize.cpp + wrap.cpp + ) - # Make sure that performance tests do not run in parallel with other tests, - # since doing so might make them flaky. - set_tests_properties(${TEST_NAMES} PROPERTIES RUN_SERIAL TRUE) +tests(GROUPS performance multithreaded + SOURCES + fan_in.cpp + inner_loop_parallel.cpp + lots_of_small_allocations.cpp + matrix_multiplication.cpp + memory_profiler.cpp + parallel_performance.cpp + profiler.cpp + rfactor.cpp + sort.cpp + stack_vs_heap.cpp + thread_safe_jit.cpp + ) - # This test needs rdynamic or equivalent - set_target_properties(performance_fast_pow PROPERTIES ENABLE_EXPORTS TRUE) -endif() +# Make sure that performance tests do not run in parallel with other tests, +# since doing so might make them flaky. +set_tests_properties(${TEST_NAMES} PROPERTIES RUN_SERIAL TRUE) + +# This test needs rdynamic or equivalent +set_target_properties(performance_fast_pow PROPERTIES ENABLE_EXPORTS TRUE) From af31318bdb9c5a4ff41fe3995e246101f83c0724 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Wed, 10 Aug 2022 22:54:47 +0000 Subject: [PATCH 05/14] add sanitizer vars back to Python tests --- python_bindings/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_bindings/CMakeLists.txt b/python_bindings/CMakeLists.txt index b4ddcd8c2d5d..0ab699ef887a 100644 --- a/python_bindings/CMakeLists.txt +++ b/python_bindings/CMakeLists.txt @@ -72,7 +72,7 @@ function(add_python_test) "${test_name}" PROPERTIES LABELS "python" - ENVIRONMENT "${ARG_ENVIRONMENT}" + ENVIRONMENT "${ARG_ENVIRONMENT};${SANITIZER_ENV_VARS}" ENVIRONMENT_MODIFICATION "${ARG_PYTHONPATH}" ) endfunction() From f168ee801bf26b152a319df689af2c71f798ef1c Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Wed, 10 Aug 2022 23:08:06 +0000 Subject: [PATCH 06/14] Allow any app to be individually turned on/off --- apps/CMakeLists.txt | 90 +++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 91237561b8fb..0c8b682f8071 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -5,54 +5,56 @@ cmake_minimum_required(VERSION 3.22) project(Halide_apps) +enable_testing() + if (WIN32) option(ENABLE_APPS_HANNK "Build apps/hannk" OFF) else () option(ENABLE_APPS_HANNK "Build apps/hannk" ON) endif () -enable_testing() +function(add_app app_name) + string(TOUPPER "ENABLE_APPS_${app_name}" opt) + option(${opt} "Build apps/${app_name}" ON) + if (${opt}) + add_subdirectory(${app_name}) + endif () +endfunction() -# add_subdirectory(HelloAndroid) # TODO(#5374): missing CMake build -# add_subdirectory(HelloAndroidCamera2) # TODO(#5374): missing CMake build -# add_subdirectory(HelloPyTorch) # TODO(#5374): missing CMake build -# add_subdirectory(HelloWasm) # TODO(#5374): missing CMake build -# add_subdirectory(HelloiOS) # TODO(#5374): missing CMake build -# add_subdirectory(auto_viz) # TODO(#5374): missing CMake build -if (Halide_ASAN_ENABLED) - message(STATUS "Skipping apps/bgu under ASAN") -else() - add_subdirectory(bgu) # Requires too much stack space for ASAN -endif() -add_subdirectory(bilateral_grid) -add_subdirectory(blur) -add_subdirectory(c_backend) -add_subdirectory(camera_pipe) -add_subdirectory(conv_layer) -add_subdirectory(cuda_mat_mul) -add_subdirectory(depthwise_separable_conv) -add_subdirectory(fft) -if (ENABLE_APPS_HANNK) - add_subdirectory(hannk) -endif () -add_subdirectory(harris) -# add_subdirectory(hexagon_benchmarks) # TODO(#5374): missing CMake build -# add_subdirectory(hexagon_dma) # TODO(#5374): missing CMake build -add_subdirectory(hist) -add_subdirectory(iir_blur) -add_subdirectory(interpolate) -add_subdirectory(lens_blur) -add_subdirectory(linear_algebra) -# add_subdirectory(linear_blur) # TODO(#5374): missing CMake build -add_subdirectory(local_laplacian) -add_subdirectory(max_filter) -add_subdirectory(nl_means) -# add_subdirectory(nn_ops) # TODO(#5374): missing CMake build -# add_subdirectory(onnx) # TODO(#5374): missing CMake build -# add_subdirectory(openglcompute) # TODO(#5374): missing CMake build -add_subdirectory(resize) -# add_subdirectory(resnet_50) # TODO(#5374): missing CMake build -# add_subdirectory(simd_op_check) # TODO(#5374): missing CMake build -add_subdirectory(stencil_chain) -add_subdirectory(unsharp) -add_subdirectory(wavelet) +# add_app(HelloAndroid) # TODO(#5374): missing CMake build +# add_app(HelloAndroidCamera2) # TODO(#5374): missing CMake build +# add_app(HelloPyTorch) # TODO(#5374): missing CMake build +# add_app(HelloWasm) # TODO(#5374): missing CMake build +# add_app(HelloiOS) # TODO(#5374): missing CMake build +# add_app(auto_viz) # TODO(#5374): missing CMake build +add_app(bgu) +add_app(bilateral_grid) +add_app(blur) +add_app(c_backend) +add_app(camera_pipe) +add_app(conv_layer) +add_app(cuda_mat_mul) +add_app(depthwise_separable_conv) +add_app(fft) +add_app(hannk) +add_app(harris) +# add_app(hexagon_benchmarks) # TODO(#5374): missing CMake build +# add_app(hexagon_dma) # TODO(#5374): missing CMake build +add_app(hist) +add_app(iir_blur) +add_app(interpolate) +add_app(lens_blur) +add_app(linear_algebra) +# add_app(linear_blur) # TODO(#5374): missing CMake build +add_app(local_laplacian) +add_app(max_filter) +add_app(nl_means) +# add_app(nn_ops) # TODO(#5374): missing CMake build +# add_app(onnx) # TODO(#5374): missing CMake build +# add_app(openglcompute) # TODO(#5374): missing CMake build +add_app(resize) +# add_app(resnet_50) # TODO(#5374): missing CMake build +# add_app(simd_op_check) # TODO(#5374): missing CMake build +add_app(stencil_chain) +add_app(unsharp) +add_app(wavelet) From f769003d03f51b13f5058ac39d1648db90367807 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Wed, 10 Aug 2022 23:09:11 +0000 Subject: [PATCH 07/14] Move ASAN detection into project --- CMakeLists.txt | 13 ++++++++++++- cmake/toolchain.linux-x64-asan.cmake | 6 ------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c6d0a379bf3..96a8df419caf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,10 +10,13 @@ enable_testing() # Set up project-wide properties ## +# Import useful standard modules +include(CMakeDependentOption) +include(CheckCXXSymbolExists) + # Make our custom helpers available throughout the project via include(). list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) include(HalideGeneratorHelpers) -include(CMakeDependentOption) # Build Halide as a shared lib by default, but still honor command-line settings. option(BUILD_SHARED_LIBS "Build shared libraries" ON) @@ -67,6 +70,14 @@ if (Halide_CCACHE_BUILD) message(STATUS "Enabling ccache usage for building.") endif () +# Detect whether or not ASAN is enabled +check_cxx_symbol_exists(HALIDE_INTERNAL_USING_ASAN "${Halide_SOURCE_DIR}/src/Util.h" Halide_ASAN_ENABLED) +if (Halide_ASAN_ENABLED) + set(Halide_ANY_SANITIZERS_ENABLED 1) +else () + set(Halide_ANY_SANITIZERS_ENABLED 0) +endif () + # Enable the SPIR-V target if requested (must declare before processing dependencies) option(TARGET_SPIRV "Include SPIR-V target" OFF) diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake index 0c6c75120ee8..86a4bf806d44 100644 --- a/cmake/toolchain.linux-x64-asan.cmake +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -36,12 +36,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # Set to empty string to indicate the resulting binaries can be natively executed set(CMAKE_CROSSCOMPILING_EMULATOR) -# A few downstream build rules need to be able to sniff these: -# - ASAN means we can't run with large stacks, so some things will overflow -set(Halide_ASAN_ENABLED ON) -# - Pretty much every sanitizer affects performance, so skip benchmarks -set(Halide_ANY_SANITIZERS_ENABLED ON) - # If running under ASAN, we need to suppress some errors: # - detect_leaks, because circular Expr chains in Halide can indeed leak, # but we don't care here From cbee01ea375c5403b301798f628183a16f15dd01 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Wed, 10 Aug 2022 23:09:33 +0000 Subject: [PATCH 08/14] Fixup: disable bgu app from toolchain --- cmake/toolchain.linux-x64-asan.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake index 86a4bf806d44..3f1d49d409eb 100644 --- a/cmake/toolchain.linux-x64-asan.cmake +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -47,3 +47,5 @@ set(SANITIZER_ENV_VARS "ASAN_OPTIONS=detect_leaks=0:detect_container_overflow=0" # Work around bug where "cmake -E env $FOO" gives error if FOO is empty set(SANITIZER_SET_ENV_VARS env ${SANITIZER_ENV_VARS}) +# The bgu app requires too much stack space for ASAN +set(ENABLE_APPS_BGU OFF) From aa05f32e552fe4bdb447e8eb1702e7b674ad4826 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Wed, 10 Aug 2022 23:10:05 +0000 Subject: [PATCH 09/14] Use LLVM_ROOT to find clang in the toolchain --- cmake/toolchain.linux-x64-asan.cmake | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake index 3f1d49d409eb..5a3837b0fd04 100644 --- a/cmake/toolchain.linux-x64-asan.cmake +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -13,10 +13,8 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR i686) -set(LLVM_INSTALL_DIR ${LLVM_DIR}/../../../) - -set(CMAKE_C_COMPILER ${LLVM_INSTALL_DIR}/bin/clang) -set(CMAKE_CXX_COMPILER ${LLVM_INSTALL_DIR}/bin/clang++) +set(CMAKE_C_COMPILER ${LLVM_ROOT}/bin/clang) +set(CMAKE_CXX_COMPILER ${LLVM_ROOT}/bin/clang++) set(_ASAN_FLAGS "-fsanitize=address") # set(_ASAN_FLAGS "-fsanitize=address -shared-libasan") @@ -42,7 +40,7 @@ set(CMAKE_CROSSCOMPILING_EMULATOR) # - detect_container_overflow, because this is a known false-positive # if compiling with a non-ASAN build of LLVM (which is usually the case) set(SANITIZER_ENV_VARS "ASAN_OPTIONS=detect_leaks=0:detect_container_overflow=0") -# set(SANITIZER_ENV_VARS "ASAN_OPTIONS=detect_leaks=0:detect_container_overflow=0;LD_PRELOAD=${LLVM_INSTALL_DIR}/lib/clang/16.0.0/lib/x86_64-unknown-linux-gnu/libclang_rt.asan.so") +# set(SANITIZER_ENV_VARS "ASAN_OPTIONS=detect_leaks=0:detect_container_overflow=0;LD_PRELOAD=${LLVM_ROOT}/lib/clang/16.0.0/lib/x86_64-unknown-linux-gnu/libclang_rt.asan.so") # Work around bug where "cmake -E env $FOO" gives error if FOO is empty set(SANITIZER_SET_ENV_VARS env ${SANITIZER_ENV_VARS}) From 39d3bbc30b42a162fc026994551127fd10790274 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 11 Aug 2022 00:17:22 +0000 Subject: [PATCH 10/14] Remove unnecessary uses of $ --- cmake/toolchain.linux-x64-asan.cmake | 3 +-- src/CMakeLists.txt | 2 +- src/autoschedulers/adams2019/CMakeLists.txt | 2 +- src/runtime/CMakeLists.txt | 10 +++++----- tutorial/CMakeLists.txt | 6 +++--- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake index 5a3837b0fd04..fc5870389821 100644 --- a/cmake/toolchain.linux-x64-asan.cmake +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -31,8 +31,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -# Set to empty string to indicate the resulting binaries can be natively executed -set(CMAKE_CROSSCOMPILING_EMULATOR) +set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/env) # If running under ASAN, we need to suppress some errors: # - detect_leaks, because circular Expr chains in Halide can indeed leak, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd86add7a13e..c31e37c32a20 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -360,7 +360,7 @@ set(HALIDE_H "${Halide_BINARY_DIR}/include/Halide.h") set(LICENSE_PATH "${Halide_SOURCE_DIR}/LICENSE.txt") add_custom_command(OUTPUT "${Halide_BINARY_DIR}/include/Halide.h" COMMAND ${CMAKE_COMMAND} -E make_directory "$" - COMMAND $ "$" ${HEADER_FILES} > "$" + COMMAND build_halide_h "$" ${HEADER_FILES} > "$" DEPENDS build_halide_h "${LICENSE_PATH}" ${HEADER_FILES} WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" VERBATIM) diff --git a/src/autoschedulers/adams2019/CMakeLists.txt b/src/autoschedulers/adams2019/CMakeLists.txt index 4f93f504351c..5b4547de7143 100644 --- a/src/autoschedulers/adams2019/CMakeLists.txt +++ b/src/autoschedulers/adams2019/CMakeLists.txt @@ -6,7 +6,7 @@ set(WF_CPP baseline.cpp) configure_file(baseline.weights baseline.weights COPYONLY) add_custom_command(OUTPUT ${WF_CPP} - COMMAND $ baseline_weights < baseline.weights > ${WF_CPP} + COMMAND binary2cpp baseline_weights < baseline.weights > ${WF_CPP} DEPENDS baseline.weights binary2cpp VERBATIM) diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index 1e25c1d90414..946784f662d5 100644 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -254,7 +254,7 @@ foreach (i IN LISTS RUNTIME_CPP) VERBATIM) add_custom_command(OUTPUT "${INITMOD}" - COMMAND $ ${SYMBOL} < "${BC}" > "${INITMOD}" + COMMAND binary2cpp ${SYMBOL} < "${BC}" > "${INITMOD}" DEPENDS "${BC}" binary2cpp VERBATIM) @@ -297,7 +297,7 @@ foreach (i IN LISTS RUNTIME_LL) DEPENDS "${LL_TRANSFORMED}" VERBATIM) add_custom_command(OUTPUT "${INITMOD}" - COMMAND $ "halide_internal_initmod_${i}_ll" < "${BC}" > "${INITMOD}" + COMMAND binary2cpp "halide_internal_initmod_${i}_ll" < "${BC}" > "${INITMOD}" DEPENDS "${BC}" binary2cpp VERBATIM) target_sources(Halide_initmod PRIVATE ${INITMOD}) @@ -308,14 +308,14 @@ foreach (i IN LISTS RUNTIME_BC) set(RT_BC "${CMAKE_CURRENT_SOURCE_DIR}/nvidia_libdevice_bitcode/libdevice.${i}.10.bc") add_custom_command(OUTPUT "${INITMOD}" - COMMAND $ "halide_internal_initmod_ptx_${i}_ll" < "$" > "${INITMOD}" + COMMAND binary2cpp "halide_internal_initmod_ptx_${i}_ll" < "$" > "${INITMOD}" DEPENDS binary2cpp "${RT_BC}" VERBATIM) target_sources(Halide_initmod PRIVATE ${INITMOD}) endforeach () add_custom_command(OUTPUT "_initmod_inlined_c.cpp" - COMMAND $ "halide_internal_initmod_inlined_c" < "$" > "_initmod_inlined_c.cpp" + COMMAND binary2cpp "halide_internal_initmod_inlined_c" < "$" > "_initmod_inlined_c.cpp" DEPENDS "halide_buffer_t.cpp" binary2cpp VERBATIM) target_sources(Halide_initmod PRIVATE "_initmod_inlined_c.cpp") @@ -323,7 +323,7 @@ target_sources(Halide_initmod PRIVATE "_initmod_inlined_c.cpp") foreach (i IN LISTS RUNTIME_HEADER_FILES) string(REPLACE "." "_" SYM_NAME "${i}") add_custom_command(OUTPUT "_initmod_${SYM_NAME}.cpp" - COMMAND $ "halide_internal_runtime_header_${SYM_NAME}" < "$" > "_initmod_${SYM_NAME}.cpp" + COMMAND binary2cpp "halide_internal_runtime_header_${SYM_NAME}" < "$" > "_initmod_${SYM_NAME}.cpp" DEPENDS "${i}" binary2cpp VERBATIM) target_sources(Halide_initmod PRIVATE "_initmod_${SYM_NAME}.cpp") diff --git a/tutorial/CMakeLists.txt b/tutorial/CMakeLists.txt index da2b185dda84..70d41690a972 100644 --- a/tutorial/CMakeLists.txt +++ b/tutorial/CMakeLists.txt @@ -81,7 +81,7 @@ if (TARGET_NVPTX) target_include_directories(lesson_10_aot_compilation_run PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") - add_test(NAME tutorial_lesson_10_aot_compilation_run COMMAND $) + add_test(NAME tutorial_lesson_10_aot_compilation_run COMMAND lesson_10_aot_compilation_run) set_tests_properties(tutorial_lesson_10_aot_compilation_run PROPERTIES LABELS "tutorial;multithreaded") endif () endif () @@ -174,7 +174,7 @@ else () Halide::ImageIO Halide::Tools) - add_test(NAME tutorial_lesson_16_rgb_run COMMAND $) + add_test(NAME tutorial_lesson_16_rgb_run COMMAND lesson_16_rgb_run) set_tests_properties(tutorial_lesson_16_rgb_run PROPERTIES LABELS tutorial) endif () @@ -204,6 +204,6 @@ if (TARGET Halide::Mullapudi2016) target_link_libraries(lesson_21_auto_scheduler_run PRIVATE auto_schedule_false auto_schedule_true Halide::Tools) - add_test(NAME tutorial_lesson_21_auto_scheduler_run COMMAND $) + add_test(NAME tutorial_lesson_21_auto_scheduler_run COMMAND lesson_21_auto_scheduler_run) set_tests_properties(tutorial_lesson_21_auto_scheduler_run PROPERTIES LABELS "tutorial;multithreaded") endif () From 6e9efc0277c33ffac2db8b25a385b9f568763810 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 11 Aug 2022 00:44:08 +0000 Subject: [PATCH 11/14] Use LLD from LLVM_ROOT --- cmake/toolchain.linux-x64-asan.cmake | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake index fc5870389821..ae35aab21050 100644 --- a/cmake/toolchain.linux-x64-asan.cmake +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -15,16 +15,14 @@ set(CMAKE_SYSTEM_PROCESSOR i686) set(CMAKE_C_COMPILER ${LLVM_ROOT}/bin/clang) set(CMAKE_CXX_COMPILER ${LLVM_ROOT}/bin/clang++) +set(CMAKE_LINKER ${LLVM_ROOT}/bin/ld.lld) -set(_ASAN_FLAGS "-fsanitize=address") -# set(_ASAN_FLAGS "-fsanitize=address -shared-libasan") +set(CMAKE_C_FLAGS_INIT "-fsanitize=address") +set(CMAKE_CXX_FLAGS_INIT "-fsanitize=address") -set(CMAKE_CXX_FLAGS_INIT ${_ASAN_FLAGS}) -set(CMAKE_C_FLAGS_INIT ${_ASAN_FLAGS}) - -set(CMAKE_EXE_LINKER_FLAGS_INIT ${_ASAN_FLAGS}) -set(CMAKE_SHARED_LINKER_FLAGS_INIT ${_ASAN_FLAGS}) -set(CMAKE_MODULE_LINKER_FLAGS_INIT ${_ASAN_FLAGS}) +set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=${CMAKE_LINKER}") +set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=${CMAKE_LINKER}") +set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=${CMAKE_LINKER}") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) From 2f576dbdc1bd4bbe29334e6b53802ad540d78f11 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 11 Aug 2022 01:34:27 +0000 Subject: [PATCH 12/14] move sanitizer env var settings to presets --- CMakePresets.json | 40 ++++++++++++++++++++++++ apps/fft/CMakeLists.txt | 4 +-- cmake/HalideGeneratorHelpers.cmake | 6 ++-- cmake/HalideTestHelpers.cmake | 2 +- cmake/toolchain.linux-x64-asan.cmake | 11 ------- python_bindings/CMakeLists.txt | 2 +- src/autoschedulers/li2018/CMakeLists.txt | 1 - tutorial/CMakeLists.txt | 4 +-- 8 files changed, 48 insertions(+), 22 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index 8e71d3c1efcf..248380ae3d66 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -12,6 +12,15 @@ "binaryDir": "build/${presetName}", "installDir": "install/${presetName}" }, + { + "name": "ci", + "hidden": true, + "inherits": "default", + "toolchainFile": "${sourceDir}/cmake/toolchain.${presetName}.cmake", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, { "name": "windows-only", "hidden": true, @@ -145,6 +154,37 @@ "BUILD_SHARED_LIBS": "NO", "Halide_BUNDLE_LLVM": "YES" } + }, + { + "name": "linux-x64-asan", + "inherits": "ci", + "displayName": "ASAN (Linux x64)", + "description": "Build everything with ASAN enabled", + "cacheVariables": { + "LLVM_ROOT": "$penv{LLVM_ROOT}" + } + } + ], + "buildPresets": [ + { + "name": "linux-x64-asan", + "configurePreset": "linux-x64-asan", + "displayName": "ASAN (Linux x64)", + "description": "Build everything with ASAN enabled" + } + ], + "testPresets": [ + { + "name": "linux-x64-asan", + "configurePreset": "linux-x64-asan", + "displayName": "ASAN (Linux x64)", + "description": "Test everything with ASAN enabled", + "environment": { + "ASAN_OPTIONS": "detect_leaks=0:detect_container_overflow=0" + }, + "output": { + "outputOnFailure": true + } } ] } diff --git a/apps/fft/CMakeLists.txt b/apps/fft/CMakeLists.txt index 98bac09a8275..95de33cec237 100644 --- a/apps/fft/CMakeLists.txt +++ b/apps/fft/CMakeLists.txt @@ -45,8 +45,8 @@ set_tests_properties(fft_aot_test PROPERTIES foreach (i IN ITEMS 8 12 16 24 32 48) add_test(NAME bench${i}x${i} COMMAND bench_fft ${i} ${i} "${CMAKE_CURRENT_BINARY_DIR}") - set_tests_properties(bench${i}x${i} + set_tests_properties(bench${i}x${i} PROPERTIES LABELS fft - ENVIRONMENT "PATH=$>;${SANITIZER_ENV_VARS}") + ENVIRONMENT "PATH=$>") endforeach () diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index ba3fdf80d370..67cdaa04f9b7 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -325,8 +325,7 @@ function(add_halide_library TARGET) endif () add_custom_command(OUTPUT ${generator_output_files} - COMMAND ${CMAKE_COMMAND} -E ${SANITIZER_SET_ENV_VARS} - $ + COMMAND ${ARG_FROM} -n "${TARGET}" -d "${gradient_descent}" -g "${ARG_GENERATOR}" @@ -401,8 +400,7 @@ function(_Halide_add_halide_runtime RT) endif () add_custom_command(OUTPUT ${GEN_OUTS} - COMMAND ${CMAKE_COMMAND} -E ${SANITIZER_SET_ENV_VARS} - $ -r "${TARGET}.runtime" -o . ${GEN_ARGS} + COMMAND ${ARG_FROM} -r "${TARGET}.runtime" -o . ${GEN_ARGS} # Defers reading the list of targets for which to generate a common runtime to CMake _generation_ time. # This prevents issues where a lower GCD is required by a later Halide library linking to this runtime. target=$,$> diff --git a/cmake/HalideTestHelpers.cmake b/cmake/HalideTestHelpers.cmake index ef2c6d16cc55..50b072f2814a 100644 --- a/cmake/HalideTestHelpers.cmake +++ b/cmake/HalideTestHelpers.cmake @@ -51,7 +51,7 @@ function(add_halide_test TARGET) set_tests_properties(${TARGET} PROPERTIES LABELS "${args_GROUPS}" - ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET};${SANITIZER_ENV_VARS}" + ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET}" PASS_REGULAR_EXPRESSION "Success!" SKIP_REGULAR_EXPRESSION "\\[SKIP\\]" WILL_FAIL ${args_EXPECT_FAILURE}) diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake index ae35aab21050..95e1837d4258 100644 --- a/cmake/toolchain.linux-x64-asan.cmake +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -31,16 +31,5 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/env) -# If running under ASAN, we need to suppress some errors: -# - detect_leaks, because circular Expr chains in Halide can indeed leak, -# but we don't care here -# - detect_container_overflow, because this is a known false-positive -# if compiling with a non-ASAN build of LLVM (which is usually the case) -set(SANITIZER_ENV_VARS "ASAN_OPTIONS=detect_leaks=0:detect_container_overflow=0") -# set(SANITIZER_ENV_VARS "ASAN_OPTIONS=detect_leaks=0:detect_container_overflow=0;LD_PRELOAD=${LLVM_ROOT}/lib/clang/16.0.0/lib/x86_64-unknown-linux-gnu/libclang_rt.asan.so") - -# Work around bug where "cmake -E env $FOO" gives error if FOO is empty -set(SANITIZER_SET_ENV_VARS env ${SANITIZER_ENV_VARS}) - # The bgu app requires too much stack space for ASAN set(ENABLE_APPS_BGU OFF) diff --git a/python_bindings/CMakeLists.txt b/python_bindings/CMakeLists.txt index 0ab699ef887a..b4ddcd8c2d5d 100644 --- a/python_bindings/CMakeLists.txt +++ b/python_bindings/CMakeLists.txt @@ -72,7 +72,7 @@ function(add_python_test) "${test_name}" PROPERTIES LABELS "python" - ENVIRONMENT "${ARG_ENVIRONMENT};${SANITIZER_ENV_VARS}" + ENVIRONMENT "${ARG_ENVIRONMENT}" ENVIRONMENT_MODIFICATION "${ARG_PYTHONPATH}" ) endfunction() diff --git a/src/autoschedulers/li2018/CMakeLists.txt b/src/autoschedulers/li2018/CMakeLists.txt index 7c02d25b669b..f1d5b3c6f90a 100644 --- a/src/autoschedulers/li2018/CMakeLists.txt +++ b/src/autoschedulers/li2018/CMakeLists.txt @@ -60,7 +60,6 @@ if (WITH_PYTHON_BINDINGS) set_tests_properties(gradient_autoscheduler_test_py PROPERTIES LABELS "Li2018;auto_schedule" - ENVIRONMENT "${SANITIZER_ENV_VARS}" ENVIRONMENT_MODIFICATION "${PYTHONPATH};${PATH}") endif () endif () diff --git a/tutorial/CMakeLists.txt b/tutorial/CMakeLists.txt index 70d41690a972..7c1b1f656132 100644 --- a/tutorial/CMakeLists.txt +++ b/tutorial/CMakeLists.txt @@ -16,7 +16,7 @@ function(add_tutorial source_file) add_test(NAME tutorial_${name} COMMAND ${name}) set_tests_properties(tutorial_${name} PROPERTIES - ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET};${SANITIZER_ENV_VARS}" + ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET}" LABELS "tutorial;${args_GROUPS}") if (args_WITH_IMAGE_IO) @@ -59,7 +59,7 @@ if (TARGET_NVPTX) set(FILTER_LIB "lesson_10_halide${CMAKE_STATIC_LIBRARY_SUFFIX}") add_custom_command(OUTPUT lesson_10_halide.h "${FILTER_LIB}" DEPENDS lesson_10_aot_compilation_generate - COMMAND ${CMAKE_COMMAND} -E ${SANITIZER_SET_ENV_VARS} $ + COMMAND lesson_10_aot_compilation_generate VERBATIM) add_custom_target(exec_lesson_10_aot_compilation_generate DEPENDS lesson_10_halide.h "${FILTER_LIB}") From c6691dfd0167fa681ca095ead3c85f28e425f917 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 11 Aug 2022 02:15:10 +0000 Subject: [PATCH 13/14] Make apps work with ASAN --- apps/CMakePresets.json | 60 ++++++++++++++++++++++++++++ cmake/HalideGeneratorHelpers.cmake | 7 ++-- cmake/toolchain.linux-x64-asan.cmake | 3 -- 3 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 apps/CMakePresets.json diff --git a/apps/CMakePresets.json b/apps/CMakePresets.json new file mode 100644 index 000000000000..788ffeb0b6e1 --- /dev/null +++ b/apps/CMakePresets.json @@ -0,0 +1,60 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 22, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default", + "hidden": true, + "binaryDir": "build/${presetName}", + "installDir": "install/${presetName}" + }, + { + "name": "ci", + "hidden": true, + "inherits": "default", + "toolchainFile": "${sourceDir}/../cmake/toolchain.${presetName}.cmake", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "linux-x64-asan", + "inherits": "ci", + "displayName": "ASAN (Linux x64)", + "description": "Build everything with ASAN enabled", + "cacheVariables": { + "LLVM_ROOT": "$penv{LLVM_ROOT}", + "ENABLE_APPS_BGU": "OFF" + } + } + ], + "buildPresets": [ + { + "name": "linux-x64-asan", + "configurePreset": "linux-x64-asan", + "displayName": "ASAN (Linux x64)", + "description": "Build everything with ASAN enabled", + "environment": { + "ASAN_OPTIONS": "detect_leaks=0:detect_container_overflow=0" + } + } + ], + "testPresets": [ + { + "name": "linux-x64-asan", + "configurePreset": "linux-x64-asan", + "displayName": "ASAN (Linux x64)", + "description": "Test everything with ASAN enabled", + "environment": { + "ASAN_OPTIONS": "detect_leaks=0:detect_container_overflow=0" + }, + "output": { + "outputOnFailure": true + } + } + ] +} diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index 67cdaa04f9b7..2bcac8bba4c5 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -80,10 +80,11 @@ function(_Halide_try_load_generators) # Communicate found information to the caller set(${ARG_PACKAGE_NAME}_FOUND "${${ARG_PACKAGE_NAME}_FOUND}" PARENT_SCOPE) - if (NOT ${ARG_PACKAGE_NAME}_FOUND AND CMAKE_CROSSCOMPILING) + if (NOT ${ARG_PACKAGE_NAME}_FOUND AND CMAKE_CROSSCOMPILING AND NOT CMAKE_CROSSCOMPILING_EMULATOR) message(WARNING - "${ARG_PACKAGE_NAME} were not found and it looks like you are cross-compiling. " - "This is likely to fail. Please set -D${ARG_PACKAGE_NAME}_ROOT=... at the CMake " + "'${ARG_PACKAGE_NAME}' was not found and it looks like you " + "are cross-compiling without an emulator. This is likely to " + "fail. Please set -D${ARG_PACKAGE_NAME}_ROOT=... at the CMake " "command line to the build directory of a host-built ${PROJECT_NAME}.") endif () endif () diff --git a/cmake/toolchain.linux-x64-asan.cmake b/cmake/toolchain.linux-x64-asan.cmake index 95e1837d4258..b582b5791715 100644 --- a/cmake/toolchain.linux-x64-asan.cmake +++ b/cmake/toolchain.linux-x64-asan.cmake @@ -30,6 +30,3 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_CROSSCOMPILING_EMULATOR /usr/bin/env) - -# The bgu app requires too much stack space for ASAN -set(ENABLE_APPS_BGU OFF) From 6800adeb55bdca54a0842bfb77cd375352881045 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Thu, 11 Aug 2022 19:29:20 +0000 Subject: [PATCH 14/14] Make Python tests preload ASAN --- python_bindings/CMakeLists.txt | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/python_bindings/CMakeLists.txt b/python_bindings/CMakeLists.txt index b4ddcd8c2d5d..bcf9e3efcf77 100644 --- a/python_bindings/CMakeLists.txt +++ b/python_bindings/CMakeLists.txt @@ -50,9 +50,25 @@ if (NOT Halide_ENABLE_RTTI OR NOT Halide_ENABLE_EXCEPTIONS) endif () ## -# A helper for creating tests with correct PYTHONPATH +# A helper for creating tests with correct PYTHONPATH and sanitizer preloading ## +if (Halide_ASAN_ENABLED) + if (NOT DEFINED Halide_Python_ASAN_LIBRARY) + # TODO: this assumes clang-on-Linux, we could be smarter here and check + # CMAKE_CXX_COMPILER_ID to behave differently on GNU, AppleClang, or + # MSVC. + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} "-print-file-name=libclang_rt.asan.so" + OUTPUT_VARIABLE Halide_Python_ASAN_LIBRARY + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif () + + set(Halide_Python_ASAN_LIBRARY "${Halide_Python_ASAN_LIBRARY}" + CACHE FILEPATH "Library to preload when running Python tests.") +endif () + function(add_python_test) cmake_parse_arguments(ARG "" "FILE;LABEL" "PYTHONPATH;ENVIRONMENT" ${ARGN}) @@ -60,6 +76,13 @@ function(add_python_test) list(TRANSFORM ARG_PYTHONPATH PREPEND "PYTHONPATH=path_list_prepend:") list(PREPEND ARG_ENVIRONMENT "HL_TARGET=${Halide_TARGET}") + if (Halide_Python_ASAN_LIBRARY) + if (APPLE) + list(PREPEND ARG_ENVIRONMENT "DYLD_INSERT_LIBRARIES=${Halide_Python_ASAN_LIBRARY}") + else () + list(PREPEND ARG_ENVIRONMENT "LD_PRELOAD=${Halide_Python_ASAN_LIBRARY}") + endif () + endif () cmake_path(GET ARG_FILE STEM test_name) set(test_name "${ARG_LABEL}_${test_name}") @@ -85,15 +108,6 @@ endfunction() add_subdirectory(src) add_subdirectory(stub) -if (Halide_ASAN_ENABLED) - # Getting asan to work in shared mode requires some LD_PRELOAD hackery - # in a lot of places; just skipping them for now. - if (WITH_TEST_PYTHON OR WITH_TUTORIALS) - message(WARNING "Python tests/tutorials are not yet supported under ASAN.") - endif() - return() -endif() - if (WITH_TEST_PYTHON) add_subdirectory(test) endif ()