From e63747c3f7fd2c8fdd9f3a77d45087567538e8ba Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 12:05:21 -0400 Subject: [PATCH 01/14] Add a Homebrew-compatible toolchain file --- cmake/toolchain.macos-homebrew.cmake | 36 ++++++++++++++++++++++++++++ run-clang-tidy.sh | 22 +---------------- 2 files changed, 37 insertions(+), 21 deletions(-) create mode 100644 cmake/toolchain.macos-homebrew.cmake diff --git a/cmake/toolchain.macos-homebrew.cmake b/cmake/toolchain.macos-homebrew.cmake new file mode 100644 index 000000000000..0f9b42c5f7e4 --- /dev/null +++ b/cmake/toolchain.macos-homebrew.cmake @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.28) + +set(CMAKE_C_COMPILER /opt/homebrew/opt/llvm@21/bin/clang) +set(CMAKE_CXX_COMPILER /opt/homebrew/opt/llvm@21/bin/clang++) + +if (NOT DEFINED CMAKE_SYSROOT) + execute_process( + COMMAND xcrun --show-sdk-path + OUTPUT_VARIABLE CMAKE_SYSROOT + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY) +endif () + +set(CMAKE_SYSROOT "${CMAKE_SYSROOT}" CACHE PATH "") + +if (NOT DEFINED XC_TOOLCHAIN_PATH) + execute_process( + COMMAND xcrun --show-toolchain-path + OUTPUT_VARIABLE XC_TOOLCHAIN_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY) +endif () + +set(XC_TOOLCHAIN_PATH "${XC_TOOLCHAIN_PATH}" CACHE PATH "") + +set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES + "${CMAKE_SYSROOT}/usr/include" + "${XC_TOOLCHAIN_PATH}/usr/include" + "${CMAKE_SYSROOT}/System/Library/Frameworks" + "${CMAKE_SYSROOT}/System/Library/SubFrameworks" +) + +set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES + "${CMAKE_SYSROOT}/usr/include/c++/v1" + ${CMAKE_C_STANDARD_INCLUDE_DIRECTORIES} +) diff --git a/run-clang-tidy.sh b/run-clang-tidy.sh index 7f261529a959..155ad32179c9 100755 --- a/run-clang-tidy.sh +++ b/run-clang-tidy.sh @@ -111,27 +111,7 @@ export CMAKE_EXPORT_COMPILE_COMMANDS=ON export Halide_LLVM_ROOT="${CLANG_TIDY_LLVM_INSTALL_DIR}" if [[ $(${CC} --version) =~ .*Homebrew.* ]]; then - # Homebrew clang 21 is badly misconfigured and needs help finding the - # system headers, even though it uses system libc++ by default. - SDKROOT="$(xcrun --show-sdk-path)" - # TOOLCHAINROOT="$(xcrun --show-toolchain-path)" - TOOLCHAINROOT="$(cd "$(dirname "$(xcrun --find clang)")"/../.. && pwd)" - RCDIR="$(xcrun clang -print-resource-dir)" - cat >"${CLANG_TIDY_BUILD_DIR}/toolchain.cmake" < Date: Mon, 16 Mar 2026 12:06:06 -0400 Subject: [PATCH 02/14] Manage libfuzzer flags from toolchain settings --- CMakePresets.json | 14 ++++++++++++++ test/CMakeLists.txt | 27 +++++---------------------- test/fuzz/CMakeLists.txt | 25 +++++-------------------- 3 files changed, 24 insertions(+), 42 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index f2df4ba9c7c1..6d8bc50b70fa 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -187,6 +187,20 @@ "Halide_LLVM_ROOT": "/opt/homebrew/opt/llvm" } }, + { + "name": "macOS-fuzz", + "displayName": "macOS (Fuzz)", + "description": "macOS fuzzing build", + "inherits": "macOS", + "toolchainFile": "${sourceDir}/cmake/toolchain.macos-homebrew.cmake", + "cacheVariables": { + "CMAKE_C_FLAGS": "-fsanitize=fuzzer-no-link -O1 -g3", + "CMAKE_CXX_FLAGS": "-fsanitize=fuzzer-no-link -O1 -g3", + "CMAKE_EXE_LINKER_FLAGS": "-fsanitize=fuzzer", + "CMAKE_MODULE_LINKER_FLAGS": "-fsanitize=fuzzer", + "CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=fuzzer" + } + }, { "name": "macOS-vcpkg", "inherits": [ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9edfd0476cbf..d5ab69683f73 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -67,36 +67,19 @@ endif () # FIXME: failing_with_issue is dead code :) -# Ensure that basic sanitizer flags are supported; -# - Address sanitizer is often used in conjunction with fuzzing as it will detect -# common high severity bugs. This sanitizer is used as a "default" for fuzzing -# when the sanitizer isn't otherwise specified. -# - Fuzzer sanitizer will link against libfuzzer and is currently only supported -# on clang/msvc and isn't supported with GCC. If you need to use these fuzzers -# with a GCC based project you should consider looking into the LIB_FUZZING_ENGINE -# env variable defined in `test/fuzz/CMakeLists.txt`. -set(CMAKE_REQUIRED_LINK_OPTIONS "-fsanitize=fuzzer,address") -set(CMAKE_REQUIRED_FLAGS "-fsanitize=fuzzer-no-link,address") +# Check that the configured toolchain can compile a libfuzzer test harness. If +# this fails, the user likely needs to set up their environment to use a +# compatible fuzzing engine (e.g. by setting up a toolchain file). check_cxx_source_compiles([[ #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, std::size_t Size) { return 0; } -]] HAS_FUZZ_FLAGS) +]] HAVE_LIBFUZZER_FLAGS) -if (NOT HAS_FUZZ_FLAGS) - message(VERBOSE "Compiler does not support libfuzzer sanitizer.") -else () - message(VERBOSE "Compiler supports libfuzzer sanitizer.") -endif () - -# Note that we want to default WITH_TEST_FUZZ to OFF, even if HAS_FUZZ_FLAGS -# is true: just because our compiler supports fuzzing doesn't mean we want to -# build the fuzz tests, because they won't really build properly without the -# right preset specified. Halide_feature(WITH_TEST_FUZZ "Build fuzz tests" AUTO - DEPENDS HAS_FUZZ_FLAGS) + DEPENDS HAVE_LIBFUZZER_FLAGS) if (WITH_TEST_FUZZ) add_subdirectory(fuzz) endif () diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt index 3d96a1d6ee97..e4bc68b96997 100644 --- a/test/fuzz/CMakeLists.txt +++ b/test/fuzz/CMakeLists.txt @@ -15,25 +15,10 @@ tests(GROUPS fuzz USE_EXIT_CODE_ONLY ) - -# By default we are going to use the libfuzzer engine. However if -# LIB_FUZZING_ENGINE is declared you can override the fuzzing engine to one of; -# - Centipede -# - Hongfuzz -# - AFL++ -# - etc. +# Allow OSS-fuzz to manage flags directly set(LIB_FUZZING_ENGINE "$ENV{LIB_FUZZING_ENGINE}" - CACHE STRING "Compiler flags necessary to link the fuzzing engine of choice e.g. libfuzzer, afl etc.") - -foreach(fuzzer "fuzz_bounds" "fuzz_cse") - target_link_libraries(${fuzzer} PRIVATE Halide::Halide) + CACHE STRING "Extra link libraries arguments for fuzz tests.") - # Allow OSS-fuzz to manage flags directly - if (LIB_FUZZING_ENGINE) - target_link_libraries(${fuzzer} PRIVATE "${LIB_FUZZING_ENGINE}") - else () - # By default just build with address-sanitizers/libfuzzer for local testing - target_compile_options(${fuzzer} PRIVATE -fsanitize=fuzzer-no-link) - target_link_options(${fuzzer} PRIVATE -fsanitize=fuzzer) - endif () -endforeach() +foreach (fuzzer IN LISTS TEST_NAMES) + target_link_libraries("${fuzzer}" PRIVATE ${LIB_FUZZING_ENGINE}) +endforeach () From f0a620451b6aaba6148928e32a008032c1148183 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 12:29:15 -0400 Subject: [PATCH 03/14] Set stage for stdlib backend --- test/fuzz/bounds.cpp | 30 +++++++++++++----------------- test/fuzz/cse.cpp | 14 +++++++------- test/fuzz/fuzz_helpers.h | 39 ++++++++++++++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/test/fuzz/bounds.cpp b/test/fuzz/bounds.cpp index 67c66410d6e8..0473acb802e0 100644 --- a/test/fuzz/bounds.cpp +++ b/test/fuzz/bounds.cpp @@ -1,7 +1,6 @@ #include "Halide.h" #include "fuzz_helpers.h" #include -#include #include #include #include @@ -26,12 +25,12 @@ std::string fuzz_var(int i) { // This is modified for each round. static Type global_var_type = Int(32); -Expr random_var(FuzzedDataProvider &fdp) { +Expr random_var(FuzzingContext &fdp) { int fuzz_count = fdp.ConsumeIntegralInRange(0, fuzz_var_count - 1); return Variable::make(global_var_type, fuzz_var(fuzz_count)); } -Type random_type(FuzzedDataProvider &fdp, int width) { +Type random_type(FuzzingContext &fdp, int width) { Type t = fdp.PickValueInArray(fuzz_types); if (width > 1) { @@ -40,7 +39,7 @@ Type random_type(FuzzedDataProvider &fdp, int width) { return t; } -int get_random_divisor(FuzzedDataProvider &fdp, Type t) { +int get_random_divisor(FuzzingContext &fdp, Type t) { std::vector divisors = {t.lanes()}; for (int dd = 2; dd < t.lanes(); dd++) { if (t.lanes() % dd == 0) { @@ -48,10 +47,10 @@ int get_random_divisor(FuzzedDataProvider &fdp, Type t) { } } - return pick_value_in_vector(fdp, divisors); + return fdp.PickValueInVector(divisors); } -Expr random_leaf(FuzzedDataProvider &fdp, Type t, bool overflow_undef = false, bool imm_only = false) { +Expr random_leaf(FuzzingContext &fdp, Type t, bool overflow_undef = false, bool imm_only = false) { if (t.is_int() && t.bits() == 32) { overflow_undef = true; } @@ -80,9 +79,9 @@ Expr random_leaf(FuzzedDataProvider &fdp, Type t, bool overflow_undef = false, b } } -Expr random_expr(FuzzedDataProvider &fdp, Type t, int depth, bool overflow_undef = false); +Expr random_expr(FuzzingContext &fdp, Type t, int depth, bool overflow_undef = false); -Expr random_condition(FuzzedDataProvider &fdp, Type t, int depth, bool maybe_scalar) { +Expr random_condition(FuzzingContext &fdp, Type t, int depth, bool maybe_scalar) { static make_bin_op_fn make_bin_op[] = { EQ::make, NE::make, @@ -101,7 +100,7 @@ Expr random_condition(FuzzedDataProvider &fdp, Type t, int depth, bool maybe_sca return fdp.PickValueInArray(make_bin_op)(a, b); } -Expr random_expr(FuzzedDataProvider &fdp, Type t, int depth, bool overflow_undef) { +Expr random_expr(FuzzingContext &fdp, Type t, int depth, bool overflow_undef) { if (t.is_int() && t.bits() == 32) { overflow_undef = true; } @@ -157,7 +156,7 @@ Expr random_expr(FuzzedDataProvider &fdp, Type t, int depth, bool overflow_undef }, [&]() { // Get a random type that isn't t or int32 (int32 can overflow and we don't care about that). - // Note also that the FuzzedDataProvider doesn't actually promise to return a random distribution -- + // Note also that the FuzzingContext doesn't actually promise to return a random distribution -- // it can (e.g.) decide to just return 0 for all data, forever -- so this loop has no guarantee // of eventually finding a different type. To remedy this, we'll just put a limit on the retries. int count = 0; @@ -285,7 +284,7 @@ Expr c(Variable::make(global_var_type, fuzz_var(2))); Expr d(Variable::make(global_var_type, fuzz_var(3))); Expr e(Variable::make(global_var_type, fuzz_var(4))); -Interval random_interval(FuzzedDataProvider &fdp, Type t) { +Interval random_interval(FuzzingContext &fdp, Type t) { Interval interval; int min_value = -128; @@ -337,7 +336,7 @@ Interval random_interval(FuzzedDataProvider &fdp, Type t) { return interval; } -int sample_interval(FuzzedDataProvider &fdp, const Interval &interval) { +int sample_interval(FuzzingContext &fdp, const Interval &interval) { // Values chosen so intervals don't repeatedly produce signed_overflow when simplified. int min_value = -128; int max_value = 128; @@ -416,7 +415,7 @@ bool test_bounds(Expr test, const Interval &interval, Type t, const map vars; for (int i = 0; i < fuzz_var_count; i++) { vars[fuzz_var(i)] = Expr(); @@ -474,9 +473,7 @@ bool test_expression_bounds(FuzzedDataProvider &fdp, Expr test, int trials, int } // namespace -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp(data, size); - +FUZZ_TEST(bounds, FuzzingContext &fdp) { // Number of random expressions to test. const int count = 100; // Depth of the randomly generated expression trees. @@ -500,6 +497,5 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { } } - std::cout << "Success!\n"; return 0; } diff --git a/test/fuzz/cse.cpp b/test/fuzz/cse.cpp index 1874bef94968..8843aaf04a1c 100644 --- a/test/fuzz/cse.cpp +++ b/test/fuzz/cse.cpp @@ -2,7 +2,6 @@ #include "fuzz_helpers.h" #include -#include #include using namespace Halide; @@ -15,14 +14,14 @@ using std::vector; // *not* int32 -- because we want to test CSE, not the simplifier's // overflow behavior, and using int32 can end up with results // containing signed_integer_overflow(), which is not helpful here. -Expr random_expr(FuzzedDataProvider &fdp, int depth, vector> &exprs) { +Expr random_expr(FuzzingContext &fdp, int depth, vector> &exprs) { if (depth <= 0) { return i16(fdp.ConsumeIntegralInRange(-5, 4)); } if (!exprs.empty() && fdp.ConsumeBool()) { // Reuse an existing expression that was generated under conditions at // least as strict as our current depth limit. - auto p = pick_value_in_vector(fdp, exprs); + auto p = fdp.PickValueInVector(exprs); if (p.second <= depth) { return p.first; } @@ -76,8 +75,7 @@ Expr random_expr(FuzzedDataProvider &fdp, int depth, vector> &ex return next; } -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - FuzzedDataProvider fdp(data, size); +FUZZ_TEST(cse, FuzzingContext &fdp) { vector> exprs; Expr orig = random_expr(fdp, 5, exprs); @@ -92,7 +90,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Don't use can_prove, because it recursively calls cse, which just confuses matters. Expr result = simplify(check); - assert(is_const_one(result)); + if (is_const_one(result)) { + return 0; + } - return 0; + return 1; } diff --git a/test/fuzz/fuzz_helpers.h b/test/fuzz/fuzz_helpers.h index 24e302f26aa2..28b12d9b4819 100644 --- a/test/fuzz/fuzz_helpers.h +++ b/test/fuzz/fuzz_helpers.h @@ -1,15 +1,44 @@ #ifndef HALIDE_FUZZ_HELPERS_H_ #define HALIDE_FUZZ_HELPERS_H_ -#include "fuzzer/FuzzedDataProvider.h" +#define HALIDE_FUZZER_BACKEND_STDLIB 0 +#define HALIDE_FUZZER_BACKEND_LIBFUZZER 1 + +#ifndef HALIDE_FUZZER_BACKEND +#warning "HALIDE_FUZZER_BACKEND not defined, defaulting to libFuzzer" +#define HALIDE_FUZZER_BACKEND HALIDE_FUZZER_BACKEND_LIBFUZZER +#endif + +/////////////////////////////////////////////////////////////////////////////// + +#if HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_LIBFUZZER +#include "fuzzer/FuzzedDataProvider.h" // IWYU pragma: export +#endif + +#include #include namespace Halide { -template -inline T pick_value_in_vector(FuzzedDataProvider &fdp, std::vector &vec) { - return vec[fdp.ConsumeIntegralInRange(0, vec.size() - 1)]; -} +#if HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_LIBFUZZER +class FuzzingContext : public FuzzedDataProvider { +public: + using FuzzedDataProvider::FuzzedDataProvider; + template + T PickValueInVector(std::vector &vec) { + return vec[ConsumeIntegralInRange(0, vec.size() - 1)]; + } +}; +#endif + } // namespace Halide +#define FUZZ_TEST(name, signature) \ + static int name##_fuzz_test(signature); \ + extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { \ + FuzzingContext fdp(data, size); \ + return name##_fuzz_test(fdp); \ + } \ + static int name##_fuzz_test(signature) + #endif // HALIDE_FUZZ_HELPERS_H_ From 1c045b97bcf93cdba1b051d21c20c512fb41afcb Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 13:12:03 -0400 Subject: [PATCH 04/14] Add stdlib-based fuzzer --- test/CMakeLists.txt | 14 +-------- test/fuzz/CMakeLists.txt | 36 +++++++++++++++++++++--- test/fuzz/fuzz_helpers.h | 61 ++++++++++++++++++++++++++++++++++++---- test/fuzz/fuzz_main.cpp | 26 +++++++++++++++++ test/fuzz/fuzz_main.h | 11 ++++++++ 5 files changed, 126 insertions(+), 22 deletions(-) create mode 100644 test/fuzz/fuzz_main.cpp create mode 100644 test/fuzz/fuzz_main.h diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d5ab69683f73..e41d7081b66a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -67,19 +67,7 @@ endif () # FIXME: failing_with_issue is dead code :) -# Check that the configured toolchain can compile a libfuzzer test harness. If -# this fails, the user likely needs to set up their environment to use a -# compatible fuzzing engine (e.g. by setting up a toolchain file). -check_cxx_source_compiles([[ -#include -#include -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, std::size_t Size) { - return 0; -} -]] HAVE_LIBFUZZER_FLAGS) - -Halide_feature(WITH_TEST_FUZZ "Build fuzz tests" AUTO - DEPENDS HAVE_LIBFUZZER_FLAGS) +Halide_feature(WITH_TEST_FUZZ "Build fuzz tests" ON) if (WITH_TEST_FUZZ) add_subdirectory(fuzz) endif () diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt index e4bc68b96997..532b6f41dac6 100644 --- a/test/fuzz/CMakeLists.txt +++ b/test/fuzz/CMakeLists.txt @@ -1,3 +1,10 @@ +if (NOT LIB_FUZZING_ENGINE) + set(LIB_FUZZING_ENGINE "$ENV{LIB_FUZZING_ENGINE}") +endif () + +set(LIB_FUZZING_ENGINE "${LIB_FUZZING_ENGINE}" + CACHE STRING "Extra link libraries arguments for fuzz tests.") + tests(GROUPS fuzz SOURCES bounds.cpp @@ -15,10 +22,31 @@ tests(GROUPS fuzz USE_EXIT_CODE_ONLY ) -# Allow OSS-fuzz to manage flags directly -set(LIB_FUZZING_ENGINE "$ENV{LIB_FUZZING_ENGINE}" - CACHE STRING "Extra link libraries arguments for fuzz tests.") +# Check whether the configured toolchain can compile a libfuzzer test harness. +# If this fails, the user likely needs to set up their environment to use a +# compatible fuzzing engine (e.g. by setting up a toolchain file). +check_cxx_source_compiles([[ +#include +#include +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, std::size_t Size) { + return 0; +} +]] HAVE_LIBFUZZER_FLAGS) + +add_library(Halide_fuzz INTERFACE) +add_library(Halide::fuzz ALIAS Halide_fuzz) + +if (NOT HAVE_LIBFUZZER_FLAGS) + if (LIB_FUZZING_ENGINE) + message(FATAL_ERROR "Cannot set LIB_FUZZING_ENGINE when not building with -fsanitize=fuzzer or a compatible fuzzing engine.") + endif () + target_sources(Halide_fuzz INTERFACE fuzz_main.cpp) + target_compile_definitions(Halide_fuzz INTERFACE HALIDE_FUZZER_BACKEND=HALIDE_FUZZER_BACKEND_STDLIB) +else () + target_link_libraries(Halide_fuzz INTERFACE ${LIB_FUZZING_ENGINE}) + target_compile_definitions(Halide_fuzz INTERFACE HALIDE_FUZZER_BACKEND=HALIDE_FUZZER_BACKEND_LIBFUZZER) +endif () foreach (fuzzer IN LISTS TEST_NAMES) - target_link_libraries("${fuzzer}" PRIVATE ${LIB_FUZZING_ENGINE}) + target_link_libraries("${fuzzer}" PRIVATE Halide::fuzz) endforeach () diff --git a/test/fuzz/fuzz_helpers.h b/test/fuzz/fuzz_helpers.h index 28b12d9b4819..dca996ad3cf5 100644 --- a/test/fuzz/fuzz_helpers.h +++ b/test/fuzz/fuzz_helpers.h @@ -5,19 +5,21 @@ #define HALIDE_FUZZER_BACKEND_LIBFUZZER 1 #ifndef HALIDE_FUZZER_BACKEND -#warning "HALIDE_FUZZER_BACKEND not defined, defaulting to libFuzzer" -#define HALIDE_FUZZER_BACKEND HALIDE_FUZZER_BACKEND_LIBFUZZER +#error "HALIDE_FUZZER_BACKEND not defined, defaulting to libFuzzer" #endif /////////////////////////////////////////////////////////////////////////////// +#include +#include + #if HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_LIBFUZZER #include "fuzzer/FuzzedDataProvider.h" // IWYU pragma: export +#elif HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_STDLIB +#include "fuzz_main.h" +#include #endif -#include -#include - namespace Halide { #if HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_LIBFUZZER @@ -29,10 +31,51 @@ class FuzzingContext : public FuzzedDataProvider { return vec[ConsumeIntegralInRange(0, vec.size() - 1)]; } }; +#elif HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_STDLIB +class FuzzingContext { + +public: + using RandomEngine = std::mt19937_64; + using SeedType = RandomEngine::result_type; + + explicit FuzzingContext(SeedType seed) : rng(seed) { + } + + template + T ConsumeIntegral() { + std::uniform_int_distribution dist(std::numeric_limits::min(), std::numeric_limits::max()); + return dist(rng); + } + + template + T ConsumeIntegralInRange(T min, T max) { + std::uniform_int_distribution dist(min, max); + return dist(rng); + } + + bool ConsumeBool() { + std::bernoulli_distribution dist; + return dist(rng); + } + + template + T PickValueInVector(std::vector &vec) { + return vec[ConsumeIntegralInRange(static_cast(0), vec.size() - 1)]; + } + + template + auto PickValueInArray(T &array) -> decltype(auto) { + return array[ConsumeIntegralInRange(static_cast(0), std::size(array) - 1)]; + } + +private: + RandomEngine rng; +}; #endif } // namespace Halide +#if HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_LIBFUZZER #define FUZZ_TEST(name, signature) \ static int name##_fuzz_test(signature); \ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { \ @@ -40,5 +83,13 @@ class FuzzingContext : public FuzzedDataProvider { return name##_fuzz_test(fdp); \ } \ static int name##_fuzz_test(signature) +#elif HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_STDLIB +#define FUZZ_TEST(name, signature) \ + static int name##_fuzz_test(signature); \ + int main(int argc, char **argv) { \ + return Halide::fuzz_main(argc, argv, name##_fuzz_test); \ + } \ + static int name##_fuzz_test(signature) +#endif #endif // HALIDE_FUZZ_HELPERS_H_ diff --git a/test/fuzz/fuzz_main.cpp b/test/fuzz/fuzz_main.cpp new file mode 100644 index 000000000000..2274c73777db --- /dev/null +++ b/test/fuzz/fuzz_main.cpp @@ -0,0 +1,26 @@ +#include "fuzz_main.h" +#include "fuzz_helpers.h" + +namespace { + +template +T initialize_rng() { + constexpr auto kStateWords = T::state_size * sizeof(typename T::result_type) / sizeof(uint32_t); + std::vector random(kStateWords); + std::generate(random.begin(), random.end(), std::random_device{}); + std::seed_seq seed_seq(random.begin(), random.end()); + return T{seed_seq}; +} +} // namespace + +namespace Halide { + +int fuzz_main(int argc, char **argv, FuzzFunction main_fn) { + auto seed_generator = initialize_rng(); + auto seed = seed_generator(); + + FuzzingContext ctx{seed}; + return main_fn(ctx); +} + +} // namespace Halide diff --git a/test/fuzz/fuzz_main.h b/test/fuzz/fuzz_main.h new file mode 100644 index 000000000000..3bfb135d1cf2 --- /dev/null +++ b/test/fuzz/fuzz_main.h @@ -0,0 +1,11 @@ +#ifndef HALIDE_BACKEND_STDLIB_MAIN_H +#define HALIDE_BACKEND_STDLIB_MAIN_H + +namespace Halide { +class FuzzingContext; +using FuzzFunction = int (*)(FuzzingContext &); + +int fuzz_main(int argc, char **argv, FuzzFunction main_fn); +} // namespace Halide + +#endif // HALIDE_BACKEND_STDLIB_MAIN_H From 5dc6a4a0eda61609806c0b17010640440561a1c6 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 16:39:49 -0400 Subject: [PATCH 05/14] Implement fuzz test runner in fuzz_main.cpp --- test/fuzz/fuzz_main.cpp | 124 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 3 deletions(-) diff --git a/test/fuzz/fuzz_main.cpp b/test/fuzz/fuzz_main.cpp index 2274c73777db..406ef462070b 100644 --- a/test/fuzz/fuzz_main.cpp +++ b/test/fuzz/fuzz_main.cpp @@ -1,6 +1,11 @@ #include "fuzz_main.h" #include "fuzz_helpers.h" +#include +#include +#include +#include + namespace { template @@ -11,16 +16,129 @@ T initialize_rng() { std::seed_seq seed_seq(random.begin(), random.end()); return T{seed_seq}; } + +void print_usage(const char *argv0) { + std::cerr + << "Usage: " << argv0 << " [options] [seed]\n" + << "\n" + << "Options:\n" + << " -runs=N Number of fuzz iterations (default: 10000)\n" + << " -timeout=N (ignored, accepted for libFuzzer compatibility)\n" + << " -max_total_time=N (ignored, accepted for libFuzzer compatibility)\n" + << " -help Print this help message and exit\n" + << "\n" + << "If a single non-option argument is given, it is used as the RNG seed.\n" + << "Options may use '-' or '--' prefixes.\n"; +} + +// Strip one or two leading dashes from arg. Returns nullptr if arg doesn't +// start with '-'. +const char *strip_dashes(const char *arg) { + if (arg[0] != '-') { + return nullptr; + } + arg++; + if (arg[0] == '-') { + arg++; + } + return arg; +} + +// Try to parse "key=N" where key matches `name`. On match, stores the parsed +// positive integer in *out and returns true. On parse error, prints a message +// and exits. Returns false if `body` doesn't start with `name=`. +bool parse_positive_int_flag(const char *body, const char *name, int *out) { + size_t len = strlen(name); + if (strncmp(body, name, len) != 0 || body[len] != '=') { + return false; + } + const char *val = body + len + 1; + int n = 0; + std::istringstream iss(val); + if (!(iss >> n) || !iss.eof() || n <= 0) { + std::cerr << "Error: -" << name << " requires a strictly positive integer, got '" << val << "'\n\n"; + print_usage("fuzz_test"); + exit(1); + } + *out = n; + return true; +} + } // namespace namespace Halide { int fuzz_main(int argc, char **argv, FuzzFunction main_fn) { + int runs = 10000; + FuzzingContext::SeedType explicit_seed = 0; + bool has_explicit_seed = false; + + // First pass: check for -help anywhere. + for (int i = 1; i < argc; i++) { + const char *body = strip_dashes(argv[i]); + if (body && strcmp(body, "help") == 0) { + print_usage(argv[0]); + return 0; + } + } + + // Second pass: parse all arguments. + for (int i = 1; i < argc; i++) { + if (const char *body = strip_dashes(argv[i])) { + int dummy = 0; + if (parse_positive_int_flag(body, "runs", &runs)) { + continue; + } + if (parse_positive_int_flag(body, "timeout", &dummy)) { + std::cerr << "Warning: -timeout is accepted but ignored.\n"; + continue; + } + if (parse_positive_int_flag(body, "max_total_time", &dummy)) { + std::cerr << "Warning: -max_total_time is accepted but ignored.\n"; + continue; + } + std::cerr << "Error: unknown option '" << argv[i] << "'\n\n"; + print_usage(argv[0]); + return 1; + } + + // Positional argument: must be the only one and must be a seed. + if (has_explicit_seed) { + std::cerr << "Error: unexpected extra argument '" << argv[i] << "'\n\n"; + print_usage(argv[0]); + return 1; + } + std::istringstream iss(argv[i]); + if (argv[i][0] == '-' || !(iss >> explicit_seed) || !iss.eof()) { + std::cerr << "Error: seed must be a non-negative integer, got '" << argv[i] << "'\n\n"; + print_usage(argv[0]); + return 1; + } + has_explicit_seed = true; + } + + if (has_explicit_seed) { + // Single run with the given seed. + std::cerr << "Seed: " << explicit_seed << "\n" + << std::flush; + FuzzingContext ctx{explicit_seed}; + return main_fn(ctx); + } + auto seed_generator = initialize_rng(); - auto seed = seed_generator(); - FuzzingContext ctx{seed}; - return main_fn(ctx); + for (int i = 0; i < runs; i++) { + auto seed = seed_generator(); + std::cerr << "Seed: " << seed << "\n" + << std::flush; + FuzzingContext ctx{seed}; + int result = main_fn(ctx); + if (result != 0) { + return result; + } + } + + return 0; } } // namespace Halide From 76b0a46db2da047bacd2bdd3fbf62754c52f54f9 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 16:54:04 -0400 Subject: [PATCH 06/14] Guess GHA still doesn't like xcrun --show-toolchain-path --- cmake/toolchain.macos-homebrew.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/toolchain.macos-homebrew.cmake b/cmake/toolchain.macos-homebrew.cmake index 0f9b42c5f7e4..60bac1270558 100644 --- a/cmake/toolchain.macos-homebrew.cmake +++ b/cmake/toolchain.macos-homebrew.cmake @@ -15,10 +15,11 @@ set(CMAKE_SYSROOT "${CMAKE_SYSROOT}" CACHE PATH "") if (NOT DEFINED XC_TOOLCHAIN_PATH) execute_process( - COMMAND xcrun --show-toolchain-path + COMMAND xcrun --find clang OUTPUT_VARIABLE XC_TOOLCHAIN_PATH OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY) + cmake_path(SET XC_TOOLCHAIN_PATH NORMALIZE "${XC_TOOLCHAIN_PATH}/../../..") endif () set(XC_TOOLCHAIN_PATH "${XC_TOOLCHAIN_PATH}" CACHE PATH "") From 3c94059d918d550969f99ae8bd6f615726b57b50 Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 16 Mar 2026 14:06:20 -0700 Subject: [PATCH 07/14] Makefile support for fuzz tests --- Makefile | 11 +++++++++++ test/fuzz/fuzz_main.cpp | 1 + 2 files changed, 12 insertions(+) diff --git a/Makefile b/Makefile index c668cf20fdcd..e315bd3ab524 100644 --- a/Makefile +++ b/Makefile @@ -1284,6 +1284,7 @@ PERFORMANCE_TESTS = $(shell ls $(ROOT_DIR)/test/performance/*.cpp) ERROR_TESTS = $(shell ls $(ROOT_DIR)/test/error/*.cpp) WARNING_TESTS = $(shell ls $(ROOT_DIR)/test/warning/*.cpp) RUNTIME_TESTS = $(shell ls $(ROOT_DIR)/test/runtime/*.cpp) +FUZZ_TESTS = $(filter-out fuzz_main.cpp, $(shell ls $(ROOT_DIR)/test/fuzz/*.cpp)) GENERATOR_EXTERNAL_TESTS := $(shell ls $(ROOT_DIR)/test/generator/*test.cpp) GENERATOR_EXTERNAL_TEST_GENERATOR := $(shell ls $(ROOT_DIR)/test/generator/*_generator.cpp) TUTORIALS = $(filter-out %_generate.cpp, $(shell ls $(ROOT_DIR)/tutorial/*.cpp)) @@ -1297,6 +1298,7 @@ test_performance: $(PERFORMANCE_TESTS:$(ROOT_DIR)/test/performance/%.cpp=perform test_error: $(ERROR_TESTS:$(ROOT_DIR)/test/error/%.cpp=error_%) test_warning: $(WARNING_TESTS:$(ROOT_DIR)/test/warning/%.cpp=warning_%) test_runtime: $(RUNTIME_TESTS:$(ROOT_DIR)/test/runtime/%.cpp=runtime_%) +test_fuzz: $(FUZZ_TESTS:$(ROOT_DIR)/test/fuzz/%.cpp=fuzz_%) test_tutorial: $(TUTORIALS:$(ROOT_DIR)/tutorial/%.cpp=tutorial_%) test_valgrind: $(CORRECTNESS_TESTS:$(ROOT_DIR)/test/correctness/%.cpp=valgrind_%) test_avx512: $(CORRECTNESS_TESTS:$(ROOT_DIR)/test/correctness/%.cpp=avx512_%) @@ -1392,6 +1394,7 @@ build_tests: $(CORRECTNESS_TESTS:$(ROOT_DIR)/test/correctness/%.cpp=$(BIN_DIR)/c $(ERROR_TESTS:$(ROOT_DIR)/test/error/%.cpp=$(BIN_DIR)/error_%) \ $(WARNING_TESTS:$(ROOT_DIR)/test/warning/%.cpp=$(BIN_DIR)/warning_%) \ $(RUNTIME_TESTS:$(ROOT_DIR)/test/runtime/%.cpp=$(BIN_DIR)/runtime_%) \ + $(FUZZ_TESTS:$(ROOT_DIR)/test/fuzz/%.cpp=$(BIN_DIR)/fuzz_%) \ $(GENERATOR_EXTERNAL_TESTS:$(ROOT_DIR)/test/generator/%_aottest.cpp=$(BIN_DIR)/$(TARGET)/generator_aot_%) \ $(GENERATOR_EXTERNAL_TESTS:$(ROOT_DIR)/test/generator/%_jittest.cpp=$(BIN_DIR)/generator_jit_%) \ $(MULLAPUDI2016_TESTS:$(ROOT_DIR)/test/autoschedulers/mullapudi2016/%.cpp=$(BIN_DIR)/mullapudi2016_%) \ @@ -1470,6 +1473,9 @@ $(BIN_DIR)/$(TARGET)/correctness_opencl_runtime: $(ROOT_DIR)/test/correctness/op $(BIN_DIR)/performance_%: $(ROOT_DIR)/test/performance/%.cpp $(TEST_DEPS) $(CXX) $(TEST_CXX_FLAGS) $(OPTIMIZE) $< -I$(INCLUDE_DIR) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(TEST_LD_FLAGS) -o $@ +$(BIN_DIR)/fuzz_%: $(ROOT_DIR)/test/fuzz/%.cpp $(ROOT_DIR)/test/fuzz/fuzz_main.cpp $(ROOT_DIR)/test/fuzz/fuzz_helpers.h $(ROOT_DIR)/test/fuzz/fuzz_main.h $(TEST_DEPS) + $(CXX) $(TEST_CXX_FLAGS) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(OPTIMIZE_FOR_BUILD_TIME) $(filter %.cpp,$^) -I$(INCLUDE_DIR) $(TEST_LD_FLAGS) -o $@ -DHALIDE_FUZZER_BACKEND=0 + # Error tests that link against libHalide $(BIN_DIR)/error_%: $(ROOT_DIR)/test/error/%.cpp $(TEST_DEPS) $(CXX) $(TEST_CXX_FLAGS) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(OPTIMIZE_FOR_BUILD_TIME) $< -I$(INCLUDE_DIR) $(TEST_LD_FLAGS) -o $@ @@ -2063,6 +2069,11 @@ quiet_correctness_%: $(BIN_DIR)/correctness_% @-mkdir -p $(TMP_DIR) @cd $(TMP_DIR) ; ( $(CURDIR)/$< 2>stderr_$*.txt > stdout_$*.txt && echo -n . ) || ( echo ; echo FAILED TEST: $* ; cat stdout_$*.txt stderr_$*.txt ; false ) +fuzz_%: $(BIN_DIR)/fuzz_% + @-mkdir -p $(TMP_DIR) + cd $(TMP_DIR) ; $(CURDIR)/$< + @-echo + valgrind_%: $(BIN_DIR)/correctness_% @-mkdir -p $(TMP_DIR) cd $(TMP_DIR) ; valgrind --error-exitcode=-1 $(CURDIR)/$< diff --git a/test/fuzz/fuzz_main.cpp b/test/fuzz/fuzz_main.cpp index 406ef462070b..1d2e6a1c19c5 100644 --- a/test/fuzz/fuzz_main.cpp +++ b/test/fuzz/fuzz_main.cpp @@ -1,6 +1,7 @@ #include "fuzz_main.h" #include "fuzz_helpers.h" +#include #include #include #include From fecdcbd019227f07c7c3f2aa8732cecf6e23fb5a Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 16 Mar 2026 14:49:13 -0700 Subject: [PATCH 08/14] Fix filter-out --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e315bd3ab524..4b60e2978eb2 100644 --- a/Makefile +++ b/Makefile @@ -1284,7 +1284,7 @@ PERFORMANCE_TESTS = $(shell ls $(ROOT_DIR)/test/performance/*.cpp) ERROR_TESTS = $(shell ls $(ROOT_DIR)/test/error/*.cpp) WARNING_TESTS = $(shell ls $(ROOT_DIR)/test/warning/*.cpp) RUNTIME_TESTS = $(shell ls $(ROOT_DIR)/test/runtime/*.cpp) -FUZZ_TESTS = $(filter-out fuzz_main.cpp, $(shell ls $(ROOT_DIR)/test/fuzz/*.cpp)) +FUZZ_TESTS = $(filter-out %fuzz_main.cpp, $(shell ls $(ROOT_DIR)/test/fuzz/*.cpp)) GENERATOR_EXTERNAL_TESTS := $(shell ls $(ROOT_DIR)/test/generator/*test.cpp) GENERATOR_EXTERNAL_TEST_GENERATOR := $(shell ls $(ROOT_DIR)/test/generator/*_generator.cpp) TUTORIALS = $(filter-out %_generate.cpp, $(shell ls $(ROOT_DIR)/tutorial/*.cpp)) From 5498e1c8eb2efd5c270329901febcad8410ac9e9 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 17:52:06 -0400 Subject: [PATCH 09/14] Make random numbers reproducible across platforms --- test/fuzz/fuzz_helpers.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/fuzz/fuzz_helpers.h b/test/fuzz/fuzz_helpers.h index dca996ad3cf5..45b781c1b758 100644 --- a/test/fuzz/fuzz_helpers.h +++ b/test/fuzz/fuzz_helpers.h @@ -11,6 +11,9 @@ /////////////////////////////////////////////////////////////////////////////// #include +#include +#include +#include #include #if HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_LIBFUZZER @@ -32,8 +35,8 @@ class FuzzingContext : public FuzzedDataProvider { } }; #elif HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_STDLIB +// IMPORTANT: we don't use std::*_distribution because they are not portable across standard libraries class FuzzingContext { - public: using RandomEngine = std::mt19937_64; using SeedType = RandomEngine::result_type; @@ -43,19 +46,21 @@ class FuzzingContext { template T ConsumeIntegral() { - std::uniform_int_distribution dist(std::numeric_limits::min(), std::numeric_limits::max()); - return dist(rng); + return static_cast(rng()); } template T ConsumeIntegralInRange(T min, T max) { - std::uniform_int_distribution dist(min, max); - return dist(rng); + // If this proves too slow, there are smarter things we can do: + // https://lemire.me/blog/2019/06/06/nearly-divisionless-random-integer-generation-on-various-systems/ + if (max < min) { + return min; + } + return min + rng() % (max - min + 1); } bool ConsumeBool() { - std::bernoulli_distribution dist; - return dist(rng); + return rng() & 1; } template From 20c93bb2f123d2d24c24789b2b56f40b83fa92ba Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 16 Mar 2026 14:54:54 -0700 Subject: [PATCH 10/14] Skip known issue --- src/Bounds.cpp | 12 ++++++++++-- test/fuzz/bounds.cpp | 13 +++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Bounds.cpp b/src/Bounds.cpp index 32b4159ea4f7..41fac3f2dba5 100644 --- a/src/Bounds.cpp +++ b/src/Bounds.cpp @@ -198,7 +198,11 @@ class Bounds : public IRVisitor { void log_line(Args &&...args) { debug(0) << self->log_spaces(); // C++17 right fold - (debug(0) << ... << args) << "\n"; + auto dump = [](auto &&arg) { + debug(0) << arg; + }; + (dump(args), ...); + debug(0) << "\n"; } ~BoundsLogger() { @@ -2144,7 +2148,11 @@ class BoxesTouched : public IRGraphVisitor { void log_line(Args &&...args) { debug(0) << self->log_spaces(); // C++17 right fold - (debug(0) << ... << args) << "\n"; + auto dump = [](auto &&arg) { + debug(0) << arg; + }; + (dump(args), ...); + debug(0) << "\n"; } BoxesTouchedLogger(BoxesTouched *self, const char *pretty_function) diff --git a/test/fuzz/bounds.cpp b/test/fuzz/bounds.cpp index 0473acb802e0..a2b2b64371bb 100644 --- a/test/fuzz/bounds.cpp +++ b/test/fuzz/bounds.cpp @@ -421,6 +421,19 @@ bool test_expression_bounds(FuzzingContext &fdp, Expr test, int trials, int samp vars[fuzz_var(i)] = Expr(); } + // Don't test expressions with potentially overflowing casts to signed + // ints. This is known to be broken (See + // https://github.com/halide/Halide/pull/7814) + bool contains_risky_cast = false; + visit_with(test, [&](auto *self, const Cast *op) { + contains_risky_cast |= (op->type.is_int() && + op->type.bits() >= 32 && + !op->type.can_represent(op->value.type())); + }); + if (contains_risky_cast) { + return true; + } + for (int i = 0; i < trials; i++) { Scope scope; From 9e75fa9b0d2e3eb0019c016214e9298d057bbcff Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 19:08:34 -0400 Subject: [PATCH 11/14] Fix naming per comments --- test/fuzz/CMakeLists.txt | 2 +- test/fuzz/bounds.cpp | 124 +++++++++--------- test/fuzz/cse.cpp | 40 +++--- test/fuzz/fuzz_helpers.h | 2 +- .../{fuzz_main.cpp => fuzz_stdlib_main.cpp} | 2 +- test/fuzz/{fuzz_main.h => fuzz_stdlib_main.h} | 6 +- 6 files changed, 88 insertions(+), 88 deletions(-) rename test/fuzz/{fuzz_main.cpp => fuzz_stdlib_main.cpp} (99%) rename test/fuzz/{fuzz_main.h => fuzz_stdlib_main.h} (60%) diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt index 532b6f41dac6..171bacae7b49 100644 --- a/test/fuzz/CMakeLists.txt +++ b/test/fuzz/CMakeLists.txt @@ -40,7 +40,7 @@ if (NOT HAVE_LIBFUZZER_FLAGS) if (LIB_FUZZING_ENGINE) message(FATAL_ERROR "Cannot set LIB_FUZZING_ENGINE when not building with -fsanitize=fuzzer or a compatible fuzzing engine.") endif () - target_sources(Halide_fuzz INTERFACE fuzz_main.cpp) + target_sources(Halide_fuzz INTERFACE fuzz_stdlib_main.cpp) target_compile_definitions(Halide_fuzz INTERFACE HALIDE_FUZZER_BACKEND=HALIDE_FUZZER_BACKEND_STDLIB) else () target_link_libraries(Halide_fuzz INTERFACE ${LIB_FUZZING_ENGINE}) diff --git a/test/fuzz/bounds.cpp b/test/fuzz/bounds.cpp index a2b2b64371bb..2a42df653fb5 100644 --- a/test/fuzz/bounds.cpp +++ b/test/fuzz/bounds.cpp @@ -25,13 +25,13 @@ std::string fuzz_var(int i) { // This is modified for each round. static Type global_var_type = Int(32); -Expr random_var(FuzzingContext &fdp) { - int fuzz_count = fdp.ConsumeIntegralInRange(0, fuzz_var_count - 1); +Expr random_var(FuzzingContext &fuzz) { + int fuzz_count = fuzz.ConsumeIntegralInRange(0, fuzz_var_count - 1); return Variable::make(global_var_type, fuzz_var(fuzz_count)); } -Type random_type(FuzzingContext &fdp, int width) { - Type t = fdp.PickValueInArray(fuzz_types); +Type random_type(FuzzingContext &fuzz, int width) { + Type t = fuzz.PickValueInArray(fuzz_types); if (width > 1) { t = t.with_lanes(width); @@ -39,7 +39,7 @@ Type random_type(FuzzingContext &fdp, int width) { return t; } -int get_random_divisor(FuzzingContext &fdp, Type t) { +int get_random_divisor(FuzzingContext &fuzz, Type t) { std::vector divisors = {t.lanes()}; for (int dd = 2; dd < t.lanes(); dd++) { if (t.lanes() % dd == 0) { @@ -47,41 +47,41 @@ int get_random_divisor(FuzzingContext &fdp, Type t) { } } - return fdp.PickValueInVector(divisors); + return fuzz.PickValueInVector(divisors); } -Expr random_leaf(FuzzingContext &fdp, Type t, bool overflow_undef = false, bool imm_only = false) { +Expr random_leaf(FuzzingContext &fuzz, Type t, bool overflow_undef = false, bool imm_only = false) { if (t.is_int() && t.bits() == 32) { overflow_undef = true; } if (t.is_scalar()) { - if (!imm_only && fdp.ConsumeBool()) { - auto v1 = random_var(fdp); + if (!imm_only && fuzz.ConsumeBool()) { + auto v1 = random_var(fuzz); return cast(t, v1); } else if (overflow_undef) { // For Int(32), we don't care about correctness during // overflow, so just use numbers that are unlikely to // overflow. - return cast(t, fdp.ConsumeIntegralInRange(-128, 127)); + return cast(t, fuzz.ConsumeIntegralInRange(-128, 127)); } else { - return cast(t, fdp.ConsumeIntegral()); + return cast(t, fuzz.ConsumeIntegral()); } } else { - int lanes = get_random_divisor(fdp, t); - if (fdp.ConsumeBool()) { - auto e1 = random_leaf(fdp, t.with_lanes(t.lanes() / lanes), overflow_undef); - auto e2 = random_leaf(fdp, t.with_lanes(t.lanes() / lanes), overflow_undef); + int lanes = get_random_divisor(fuzz, t); + if (fuzz.ConsumeBool()) { + auto e1 = random_leaf(fuzz, t.with_lanes(t.lanes() / lanes), overflow_undef); + auto e2 = random_leaf(fuzz, t.with_lanes(t.lanes() / lanes), overflow_undef); return Ramp::make(e1, e2, lanes); } else { - auto e1 = random_leaf(fdp, t.with_lanes(t.lanes() / lanes), overflow_undef); + auto e1 = random_leaf(fuzz, t.with_lanes(t.lanes() / lanes), overflow_undef); return Broadcast::make(e1, lanes); } } } -Expr random_expr(FuzzingContext &fdp, Type t, int depth, bool overflow_undef = false); +Expr random_expr(FuzzingContext &fuzz, Type t, int depth, bool overflow_undef = false); -Expr random_condition(FuzzingContext &fdp, Type t, int depth, bool maybe_scalar) { +Expr random_condition(FuzzingContext &fuzz, Type t, int depth, bool maybe_scalar) { static make_bin_op_fn make_bin_op[] = { EQ::make, NE::make, @@ -91,68 +91,68 @@ Expr random_condition(FuzzingContext &fdp, Type t, int depth, bool maybe_scalar) GE::make, }; - if (maybe_scalar && fdp.ConsumeBool()) { + if (maybe_scalar && fuzz.ConsumeBool()) { t = t.element_of(); } - Expr a = random_expr(fdp, t, depth); - Expr b = random_expr(fdp, t, depth); - return fdp.PickValueInArray(make_bin_op)(a, b); + Expr a = random_expr(fuzz, t, depth); + Expr b = random_expr(fuzz, t, depth); + return fuzz.PickValueInArray(make_bin_op)(a, b); } -Expr random_expr(FuzzingContext &fdp, Type t, int depth, bool overflow_undef) { +Expr random_expr(FuzzingContext &fuzz, Type t, int depth, bool overflow_undef) { if (t.is_int() && t.bits() == 32) { overflow_undef = true; } if (depth-- <= 0) { - return random_leaf(fdp, t, overflow_undef); + return random_leaf(fuzz, t, overflow_undef); } std::function operations[] = { [&]() { - return random_leaf(fdp, t); + return random_leaf(fuzz, t); }, [&]() { - auto c = random_condition(fdp, t, depth, true); - auto e1 = random_expr(fdp, t, depth, overflow_undef); - auto e2 = random_expr(fdp, t, depth, overflow_undef); + auto c = random_condition(fuzz, t, depth, true); + auto e1 = random_expr(fuzz, t, depth, overflow_undef); + auto e2 = random_expr(fuzz, t, depth, overflow_undef); // Don't use Select::make: we want to use select() here to // ensure that the condition and values match types. return select(c, e1, e2); }, [&]() { if (t.lanes() != 1) { - int lanes = get_random_divisor(fdp, t); - auto e1 = random_expr(fdp, t.with_lanes(t.lanes() / lanes), depth, overflow_undef); + int lanes = get_random_divisor(fuzz, t); + auto e1 = random_expr(fuzz, t.with_lanes(t.lanes() / lanes), depth, overflow_undef); return Broadcast::make(e1, lanes); } // If we got here, try again. - return random_expr(fdp, t, depth, overflow_undef); + return random_expr(fuzz, t, depth, overflow_undef); }, [&]() { if (t.lanes() != 1) { - int lanes = get_random_divisor(fdp, t); - auto e1 = random_expr(fdp, t.with_lanes(t.lanes() / lanes), depth, overflow_undef); - auto e2 = random_expr(fdp, t.with_lanes(t.lanes() / lanes), depth, overflow_undef); + int lanes = get_random_divisor(fuzz, t); + auto e1 = random_expr(fuzz, t.with_lanes(t.lanes() / lanes), depth, overflow_undef); + auto e2 = random_expr(fuzz, t.with_lanes(t.lanes() / lanes), depth, overflow_undef); return Ramp::make(e1, e2, lanes); } // If we got here, try again. - return random_expr(fdp, t, depth, overflow_undef); + return random_expr(fuzz, t, depth, overflow_undef); }, [&]() { if (t.is_bool()) { - auto e1 = random_expr(fdp, t, depth); + auto e1 = random_expr(fuzz, t, depth); return Not::make(e1); } // If we got here, try again. - return random_expr(fdp, t, depth, overflow_undef); + return random_expr(fuzz, t, depth, overflow_undef); }, [&]() { if (t.is_bool()) { - return random_condition(fdp, random_type(fdp, t.lanes()), depth, false); + return random_condition(fuzz, random_type(fuzz, t.lanes()), depth, false); } // If we got here, try again. - return random_expr(fdp, t, depth, overflow_undef); + return random_expr(fuzz, t, depth, overflow_undef); }, [&]() { // Get a random type that isn't t or int32 (int32 can overflow and we don't care about that). @@ -162,9 +162,9 @@ Expr random_expr(FuzzingContext &fdp, Type t, int depth, bool overflow_undef) { int count = 0; Type subtype; do { - subtype = random_type(fdp, t.lanes()); + subtype = random_type(fuzz, t.lanes()); } while (++count < 10 && (subtype == t || (subtype.is_int() && subtype.bits() == 32))); - auto e1 = random_expr(fdp, subtype, depth, overflow_undef); + auto e1 = random_expr(fuzz, subtype, depth, overflow_undef); return Cast::make(t, e1); }, [&]() { @@ -178,9 +178,9 @@ Expr random_expr(FuzzingContext &fdp, Type t, int depth, bool overflow_undef) { Div::make, Mod::make, }; - make_bin_op_fn maker = fdp.PickValueInArray(make_bin_op); - Expr a = random_expr(fdp, t, depth, overflow_undef); - Expr b = random_expr(fdp, t, depth, overflow_undef); + make_bin_op_fn maker = fuzz.PickValueInArray(make_bin_op); + Expr a = random_expr(fuzz, t, depth, overflow_undef); + Expr b = random_expr(fuzz, t, depth, overflow_undef); return maker(a, b); }, [&]() { @@ -191,16 +191,16 @@ Expr random_expr(FuzzingContext &fdp, Type t, int depth, bool overflow_undef) { }; // Boolean operations -- both sides must be cast to booleans, // and then we must cast the result back to 't'. - make_bin_op_fn maker = fdp.PickValueInArray(make_bin_op); - Expr a = random_expr(fdp, t, depth, overflow_undef); - Expr b = random_expr(fdp, t, depth, overflow_undef); + make_bin_op_fn maker = fuzz.PickValueInArray(make_bin_op); + Expr a = random_expr(fuzz, t, depth, overflow_undef); + Expr b = random_expr(fuzz, t, depth, overflow_undef); Type bool_with_lanes = Bool(t.lanes()); a = cast(bool_with_lanes, a); b = cast(bool_with_lanes, b); return cast(t, maker(a, b)); }, }; - return fdp.PickValueInArray(operations)(); + return fuzz.PickValueInArray(operations)(); } // These are here to enable copy of failed output expressions @@ -284,7 +284,7 @@ Expr c(Variable::make(global_var_type, fuzz_var(2))); Expr d(Variable::make(global_var_type, fuzz_var(3))); Expr e(Variable::make(global_var_type, fuzz_var(4))); -Interval random_interval(FuzzingContext &fdp, Type t) { +Interval random_interval(FuzzingContext &fuzz, Type t) { Interval interval; int min_value = -128; @@ -318,10 +318,10 @@ Interval random_interval(FuzzingContext &fdp, Type t) { max_value = std::min(max_value, 128); // change the min_value for the calculation of max - min_value = fdp.ConsumeIntegralInRange(min_value, max_value); + min_value = fuzz.ConsumeIntegralInRange(min_value, max_value); interval.min = cast(t, min_value); - max_value = fdp.ConsumeIntegralInRange(min_value, max_value); + max_value = fuzz.ConsumeIntegralInRange(min_value, max_value); interval.max = cast(t, max_value); if (min_value > max_value || (interval.is_bounded() && can_prove(interval.min > interval.max))) { @@ -336,7 +336,7 @@ Interval random_interval(FuzzingContext &fdp, Type t) { return interval; } -int sample_interval(FuzzingContext &fdp, const Interval &interval) { +int sample_interval(FuzzingContext &fuzz, const Interval &interval) { // Values chosen so intervals don't repeatedly produce signed_overflow when simplified. int min_value = -128; int max_value = 128; @@ -363,7 +363,7 @@ int sample_interval(FuzzingContext &fdp, const Interval &interval) { } } - return fdp.ConsumeIntegralInRange(min_value, max_value); + return fuzz.ConsumeIntegralInRange(min_value, max_value); } bool test_bounds(Expr test, const Interval &interval, Type t, const map &vars) { @@ -415,7 +415,7 @@ bool test_bounds(Expr test, const Interval &interval, Type t, const map vars; for (int i = 0; i < fuzz_var_count; i++) { vars[fuzz_var(i)] = Expr(); @@ -439,7 +439,7 @@ bool test_expression_bounds(FuzzingContext &fdp, Expr test, int trials, int samp for (auto v = vars.begin(); v != vars.end(); v++) { // This type is used because the variables will be this type for a given round. - Interval interval = random_interval(fdp, global_var_type); + Interval interval = random_interval(fuzz, global_var_type); scope.push(v->first, interval); } @@ -468,7 +468,7 @@ bool test_expression_bounds(FuzzingContext &fdp, Expr test, int trials, int samp for (int j = 0; j < samples_per_trial; j++) { for (std::map::iterator v = vars.begin(); v != vars.end(); v++) { Interval interval = scope.get(v->first); - v->second = cast(global_var_type, sample_interval(fdp, interval)); + v->second = cast(global_var_type, sample_interval(fuzz, interval)); } if (!test_bounds(test, interval, test.type(), vars)) { @@ -486,7 +486,7 @@ bool test_expression_bounds(FuzzingContext &fdp, Expr test, int trials, int samp } // namespace -FUZZ_TEST(bounds, FuzzingContext &fdp) { +FUZZ_TEST(bounds, FuzzingContext &fuzz) { // Number of random expressions to test. const int count = 100; // Depth of the randomly generated expression trees. @@ -498,14 +498,14 @@ FUZZ_TEST(bounds, FuzzingContext &fdp) { std::array vector_widths = {1, 2, 3, 4, 6, 8}; for (int n = 0; n < count; n++) { - int width = fdp.PickValueInArray(vector_widths); + int width = fuzz.PickValueInArray(vector_widths); // This is the type that will be the innermost (leaf) value type. - Type expr_type = random_type(fdp, width); - Type var_type = random_type(fdp, 1); + Type expr_type = random_type(fuzz, width); + Type var_type = random_type(fuzz, 1); global_var_type = var_type; // Generate a random expr... - Expr test = random_expr(fdp, expr_type, depth); - if (!test_expression_bounds(fdp, test, trials, samples)) { + Expr test = random_expr(fuzz, expr_type, depth); + if (!test_expression_bounds(fuzz, test, trials, samples)) { return 1; } } diff --git a/test/fuzz/cse.cpp b/test/fuzz/cse.cpp index 8843aaf04a1c..0c15b74e8921 100644 --- a/test/fuzz/cse.cpp +++ b/test/fuzz/cse.cpp @@ -14,14 +14,14 @@ using std::vector; // *not* int32 -- because we want to test CSE, not the simplifier's // overflow behavior, and using int32 can end up with results // containing signed_integer_overflow(), which is not helpful here. -Expr random_expr(FuzzingContext &fdp, int depth, vector> &exprs) { +Expr random_expr(FuzzingContext &fuzz, int depth, vector> &exprs) { if (depth <= 0) { - return i16(fdp.ConsumeIntegralInRange(-5, 4)); + return i16(fuzz.ConsumeIntegralInRange(-5, 4)); } - if (!exprs.empty() && fdp.ConsumeBool()) { + if (!exprs.empty() && fuzz.ConsumeBool()) { // Reuse an existing expression that was generated under conditions at // least as strict as our current depth limit. - auto p = fdp.PickValueInVector(exprs); + auto p = fuzz.PickValueInVector(exprs); if (p.second <= depth) { return p.first; } @@ -40,44 +40,44 @@ Expr random_expr(FuzzingContext &fdp, int depth, vector> &exprs) return Variable::make(Int(16), "z"); }, [&]() { - Expr next = random_expr(fdp, depth - 1, exprs); - next += random_expr(fdp, depth - 1, exprs); + Expr next = random_expr(fuzz, depth - 1, exprs); + next += random_expr(fuzz, depth - 1, exprs); return next; }, [&]() { - Expr a = random_expr(fdp, depth - 2, exprs); - Expr b = random_expr(fdp, depth - 2, exprs); - Expr c = random_expr(fdp, depth - 2, exprs); - Expr d = random_expr(fdp, depth - 2, exprs); + Expr a = random_expr(fuzz, depth - 2, exprs); + Expr b = random_expr(fuzz, depth - 2, exprs); + Expr c = random_expr(fuzz, depth - 2, exprs); + Expr d = random_expr(fuzz, depth - 2, exprs); return select(a > b, c, d); }, [&]() { - Expr a = random_expr(fdp, depth - 1, exprs); - Expr b = random_expr(fdp, depth - 1, exprs); + Expr a = random_expr(fuzz, depth - 1, exprs); + Expr b = random_expr(fuzz, depth - 1, exprs); return i16(Let::make("x", a, b)); }, [&]() { - Expr a = random_expr(fdp, depth - 1, exprs); - Expr b = random_expr(fdp, depth - 1, exprs); + Expr a = random_expr(fuzz, depth - 1, exprs); + Expr b = random_expr(fuzz, depth - 1, exprs); return i16(Let::make("y", a, b)); }, [&]() { - Expr a = random_expr(fdp, depth - 1, exprs); - Expr b = random_expr(fdp, depth - 1, exprs); + Expr a = random_expr(fuzz, depth - 1, exprs); + Expr b = random_expr(fuzz, depth - 1, exprs); return i16(Let::make("z", a, b)); }, [&]() { - return i16(fdp.ConsumeIntegralInRange(-5, 4)); + return i16(fuzz.ConsumeIntegralInRange(-5, 4)); }, }; - Expr next = fdp.PickValueInArray(build_next_expr)(); + Expr next = fuzz.PickValueInArray(build_next_expr)(); exprs.emplace_back(next, depth); return next; } -FUZZ_TEST(cse, FuzzingContext &fdp) { +FUZZ_TEST(cse, FuzzingContext &fuzz) { vector> exprs; - Expr orig = random_expr(fdp, 5, exprs); + Expr orig = random_expr(fuzz, 5, exprs); Expr csed = common_subexpression_elimination(orig); diff --git a/test/fuzz/fuzz_helpers.h b/test/fuzz/fuzz_helpers.h index 45b781c1b758..e35d807a1142 100644 --- a/test/fuzz/fuzz_helpers.h +++ b/test/fuzz/fuzz_helpers.h @@ -19,7 +19,7 @@ #if HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_LIBFUZZER #include "fuzzer/FuzzedDataProvider.h" // IWYU pragma: export #elif HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_STDLIB -#include "fuzz_main.h" +#include "fuzz_stdlib_main.h" #include #endif diff --git a/test/fuzz/fuzz_main.cpp b/test/fuzz/fuzz_stdlib_main.cpp similarity index 99% rename from test/fuzz/fuzz_main.cpp rename to test/fuzz/fuzz_stdlib_main.cpp index 1d2e6a1c19c5..a69382e98d6c 100644 --- a/test/fuzz/fuzz_main.cpp +++ b/test/fuzz/fuzz_stdlib_main.cpp @@ -1,4 +1,4 @@ -#include "fuzz_main.h" +#include "fuzz_stdlib_main.h" #include "fuzz_helpers.h" #include diff --git a/test/fuzz/fuzz_main.h b/test/fuzz/fuzz_stdlib_main.h similarity index 60% rename from test/fuzz/fuzz_main.h rename to test/fuzz/fuzz_stdlib_main.h index 3bfb135d1cf2..ca9af5aa61ea 100644 --- a/test/fuzz/fuzz_main.h +++ b/test/fuzz/fuzz_stdlib_main.h @@ -1,5 +1,5 @@ -#ifndef HALIDE_BACKEND_STDLIB_MAIN_H -#define HALIDE_BACKEND_STDLIB_MAIN_H +#ifndef HALIDE_FUZZ_STDLIB_MAIN_H +#define HALIDE_FUZZ_STDLIB_MAIN_H namespace Halide { class FuzzingContext; @@ -8,4 +8,4 @@ using FuzzFunction = int (*)(FuzzingContext &); int fuzz_main(int argc, char **argv, FuzzFunction main_fn); } // namespace Halide -#endif // HALIDE_BACKEND_STDLIB_MAIN_H +#endif // HALIDE_FUZZ_STDLIB_MAIN_H From 4fe04eaa5e9d329ad8cb3f998248cb1894db4a61 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 20:44:33 -0400 Subject: [PATCH 12/14] Fix Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4b60e2978eb2..29608db6a87b 100644 --- a/Makefile +++ b/Makefile @@ -1284,7 +1284,7 @@ PERFORMANCE_TESTS = $(shell ls $(ROOT_DIR)/test/performance/*.cpp) ERROR_TESTS = $(shell ls $(ROOT_DIR)/test/error/*.cpp) WARNING_TESTS = $(shell ls $(ROOT_DIR)/test/warning/*.cpp) RUNTIME_TESTS = $(shell ls $(ROOT_DIR)/test/runtime/*.cpp) -FUZZ_TESTS = $(filter-out %fuzz_main.cpp, $(shell ls $(ROOT_DIR)/test/fuzz/*.cpp)) +FUZZ_TESTS = $(filter-out %fuzz_stdlib_main.cpp, $(shell ls $(ROOT_DIR)/test/fuzz/*.cpp)) GENERATOR_EXTERNAL_TESTS := $(shell ls $(ROOT_DIR)/test/generator/*test.cpp) GENERATOR_EXTERNAL_TEST_GENERATOR := $(shell ls $(ROOT_DIR)/test/generator/*_generator.cpp) TUTORIALS = $(filter-out %_generate.cpp, $(shell ls $(ROOT_DIR)/tutorial/*.cpp)) @@ -1473,7 +1473,7 @@ $(BIN_DIR)/$(TARGET)/correctness_opencl_runtime: $(ROOT_DIR)/test/correctness/op $(BIN_DIR)/performance_%: $(ROOT_DIR)/test/performance/%.cpp $(TEST_DEPS) $(CXX) $(TEST_CXX_FLAGS) $(OPTIMIZE) $< -I$(INCLUDE_DIR) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(TEST_LD_FLAGS) -o $@ -$(BIN_DIR)/fuzz_%: $(ROOT_DIR)/test/fuzz/%.cpp $(ROOT_DIR)/test/fuzz/fuzz_main.cpp $(ROOT_DIR)/test/fuzz/fuzz_helpers.h $(ROOT_DIR)/test/fuzz/fuzz_main.h $(TEST_DEPS) +$(BIN_DIR)/fuzz_%: $(ROOT_DIR)/test/fuzz/%.cpp $(ROOT_DIR)/test/fuzz/fuzz_stdlib_main.cpp $(ROOT_DIR)/test/fuzz/fuzz_helpers.h $(ROOT_DIR)/test/fuzz/fuzz_main.h $(TEST_DEPS) $(CXX) $(TEST_CXX_FLAGS) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(OPTIMIZE_FOR_BUILD_TIME) $(filter %.cpp,$^) -I$(INCLUDE_DIR) $(TEST_LD_FLAGS) -o $@ -DHALIDE_FUZZER_BACKEND=0 # Error tests that link against libHalide From d4920f0fd543cb820ad7f58f4dee1113b6030ffb Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 21:38:22 -0400 Subject: [PATCH 13/14] Fix Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 29608db6a87b..1f62ee260737 100644 --- a/Makefile +++ b/Makefile @@ -1473,7 +1473,7 @@ $(BIN_DIR)/$(TARGET)/correctness_opencl_runtime: $(ROOT_DIR)/test/correctness/op $(BIN_DIR)/performance_%: $(ROOT_DIR)/test/performance/%.cpp $(TEST_DEPS) $(CXX) $(TEST_CXX_FLAGS) $(OPTIMIZE) $< -I$(INCLUDE_DIR) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(TEST_LD_FLAGS) -o $@ -$(BIN_DIR)/fuzz_%: $(ROOT_DIR)/test/fuzz/%.cpp $(ROOT_DIR)/test/fuzz/fuzz_stdlib_main.cpp $(ROOT_DIR)/test/fuzz/fuzz_helpers.h $(ROOT_DIR)/test/fuzz/fuzz_main.h $(TEST_DEPS) +$(BIN_DIR)/fuzz_%: $(ROOT_DIR)/test/fuzz/%.cpp $(ROOT_DIR)/test/fuzz/fuzz_stdlib_main.cpp $(ROOT_DIR)/test/fuzz/fuzz_helpers.h $(ROOT_DIR)/test/fuzz/fuzz_stdlib_main.h $(TEST_DEPS) $(CXX) $(TEST_CXX_FLAGS) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(OPTIMIZE_FOR_BUILD_TIME) $(filter %.cpp,$^) -I$(INCLUDE_DIR) $(TEST_LD_FLAGS) -o $@ -DHALIDE_FUZZER_BACKEND=0 # Error tests that link against libHalide From 12f62fd84d55d5c13a92f402e2fbf8f46c592fd1 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Mon, 16 Mar 2026 21:41:03 -0400 Subject: [PATCH 14/14] Final name: halide_fuzz_main --- Makefile | 4 ++-- test/fuzz/CMakeLists.txt | 2 +- test/fuzz/fuzz_helpers.h | 2 +- test/fuzz/{fuzz_stdlib_main.cpp => halide_fuzz_main.cpp} | 2 +- test/fuzz/{fuzz_stdlib_main.h => halide_fuzz_main.h} | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename test/fuzz/{fuzz_stdlib_main.cpp => halide_fuzz_main.cpp} (99%) rename test/fuzz/{fuzz_stdlib_main.h => halide_fuzz_main.h} (100%) diff --git a/Makefile b/Makefile index 1f62ee260737..4e5cb36364f8 100644 --- a/Makefile +++ b/Makefile @@ -1284,7 +1284,7 @@ PERFORMANCE_TESTS = $(shell ls $(ROOT_DIR)/test/performance/*.cpp) ERROR_TESTS = $(shell ls $(ROOT_DIR)/test/error/*.cpp) WARNING_TESTS = $(shell ls $(ROOT_DIR)/test/warning/*.cpp) RUNTIME_TESTS = $(shell ls $(ROOT_DIR)/test/runtime/*.cpp) -FUZZ_TESTS = $(filter-out %fuzz_stdlib_main.cpp, $(shell ls $(ROOT_DIR)/test/fuzz/*.cpp)) +FUZZ_TESTS = $(filter-out %halide_fuzz_main.cpp, $(shell ls $(ROOT_DIR)/test/fuzz/*.cpp)) GENERATOR_EXTERNAL_TESTS := $(shell ls $(ROOT_DIR)/test/generator/*test.cpp) GENERATOR_EXTERNAL_TEST_GENERATOR := $(shell ls $(ROOT_DIR)/test/generator/*_generator.cpp) TUTORIALS = $(filter-out %_generate.cpp, $(shell ls $(ROOT_DIR)/tutorial/*.cpp)) @@ -1473,7 +1473,7 @@ $(BIN_DIR)/$(TARGET)/correctness_opencl_runtime: $(ROOT_DIR)/test/correctness/op $(BIN_DIR)/performance_%: $(ROOT_DIR)/test/performance/%.cpp $(TEST_DEPS) $(CXX) $(TEST_CXX_FLAGS) $(OPTIMIZE) $< -I$(INCLUDE_DIR) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(TEST_LD_FLAGS) -o $@ -$(BIN_DIR)/fuzz_%: $(ROOT_DIR)/test/fuzz/%.cpp $(ROOT_DIR)/test/fuzz/fuzz_stdlib_main.cpp $(ROOT_DIR)/test/fuzz/fuzz_helpers.h $(ROOT_DIR)/test/fuzz/fuzz_stdlib_main.h $(TEST_DEPS) +$(BIN_DIR)/fuzz_%: $(ROOT_DIR)/test/fuzz/%.cpp $(ROOT_DIR)/test/fuzz/halide_fuzz_main.cpp $(ROOT_DIR)/test/fuzz/fuzz_helpers.h $(ROOT_DIR)/test/fuzz/halide_fuzz_main.h $(TEST_DEPS) $(CXX) $(TEST_CXX_FLAGS) -I$(ROOT_DIR)/src/runtime -I$(ROOT_DIR)/test/common $(OPTIMIZE_FOR_BUILD_TIME) $(filter %.cpp,$^) -I$(INCLUDE_DIR) $(TEST_LD_FLAGS) -o $@ -DHALIDE_FUZZER_BACKEND=0 # Error tests that link against libHalide diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt index 171bacae7b49..65376c7ebeb7 100644 --- a/test/fuzz/CMakeLists.txt +++ b/test/fuzz/CMakeLists.txt @@ -40,7 +40,7 @@ if (NOT HAVE_LIBFUZZER_FLAGS) if (LIB_FUZZING_ENGINE) message(FATAL_ERROR "Cannot set LIB_FUZZING_ENGINE when not building with -fsanitize=fuzzer or a compatible fuzzing engine.") endif () - target_sources(Halide_fuzz INTERFACE fuzz_stdlib_main.cpp) + target_sources(Halide_fuzz INTERFACE halide_fuzz_main.cpp halide_fuzz_main.h) target_compile_definitions(Halide_fuzz INTERFACE HALIDE_FUZZER_BACKEND=HALIDE_FUZZER_BACKEND_STDLIB) else () target_link_libraries(Halide_fuzz INTERFACE ${LIB_FUZZING_ENGINE}) diff --git a/test/fuzz/fuzz_helpers.h b/test/fuzz/fuzz_helpers.h index e35d807a1142..5b9740070be8 100644 --- a/test/fuzz/fuzz_helpers.h +++ b/test/fuzz/fuzz_helpers.h @@ -19,7 +19,7 @@ #if HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_LIBFUZZER #include "fuzzer/FuzzedDataProvider.h" // IWYU pragma: export #elif HALIDE_FUZZER_BACKEND == HALIDE_FUZZER_BACKEND_STDLIB -#include "fuzz_stdlib_main.h" +#include "halide_fuzz_main.h" #include #endif diff --git a/test/fuzz/fuzz_stdlib_main.cpp b/test/fuzz/halide_fuzz_main.cpp similarity index 99% rename from test/fuzz/fuzz_stdlib_main.cpp rename to test/fuzz/halide_fuzz_main.cpp index a69382e98d6c..085500f4ac7b 100644 --- a/test/fuzz/fuzz_stdlib_main.cpp +++ b/test/fuzz/halide_fuzz_main.cpp @@ -1,4 +1,4 @@ -#include "fuzz_stdlib_main.h" +#include "halide_fuzz_main.h" #include "fuzz_helpers.h" #include diff --git a/test/fuzz/fuzz_stdlib_main.h b/test/fuzz/halide_fuzz_main.h similarity index 100% rename from test/fuzz/fuzz_stdlib_main.h rename to test/fuzz/halide_fuzz_main.h