[tint][fuzz][ast] Add BuiltinPolyfill fuzzer

Bug: tint:2223
Change-Id: I3c542c4e1fb1ecc899d61edd47ee04e3c7b19c0a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/185625
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.cmake b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
index 2af7445..06f5358 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
@@ -252,6 +252,7 @@
   lang/wgsl/ast/transform/add_empty_entry_point_fuzz.cc
   lang/wgsl/ast/transform/array_length_from_uniform_fuzz.cc
   lang/wgsl/ast/transform/binding_remapper_fuzz.cc
+  lang/wgsl/ast/transform/builtin_polyfill_fuzz.cc
   lang/wgsl/ast/transform/zero_init_workgroup_memory_fuzz.cc
 )
 
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.gn b/src/tint/lang/wgsl/ast/transform/BUILD.gn
index cd2581a..b5eb4a9 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.gn
@@ -242,6 +242,7 @@
       "add_empty_entry_point_fuzz.cc",
       "array_length_from_uniform_fuzz.cc",
       "binding_remapper_fuzz.cc",
+      "builtin_polyfill_fuzz.cc",
       "zero_init_workgroup_memory_fuzz.cc",
     ]
     deps = [
diff --git a/src/tint/lang/wgsl/ast/transform/builtin_polyfill.cc b/src/tint/lang/wgsl/ast/transform/builtin_polyfill.cc
index f82fe95..640af4d 100644
--- a/src/tint/lang/wgsl/ast/transform/builtin_polyfill.cc
+++ b/src/tint/lang/wgsl/ast/transform/builtin_polyfill.cc
@@ -1602,6 +1602,7 @@
     return State{src, *cfg}.Run();
 }
 
+BuiltinPolyfill::Config::Config() = default;
 BuiltinPolyfill::Config::Config(const Builtins& b) : builtins(b) {}
 BuiltinPolyfill::Config::Config(const Config&) = default;
 BuiltinPolyfill::Config::~Config() = default;
diff --git a/src/tint/lang/wgsl/ast/transform/builtin_polyfill.h b/src/tint/lang/wgsl/ast/transform/builtin_polyfill.h
index bdbe157..6f999b1 100644
--- a/src/tint/lang/wgsl/ast/transform/builtin_polyfill.h
+++ b/src/tint/lang/wgsl/ast/transform/builtin_polyfill.h
@@ -29,6 +29,7 @@
 #define SRC_TINT_LANG_WGSL_AST_TRANSFORM_BUILTIN_POLYFILL_H_
 
 #include "src/tint/lang/wgsl/ast/transform/transform.h"
+#include "src/tint/utils/reflection/reflection.h"
 
 namespace tint::ast::transform {
 
@@ -108,12 +109,43 @@
         /// Should `pack4xU8Clamp()` be polyfilled?
         /// TODO(tint:1497): remove the option once the bug in DXC is fixed.
         bool pack_4xu8_clamp = false;
+
+        /// Reflection for this struct
+        TINT_REFLECT(Builtins,
+                     acosh,
+                     asinh,
+                     atanh,
+                     bgra8unorm,
+                     bitshift_modulo,
+                     clamp_int,
+                     count_leading_zeros,
+                     count_trailing_zeros,
+                     conv_f32_to_iu32,
+                     extract_bits,
+                     first_leading_bit,
+                     first_trailing_bit,
+                     fwidth_fine,
+                     insert_bits,
+                     int_div_mod,
+                     precise_float_mod,
+                     reflect_vec2_f32,
+                     saturate,
+                     sign_int,
+                     texture_sample_base_clamp_to_edge_2d_f32,
+                     quantize_to_vec_f16,
+                     workgroup_uniform_load,
+                     dot_4x8_packed,
+                     pack_unpack_4x8,
+                     pack_4xu8_clamp);
     };
 
     /// Config is consumed by the BuiltinPolyfill transform.
     /// Config specifies the builtins that should be polyfilled.
     struct Config final : public Castable<Config, Data> {
         /// Constructor
+        Config();
+
+        /// Constructor
         /// @param b the list of builtins to polyfill
         explicit Config(const Builtins& b);
 
@@ -124,7 +156,10 @@
         ~Config() override;
 
         /// The builtins to polyfill
-        const Builtins builtins;
+        Builtins builtins;
+
+        /// Reflection for this struct
+        TINT_REFLECT(Config, builtins);
     };
 
     /// @copydoc Transform::Apply
@@ -138,4 +173,11 @@
 
 }  // namespace tint::ast::transform
 
+namespace tint {
+
+/// Level reflection information
+TINT_REFLECT_ENUM_RANGE(ast::transform::BuiltinPolyfill::Level, kNone, kFull);
+
+}  // namespace tint
+
 #endif  // SRC_TINT_LANG_WGSL_AST_TRANSFORM_BUILTIN_POLYFILL_H_
diff --git a/src/tint/lang/wgsl/ast/transform/builtin_polyfill_fuzz.cc b/src/tint/lang/wgsl/ast/transform/builtin_polyfill_fuzz.cc
new file mode 100644
index 0000000..adce548
--- /dev/null
+++ b/src/tint/lang/wgsl/ast/transform/builtin_polyfill_fuzz.cc
@@ -0,0 +1,49 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/cmd/fuzz/wgsl/fuzz.h"
+#include "src/tint/lang/wgsl/ast/transform/builtin_polyfill.h"
+
+namespace tint::ast::transform {
+namespace {
+
+void BuiltinPolyfillFuzzer(const Program& program, const BuiltinPolyfill::Config& config) {
+    DataMap inputs;
+    inputs.Add<BuiltinPolyfill::Config>(std::move(config));
+
+    DataMap outputs;
+    if (auto result = BuiltinPolyfill{}.Apply(program, inputs, outputs)) {
+        if (!result->IsValid()) {
+            TINT_ICE() << "BuiltinPolyfill returned invalid program:\n" << result->Diagnostics();
+        }
+    }
+}
+
+}  // namespace
+}  // namespace tint::ast::transform
+
+TINT_WGSL_PROGRAM_FUZZER(tint::ast::transform::BuiltinPolyfillFuzzer);
diff --git a/src/tint/utils/macros/foreach.h b/src/tint/utils/macros/foreach.h
index 9ec27cc..f234a38 100644
--- a/src/tint/utils/macros/foreach.h
+++ b/src/tint/utils/macros/foreach.h
@@ -39,13 +39,15 @@
 /// TINT_COUNT_ARGUMENTS_NTH_ARG is used by TINT_COUNT_ARGUMENTS to get the number of arguments in a
 /// variadic macro call.
 #define TINT_COUNT_ARGUMENTS_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, \
-                                     _15, _16, N, ...)                                            \
+                                     _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26,  \
+                                     _27, _28, _29, _30, _31, _32, N, ...)                        \
     N
 
 /// TINT_COUNT_ARGUMENTS evaluates to the number of arguments passed to the macro
-#define TINT_COUNT_ARGUMENTS(...)                                                                 \
-    TINT_MSVC_EXPAND_BUG(TINT_COUNT_ARGUMENTS_NTH_ARG(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, \
-                                                      8, 7, 6, 5, 4, 3, 2, 1, 0))
+#define TINT_COUNT_ARGUMENTS(...)                                                                \
+    TINT_MSVC_EXPAND_BUG(TINT_COUNT_ARGUMENTS_NTH_ARG(                                           \
+        __VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, \
+        13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
 
 // Correctness checks.
 static_assert(1 == TINT_COUNT_ARGUMENTS(a), "TINT_COUNT_ARGUMENTS broken");
@@ -100,5 +102,88 @@
 #define TINT_FOREACH_15(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
     TINT_FOREACH_14(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14)          \
     CB(_15)
+#define TINT_FOREACH_16(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
+    TINT_FOREACH_15(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15)          \
+    CB(_16)
+#define TINT_FOREACH_17(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17)                                                                       \
+    TINT_FOREACH_16(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16)     \
+    CB(_17)
+#define TINT_FOREACH_18(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18)                                                                  \
+    TINT_FOREACH_17(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17)                                                                           \
+    CB(_18)
+#define TINT_FOREACH_19(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19)                                                             \
+    TINT_FOREACH_18(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18)                                                                      \
+    CB(_19)
+#define TINT_FOREACH_20(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20)                                                        \
+    TINT_FOREACH_19(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19)                                                                 \
+    CB(_20)
+#define TINT_FOREACH_21(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21)                                                   \
+    TINT_FOREACH_20(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20)                                                            \
+    CB(_21)
+#define TINT_FOREACH_22(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22)                                              \
+    TINT_FOREACH_21(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21)                                                       \
+    CB(_22)
+#define TINT_FOREACH_23(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23)                                         \
+    TINT_FOREACH_22(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22)                                                  \
+    CB(_23)
+#define TINT_FOREACH_24(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24)                                    \
+    TINT_FOREACH_23(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23)                                             \
+    CB(_24)
+#define TINT_FOREACH_25(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24, _25)                               \
+    TINT_FOREACH_24(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23, _24)                                        \
+    CB(_25)
+#define TINT_FOREACH_26(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26)                          \
+    TINT_FOREACH_25(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23, _24, _25)                                   \
+    CB(_26)
+#define TINT_FOREACH_27(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27)                     \
+    TINT_FOREACH_26(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23, _24, _25, _26)                              \
+    CB(_27)
+#define TINT_FOREACH_28(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28)                \
+    TINT_FOREACH_27(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27)                         \
+    CB(_28)
+#define TINT_FOREACH_29(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29)           \
+    TINT_FOREACH_28(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28)                    \
+    CB(_29)
+#define TINT_FOREACH_30(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30)      \
+    TINT_FOREACH_29(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29)               \
+    CB(_30)
+#define TINT_FOREACH_31(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31) \
+    TINT_FOREACH_30(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30)          \
+    CB(_31)
+#define TINT_FOREACH_32(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+                        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \
+                        _32)                                                                       \
+    TINT_FOREACH_31(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,     \
+                    _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31)     \
+    CB(_32)
 
 #endif  // SRC_TINT_UTILS_MACROS_FOREACH_H_