fuzzers: Shuffle module scope declarations

For the tint_all_transforms_fuzzer. Exercises the fact we now allow
declarations in any order.

Bug: tint:1266
Change-Id: I9ddfac90aaafe213cd860944f210718216cb3d13
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/79770
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/fuzzers/BUILD.gn b/fuzzers/BUILD.gn
index eb017d3..e674ab1 100644
--- a/fuzzers/BUILD.gn
+++ b/fuzzers/BUILD.gn
@@ -73,6 +73,8 @@
       "random_generator.h",
       "random_generator_engine.cc",
       "random_generator_engine.h",
+      "shuffle_transform.cc",
+      "shuffle_transform.h",
       "tint_common_fuzzer.cc",
       "tint_common_fuzzer.h",
       "tint_reader_writer_fuzzer.h",
diff --git a/fuzzers/CMakeLists.txt b/fuzzers/CMakeLists.txt
index 36d9e1f..55c9963 100644
--- a/fuzzers/CMakeLists.txt
+++ b/fuzzers/CMakeLists.txt
@@ -26,6 +26,8 @@
     random_generator.h
     random_generator_engine.cc
     random_generator_engine.h
+    shuffle_transform.cc
+    shuffle_transform.h
     tint_common_fuzzer.cc
     tint_common_fuzzer.h
     tint_reader_writer_fuzzer.h
diff --git a/fuzzers/shuffle_transform.cc b/fuzzers/shuffle_transform.cc
new file mode 100644
index 0000000..1407f10
--- /dev/null
+++ b/fuzzers/shuffle_transform.cc
@@ -0,0 +1,38 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "fuzzers/shuffle_transform.h"
+
+#include <random>
+
+#include "src/program_builder.h"
+
+namespace tint {
+namespace fuzzers {
+
+ShuffleTransform::ShuffleTransform(size_t seed) : seed_(seed) {}
+
+void ShuffleTransform::Run(CloneContext& ctx,
+                           const tint::transform::DataMap&,
+                           tint::transform::DataMap&) const {
+  auto decls = ctx.src->AST().GlobalDeclarations();
+  auto rng = std::mt19937_64{seed_};
+  std::shuffle(std::begin(decls), std::end(decls), rng);
+  for (auto* decl : decls) {
+    ctx.dst->AST().AddGlobalDeclaration(ctx.Clone(decl));
+  }
+}
+
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/shuffle_transform.h b/fuzzers/shuffle_transform.h
new file mode 100644
index 0000000..3e1ca1e
--- /dev/null
+++ b/fuzzers/shuffle_transform.h
@@ -0,0 +1,42 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef FUZZERS_SHUFFLE_TRANSFORM_H_
+#define FUZZERS_SHUFFLE_TRANSFORM_H_
+
+#include "src/transform/transform.h"
+
+namespace tint {
+namespace fuzzers {
+
+/// ShuffleTransform reorders the module scope declarations into a random order
+class ShuffleTransform : public tint::transform::Transform {
+ public:
+  /// Constructor
+  /// @param seed the random seed to use for the shuffling
+  explicit ShuffleTransform(size_t seed);
+
+ protected:
+  void Run(CloneContext& ctx,
+           const tint::transform::DataMap&,
+           tint::transform::DataMap&) const override;
+
+ private:
+  size_t seed_;
+};
+
+}  // namespace fuzzers
+}  // namespace tint
+
+#endif  // FUZZERS_SHUFFLE_TRANSFORM_H_
diff --git a/fuzzers/tint_all_transforms_fuzzer.cc b/fuzzers/tint_all_transforms_fuzzer.cc
index 7812b38..5b1b154 100644
--- a/fuzzers/tint_all_transforms_fuzzer.cc
+++ b/fuzzers/tint_all_transforms_fuzzer.cc
@@ -23,6 +23,7 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   {
     TransformBuilder tb(data, size);
+    tb.AddTransform<ShuffleTransform>();
     tb.AddPlatformIndependentPasses();
 
     fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
@@ -36,6 +37,7 @@
 #if TINT_BUILD_HLSL_WRITER
   {
     TransformBuilder tb(data, size);
+    tb.AddTransform<ShuffleTransform>();
     tb.AddPlatformIndependentPasses();
 
     fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kHLSL);
@@ -50,6 +52,7 @@
 #if TINT_BUILD_MSL_WRITER
   {
     TransformBuilder tb(data, size);
+    tb.AddTransform<ShuffleTransform>();
     tb.AddPlatformIndependentPasses();
 
     fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kMSL);
@@ -63,6 +66,7 @@
 #if TINT_BUILD_SPV_WRITER
   {
     TransformBuilder tb(data, size);
+    tb.AddTransform<ShuffleTransform>();
     tb.AddPlatformIndependentPasses();
 
     fuzzers::CommonFuzzer fuzzer(InputFormat::kWGSL, OutputFormat::kSpv);
diff --git a/fuzzers/transform_builder.h b/fuzzers/transform_builder.h
index 8ba5e47..b74a405 100644
--- a/fuzzers/transform_builder.h
+++ b/fuzzers/transform_builder.h
@@ -21,6 +21,7 @@
 #include "include/tint/tint.h"
 
 #include "fuzzers/data_builder.h"
+#include "fuzzers/shuffle_transform.h"
 
 namespace tint {
 namespace fuzzers {
@@ -81,6 +82,16 @@
   template <typename T>
   struct AddTransformImpl;
 
+  /// Implementation of AddTransform for ShuffleTransform
+  template <>
+  struct AddTransformImpl<ShuffleTransform> {
+    /// Add instance of ShuffleTransform to TransformBuilder
+    /// @param tb - TransformBuilder to add transform to
+    static void impl(TransformBuilder* tb) {
+      tb->manager()->Add<ShuffleTransform>(tb->builder_.build<size_t>());
+    }
+  };
+
   /// Implementation of AddTransform for transform::Robustness
   template <>
   struct AddTransformImpl<transform::Robustness> {