[tint] Move ToProgram to wgsl/writer

This belongs inside the wgsl language writer subdirectory.

Bug: tint:1988
Change-Id: Id319a0fed5946e12391c1bcd9f544e2a322fa92e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/143200
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 6b902ff..602daa8 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -496,8 +496,6 @@
       "lang/core/ir/transform/block_decorated_structs.h",
       "lang/core/ir/transform/demote_to_helper.cc",
       "lang/core/ir/transform/demote_to_helper.h",
-      "lang/core/ir/transform/rename_conflicts_wgsl.cc",
-      "lang/core/ir/transform/rename_conflicts_wgsl.h",
       "lang/core/ir/transform/shader_io.cc",
       "lang/core/ir/transform/shader_io.h",
     ]
@@ -1035,10 +1033,10 @@
       "lang/spirv/writer/printer/printer.h",
     ]
     deps += [
-      ":libtint_ir_builder_src",
       ":libtint_ir_src",
       ":libtint_ir_transform_src",
       ":libtint_wgsl_reader_program_to_ir_src",
+      ":libtint_wgsl_writer_ir_to_program_src",
     ]
   }
 }
@@ -1068,17 +1066,39 @@
   ]
 }
 
-libtint_source_set("libtint_wgsl_reader_program_to_ir_src") {
-  sources = []
-  deps = []
+if (tint_build_ir) {
+  libtint_source_set("libtint_wgsl_reader_program_to_ir_src") {
+    sources = []
+    deps = []
 
-  if (tint_build_ir) {
-    sources += [
-      "lang/wgsl/reader/program_to_ir/program_to_ir.cc",
-      "lang/wgsl/reader/program_to_ir/program_to_ir.h",
+    if (tint_build_ir) {
+      sources += [
+        "lang/wgsl/reader/program_to_ir/program_to_ir.cc",
+        "lang/wgsl/reader/program_to_ir/program_to_ir.h",
+      ]
+      deps += [
+        ":libtint_ast_src",
+        ":libtint_ir_src",
+        ":libtint_program_src",
+        ":libtint_sem_src",
+        ":libtint_symbols_src",
+        ":libtint_type_src",
+        ":libtint_utils_src",
+      ]
+    }
+  }
+
+  libtint_source_set("libtint_wgsl_writer_ir_to_program_src") {
+    sources = [
+      "lang/wgsl/writer/ir_to_program/ir_to_program.cc",
+      "lang/wgsl/writer/ir_to_program/ir_to_program.h",
+      "lang/wgsl/writer/ir_to_program/rename_conflicts.cc",
+      "lang/wgsl/writer/ir_to_program/rename_conflicts.h",
     ]
-    deps += [
+    deps = [
       ":libtint_ast_src",
+      ":libtint_builtins_src",
+      ":libtint_constant_src",
       ":libtint_ir_src",
       ":libtint_program_src",
       ":libtint_sem_src",
@@ -1148,9 +1168,9 @@
       "lang/msl/writer/printer/printer.h",
     ]
     deps += [
-      ":libtint_ir_builder_src",
       ":libtint_ir_src",
       ":libtint_ir_transform_src",
+      ":libtint_wgsl_writer_ir_to_program_src",
     ]
   }
 }
@@ -1228,25 +1248,6 @@
 }
 
 if (tint_build_ir) {
-  libtint_source_set("libtint_ir_builder_src") {
-    sources = [
-      "lang/core/ir/to_program.cc",
-      "lang/core/ir/to_program.h",
-    ]
-    deps = [
-      ":libtint_ast_src",
-      ":libtint_builtins_src",
-      ":libtint_constant_src",
-      ":libtint_ir_src",
-      ":libtint_ir_transform_src",
-      ":libtint_program_src",
-      ":libtint_sem_src",
-      ":libtint_symbols_src",
-      ":libtint_type_src",
-      ":libtint_utils_src",
-    ]
-  }
-
   libtint_source_set("libtint_ir_src") {
     sources = [
       "lang/core/ir/access.cc",
@@ -1413,8 +1414,8 @@
     assert(!build_with_chromium,
            "tint_build_ir cannot be used when building Chromium")
     public_deps += [
-      ":libtint_ir_builder_src",
       ":libtint_ir_src",
+      ":libtint_wgsl_writer_ir_to_program_src",
     ]
   }
 
@@ -1898,10 +1899,6 @@
           "lang/core/ir/transform/var_for_dynamic_index_test.cc",
         ]
       }
-
-      if (tint_build_wgsl_writer) {
-        sources += [ "lang/core/ir/transform/rename_conflicts_wgsl_test.cc" ]
-      }
     }
   }
 
@@ -2188,6 +2185,40 @@
       deps += [
         ":libtint_ir_src",
         ":tint_unittests_ir_src",
+        ":tint_unittests_wgsl_ir_helper",
+      ]
+    }
+  }
+
+  tint_unittests_source_set("tint_unittests_wgsl_writer_ir_to_program_src") {
+    sources = []
+    deps = []
+
+    if (tint_build_ir) {
+      sources += [
+        "lang/wgsl/writer/ir_to_program/inlining_test.cc",
+        "lang/wgsl/writer/ir_to_program/ir_to_program_test.cc",
+        "lang/wgsl/writer/ir_to_program/ir_to_program_test.h",
+        "lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc",
+      ]
+      deps += [
+        ":libtint_ir_src",
+        ":tint_unittests_ir_src",
+      ]
+    }
+  }
+
+  tint_unittests_source_set("tint_unittests_wgsl_ir_roundtrip_src") {
+    sources = []
+    deps = []
+
+    if (tint_build_ir) {
+      sources += [ "lang/wgsl/ir_roundtrip_test.cc" ]
+      deps += [
+        ":libtint_ir_src",
+        ":libtint_wgsl_reader_program_to_ir_src",
+        ":tint_unittests_ir_src",
+        ":tint_unittests_wgsl_ir_helper",
       ]
     }
   }
@@ -2415,16 +2446,19 @@
       ":libtint_unittests_ast_helper",
       ":tint_unittests_ast_src",
     ]
-
-    if (tint_build_ir) {
-      deps += [
-        ":libtint_ir_builder_src",
-        ":libtint_ir_src",
-      ]
-    }
   }
 
   if (tint_build_ir) {
+    tint_unittests_source_set("tint_unittests_wgsl_ir_helper") {
+      sources = [ "lang/wgsl/helpers/ir_program_test.h" ]
+      deps = [
+        ":libtint_builtins_src",
+        ":libtint_ir_src",
+        ":libtint_wgsl_reader_program_to_ir_src",
+        ":libtint_wgsl_writer_ir_to_program_src",
+      ]
+    }
+
     tint_unittests_source_set("tint_unittests_ir_src") {
       sources = [
         "lang/core/ir/access_test.cc",
@@ -2448,7 +2482,6 @@
         "lang/core/ir/instruction_result_test.cc",
         "lang/core/ir/instruction_test.cc",
         "lang/core/ir/intrinsic_call_test.cc",
-        "lang/core/ir/ir_test_helper.h",
         "lang/core/ir/let_test.cc",
         "lang/core/ir/load_test.cc",
         "lang/core/ir/load_vector_element_test.cc",
@@ -2457,15 +2490,11 @@
         "lang/core/ir/multi_in_block_test.cc",
         "lang/core/ir/next_iteration_test.cc",
         "lang/core/ir/operand_instruction_test.cc",
-        "lang/core/ir/program_test_helper.h",
         "lang/core/ir/return_test.cc",
         "lang/core/ir/store_test.cc",
         "lang/core/ir/store_vector_element_test.cc",
         "lang/core/ir/switch_test.cc",
         "lang/core/ir/swizzle_test.cc",
-        "lang/core/ir/to_program_inlining_test.cc",
-        "lang/core/ir/to_program_roundtrip_test.cc",
-        "lang/core/ir/to_program_test.cc",
         "lang/core/ir/unary_test.cc",
         "lang/core/ir/user_call_test.cc",
         "lang/core/ir/validator_test.cc",
@@ -2475,9 +2504,9 @@
 
       deps = [
         ":libtint_builtins_src",
-        ":libtint_ir_builder_src",
         ":libtint_ir_src",
         ":libtint_wgsl_reader_program_to_ir_src",
+        ":libtint_wgsl_writer_ir_to_program_src",
       ]
     }
   }
@@ -2550,8 +2579,17 @@
       deps += [
         ":tint_unittests_ir_src",
         ":tint_unittests_ir_transform_src",
-        ":tint_unittests_wgsl_reader_program_to_ir_src",
       ]
+
+      if (tint_build_wgsl_reader) {
+        deps += [ ":tint_unittests_wgsl_reader_program_to_ir_src" ]
+      }
+      if (tint_build_wgsl_writer) {
+        deps += [ ":tint_unittests_wgsl_writer_ir_to_program_src" ]
+      }
+      if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
+        deps += [ ":tint_unittests_wgsl_ir_roundtrip_src" ]
+      }
     }
 
     if (build_with_chromium) {
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 98d2aee..1a4a3ec 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -695,6 +695,15 @@
     lang/wgsl/writer/ast_printer/ast_printer.cc
     lang/wgsl/writer/ast_printer/ast_printer.h
   )
+
+  if(${TINT_BUILD_IR})
+    list(APPEND TINT_LIB_SRCS
+      lang/wgsl/writer/ir_to_program/ir_to_program.cc
+      lang/wgsl/writer/ir_to_program/ir_to_program.h
+      lang/wgsl/writer/ir_to_program/rename_conflicts.cc
+      lang/wgsl/writer/ir_to_program/rename_conflicts.h
+    )
+  endif()
 endif()
 
 if(${TINT_BUILD_MSL_WRITER})
@@ -841,8 +850,6 @@
     lang/core/ir/terminate_invocation.h
     lang/core/ir/terminator.cc
     lang/core/ir/terminator.h
-    lang/core/ir/to_program.cc
-    lang/core/ir/to_program.h
     lang/core/ir/unary.cc
     lang/core/ir/unary.h
     lang/core/ir/unreachable.cc
@@ -861,8 +868,6 @@
     lang/core/ir/transform/block_decorated_structs.h
     lang/core/ir/transform/demote_to_helper.cc
     lang/core/ir/transform/demote_to_helper.h
-    lang/core/ir/transform/rename_conflicts_wgsl.cc
-    lang/core/ir/transform/rename_conflicts_wgsl.h
     lang/core/ir/transform/shader_io.cc
     lang/core/ir/transform/shader_io.h
     lang/core/ir/transform/transform.cc
@@ -1161,7 +1166,7 @@
     utils/traits/traits_test.cc
   )
 
-  # Noet, the source files are included here otherwise the cmd sources would not be included in the
+  # Note, the source files are included here otherwise the cmd sources would not be included in the
   # test binary.
   list(APPEND TINT_TEST_SRCS
     cmd/generate_external_texture_bindings.cc
@@ -1226,6 +1231,13 @@
     )
   endif()
 
+
+  if(${TINT_BUILD_IR})
+    list(APPEND TINT_TEST_SRCS
+      lang/wgsl/helpers/ir_program_test.h
+    )
+  endif()
+
   if(${TINT_BUILD_WGSL_READER})
     list(APPEND TINT_TEST_SRCS
       lang/wgsl/reader/parser/additive_expression_test.cc
@@ -1384,12 +1396,6 @@
         lang/spirv/writer/var_test.cc
         lang/spirv/writer/writer_test.cc
       )
-
-      if (${TINT_BUILD_WGSL_WRITER})
-        list(APPEND TINT_TEST_SRCS
-          lang/core/ir/transform/rename_conflicts_wgsl_test.cc
-        )
-      endif()
     endif()
   endif()
 
@@ -1427,8 +1433,18 @@
       lang/wgsl/writer/ast_printer/variable_test.cc
       lang/wgsl/writer/ast_printer/test_helper.h
     )
+
+    if (${TINT_BUILD_IR})
+      list(APPEND TINT_TEST_SRCS
+        lang/wgsl/writer/ir_to_program/inlining_test.cc
+        lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+        lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc
+      )
+    endif()
   endif()
 
+
+
   if(${TINT_BUILD_WGSL_READER} AND ${TINT_BUILD_WGSL_WRITER})
     list(APPEND TINT_TEST_SRCS
       lang/wgsl/ast/module_clone_test.cc
@@ -1631,7 +1647,6 @@
       lang/core/ir/instruction_result_test.cc
       lang/core/ir/instruction_test.cc
       lang/core/ir/intrinsic_call_test.cc
-      lang/core/ir/ir_test_helper.h
       lang/core/ir/let_test.cc
       lang/core/ir/load_test.cc
       lang/core/ir/load_vector_element_test.cc
@@ -1640,7 +1655,6 @@
       lang/core/ir/multi_in_block_test.cc
       lang/core/ir/next_iteration_test.cc
       lang/core/ir/operand_instruction_test.cc
-      lang/core/ir/program_test_helper.h
       lang/core/ir/return_test.cc
       lang/core/ir/store_test.cc
       lang/core/ir/store_vector_element_test.cc
@@ -1659,14 +1673,7 @@
 
   if (${TINT_BUILD_IR} AND ${TINT_BUILD_WGSL_READER} AND ${TINT_BUILD_WGSL_WRITER})
     list(APPEND TINT_TEST_SRCS
-      lang/core/ir/to_program_roundtrip_test.cc
-    )
-  endif()
-
-  if (${TINT_BUILD_IR} AND ${TINT_BUILD_WGSL_WRITER})
-    list(APPEND TINT_TEST_SRCS
-      lang/core/ir/to_program_inlining_test.cc
-      lang/core/ir/to_program_test.cc
+      lang/wgsl/ir_roundtrip_test.cc
     )
   endif()
 
diff --git a/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc b/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc
index 964bd44..757b8f4 100644
--- a/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc
+++ b/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc
@@ -17,9 +17,9 @@
 #include <unordered_set>
 
 #include "src/tint/fuzzers/apply_substitute_overrides.h"
-#include "src/tint/lang/core/ir/to_program.h"
 #include "src/tint/lang/wgsl/reader/parser/parser.h"
 #include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
 #include "src/tint/lang/wgsl/writer/writer.h"
 
 [[noreturn]] void TintInternalCompilerErrorReporter(const tint::diag::List& diagnostics) {
@@ -77,7 +77,7 @@
         __builtin_trap();
     }
 
-    auto dst = tint::ir::ToProgram(ir.Get());
+    auto dst = tint::wgsl::writer::IRToProgram(ir.Get());
     if (!dst.IsValid()) {
 #if TINT_BUILD_WGSL_WRITER
         if (auto result = tint::wgsl::writer::Generate(&dst, {}); result.success) {
diff --git a/src/tint/lang/core/ir/transform/rename_conflicts_wgsl.h b/src/tint/lang/core/ir/transform/rename_conflicts_wgsl.h
deleted file mode 100644
index a5146fc..0000000
--- a/src/tint/lang/core/ir/transform/rename_conflicts_wgsl.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2023 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 SRC_TINT_LANG_CORE_IR_TRANSFORM_RENAME_CONFLICTS_WGSL_H_
-#define SRC_TINT_LANG_CORE_IR_TRANSFORM_RENAME_CONFLICTS_WGSL_H_
-
-#include "src/tint/lang/core/ir/transform/transform.h"
-
-// Forward declarations
-namespace tint::ir {
-class BuiltinCall;
-}  // namespace tint::ir
-namespace tint::type {
-class Type;
-}  // namespace tint::type
-
-namespace tint::ir::transform {
-
-/// RenameConflictsWGSL is a transform that renames declarations which prevent identifiers from
-/// resolving to the correct declaration, and those with identical identifiers declared in the same
-/// scope.
-class RenameConflictsWGSL final : public utils::Castable<RenameConflictsWGSL, Transform> {
-  public:
-    /// Constructor
-    RenameConflictsWGSL();
-    /// Destructor
-    ~RenameConflictsWGSL() override;
-
-    /// @copydoc Transform::Run
-    void Run(ir::Module* module) const override;
-
-  private:
-    struct State;
-};
-
-}  // namespace tint::ir::transform
-
-#endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_RENAME_CONFLICTS_WGSL_H_
diff --git a/src/tint/lang/core/ir/program_test_helper.h b/src/tint/lang/wgsl/helpers/ir_program_test.h
similarity index 75%
rename from src/tint/lang/core/ir/program_test_helper.h
rename to src/tint/lang/wgsl/helpers/ir_program_test.h
index 12431a9..129e140 100644
--- a/src/tint/lang/core/ir/program_test_helper.h
+++ b/src/tint/lang/wgsl/helpers/ir_program_test.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef SRC_TINT_LANG_CORE_IR_PROGRAM_TEST_HELPER_H_
-#define SRC_TINT_LANG_CORE_IR_PROGRAM_TEST_HELPER_H_
+#ifndef SRC_TINT_LANG_WGSL_HELPERS_IR_PROGRAM_TEST_H_
+#define SRC_TINT_LANG_WGSL_HELPERS_IR_PROGRAM_TEST_H_
 
 #include <memory>
 #include <string>
@@ -28,18 +28,18 @@
 #include "src/tint/lang/wgsl/reader/reader.h"
 #include "src/tint/utils/text/string_stream.h"
 
-namespace tint::ir {
+namespace tint::wgsl::helpers {
 
-/// Helper class for testing
+/// Helper class for testing IR with an input WGSL program.
 template <typename BASE>
-class ProgramTestHelperBase : public BASE, public ProgramBuilder {
+class IRProgramTestBase : public BASE, public ProgramBuilder {
   public:
-    ProgramTestHelperBase() = default;
-    ~ProgramTestHelperBase() override = default;
+    IRProgramTestBase() = default;
+    ~IRProgramTestBase() override = default;
 
     /// Build the module, cleaning up the program before returning.
     /// @returns the generated module
-    utils::Result<Module, std::string> Build() {
+    utils::Result<ir::Module, std::string> Build() {
         SetResolveOnBuild(true);
 
         Program program{std::move(*this)};
@@ -60,7 +60,7 @@
     /// Build the module from the given WGSL.
     /// @param wgsl the WGSL to convert to IR
     /// @returns the generated module
-    utils::Result<Module, std::string> Build(std::string wgsl) {
+    utils::Result<ir::Module, std::string> Build(std::string wgsl) {
 #if TINT_BUILD_WGSL_READER
         Source::File file("test.wgsl", std::move(wgsl));
         auto program = wgsl::reader::Parse(&file);
@@ -83,17 +83,17 @@
 
     /// @param mod the module
     /// @returns the disassembly string of the module
-    std::string Disassemble(Module& mod) {
-        Disassembler d(mod);
+    std::string Disassemble(ir::Module& mod) {
+        ir::Disassembler d(mod);
         return d.Disassemble();
     }
 };
 
-using ProgramTestHelper = ProgramTestHelperBase<testing::Test>;
+using IRProgramTest = IRProgramTestBase<testing::Test>;
 
 template <typename T>
-using ProgramTestParamHelper = ProgramTestHelperBase<testing::TestWithParam<T>>;
+using IRProgramTestParam = IRProgramTestBase<testing::TestWithParam<T>>;
 
-}  // namespace tint::ir
+}  // namespace tint::wgsl::helpers
 
-#endif  // SRC_TINT_LANG_CORE_IR_PROGRAM_TEST_HELPER_H_
+#endif  // SRC_TINT_LANG_WGSL_HELPERS_IR_PROGRAM_TEST_H_
diff --git a/src/tint/lang/core/ir/to_program_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
similarity index 98%
rename from src/tint/lang/core/ir/to_program_roundtrip_test.cc
rename to src/tint/lang/wgsl/ir_roundtrip_test.cc
index 1a268d3..b38c10f 100644
--- a/src/tint/lang/core/ir/to_program_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -12,23 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/lang/core/ir/program_test_helper.h"
-#include "src/tint/lang/core/ir/to_program.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 #include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
 #include "src/tint/lang/wgsl/reader/reader.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
 #include "src/tint/lang/wgsl/writer/writer.h"
 #include "src/tint/utils/text/string.h"
 
 #if !TINT_BUILD_WGSL_READER || !TINT_BUILD_WGSL_WRITER
-#error "to_program_roundtrip_test.cc requires both the WGSL reader and writer to be enabled"
+#error "ir_roundtrip_test.cc requires both the WGSL reader and writer to be enabled"
 #endif
 
-namespace tint::ir {
+namespace tint::wgsl {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-class IRToProgramRoundtripTest : public ProgramTestHelper {
+class IRToProgramRoundtripTest : public helpers::IRProgramTest {
   public:
     void Test(std::string_view input_wgsl, std::string_view expected_wgsl) {
         auto input = utils::TrimSpace(input_wgsl);
@@ -42,7 +42,7 @@
         tint::ir::Disassembler d{ir_module.Get()};
         auto disassembly = d.Disassemble();
 
-        auto output_program = ToProgram(ir_module.Get());
+        auto output_program = wgsl::writer::IRToProgram(ir_module.Get());
         if (!output_program.IsValid()) {
             FAIL() << output_program.Diagnostics().str() << std::endl  //
                    << "IR:" << std::endl                               //
@@ -3151,4 +3151,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/accessor_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/accessor_test.cc
index e7a31d4..a166366 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/accessor_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/accessor_test.cc
@@ -16,10 +16,10 @@
 #include "src/tint/lang/core/constant/scalar.h"
 #include "src/tint/lang/core/ir/block.h"
 #include "src/tint/lang/core/ir/constant.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/core/ir/var.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
@@ -27,7 +27,7 @@
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using ProgramToIRAccessorTest = ir::ProgramTestHelper;
+using ProgramToIRAccessorTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRAccessorTest, Accessor_Var_ArraySingleIndex) {
     // var a: array<u32, 3>
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/binary_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/binary_test.cc
index 8376845..c36254a 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/binary_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/binary_test.cc
@@ -14,16 +14,16 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/constant/scalar.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using ProgramToIRBinaryTest = ir::ProgramTestHelper;
+using ProgramToIRBinaryTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Add) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/builtin_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/builtin_test.cc
index d24c0bd..01f069b 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/builtin_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/builtin_test.cc
@@ -14,16 +14,16 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/constant/scalar.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using ProgramToIRBuiltinTest = ir::ProgramTestHelper;
+using ProgramToIRBuiltinTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRBuiltinTest, EmitExpression_Builtin) {
     auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f));
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/call_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/call_test.cc
index 56f53e7..fc7799e 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/call_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/call_test.cc
@@ -14,9 +14,9 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/constant/scalar.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
@@ -24,7 +24,7 @@
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using ProgramToIRCallTest = ir::ProgramTestHelper;
+using ProgramToIRCallTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRCallTest, EmitExpression_Bitcast) {
     Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/function_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/function_test.cc
index 47d2497..d773315 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/function_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/function_test.cc
@@ -14,9 +14,9 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/constant/scalar.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
@@ -24,7 +24,7 @@
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using ProgramToIRFunctionTest = ir::ProgramTestHelper;
+using ProgramToIRFunctionTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRFunctionTest, EmitFunction_Vertex) {
     Func("test", utils::Empty, ty.vec4<f32>(),
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/let_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/let_test.cc
index 3fca4cb..fcda990 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/let_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/let_test.cc
@@ -14,16 +14,16 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/constant/scalar.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using ProgramToIRLetTest = ir::ProgramTestHelper;
+using ProgramToIRLetTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRLetTest, Constant) {
     WrapInFunction(Let("a", Expr(42_i)));
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/literal_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/literal_test.cc
index 2810cea..a6d0bf8 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/literal_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/literal_test.cc
@@ -16,10 +16,10 @@
 #include "src/tint/lang/core/constant/scalar.h"
 #include "src/tint/lang/core/ir/block.h"
 #include "src/tint/lang/core/ir/constant.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/core/ir/var.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
@@ -41,7 +41,7 @@
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using ProgramToIRLiteralTest = ir::ProgramTestHelper;
+using ProgramToIRLiteralTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRLiteralTest, EmitLiteral_Bool_True) {
     auto* expr = Expr(true);
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/materialize_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/materialize_test.cc
index 698f255..c47ef08 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/materialize_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/materialize_test.cc
@@ -14,16 +14,16 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/constant/scalar.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using ProgramToIRMaterializeTest = ir::ProgramTestHelper;
+using ProgramToIRMaterializeTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRMaterializeTest, EmitExpression_MaterializedCall) {
     auto* expr = Return(Call("trunc", 2.5_f));
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc
index d83002f..bfaf84a 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc
@@ -18,10 +18,10 @@
 #include "src/tint/lang/core/ir/if.h"
 #include "src/tint/lang/core/ir/loop.h"
 #include "src/tint/lang/core/ir/multi_in_block.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/core/ir/switch.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
@@ -51,7 +51,7 @@
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramTest = ir::ProgramTestHelper;
+using IR_FromProgramTest = helpers::IRProgramTest;
 
 TEST_F(IR_FromProgramTest, Func) {
     Func("f", utils::Empty, ty.void_(), utils::Empty);
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/shadowing_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/shadowing_test.cc
index 66f9963..3001208 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/shadowing_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/shadowing_test.cc
@@ -16,18 +16,18 @@
 #include "src/tint/lang/core/constant/scalar.h"
 #include "src/tint/lang/core/ir/block.h"
 #include "src/tint/lang/core/ir/constant.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/core/ir/var.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
-namespace tint::ir {
+namespace tint::wgsl {
 namespace {
 
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using ProgramToIRShadowingTest = ProgramTestHelper;
+using ProgramToIRShadowingTest = helpers::IRProgramTest;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Shadowing tests
@@ -807,4 +807,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/store_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/store_test.cc
index d0a10b5..b7b14b0 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/store_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/store_test.cc
@@ -14,16 +14,16 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/constant/scalar.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using ProgramToIRStoreTest = ir::ProgramTestHelper;
+using ProgramToIRStoreTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRStoreTest, EmitStatement_Assign) {
     GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate);
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/unary_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/unary_test.cc
index 2ff5f01..d124aa9 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/unary_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/unary_test.cc
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/lang/core/ir/program_test_helper.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 #include "src/tint/lang/core/constant/scalar.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
@@ -23,7 +23,7 @@
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using ProgramToIRUnaryTest = ir::ProgramTestHelper;
+using ProgramToIRUnaryTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRUnaryTest, EmitExpression_Unary_Not) {
     Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(false)});
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/var_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/var_test.cc
index 2ee91ad..1ecedad 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/var_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/var_test.cc
@@ -14,9 +14,9 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/constant/scalar.h"
-#include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
+#include "src/tint/lang/wgsl/helpers/ir_program_test.h"
 
 namespace tint::wgsl::reader {
 namespace {
@@ -24,7 +24,7 @@
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using ProgramToIRVarTest = ir::ProgramTestHelper;
+using ProgramToIRVarTest = helpers::IRProgramTest;
 
 TEST_F(ProgramToIRVarTest, Emit_GlobalVar_NoInit) {
     GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate);
diff --git a/src/tint/lang/core/ir/to_program_inlining_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
similarity index 97%
rename from src/tint/lang/core/ir/to_program_inlining_test.cc
rename to src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
index d446c73..7991632 100644
--- a/src/tint/lang/core/ir/to_program_inlining_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
@@ -15,14 +15,14 @@
 #include <string>
 
 #include "src/tint/lang/core/ir/disassembler.h"
-#include "src/tint/lang/core/ir/to_program.h"
-#include "src/tint/lang/core/ir/to_program_test.h"
 #include "src/tint/lang/core/type/array.h"
 #include "src/tint/lang/core/type/matrix.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h"
 #include "src/tint/lang/wgsl/writer/writer.h"
 #include "src/tint/utils/text/string.h"
 
-namespace tint::ir::test {
+namespace tint::wgsl::writer {
 namespace {
 
 using namespace tint::number_suffixes;        // NOLINT
@@ -922,7 +922,7 @@
     b.Append(fn->Block(), [&] {
         auto* v = b.Add(ty.i32(), 1_i, 2_i);
         auto* switch_ = b.Switch(3_i);
-        auto* case_ = b.Case(switch_, {Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {ir::Switch::CaseSelector{}});
         b.Append(case_, [&] { b.Return(fn, v); });
         b.Return(fn, 0_i);
     });
@@ -947,7 +947,7 @@
         auto* v_1 = b.Load(var);
         auto* v_2 = b.Add(ty.i32(), v_1, 2_i);
         auto* switch_ = b.Switch(3_i);
-        auto* case_ = b.Case(switch_, {Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {ir::Switch::CaseSelector{}});
         b.Append(case_, [&] { b.Return(fn, v_2); });
         b.Return(fn, 0_i);
     });
@@ -971,7 +971,7 @@
     b.Append(fn->Block(), [&] {
         auto* v = b.Add(ty.i32(), 1_i, 2_i);
         auto* switch_ = b.Switch(v);
-        auto* case_ = b.Case(switch_, {Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {ir::Switch::CaseSelector{}});
         b.Append(case_, [&] { b.Return(fn, 3_i); });
         b.Return(fn, 0_i);
     });
@@ -995,7 +995,7 @@
         var->SetInitializer(b.Constant(1_i));
         auto* v_1 = b.Load(var);
         auto* switch_ = b.Switch(v_1);
-        auto* case_ = b.Case(switch_, {Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {ir::Switch::CaseSelector{}});
         b.Append(case_, [&] { b.Return(fn, 3_i); });
         b.Return(fn, 0_i);
     });
@@ -1020,7 +1020,7 @@
         b.Store(var, 1_i);
         auto* load = b.Load(var);
         auto* switch_ = b.Switch(1_i);
-        auto* case_ = b.Case(switch_, {Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {ir::Switch::CaseSelector{}});
         b.Append(case_, [&] {
             b.Store(var, 2_i);
             b.ExitSwitch(switch_);
@@ -1393,4 +1393,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::test
+}  // namespace tint::wgsl::writer
diff --git a/src/tint/lang/core/ir/to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
similarity index 98%
rename from src/tint/lang/core/ir/to_program.cc
rename to src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 56497e0..671b1b4 100644
--- a/src/tint/lang/core/ir/to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/lang/core/ir/to_program.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
 
 #include <string>
 #include <tuple>
@@ -49,7 +49,6 @@
 #include "src/tint/lang/core/ir/store_vector_element.h"
 #include "src/tint/lang/core/ir/switch.h"
 #include "src/tint/lang/core/ir/swizzle.h"
-#include "src/tint/lang/core/ir/transform/rename_conflicts_wgsl.h"
 #include "src/tint/lang/core/ir/unary.h"
 #include "src/tint/lang/core/ir/unreachable.h"
 #include "src/tint/lang/core/ir/user_call.h"
@@ -64,6 +63,7 @@
 #include "src/tint/lang/core/type/sampler.h"
 #include "src/tint/lang/core/type/texture.h"
 #include "src/tint/lang/wgsl/program/program_builder.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.h"
 #include "src/tint/utils/containers/hashmap.h"
 #include "src/tint/utils/containers/predicates.h"
 #include "src/tint/utils/containers/reverse.h"
@@ -84,22 +84,22 @@
     nesting_depth_++;    \
     TINT_DEFER(nesting_depth_--)
 
-namespace tint::ir {
+namespace tint::wgsl::writer {
 
 namespace {
 
 class State {
   public:
-    explicit State(Module& m) : mod(m) {}
+    explicit State(ir::Module& m) : mod(m) {}
 
     Program Run() {
-        if (auto res = Validate(mod); !res) {
+        if (auto res = ir::Validate(mod); !res) {
             // IR module failed validation.
             b.Diagnostics() = res.Failure();
             return Program{std::move(b)};
         }
 
-        transform::RenameConflictsWGSL{}.Run(&mod);
+        RenameConflicts{}.Run(&mod);
 
         if (mod.root_block) {
             RootBlock(mod.root_block);
@@ -119,7 +119,7 @@
     };
 
     /// The source IR module
-    Module& mod;
+    ir::Module& mod;
 
     /// The target ProgramBuilder
     ProgramBuilder b;
@@ -144,10 +144,10 @@
     using ValueBinding = std::variant<VariableValue, InlinedValue, ConsumedValue>;
 
     /// IR values to their representation
-    utils::Hashmap<Value*, ValueBinding, 32> bindings_;
+    utils::Hashmap<ir::Value*, ValueBinding, 32> bindings_;
 
     /// Names for values
-    utils::Hashmap<Value*, Symbol, 32> names_;
+    utils::Hashmap<ir::Value*, Symbol, 32> names_;
 
     /// The nesting depth of the currently generated AST
     /// 0  is module scope
@@ -187,7 +187,7 @@
 
         // TODO(crbug.com/tint/1915): Properly implement this when we've fleshed out Function
         static constexpr size_t N = decltype(ast::Function::params)::static_length;
-        auto params = utils::Transform<N>(fn->Params(), [&](FunctionParam* param) {
+        auto params = utils::Transform<N>(fn->Params(), [&](ir::FunctionParam* param) {
             auto ty = Type(param->Type());
             auto name = NameFor(param);
             Bind(param, name, PtrKind::kPtr);
@@ -987,7 +987,7 @@
 
     /// @returns the AST name for the given value, creating and returning a new name on the first
     /// call.
-    Symbol NameFor(Value* value, std::string_view suggested = {}) {
+    Symbol NameFor(ir::Value* value, std::string_view suggested = {}) {
         return names_.GetOrCreate(value, [&] {
             if (!suggested.empty()) {
                 return b.Symbols().Register(suggested);
@@ -1155,8 +1155,8 @@
 
 }  // namespace
 
-Program ToProgram(Module& i) {
+Program IRToProgram(ir::Module& i) {
     return State{i}.Run();
 }
 
-}  // namespace tint::ir
+}  // namespace tint::wgsl::writer
diff --git a/src/tint/lang/core/ir/to_program.h b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
similarity index 73%
rename from src/tint/lang/core/ir/to_program.h
rename to src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
index 69d0210..e4186a4 100644
--- a/src/tint/lang/core/ir/to_program.h
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef SRC_TINT_LANG_CORE_IR_TO_PROGRAM_H_
-#define SRC_TINT_LANG_CORE_IR_TO_PROGRAM_H_
+#ifndef SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_H_
+#define SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_H_
 
 #include "src/tint/lang/wgsl/program/program.h"
 
@@ -21,14 +21,14 @@
 class Module;
 }
 
-namespace tint::ir {
+namespace tint::wgsl::writer {
 
 /// Builds a tint::Program from an ir::Module
 /// @param module the IR module
 /// @return the tint::Program.
 /// @note Check the returned Program::Diagnostics() for any errors.
-Program ToProgram(Module& module);
+Program IRToProgram(ir::Module& module);
 
-}  // namespace tint::ir
+}  // namespace tint::wgsl::writer
 
-#endif  // SRC_TINT_LANG_CORE_IR_TO_PROGRAM_H_
+#endif  // SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_H_
diff --git a/src/tint/lang/core/ir/to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
similarity index 97%
rename from src/tint/lang/core/ir/to_program_test.cc
rename to src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index bae2be9..f1b29fa 100644
--- a/src/tint/lang/core/ir/to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -16,12 +16,12 @@
 #include <string>
 
 #include "src/tint/lang/core/ir/disassembler.h"
-#include "src/tint/lang/core/ir/to_program.h"
-#include "src/tint/lang/core/ir/to_program_test.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h"
 #include "src/tint/lang/wgsl/writer/writer.h"
 #include "src/tint/utils/text/string.h"
 
-namespace tint::ir::test {
+namespace tint::wgsl::writer {
 
 using namespace tint::number_suffixes;        // NOLINT
 using namespace tint::builtin::fluent_types;  // NOLINT
@@ -32,7 +32,7 @@
     tint::ir::Disassembler d{mod};
     result.ir = d.Disassemble();
 
-    auto output_program = ToProgram(mod);
+    auto output_program = IRToProgram(mod);
     if (!output_program.IsValid()) {
         result.err = output_program.Diagnostics().str();
         result.ast = Program::printer(&output_program);
@@ -1819,7 +1819,7 @@
         v->SetInitializer(b.Constant(42_i));
 
         auto s = b.Switch(b.Load(v));
-        b.Append(b.Case(s, {Switch::CaseSelector{}}), [&] {
+        b.Append(b.Case(s, {ir::Switch::CaseSelector{}}), [&] {
             b.Call(ty.void_(), fn_a);
             b.ExitSwitch(s);
         });
@@ -1859,20 +1859,20 @@
         v->SetInitializer(b.Constant(42_i));
 
         auto s = b.Switch(b.Load(v));
-        b.Append(b.Case(s, {Switch::CaseSelector{b.Constant(0_i)}}), [&] {
+        b.Append(b.Case(s, {ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] {
             b.Call(ty.void_(), fn_a);
             b.ExitSwitch(s);
         });
         b.Append(b.Case(s,
                         {
-                            Switch::CaseSelector{b.Constant(1_i)},
-                            Switch::CaseSelector{},
+                            ir::Switch::CaseSelector{b.Constant(1_i)},
+                            ir::Switch::CaseSelector{},
                         }),
                  [&] {
                      b.Call(ty.void_(), fn_b);
                      b.ExitSwitch(s);
                  });
-        b.Append(b.Case(s, {Switch::CaseSelector{b.Constant(2_i)}}), [&] {
+        b.Append(b.Case(s, {ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] {
             b.Call(ty.void_(), fn_c);
             b.ExitSwitch(s);
         });
@@ -1918,14 +1918,14 @@
         v->SetInitializer(b.Constant(42_i));
 
         auto s = b.Switch(b.Load(v));
-        b.Append(b.Case(s, {Switch::CaseSelector{b.Constant(0_i)}}), [&] { b.Return(fn); });
+        b.Append(b.Case(s, {ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] { b.Return(fn); });
         b.Append(b.Case(s,
                         {
-                            Switch::CaseSelector{b.Constant(1_i)},
-                            Switch::CaseSelector{},
+                            ir::Switch::CaseSelector{b.Constant(1_i)},
+                            ir::Switch::CaseSelector{},
                         }),
                  [&] { b.Return(fn); });
-        b.Append(b.Case(s, {Switch::CaseSelector{b.Constant(2_i)}}), [&] { b.Return(fn); });
+        b.Append(b.Case(s, {ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] { b.Return(fn); });
 
         b.Call(ty.void_(), fn_a);
         b.Return(fn);
@@ -1972,29 +1972,29 @@
         v2->SetInitializer(b.Constant(24_i));
 
         auto s1 = b.Switch(b.Load(v1));
-        b.Append(b.Case(s1, {Switch::CaseSelector{b.Constant(0_i)}}), [&] {
+        b.Append(b.Case(s1, {ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] {
             b.Call(ty.void_(), fn_a);
             b.ExitSwitch(s1);
         });
         b.Append(b.Case(s1,
                         {
-                            Switch::CaseSelector{b.Constant(1_i)},
-                            Switch::CaseSelector{},
+                            ir::Switch::CaseSelector{b.Constant(1_i)},
+                            ir::Switch::CaseSelector{},
                         }),
                  [&] {
                      auto s2 = b.Switch(b.Load(v2));
-                     b.Append(b.Case(s2, {Switch::CaseSelector{b.Constant(0_i)}}),
+                     b.Append(b.Case(s2, {ir::Switch::CaseSelector{b.Constant(0_i)}}),
                               [&] { b.ExitSwitch(s2); });
                      b.Append(b.Case(s2,
                                      {
-                                         Switch::CaseSelector{b.Constant(1_i)},
-                                         Switch::CaseSelector{},
+                                         ir::Switch::CaseSelector{b.Constant(1_i)},
+                                         ir::Switch::CaseSelector{},
                                      }),
                               [&] { b.Return(fn); });
 
                      b.ExitSwitch(s1);
                  });
-        b.Append(b.Case(s1, {Switch::CaseSelector{b.Constant(2_i)}}), [&] {
+        b.Append(b.Case(s1, {ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] {
             b.Call(ty.void_(), fn_c);
             b.ExitSwitch(s1);
         });
@@ -2724,4 +2724,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::test
+}  // namespace tint::wgsl::writer
diff --git a/src/tint/lang/core/ir/to_program_test.h b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h
similarity index 84%
rename from src/tint/lang/core/ir/to_program_test.h
rename to src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h
index d99a5d3..d6f4e0a 100644
--- a/src/tint/lang/core/ir/to_program_test.h
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h
@@ -12,21 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef SRC_TINT_LANG_CORE_IR_TO_PROGRAM_TEST_H_
-#define SRC_TINT_LANG_CORE_IR_TO_PROGRAM_TEST_H_
+#ifndef SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_TEST_H_
+#define SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_TEST_H_
 
 #include <string>
 
 #include "src/tint/lang/core/ir/ir_test_helper.h"
 
-#if !TINT_BUILD_WGSL_WRITER
-#error "to_program_test.h requires the WGSL writer to be enabled"
-#endif
-
-namespace tint::ir::test {
+namespace tint::wgsl::writer {
 
 /// Class used for IR to Program tests
-class IRToProgramTest : public IRTestHelper {
+class IRToProgramTest : public ir::IRTestHelper {
   public:
     /// The result of Run()
     struct Result {
@@ -58,6 +54,6 @@
         }                                                                 \
     } while (false)
 
-}  // namespace tint::ir::test
+}  // namespace tint::wgsl::writer
 
-#endif  // SRC_TINT_LANG_CORE_IR_TO_PROGRAM_TEST_H_
+#endif  // SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_IR_TO_PROGRAM_TEST_H_
diff --git a/src/tint/lang/core/ir/transform/rename_conflicts_wgsl.cc b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.cc
similarity index 91%
rename from src/tint/lang/core/ir/transform/rename_conflicts_wgsl.cc
rename to src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.cc
index de0012a..d5b57f1 100644
--- a/src/tint/lang/core/ir/transform/rename_conflicts_wgsl.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.cc
@@ -22,12 +22,12 @@
 #include "src/tint/lang/core/ir/loop.h"
 #include "src/tint/lang/core/ir/module.h"
 #include "src/tint/lang/core/ir/multi_in_block.h"
-#include "src/tint/lang/core/ir/transform/rename_conflicts_wgsl.h"
 #include "src/tint/lang/core/ir/var.h"
 #include "src/tint/lang/core/type/matrix.h"
 #include "src/tint/lang/core/type/scalar.h"
 #include "src/tint/lang/core/type/struct.h"
 #include "src/tint/lang/core/type/vector.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.h"
 #include "src/tint/utils/containers/hashset.h"
 #include "src/tint/utils/containers/reverse.h"
 #include "src/tint/utils/containers/scope_stack.h"
@@ -35,15 +35,15 @@
 #include "src/tint/utils/rtti/switch.h"
 #include "src/tint/utils/text/string.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::transform::RenameConflictsWGSL);
+TINT_INSTANTIATE_TYPEINFO(tint::wgsl::writer::RenameConflicts);
 
-namespace tint::ir::transform {
+namespace tint::wgsl::writer {
 
 /// PIMPL state for the transform, for a single function.
-struct RenameConflictsWGSL::State {
+struct RenameConflicts::State {
     /// Constructor
     /// @param i the IR module
-    explicit State(Module* i) : ir(i) {}
+    explicit State(ir::Module* i) : ir(i) {}
 
     /// Processes the module, renaming all declarations that would prevent an identifier resolving
     /// to the correct declaration.
@@ -80,7 +80,7 @@
     using Scope = utils::Hashmap<std::string_view, CastableBase*, 8>;
 
     /// The IR module.
-    Module* ir = nullptr;
+    ir::Module* ir = nullptr;
 
     /// Stack of scopes
     utils::Vector<Scope, 8> scopes{};
@@ -118,7 +118,7 @@
     }
 
     /// Processes the instructions of the block
-    void Process(Block* block) {
+    void Process(ir::Block* block) {
         for (auto* inst : *block) {
             Process(inst);
         }
@@ -126,7 +126,7 @@
 
     /// Processes an instruction, ensuring that all identifier references resolve to the correct
     /// declaration. This may involve renaming of declarations in the outer scopes.
-    void Process(Instruction* inst) {
+    void Process(ir::Instruction* inst) {
         // Check resolving of operands
         for (auto* operand : inst->Operands()) {
             if (operand) {
@@ -135,7 +135,7 @@
                     EnsureResolvesTo(symbol.NameView(), operand);
                 }
                 // If the operand is a constant, then ensure that type name can be resolved.
-                if (auto* c = operand->As<Constant>()) {
+                if (auto* c = operand->As<ir::Constant>()) {
                     EnsureResolvable(c->Type());
                 }
             }
@@ -143,7 +143,7 @@
 
         Switch(
             inst,  //
-            [&](Loop* loop) {
+            [&](ir::Loop* loop) {
                 // Initializer's scope encompasses the body and continuing
                 scopes.Push(Scope{});
                 TINT_DEFER(scopes.Pop());
@@ -160,23 +160,23 @@
                     }
                 }
             },
-            [&](ControlInstruction* ctrl) {
+            [&](ir::ControlInstruction* ctrl) {
                 // Traverse into the control instruction's blocks
-                ctrl->ForeachBlock([&](Block* block) {
+                ctrl->ForeachBlock([&](ir::Block* block) {
                     scopes.Push(Scope{});
                     TINT_DEFER(scopes.Pop());
                     Process(block);
                 });
             },
-            [&](Var*) {
+            [&](ir::Var*) {
                 // Ensure the var's type is resolvable
                 EnsureResolvable(inst->Result()->Type());
             },
-            [&](Construct*) {
+            [&](ir::Construct*) {
                 // Ensure the type of a type constructor is resolvable
                 EnsureResolvable(inst->Result()->Type());
             },
-            [&](CoreBuiltinCall* call) {
+            [&](ir::CoreBuiltinCall* call) {
                 // Ensure builtin of a builtin call is resolvable
                 auto name = utils::ToString(call->Func());
                 EnsureResolvesTo(name, nullptr);
@@ -274,11 +274,11 @@
     }
 };
 
-RenameConflictsWGSL::RenameConflictsWGSL() = default;
-RenameConflictsWGSL::~RenameConflictsWGSL() = default;
+RenameConflicts::RenameConflicts() = default;
+RenameConflicts::~RenameConflicts() = default;
 
-void RenameConflictsWGSL::Run(Module* ir) const {
+void RenameConflicts::Run(ir::Module* ir) const {
     State{ir}.Process();
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::wgsl::writer
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.h b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.h
new file mode 100644
index 0000000..2033dde
--- /dev/null
+++ b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.h
@@ -0,0 +1,41 @@
+// Copyright 2023 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 SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_RENAME_CONFLICTS_H_
+#define SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_RENAME_CONFLICTS_H_
+
+#include "src/tint/lang/core/ir/transform/transform.h"
+
+namespace tint::wgsl::writer {
+
+/// RenameConflicts is a transform that renames declarations which prevent identifiers from
+/// resolving to the correct declaration, and those with identical identifiers declared in the same
+/// scope.
+class RenameConflicts final : public utils::Castable<RenameConflicts, ir::transform::Transform> {
+  public:
+    /// Constructor
+    RenameConflicts();
+    /// Destructor
+    ~RenameConflicts() override;
+
+    /// @copydoc ir::transform::Transform::Run
+    void Run(ir::Module* module) const override;
+
+  private:
+    struct State;
+};
+
+}  // namespace tint::wgsl::writer
+
+#endif  // SRC_TINT_LANG_WGSL_WRITER_IR_TO_PROGRAM_RENAME_CONFLICTS_H_
diff --git a/src/tint/lang/core/ir/transform/rename_conflicts_wgsl_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc
similarity index 83%
rename from src/tint/lang/core/ir/transform/rename_conflicts_wgsl_test.cc
rename to src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc
index 32dd8bf..95279ae 100644
--- a/src/tint/lang/core/ir/transform/rename_conflicts_wgsl_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc
@@ -12,22 +12,59 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/lang/core/ir/transform/rename_conflicts_wgsl.h"
+#include "src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.h"
 
+#include <string>
 #include <utility>
 
-#include "src/tint/lang/core/ir/transform/test_helper.h"
+#include "gtest/gtest.h"
+#include "src/tint/lang/core/ir/builder.h"
+#include "src/tint/lang/core/ir/validator.h"
 #include "src/tint/lang/core/type/matrix.h"
 
-namespace tint::ir::transform {
+namespace tint::wgsl::writer {
 namespace {
 
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using IR_RenameConflictsWGSLTest = TransformTest;
+class IRToProgramRenameConflictsTest : public testing::Test {
+  public:
+    /// Transforms the module, using the transforms `TRANSFORMS`.
+    void Run() {
+        // Validate the input IR.
+        {
+            auto res = ir::Validate(mod);
+            EXPECT_TRUE(res) << res.Failure().str();
+            if (!res) {
+                return;
+            }
+        }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_SingleNamedRootBlockVar) {
+        // Run the transforms.
+        RenameConflicts{}.Run(&mod);
+
+        // Validate the output IR.
+        auto res = ir::Validate(mod);
+        EXPECT_TRUE(res) << res.Failure().str();
+    }
+
+    /// @returns the transformed module as a disassembled string
+    std::string str() {
+        ir::Disassembler dis(mod);
+        return "\n" + dis.Disassemble();
+    }
+
+  protected:
+    /// The test IR module.
+    ir::Module mod;
+    /// The test IR builder.
+    ir::Builder b{mod};
+    /// The type manager.
+    type::Manager& ty{mod.Types()};
+};
+
+TEST_F(IRToProgramRenameConflictsTest, NoModify_SingleNamedRootBlockVar) {
     b.Append(b.RootBlock(), [&] { b.ir.SetName(b.Var(ty.ptr<private_, i32>()), "v"); });
 
     auto* src = R"(
@@ -40,12 +77,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_TwoRootBlockVarsWithSameName) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_TwoRootBlockVarsWithSameName) {
     b.Append(b.RootBlock(), [&] {
         b.ir.SetName(b.Var(ty.ptr<private_, i32>()), "v");
         b.ir.SetName(b.Var(ty.ptr<private_, u32>()), "v");
@@ -68,12 +105,12 @@
 
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_RootBlockVarAndStructWithSameName) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_RootBlockVarAndStructWithSameName) {
     auto* s = ty.Struct(b.ir.symbols.New("v"), {{b.ir.symbols.New("x"), ty.i32()}});
     b.Append(b.RootBlock(), [&] { b.ir.SetName(b.Var(ty.ptr(function, s)), "v"); });
 
@@ -100,12 +137,12 @@
 
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_RootBlockVarAndFnWithSameName) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_RootBlockVarAndFnWithSameName) {
     b.Append(b.RootBlock(), [&] { b.ir.SetName(b.Var(ty.ptr<private_, i32>()), "v"); });
 
     auto* fn = b.Function("v", ty.void_());
@@ -136,12 +173,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_RootBlockVar_ShadowedBy_FnVar) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_RootBlockVar_ShadowedBy_FnVar) {
     b.Append(b.RootBlock(), [&] {
         auto* outer = b.Var(ty.ptr<private_, i32>());
         b.ir.SetName(outer, "v");
@@ -177,12 +214,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_RootBlockVar_ShadowedBy_FnVar) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_RootBlockVar_ShadowedBy_FnVar) {
     b.Append(b.RootBlock(), [&] {
         auto* outer = b.Var(ty.ptr<private_, i32>());
         b.ir.SetName(outer, "v");
@@ -231,12 +268,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_FnVar_ShadowedBy_IfVar) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_FnVar_ShadowedBy_IfVar) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* outer = b.Var(ty.ptr<function, f32>());
@@ -277,12 +314,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_FnVar_ShadowedBy_IfVar) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_FnVar_ShadowedBy_IfVar) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* outer = b.Var(ty.ptr<function, f32>());
@@ -338,12 +375,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_LoopInitVar_ShadowedBy_LoopBodyVar) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_LoopInitVar_ShadowedBy_LoopBodyVar) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* loop = b.Loop();
@@ -390,12 +427,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_LoopInitVar_ShadowedBy_LoopBodyVar) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_LoopInitVar_ShadowedBy_LoopBodyVar) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* loop = b.Loop();
@@ -460,12 +497,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_LoopBodyVar_ShadowedBy_LoopContVar) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_LoopBodyVar_ShadowedBy_LoopContVar) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* loop = b.Loop();
@@ -516,12 +553,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_LoopBodyVar_ShadowedBy_LoopContVar) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_LoopBodyVar_ShadowedBy_LoopContVar) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* loop = b.Loop();
@@ -593,12 +630,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_BuiltinScalar_ShadowedBy_Param) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_BuiltinScalar_ShadowedBy_Param) {
     auto* fn = b.Function("f", ty.void_());
     auto* p = b.FunctionParam(ty.i32());
     b.ir.SetName(p, "i32");
@@ -628,12 +665,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_BuiltinVector_ShadowedBy_Param) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_BuiltinVector_ShadowedBy_Param) {
     auto* fn = b.Function("f", ty.void_());
     auto* p = b.FunctionParam(ty.i32());
     b.ir.SetName(p, "vec2");
@@ -656,12 +693,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_BuiltinVector_ShadowedBy_Param) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_BuiltinVector_ShadowedBy_Param) {
     auto* fn = b.Function("f", ty.void_());
     auto* p = b.FunctionParam(ty.i32());
     b.ir.SetName(p, "vec3");
@@ -691,12 +728,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_BuiltinMatrix_ShadowedBy_Param) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_BuiltinMatrix_ShadowedBy_Param) {
     auto* fn = b.Function("f", ty.void_());
     auto* p = b.FunctionParam(ty.i32());
     b.ir.SetName(p, "mat3x2");
@@ -719,12 +756,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_BuiltinMatrix_ShadowedBy_Param) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_BuiltinMatrix_ShadowedBy_Param) {
     auto* fn = b.Function("f", ty.void_());
     auto* p = b.FunctionParam(ty.i32());
     b.ir.SetName(p, "mat2x4");
@@ -754,12 +791,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_BuiltinScalar_ShadowedBy_FnVar) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_BuiltinScalar_ShadowedBy_FnVar) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* v = b.Var(ty.ptr<function, i32>());
@@ -781,12 +818,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_BuiltinScalar_ShadowedBy_FnVar) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_BuiltinScalar_ShadowedBy_FnVar) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* v = b.Var(ty.ptr<function, i32>());
@@ -816,12 +853,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_BuiltinScalar_ShadowedBy_NamedInst) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_BuiltinScalar_ShadowedBy_NamedInst) {
     auto* fn = b.Function("f", ty.i32());
     b.Append(fn->Block(), [&] {
         auto* i = b.Add(ty.i32(), 1_i, 2_i);
@@ -842,12 +879,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_BuiltinScalar_ShadowedBy_NamedInst) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_BuiltinScalar_ShadowedBy_NamedInst) {
     auto* fn = b.Function("f", ty.f32());
     b.Append(fn->Block(), [&] {
         auto* i = b.Add(ty.i32(), 1_i, 2_i);
@@ -877,12 +914,12 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_BuiltinAddressSpace_ShadowedBy_RootBlockVar) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_BuiltinAddressSpace_ShadowedBy_RootBlockVar) {
     b.Append(b.RootBlock(), [&] {  //
         b.ir.SetName(b.Var(ty.ptr<private_, i32>()), "function");
     });
@@ -897,12 +934,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_BuiltinAddressSpace_ShadowedBy_RootBlockVar) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_BuiltinAddressSpace_ShadowedBy_RootBlockVar) {
     b.Append(b.RootBlock(), [&] {  //
         b.ir.SetName(b.Var(ty.ptr<private_, i32>()), "private");
     });
@@ -922,12 +959,12 @@
 
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_BuiltinAccess_ShadowedBy_RootBlockVar) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_BuiltinAccess_ShadowedBy_RootBlockVar) {
     b.Append(b.RootBlock(), [&] {  //
         b.ir.SetName(b.Var(ty.ptr<private_, i32>()), "read");
     });
@@ -942,12 +979,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_BuiltinAccess_ShadowedBy_RootBlockVar) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_BuiltinAccess_ShadowedBy_RootBlockVar) {
     b.Append(b.RootBlock(), [&] {  //
         b.ir.SetName(b.Var(ty.ptr<private_, i32>()), "read_write");
     });
@@ -967,12 +1004,12 @@
 
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, NoModify_BuiltinFn_ShadowedBy_RootBlockVar) {
+TEST_F(IRToProgramRenameConflictsTest, NoModify_BuiltinFn_ShadowedBy_RootBlockVar) {
     b.Append(b.RootBlock(), [&] {  //
         auto* v = b.Var(ty.ptr<private_, i32>());
         b.ir.SetName(v, "min");
@@ -1000,12 +1037,12 @@
 
     auto* expect = src;
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(IR_RenameConflictsWGSLTest, Conflict_BuiltinFn_ShadowedBy_RootBlockVar) {
+TEST_F(IRToProgramRenameConflictsTest, Conflict_BuiltinFn_ShadowedBy_RootBlockVar) {
     b.Append(b.RootBlock(), [&] {  //
         auto* v = b.Var(ty.ptr<private_, i32>());
         b.ir.SetName(v, "max");
@@ -1044,10 +1081,10 @@
 }
 )";
 
-    Run<RenameConflictsWGSL>();
+    Run();
 
     EXPECT_EQ(expect, str());
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::wgsl::writer