[tint] Move FromProgram to wgsl/reader

This belongs inside the wgsl language reader subdirectory.

Bug: tint:1988
Change-Id: I64f19b736323ee8335de4e652e6f63f24410937c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/143160
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index c0444aa..6b902ff 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -1038,6 +1038,7 @@
       ":libtint_ir_builder_src",
       ":libtint_ir_src",
       ":libtint_ir_transform_src",
+      ":libtint_wgsl_reader_program_to_ir_src",
     ]
   }
 }
@@ -1067,6 +1068,27 @@
   ]
 }
 
+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",
+    ]
+    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_src") {
   sources = [
     "lang/wgsl/writer/ast_printer/ast_printer.cc",
@@ -1208,8 +1230,6 @@
 if (tint_build_ir) {
   libtint_source_set("libtint_ir_builder_src") {
     sources = [
-      "lang/core/ir/from_program.cc",
-      "lang/core/ir/from_program.h",
       "lang/core/ir/to_program.cc",
       "lang/core/ir/to_program.h",
     ]
@@ -1488,7 +1508,7 @@
       }
 
       if (tint_build_msl_writer) {
-        deps += [ ":tint_unittests_msl_writer_src" ]
+        deps += [ ":tint_unittests_msl_writer_ast_printer_src" ]
       }
 
       if (tint_build_spv_reader) {
@@ -2145,6 +2165,33 @@
     ]
   }
 
+  tint_unittests_source_set("tint_unittests_wgsl_reader_program_to_ir_src") {
+    sources = []
+    deps = []
+
+    if (tint_build_ir) {
+      sources += [
+        "lang/wgsl/reader/program_to_ir/accessor_test.cc",
+        "lang/wgsl/reader/program_to_ir/binary_test.cc",
+        "lang/wgsl/reader/program_to_ir/builtin_test.cc",
+        "lang/wgsl/reader/program_to_ir/call_test.cc",
+        "lang/wgsl/reader/program_to_ir/function_test.cc",
+        "lang/wgsl/reader/program_to_ir/let_test.cc",
+        "lang/wgsl/reader/program_to_ir/literal_test.cc",
+        "lang/wgsl/reader/program_to_ir/materialize_test.cc",
+        "lang/wgsl/reader/program_to_ir/program_to_ir_test.cc",
+        "lang/wgsl/reader/program_to_ir/shadowing_test.cc",
+        "lang/wgsl/reader/program_to_ir/store_test.cc",
+        "lang/wgsl/reader/program_to_ir/unary_test.cc",
+        "lang/wgsl/reader/program_to_ir/var_test.cc",
+      ]
+      deps += [
+        ":libtint_ir_src",
+        ":tint_unittests_ir_src",
+      ]
+    }
+  }
+
   tint_unittests_source_set("tint_unittests_wgsl_writer_src") {
     sources = [
       "lang/wgsl/writer/ast_printer/alias_type_test.cc",
@@ -2188,7 +2235,7 @@
     ]
   }
 
-  tint_unittests_source_set("tint_unittests_msl_writer_src") {
+  tint_unittests_source_set("tint_unittests_msl_writer_ast_printer_src") {
     sources = [
       "lang/msl/writer/ast_printer/array_accessor_test.cc",
       "lang/msl/writer/ast_printer/assign_test.cc",
@@ -2228,6 +2275,16 @@
       ":libtint_utils_src",
       ":tint_unittests_ast_src",
     ]
+  }
+
+  tint_unittests_source_set("tint_unittests_msl_writer_printer_src") {
+    sources = []
+
+    deps = [
+      ":libtint_msl_writer_src",
+      ":libtint_utils_src",
+      ":tint_unittests_ast_src",
+    ]
 
     if (tint_build_ir) {
       sources += [
@@ -2236,7 +2293,12 @@
         "lang/msl/writer/printer/test_helper.h",
         "lang/msl/writer/printer/type_test.cc",
       ]
-      deps += [ ":libtint_ir_src" ]
+      deps += [
+        ":libtint_ir_src",
+        ":libtint_msl_writer_src",
+        ":libtint_utils_src",
+        ":tint_unittests_ast_src",
+      ]
     }
   }
 
@@ -2380,19 +2442,6 @@
         "lang/core/ir/exit_if_test.cc",
         "lang/core/ir/exit_loop_test.cc",
         "lang/core/ir/exit_switch_test.cc",
-        "lang/core/ir/from_program_accessor_test.cc",
-        "lang/core/ir/from_program_binary_test.cc",
-        "lang/core/ir/from_program_builtin_test.cc",
-        "lang/core/ir/from_program_call_test.cc",
-        "lang/core/ir/from_program_function_test.cc",
-        "lang/core/ir/from_program_let_test.cc",
-        "lang/core/ir/from_program_literal_test.cc",
-        "lang/core/ir/from_program_materialize_test.cc",
-        "lang/core/ir/from_program_shadowing_test.cc",
-        "lang/core/ir/from_program_store_test.cc",
-        "lang/core/ir/from_program_test.cc",
-        "lang/core/ir/from_program_unary_test.cc",
-        "lang/core/ir/from_program_var_test.cc",
         "lang/core/ir/function_param_test.cc",
         "lang/core/ir/function_test.cc",
         "lang/core/ir/if_test.cc",
@@ -2428,6 +2477,7 @@
         ":libtint_builtins_src",
         ":libtint_ir_builder_src",
         ":libtint_ir_src",
+        ":libtint_wgsl_reader_program_to_ir_src",
       ]
     }
   }
@@ -2482,7 +2532,10 @@
     }
 
     if (tint_build_msl_writer) {
-      deps += [ ":tint_unittests_msl_writer_src" ]
+      deps += [
+        ":tint_unittests_msl_writer_ast_printer_src",
+        ":tint_unittests_msl_writer_printer_src",
+      ]
     }
 
     if (tint_build_hlsl_writer) {
@@ -2497,6 +2550,7 @@
       deps += [
         ":tint_unittests_ir_src",
         ":tint_unittests_ir_transform_src",
+        ":tint_unittests_wgsl_reader_program_to_ir_src",
       ]
     }
 
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index ffbaa25..98d2aee 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -634,6 +634,13 @@
     lang/wgsl/reader/reader.cc
     lang/wgsl/reader/reader.h
   )
+
+  if(${TINT_BUILD_IR})
+    list(APPEND TINT_LIB_SRCS
+      lang/wgsl/reader/program_to_ir/program_to_ir.cc
+      lang/wgsl/reader/program_to_ir/program_to_ir.h
+    )
+  endif()
 endif()
 
 if(${TINT_BUILD_SPV_WRITER})
@@ -791,8 +798,6 @@
     lang/core/ir/exit_switch.h
     lang/core/ir/exit.cc
     lang/core/ir/exit.h
-    lang/core/ir/from_program.cc
-    lang/core/ir/from_program.h
     lang/core/ir/function.cc
     lang/core/ir/function.h
     lang/core/ir/function_param.cc
@@ -1291,6 +1296,24 @@
       lang/wgsl/reader/parser/variable_stmt_test.cc
       lang/wgsl/reader/parser/while_stmt_test.cc
     )
+
+    if(${TINT_BUILD_IR})
+      list(APPEND TINT_TEST_SRCS
+        lang/wgsl/reader/program_to_ir/accessor_test.cc
+        lang/wgsl/reader/program_to_ir/binary_test.cc
+        lang/wgsl/reader/program_to_ir/builtin_test.cc
+        lang/wgsl/reader/program_to_ir/call_test.cc
+        lang/wgsl/reader/program_to_ir/function_test.cc
+        lang/wgsl/reader/program_to_ir/let_test.cc
+        lang/wgsl/reader/program_to_ir/literal_test.cc
+        lang/wgsl/reader/program_to_ir/materialize_test.cc
+        lang/wgsl/reader/program_to_ir/program_to_ir_test.cc
+        lang/wgsl/reader/program_to_ir/shadowing_test.cc
+        lang/wgsl/reader/program_to_ir/store_test.cc
+        lang/wgsl/reader/program_to_ir/unary_test.cc
+        lang/wgsl/reader/program_to_ir/var_test.cc
+      )
+    endif()
   endif()
 
   if(${TINT_BUILD_SPV_WRITER})
@@ -1602,18 +1625,6 @@
       lang/core/ir/exit_if_test.cc
       lang/core/ir/exit_loop_test.cc
       lang/core/ir/exit_switch_test.cc
-      lang/core/ir/from_program_accessor_test.cc
-      lang/core/ir/from_program_binary_test.cc
-      lang/core/ir/from_program_builtin_test.cc
-      lang/core/ir/from_program_call_test.cc
-      lang/core/ir/from_program_function_test.cc
-      lang/core/ir/from_program_let_test.cc
-      lang/core/ir/from_program_literal_test.cc
-      lang/core/ir/from_program_materialize_test.cc
-      lang/core/ir/from_program_store_test.cc
-      lang/core/ir/from_program_test.cc
-      lang/core/ir/from_program_unary_test.cc
-      lang/core/ir/from_program_var_test.cc
       lang/core/ir/function_param_test.cc
       lang/core/ir/function_test.cc
       lang/core/ir/if_test.cc
@@ -1652,12 +1663,6 @@
     )
   endif()
 
-  if (${TINT_BUILD_IR} AND ${TINT_BUILD_WGSL_READER})
-    list(APPEND TINT_TEST_SRCS
-      lang/core/ir/from_program_shadowing_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
diff --git a/src/tint/cmd/loopy.cc b/src/tint/cmd/loopy.cc
index 5617350..9bff701 100644
--- a/src/tint/cmd/loopy.cc
+++ b/src/tint/cmd/loopy.cc
@@ -19,8 +19,8 @@
 #include "tint/tint.h"
 
 #if TINT_BUILD_IR
-#include "src/tint/lang/core/ir/from_program.h"
 #include "src/tint/lang/core/ir/module.h"
+#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
 #endif  // TINT_BUILD_IR
 
 namespace {
@@ -371,14 +371,14 @@
         program = std::move(info.program);
         source_file = std::move(info.source_file);
     }
-#if TINT_BUILD_IR
+#if TINT_BUILD_WGSL_READER && TINT_BUILD_IR
     {
         uint32_t loop_count = 1;
         if (options.loop == Looper::kIRGenerate) {
             loop_count = options.loop_count;
         }
         for (uint32_t i = 0; i < loop_count; ++i) {
-            auto result = tint::ir::FromProgram(program.get());
+            auto result = tint::wgsl::reader::ProgramToIR(program.get());
             if (!result) {
                 std::cerr << "Failed to build IR from program: " << result.Failure() << std::endl;
             }
diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc
index f56d8c6..2302f12 100644
--- a/src/tint/cmd/main.cc
+++ b/src/tint/cmd/main.cc
@@ -47,10 +47,10 @@
 #include "tint/tint.h"
 
 #if TINT_BUILD_IR
-#include "src/tint/lang/core/ir/disassembler.h"  // nogncheck
-#include "src/tint/lang/core/ir/from_program.h"  // nogncheck
-#include "src/tint/lang/core/ir/module.h"        // nogncheck
-#endif                                           // TINT_BUILD_IR
+#include "src/tint/lang/core/ir/disassembler.h"                     // nogncheck
+#include "src/tint/lang/core/ir/module.h"                           // nogncheck
+#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"  // nogncheck
+#endif                                                              // TINT_BUILD_IR
 
 #if TINT_BUILD_SPV_WRITER
 #define SPV_WRITER_ONLY(x) x
@@ -1039,9 +1039,9 @@
     }
 #endif  // TINT_BUILD_SYNTAX_TREE_WRITER
 
-#if TINT_BUILD_IR
+#if TINT_BUILD_WGSL_READER && TINT_BUILD_IR
     if (options.dump_ir) {
-        auto result = tint::ir::FromProgram(program.get());
+        auto result = tint::wgsl::reader::ProgramToIR(program.get());
         if (!result) {
             std::cerr << "Failed to build IR from program: " << result.Failure() << std::endl;
         } else {
@@ -1052,7 +1052,7 @@
             }
         }
     }
-#endif  // TINT_BUILD_IR
+#endif  // TINT_BUILD_WGSL_READER && TINT_BUILD_IR
 
     tint::inspector::Inspector inspector(program.get());
     if (options.dump_inspector_bindings) {
diff --git a/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc b/src/tint/fuzzers/tint_ir_roundtrip_fuzzer.cc
index d4d8e68..964bd44 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/from_program.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/writer.h"
 
 [[noreturn]] void TintInternalCompilerErrorReporter(const tint::diag::List& diagnostics) {
@@ -71,7 +71,7 @@
         return 0;
     }
 
-    auto ir = tint::ir::FromProgram(&src);
+    auto ir = tint::wgsl::reader::ProgramToIR(&src);
     if (!ir) {
         std::cerr << ir.Failure() << std::endl;
         __builtin_trap();
diff --git a/src/tint/lang/core/ir/program_test_helper.h b/src/tint/lang/core/ir/program_test_helper.h
index b45c029..12431a9 100644
--- a/src/tint/lang/core/ir/program_test_helper.h
+++ b/src/tint/lang/core/ir/program_test_helper.h
@@ -22,9 +22,9 @@
 #include "gtest/gtest.h"
 #include "src/tint/lang/core/builtin/number.h"
 #include "src/tint/lang/core/ir/disassembler.h"
-#include "src/tint/lang/core/ir/from_program.h"
 #include "src/tint/lang/core/ir/validator.h"
 #include "src/tint/lang/wgsl/program/program_builder.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/utils/text/string_stream.h"
 
@@ -47,7 +47,7 @@
             return program.Diagnostics().str();
         }
 
-        auto result = FromProgram(&program);
+        auto result = wgsl::reader::ProgramToIR(&program);
         if (result) {
             auto validated = ir::Validate(result.Get());
             if (!validated) {
@@ -68,7 +68,7 @@
             return program.Diagnostics().str();
         }
 
-        auto result = FromProgram(&program);
+        auto result = wgsl::reader::ProgramToIR(&program);
         if (result) {
             auto validated = ir::Validate(result.Get());
             if (!validated) {
diff --git a/src/tint/lang/core/ir/to_program_roundtrip_test.cc b/src/tint/lang/core/ir/to_program_roundtrip_test.cc
index d5d68cb..1a268d3 100644
--- a/src/tint/lang/core/ir/to_program_roundtrip_test.cc
+++ b/src/tint/lang/core/ir/to_program_roundtrip_test.cc
@@ -12,9 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/lang/core/ir/from_program.h"
 #include "src/tint/lang/core/ir/program_test_helper.h"
 #include "src/tint/lang/core/ir/to_program.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/writer.h"
 #include "src/tint/utils/text/string.h"
@@ -36,7 +36,7 @@
         auto input_program = wgsl::reader::Parse(&file);
         ASSERT_TRUE(input_program.IsValid()) << input_program.Diagnostics().str();
 
-        auto ir_module = FromProgram(&input_program);
+        auto ir_module = wgsl::reader::ProgramToIR(&input_program);
         ASSERT_TRUE(ir_module) << (ir_module ? "" : ir_module.Failure());
 
         tint::ir::Disassembler d{ir_module.Get()};
diff --git a/src/tint/lang/msl/writer/writer.cc b/src/tint/lang/msl/writer/writer.cc
index ea00595..e4535c2 100644
--- a/src/tint/lang/msl/writer/writer.cc
+++ b/src/tint/lang/msl/writer/writer.cc
@@ -20,9 +20,9 @@
 #include "src/tint/lang/msl/writer/ast_printer/ast_printer.h"
 
 #if TINT_BUILD_IR
-#include "src/tint/lang/core/ir/from_program.h"        // nogncheck
-#include "src/tint/lang/msl/writer/printer/printer.h"  // nogncheck
-#endif                                                 // TINT_BUILD_IR
+#include "src/tint/lang/msl/writer/printer/printer.h"               // nogncheck
+#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"  // nogncheck
+#endif                                                              // TINT_BUILD_IR
 
 namespace tint::msl::writer {
 
@@ -36,7 +36,7 @@
 #if TINT_BUILD_IR
     if (options.use_tint_ir) {
         // Convert the AST program to an IR module.
-        auto converted = ir::FromProgram(program);
+        auto converted = wgsl::reader::ProgramToIR(program);
         if (!converted) {
             result.error = "IR converter: " + converted.Failure();
             return result;
diff --git a/src/tint/lang/spirv/writer/writer.cc b/src/tint/lang/spirv/writer/writer.cc
index 90e122a..bab2845 100644
--- a/src/tint/lang/spirv/writer/writer.cc
+++ b/src/tint/lang/spirv/writer/writer.cc
@@ -19,9 +19,9 @@
 
 #include "src/tint/lang/spirv/writer/ast_printer/ast_printer.h"
 #if TINT_BUILD_IR
-#include "src/tint/lang/core/ir/from_program.h"          // nogncheck
-#include "src/tint/lang/spirv/writer/printer/printer.h"  // nogncheck
-#endif                                                   // TINT_BUILD_IR
+#include "src/tint/lang/spirv/writer/printer/printer.h"             // nogncheck
+#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"  // nogncheck
+#endif                                                              // TINT_BUILD_IR
 
 namespace tint::spirv::writer {
 
@@ -42,7 +42,7 @@
 #if TINT_BUILD_IR
     if (options.use_tint_ir) {
         // Convert the AST program to an IR module.
-        auto converted = ir::FromProgram(program);
+        auto converted = wgsl::reader::ProgramToIR(program);
         if (!converted) {
             result.error = "IR converter: " + converted.Failure();
             return result;
diff --git a/src/tint/lang/core/ir/from_program_accessor_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/accessor_test.cc
similarity index 91%
rename from src/tint/lang/core/ir/from_program_accessor_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/accessor_test.cc
index ce03178..e7a31d4 100644
--- a/src/tint/lang/core/ir/from_program_accessor_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/accessor_test.cc
@@ -21,15 +21,15 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using IR_FromProgramAccessorTest = ProgramTestHelper;
+using ProgramToIRAccessorTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_ArraySingleIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_ArraySingleIndex) {
     // var a: array<u32, 3>
     // let b = a[2]
 
@@ -52,7 +52,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Multiple) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Multiple) {
     // let a: vec4<u32> = vec4();
     // let b = a[2]
     // let c = a[1]
@@ -78,7 +78,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_VectorSingleIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_VectorSingleIndex) {
     // var a: vec3<u32>
     // let b = a[2]
 
@@ -100,7 +100,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_ArraysMultiIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_ArraysMultiIndex) {
     // var a: array<array<f32, 4>, 3>
     // let b = a[2][3]
 
@@ -123,7 +123,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_MatrixMultiIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_MatrixMultiIndex) {
     // var a: mat3x4<f32>
     // let b = a[2][3]
 
@@ -146,7 +146,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_SingleMember) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_SingleMember) {
     // struct MyStruct { foo: i32 }
     // var a: MyStruct;
     // let b = a.foo
@@ -177,7 +177,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_MultiMember) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_MultiMember) {
     // struct Inner { bar: f32 }
     // struct Outer { a: i32, foo: Inner }
     // var a: Outer;
@@ -218,7 +218,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_Mixed) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_Mixed) {
     // struct Inner { b: i32, c: f32, bar: vec4<f32> }
     // struct Outer { a: i32, foo: array<Inner, 4> }
     // var a: array<Outer, 4>
@@ -265,7 +265,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_AssignmentLHS) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_AssignmentLHS) {
     // var a: array<u32, 4>();
     // a[2] = 0;
 
@@ -288,7 +288,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_VectorElementSwizzle) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_VectorElementSwizzle) {
     // var a: vec2<f32>
     // let b = a.y
 
@@ -310,7 +310,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_MultiElementSwizzle) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_MultiElementSwizzle) {
     // var a: vec3<f32>
     // let b = a.zyxz
 
@@ -333,7 +333,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_MultiElementSwizzleOfSwizzle) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_MultiElementSwizzleOfSwizzle) {
     // var a: vec3<f32>
     // let b = a.zyx.yy
 
@@ -357,7 +357,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Var_MultiElementSwizzle_MiddleOfChain) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Var_MultiElementSwizzle_MiddleOfChain) {
     // struct MyStruct { a: i32; foo: vec4<f32> }
     // var a: MyStruct;
     // let b = a.foo.zyx.yx[0]
@@ -395,7 +395,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_SingleIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_SingleIndex) {
     // let a: vec3<u32> = vec3()
     // let b = a[2]
     auto* a = Let("a", ty.vec3<u32>(), vec(ty.u32(), 3));
@@ -416,7 +416,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_MultiIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_MultiIndex) {
     // let a: mat3x4<f32> = mat3x4<u32>()
     // let b = a[2][3]
 
@@ -438,7 +438,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_SingleMember) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_SingleMember) {
     // struct MyStruct { foo: i32 }
     // let a: MyStruct = MyStruct();
     // let b = a.foo
@@ -468,7 +468,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_MultiMember) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_MultiMember) {
     // struct Inner { bar: f32 }
     // struct Outer { a: i32, foo: Inner }
     // let a: Outer = Outer();
@@ -508,7 +508,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_Mixed) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_Mixed) {
     // struct Outer { a: i32, foo: array<Inner, 4> }
     // struct Inner { b: i32, c: f32, bar: vec4<f32> }
     // let a: array<Outer, 4> = array();
@@ -554,7 +554,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_SingleElement) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_SingleElement) {
     // let a: vec2<f32> = vec2()
     // let b = a.y
 
@@ -576,7 +576,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_MultiElementSwizzle) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_MultiElementSwizzle) {
     // let a: vec3<f32 = vec3()>
     // let b = a.zyxz
 
@@ -598,7 +598,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_MultiElementSwizzleOfSwizzle) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_MultiElementSwizzleOfSwizzle) {
     // let a: vec3<f32> = vec3();
     // let b = a.zyx.yy
 
@@ -621,7 +621,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Let_MultiElementSwizzle_MiddleOfChain) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Let_MultiElementSwizzle_MiddleOfChain) {
     // struct MyStruct { a: i32; foo: vec4<f32> }
     // let a: MyStruct = MyStruct();
     // let b = a.foo.zyx.yx[0]
@@ -658,7 +658,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Const_AbstractVectorWithIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Const_AbstractVectorWithIndex) {
     // const v = vec3(1, 2, 3);
     // let i = 1;
     // var b = v[i];
@@ -683,7 +683,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Const_AbstractVectorWithSwizzleAndIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Const_AbstractVectorWithSwizzleAndIndex) {
     // const v = vec3(1, 2, 3);
     // let i = 1;
     // var b = v.rg[i];
@@ -708,7 +708,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramAccessorTest, Accessor_Const_ExpressionIndex) {
+TEST_F(ProgramToIRAccessorTest, Accessor_Const_ExpressionIndex) {
     // const v = vec3(1, 2, 3);
     // let i = 1;
     // var b = v.rg[i + 2 - 3];
@@ -736,4 +736,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_binary_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/binary_test.cc
similarity index 88%
rename from src/tint/lang/core/ir/from_program_binary_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/binary_test.cc
index 6d2a6e5..8376845 100644
--- a/src/tint/lang/core/ir/from_program_binary_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/binary_test.cc
@@ -18,14 +18,14 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramBinaryTest = ProgramTestHelper;
+using ProgramToIRBinaryTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Add) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Add) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Add(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -48,7 +48,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Increment) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Increment) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = Increment("v1");
     WrapInFunction(expr);
@@ -71,7 +71,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundAdd) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundAdd) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kAdd);
     WrapInFunction(expr);
@@ -94,7 +94,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Subtract) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Subtract) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Sub(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -117,7 +117,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Decrement) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Decrement) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.i32());
     auto* expr = Decrement("v1");
     WrapInFunction(expr);
@@ -140,7 +140,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundSubtract) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundSubtract) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kSubtract);
     WrapInFunction(expr);
@@ -163,7 +163,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Multiply) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Multiply) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Mul(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -186,7 +186,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundMultiply) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundMultiply) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kMultiply);
     WrapInFunction(expr);
@@ -209,7 +209,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Div) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Div) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Div(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -232,7 +232,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundDiv) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundDiv) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kDivide);
     WrapInFunction(expr);
@@ -255,7 +255,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Modulo) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Modulo) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Mod(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -278,7 +278,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundModulo) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundModulo) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kModulo);
     WrapInFunction(expr);
@@ -301,7 +301,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_And) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_And) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = And(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -324,7 +324,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundAnd) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundAnd) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.bool_());
     auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kAnd);
     WrapInFunction(expr);
@@ -347,7 +347,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Or) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Or) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Or(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -370,7 +370,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundOr) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundOr) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.bool_());
     auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kOr);
     WrapInFunction(expr);
@@ -393,7 +393,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Xor) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Xor) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Xor(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -416,7 +416,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundXor) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundXor) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kXor);
     WrapInFunction(expr);
@@ -439,7 +439,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_LogicalAnd) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_LogicalAnd) {
     Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
     auto* let = Let("logical_and", LogicalAnd(Call("my_func"), false));
     auto* expr = If(let, Block());
@@ -475,7 +475,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_LogicalOr) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_LogicalOr) {
     Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
     auto* let = Let("logical_or", LogicalOr(Call("my_func"), true));
     auto* expr = If(let, Block());
@@ -511,7 +511,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Equal) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Equal) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Equal(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -534,7 +534,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_NotEqual) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_NotEqual) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = NotEqual(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -557,7 +557,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_LessThan) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_LessThan) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = LessThan(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -580,7 +580,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_GreaterThan) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_GreaterThan) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = GreaterThan(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -603,7 +603,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_LessThanEqual) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_LessThanEqual) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = LessThanEqual(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -626,7 +626,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_GreaterThanEqual) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_GreaterThanEqual) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = GreaterThanEqual(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -649,7 +649,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_ShiftLeft) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_ShiftLeft) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Shl(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -672,7 +672,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundShiftLeft) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundShiftLeft) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftLeft);
     WrapInFunction(expr);
@@ -695,7 +695,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_ShiftRight) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_ShiftRight) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
     auto* expr = Shr(Call("my_func"), 4_u);
     WrapInFunction(expr);
@@ -718,7 +718,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_CompoundShiftRight) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_CompoundShiftRight) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.u32());
     auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftRight);
     WrapInFunction(expr);
@@ -741,7 +741,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Compound) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Compound) {
     Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
 
     auto* expr = LogicalAnd(LessThan(Call("my_func"), 2_f),
@@ -779,7 +779,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramBinaryTest, EmitExpression_Binary_Compound_WithConstEval) {
+TEST_F(ProgramToIRBinaryTest, EmitExpression_Binary_Compound_WithConstEval) {
     Func("my_func", utils::Vector{Param("p", ty.bool_())}, ty.bool_(), utils::Vector{Return(true)});
     auto* expr = Call("my_func", LogicalAnd(LessThan(2.4_f, 2_f),
                                             GreaterThan(2.5_f, Div(10_f, Mul(2.3_f, 9.4_f)))));
@@ -803,4 +803,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_builtin_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/builtin_test.cc
similarity index 88%
rename from src/tint/lang/core/ir/from_program_builtin_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/builtin_test.cc
index 0e9ee13..d24c0bd 100644
--- a/src/tint/lang/core/ir/from_program_builtin_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/builtin_test.cc
@@ -18,14 +18,14 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramBuiltinTest = ProgramTestHelper;
+using ProgramToIRBuiltinTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramBuiltinTest, EmitExpression_Builtin) {
+TEST_F(ProgramToIRBuiltinTest, EmitExpression_Builtin) {
     auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f));
     auto* expr = Call("asin", i);
     WrapInFunction(expr);
@@ -48,4 +48,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_call_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/call_test.cc
similarity index 88%
rename from src/tint/lang/core/ir/from_program_call_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/call_test.cc
index a269dec8..56f53e7 100644
--- a/src/tint/lang/core/ir/from_program_call_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/call_test.cc
@@ -18,15 +18,15 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using IR_FromProgramCallTest = ProgramTestHelper;
+using ProgramToIRCallTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramCallTest, EmitExpression_Bitcast) {
+TEST_F(ProgramToIRCallTest, EmitExpression_Bitcast) {
     Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
 
     auto* expr = Bitcast<f32>(Call("my_func"));
@@ -50,7 +50,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramCallTest, EmitStatement_Discard) {
+TEST_F(ProgramToIRCallTest, EmitStatement_Discard) {
     auto* expr = Discard();
     Func("test_function", {}, ty.void_(), expr,
          utils::Vector{
@@ -69,7 +69,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramCallTest, EmitStatement_UserFunction) {
+TEST_F(ProgramToIRCallTest, EmitStatement_UserFunction) {
     Func("my_func", utils::Vector{Param("p", ty.f32())}, ty.void_(), utils::Empty);
 
     auto* stmt = CallStmt(Call("my_func", Mul(2_a, 3_a)));
@@ -91,7 +91,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramCallTest, EmitExpression_Convert) {
+TEST_F(ProgramToIRCallTest, EmitExpression_Convert) {
     auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_i));
     auto* expr = Call<f32>(i);
     WrapInFunction(expr);
@@ -113,7 +113,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramCallTest, EmitExpression_ConstructEmpty) {
+TEST_F(ProgramToIRCallTest, EmitExpression_ConstructEmpty) {
     auto* expr = Call<vec3<f32>>();
     GlobalVar("i", builtin::AddressSpace::kPrivate, expr);
 
@@ -127,7 +127,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramCallTest, EmitExpression_Construct) {
+TEST_F(ProgramToIRCallTest, EmitExpression_Construct) {
     auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f));
     auto* expr = Call<vec3<f32>>(2_f, 3_f, i);
     WrapInFunction(expr);
@@ -150,4 +150,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_function_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/function_test.cc
similarity index 87%
rename from src/tint/lang/core/ir/from_program_function_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/function_test.cc
index eb6e27b..47d2497 100644
--- a/src/tint/lang/core/ir/from_program_function_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/function_test.cc
@@ -18,15 +18,15 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using IR_FromProgramFunctionTest = ProgramTestHelper;
+using ProgramToIRFunctionTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_Vertex) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_Vertex) {
     Func("test", utils::Empty, ty.vec4<f32>(),
          utils::Vector{Return(Call<vec4<f32>>(0_f, 0_f, 0_f, 0_f))},
          utils::Vector{Stage(ast::PipelineStage::kVertex)},
@@ -43,7 +43,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_Fragment) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_Fragment) {
     Func("test", utils::Empty, ty.void_(), utils::Empty,
          utils::Vector{Stage(ast::PipelineStage::kFragment)});
 
@@ -58,7 +58,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_Compute) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_Compute) {
     Func("test", utils::Empty, ty.void_(), utils::Empty,
          utils::Vector{Stage(ast::PipelineStage::kCompute), WorkgroupSize(8_i, 4_i, 2_i)});
 
@@ -74,7 +74,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_Return) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_Return) {
     Func("test", utils::Empty, ty.vec3<f32>(),
          utils::Vector{Return(Call<vec3<f32>>(0_f, 0_f, 0_f))}, utils::Empty);
 
@@ -89,7 +89,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_UnreachableEnd_ReturnValue) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_UnreachableEnd_ReturnValue) {
     Func("test", utils::Empty, ty.f32(),
          utils::Vector{If(true, Block(Return(0_f)), Else(Block(Return(1_f))))}, utils::Empty);
 
@@ -112,7 +112,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnPosition) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_ReturnPosition) {
     Func("test", utils::Empty, ty.vec4<f32>(),
          utils::Vector{Return(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))},
          utils::Vector{Stage(ast::PipelineStage::kVertex)},
@@ -129,7 +129,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnPositionInvariant) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_ReturnPositionInvariant) {
     Func("test", utils::Empty, ty.vec4<f32>(),
          utils::Vector{Return(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))},
          utils::Vector{Stage(ast::PipelineStage::kVertex)},
@@ -147,7 +147,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnLocation) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_ReturnLocation) {
     Func("test", utils::Empty, ty.vec4<f32>(),
          utils::Vector{Return(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))},
          utils::Vector{Stage(ast::PipelineStage::kFragment)}, utils::Vector{Location(1_i)});
@@ -164,7 +164,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnLocation_Interpolate) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_ReturnLocation_Interpolate) {
     Func("test", utils::Empty, ty.vec4<f32>(),
          utils::Vector{Return(Call<vec4<f32>>(1_f, 2_f, 3_f, 4_f))},
          utils::Vector{Stage(ast::PipelineStage::kFragment)},
@@ -184,7 +184,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnFragDepth) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_ReturnFragDepth) {
     Func("test", utils::Empty, ty.f32(), utils::Vector{Return(1_f)},
          utils::Vector{Stage(ast::PipelineStage::kFragment)},
          utils::Vector{Builtin(builtin::BuiltinValue::kFragDepth)});
@@ -200,7 +200,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramFunctionTest, EmitFunction_ReturnSampleMask) {
+TEST_F(ProgramToIRFunctionTest, EmitFunction_ReturnSampleMask) {
     Func("test", utils::Empty, ty.u32(), utils::Vector{Return(1_u)},
          utils::Vector{Stage(ast::PipelineStage::kFragment)},
          utils::Vector{Builtin(builtin::BuiltinValue::kSampleMask)});
@@ -217,4 +217,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_let_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/let_test.cc
similarity index 88%
rename from src/tint/lang/core/ir/from_program_let_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/let_test.cc
index 61b84cc..3fca4cb 100644
--- a/src/tint/lang/core/ir/from_program_let_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/let_test.cc
@@ -18,14 +18,14 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramLetTest = ProgramTestHelper;
+using ProgramToIRLetTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramLetTest, Constant) {
+TEST_F(ProgramToIRLetTest, Constant) {
     WrapInFunction(Let("a", Expr(42_i)));
 
     auto m = Build();
@@ -41,7 +41,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramLetTest, BinaryOp) {
+TEST_F(ProgramToIRLetTest, BinaryOp) {
     WrapInFunction(Let("a", Add(1_i, 2_i)));
 
     auto m = Build();
@@ -57,7 +57,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramLetTest, Chain) {
+TEST_F(ProgramToIRLetTest, Chain) {
     WrapInFunction(Let("a", Expr(1_i)),  //
                    Let("b", Expr("a")),  //
                    Let("c", Expr("b")));
@@ -78,4 +78,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_literal_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/literal_test.cc
similarity index 84%
rename from src/tint/lang/core/ir/from_program_literal_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/literal_test.cc
index 90870e0..2810cea 100644
--- a/src/tint/lang/core/ir/from_program_literal_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/literal_test.cc
@@ -21,10 +21,10 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
-Value* GlobalVarInitializer(Module& m) {
+ir::Value* GlobalVarInitializer(ir::Module& m) {
     if (m.root_block->Length() == 0u) {
         ADD_FAILURE() << "m.root_block has no instruction";
         return nullptr;
@@ -41,9 +41,9 @@
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramLiteralTest = ProgramTestHelper;
+using ProgramToIRLiteralTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_Bool_True) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_Bool_True) {
     auto* expr = Expr(true);
     GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, expr);
 
@@ -51,13 +51,13 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<Constant>(init));
-    auto* val = init->As<Constant>()->Value();
+    ASSERT_TRUE(Is<ir::Constant>(init));
+    auto* val = init->As<ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
     EXPECT_TRUE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_Bool_False) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_Bool_False) {
     auto* expr = Expr(false);
     GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, expr);
 
@@ -65,13 +65,13 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<Constant>(init));
-    auto* val = init->As<Constant>()->Value();
+    ASSERT_TRUE(Is<ir::Constant>(init));
+    auto* val = init->As<ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
     EXPECT_FALSE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_Bool_Deduped) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_Bool_Deduped) {
     GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, Expr(true));
     GlobalVar("b", ty.bool_(), builtin::AddressSpace::kPrivate, Expr(false));
     GlobalVar("c", ty.bool_(), builtin::AddressSpace::kPrivate, Expr(true));
@@ -101,7 +101,7 @@
     ASSERT_NE(var_a->Initializer(), var_b->Initializer());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_F32) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_F32) {
     auto* expr = Expr(1.2_f);
     GlobalVar("a", ty.f32(), builtin::AddressSpace::kPrivate, expr);
 
@@ -109,13 +109,13 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<Constant>(init));
-    auto* val = init->As<Constant>()->Value();
+    ASSERT_TRUE(Is<ir::Constant>(init));
+    auto* val = init->As<ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<constant::Scalar<f32>>());
     EXPECT_EQ(1.2_f, val->As<constant::Scalar<f32>>()->ValueAs<f32>());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_F32_Deduped) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_F32_Deduped) {
     GlobalVar("a", ty.f32(), builtin::AddressSpace::kPrivate, Expr(1.2_f));
     GlobalVar("b", ty.f32(), builtin::AddressSpace::kPrivate, Expr(1.25_f));
     GlobalVar("c", ty.f32(), builtin::AddressSpace::kPrivate, Expr(1.2_f));
@@ -139,7 +139,7 @@
     ASSERT_NE(var_a->Initializer(), var_b->Initializer());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_F16) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_F16) {
     Enable(builtin::Extension::kF16);
     auto* expr = Expr(1.2_h);
     GlobalVar("a", ty.f16(), builtin::AddressSpace::kPrivate, expr);
@@ -148,13 +148,13 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<Constant>(init));
-    auto* val = init->As<Constant>()->Value();
+    ASSERT_TRUE(Is<ir::Constant>(init));
+    auto* val = init->As<ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<constant::Scalar<f16>>());
     EXPECT_EQ(1.2_h, val->As<constant::Scalar<f16>>()->ValueAs<f32>());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_F16_Deduped) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_F16_Deduped) {
     Enable(builtin::Extension::kF16);
     GlobalVar("a", ty.f16(), builtin::AddressSpace::kPrivate, Expr(1.2_h));
     GlobalVar("b", ty.f16(), builtin::AddressSpace::kPrivate, Expr(1.25_h));
@@ -179,7 +179,7 @@
     ASSERT_NE(var_a->Initializer(), var_b->Initializer());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_I32) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_I32) {
     auto* expr = Expr(-2_i);
     GlobalVar("a", ty.i32(), builtin::AddressSpace::kPrivate, expr);
 
@@ -187,13 +187,13 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<Constant>(init));
-    auto* val = init->As<Constant>()->Value();
+    ASSERT_TRUE(Is<ir::Constant>(init));
+    auto* val = init->As<ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<constant::Scalar<i32>>());
     EXPECT_EQ(-2_i, val->As<constant::Scalar<i32>>()->ValueAs<f32>());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_I32_Deduped) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_I32_Deduped) {
     GlobalVar("a", ty.i32(), builtin::AddressSpace::kPrivate, Expr(-2_i));
     GlobalVar("b", ty.i32(), builtin::AddressSpace::kPrivate, Expr(2_i));
     GlobalVar("c", ty.i32(), builtin::AddressSpace::kPrivate, Expr(-2_i));
@@ -217,7 +217,7 @@
     ASSERT_NE(var_a->Initializer(), var_b->Initializer());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_U32) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_U32) {
     auto* expr = Expr(2_u);
     GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, expr);
 
@@ -225,13 +225,13 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<Constant>(init));
-    auto* val = init->As<Constant>()->Value();
+    ASSERT_TRUE(Is<ir::Constant>(init));
+    auto* val = init->As<ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<constant::Scalar<u32>>());
     EXPECT_EQ(2_u, val->As<constant::Scalar<u32>>()->ValueAs<f32>());
 }
 
-TEST_F(IR_FromProgramLiteralTest, EmitLiteral_U32_Deduped) {
+TEST_F(ProgramToIRLiteralTest, EmitLiteral_U32_Deduped) {
     GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, Expr(2_u));
     GlobalVar("b", ty.u32(), builtin::AddressSpace::kPrivate, Expr(3_u));
     GlobalVar("c", ty.u32(), builtin::AddressSpace::kPrivate, Expr(2_u));
@@ -256,4 +256,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_materialize_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/materialize_test.cc
similarity index 85%
rename from src/tint/lang/core/ir/from_program_materialize_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/materialize_test.cc
index 47d4c21..698f255 100644
--- a/src/tint/lang/core/ir/from_program_materialize_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/materialize_test.cc
@@ -18,14 +18,14 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramMaterializeTest = ProgramTestHelper;
+using ProgramToIRMaterializeTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramMaterializeTest, EmitExpression_MaterializedCall) {
+TEST_F(ProgramToIRMaterializeTest, EmitExpression_MaterializedCall) {
     auto* expr = Return(Call("trunc", 2.5_f));
 
     Func("test_function", {}, ty.f32(), expr, utils::Empty);
@@ -42,4 +42,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
similarity index 93%
rename from src/tint/lang/core/ir/from_program.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
index 845b228..649f070 100644
--- a/src/tint/lang/core/ir/from_program.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.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/from_program.h"
+#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
 
 #include <iostream>
 #include <unordered_map>
@@ -106,11 +106,11 @@
 
 using namespace tint::number_suffixes;  // NOLINT
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 
 namespace {
 
-using ResultType = utils::Result<Module, diag::List>;
+using ResultType = utils::Result<ir::Module, diag::List>;
 
 /// Impl is the private-implementation of FromProgram().
 class Impl {
@@ -130,10 +130,10 @@
     const Program* program_ = nullptr;
 
     /// The IR module being built
-    Module mod;
+    ir::Module mod;
 
     /// The IR builder being used by the impl.
-    Builder builder_{mod};
+    ir::Builder builder_{mod};
 
     // The clone context used to clone data from #program_
     constant::CloneContext clone_ctx_{
@@ -145,7 +145,7 @@
     };
 
     /// The stack of flow control instructions.
-    utils::Vector<ControlInstruction*, 8> control_stack_;
+    utils::Vector<ir::ControlInstruction*, 8> control_stack_;
 
     struct VectorRefElementAccess {
         ir::Value* vector = nullptr;
@@ -155,13 +155,13 @@
     using ValueOrVecElAccess = std::variant<ir::Value*, VectorRefElementAccess>;
 
     /// The current block for expressions.
-    Block* current_block_ = nullptr;
+    ir::Block* current_block_ = nullptr;
 
     /// The current function being processed.
-    Function* current_function_ = nullptr;
+    ir::Function* current_function_ = nullptr;
 
     /// The current stack of scopes being processed.
-    ScopeStack<Symbol, Value*> scopes_;
+    ScopeStack<Symbol, ir::Value*> scopes_;
 
     /// The diagnostic that have been raised.
     diag::List diagnostics_;
@@ -178,7 +178,7 @@
 
     class ControlStackScope : public StackScope {
       public:
-        ControlStackScope(Impl* impl, ControlInstruction* b) : StackScope(impl) {
+        ControlStackScope(Impl* impl, ir::ControlInstruction* b) : StackScope(impl) {
             impl_->control_stack_.Push(b);
         }
 
@@ -191,7 +191,7 @@
 
     bool NeedTerminator() { return current_block_ && !current_block_->HasTerminator(); }
 
-    void SetTerminator(Terminator* terminator) {
+    void SetTerminator(ir::Terminator* terminator) {
         TINT_ASSERT(IR, current_block_);
         TINT_ASSERT(IR, !current_block_->HasTerminator());
 
@@ -199,15 +199,15 @@
         current_block_ = nullptr;
     }
 
-    Instruction* FindEnclosingControl(ControlFlags flags) {
+    ir::Instruction* FindEnclosingControl(ControlFlags flags) {
         for (auto it = control_stack_.rbegin(); it != control_stack_.rend(); ++it) {
-            if ((*it)->Is<Loop>()) {
+            if ((*it)->Is<ir::Loop>()) {
                 return *it;
             }
             if (flags == ControlFlags::kExcludeSwitch) {
                 continue;
             }
-            if ((*it)->Is<Switch>()) {
+            if ((*it)->Is<ir::Switch>()) {
                 return *it;
             }
         }
@@ -289,13 +289,13 @@
         if (ast_func->IsEntryPoint()) {
             switch (ast_func->PipelineStage()) {
                 case ast::PipelineStage::kVertex:
-                    ir_func->SetStage(Function::PipelineStage::kVertex);
+                    ir_func->SetStage(ir::Function::PipelineStage::kVertex);
                     break;
                 case ast::PipelineStage::kFragment:
-                    ir_func->SetStage(Function::PipelineStage::kFragment);
+                    ir_func->SetStage(ir::Function::PipelineStage::kFragment);
                     break;
                 case ast::PipelineStage::kCompute: {
-                    ir_func->SetStage(Function::PipelineStage::kCompute);
+                    ir_func->SetStage(ir::Function::PipelineStage::kCompute);
 
                     auto wg_size = sem->WorkgroupSize();
                     ir_func->SetWorkgroupSize(wg_size[0].value(), wg_size[1].value_or(1),
@@ -325,13 +325,16 @@
                                     ->As<sem::BuiltinEnumExpression<builtin::BuiltinValue>>()) {
                             switch (ident_sem->Value()) {
                                 case builtin::BuiltinValue::kPosition:
-                                    ir_func->SetReturnBuiltin(Function::ReturnBuiltin::kPosition);
+                                    ir_func->SetReturnBuiltin(
+                                        ir::Function::ReturnBuiltin::kPosition);
                                     break;
                                 case builtin::BuiltinValue::kFragDepth:
-                                    ir_func->SetReturnBuiltin(Function::ReturnBuiltin::kFragDepth);
+                                    ir_func->SetReturnBuiltin(
+                                        ir::Function::ReturnBuiltin::kFragDepth);
                                     break;
                                 case builtin::BuiltinValue::kSampleMask:
-                                    ir_func->SetReturnBuiltin(Function::ReturnBuiltin::kSampleMask);
+                                    ir_func->SetReturnBuiltin(
+                                        ir::Function::ReturnBuiltin::kSampleMask);
                                     break;
                                 default:
                                     TINT_ICE(IR, diagnostics_)
@@ -353,7 +356,7 @@
         scopes_.Push();
         TINT_DEFER(scopes_.Pop());
 
-        utils::Vector<FunctionParam*, 1> params;
+        utils::Vector<ir::FunctionParam*, 1> params;
         for (auto* p : ast_func->params) {
             const auto* param_sem = program_->Sem().Get(p)->As<sem::Parameter>();
             auto* ty = param_sem->Type()->Clone(clone_ctx_.type_ctx);
@@ -376,38 +379,40 @@
                                     ->As<sem::BuiltinEnumExpression<builtin::BuiltinValue>>()) {
                             switch (ident_sem->Value()) {
                                 case builtin::BuiltinValue::kVertexIndex:
-                                    param->SetBuiltin(FunctionParam::Builtin::kVertexIndex);
+                                    param->SetBuiltin(ir::FunctionParam::Builtin::kVertexIndex);
                                     break;
                                 case builtin::BuiltinValue::kInstanceIndex:
-                                    param->SetBuiltin(FunctionParam::Builtin::kInstanceIndex);
+                                    param->SetBuiltin(ir::FunctionParam::Builtin::kInstanceIndex);
                                     break;
                                 case builtin::BuiltinValue::kPosition:
-                                    param->SetBuiltin(FunctionParam::Builtin::kPosition);
+                                    param->SetBuiltin(ir::FunctionParam::Builtin::kPosition);
                                     break;
                                 case builtin::BuiltinValue::kFrontFacing:
-                                    param->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+                                    param->SetBuiltin(ir::FunctionParam::Builtin::kFrontFacing);
                                     break;
                                 case builtin::BuiltinValue::kLocalInvocationId:
-                                    param->SetBuiltin(FunctionParam::Builtin::kLocalInvocationId);
+                                    param->SetBuiltin(
+                                        ir::FunctionParam::Builtin::kLocalInvocationId);
                                     break;
                                 case builtin::BuiltinValue::kLocalInvocationIndex:
                                     param->SetBuiltin(
-                                        FunctionParam::Builtin::kLocalInvocationIndex);
+                                        ir::FunctionParam::Builtin::kLocalInvocationIndex);
                                     break;
                                 case builtin::BuiltinValue::kGlobalInvocationId:
-                                    param->SetBuiltin(FunctionParam::Builtin::kGlobalInvocationId);
+                                    param->SetBuiltin(
+                                        ir::FunctionParam::Builtin::kGlobalInvocationId);
                                     break;
                                 case builtin::BuiltinValue::kWorkgroupId:
-                                    param->SetBuiltin(FunctionParam::Builtin::kWorkgroupId);
+                                    param->SetBuiltin(ir::FunctionParam::Builtin::kWorkgroupId);
                                     break;
                                 case builtin::BuiltinValue::kNumWorkgroups:
-                                    param->SetBuiltin(FunctionParam::Builtin::kNumWorkgroups);
+                                    param->SetBuiltin(ir::FunctionParam::Builtin::kNumWorkgroups);
                                     break;
                                 case builtin::BuiltinValue::kSampleIndex:
-                                    param->SetBuiltin(FunctionParam::Builtin::kSampleIndex);
+                                    param->SetBuiltin(ir::FunctionParam::Builtin::kSampleIndex);
                                     break;
                                 case builtin::BuiltinValue::kSampleMask:
-                                    param->SetBuiltin(FunctionParam::Builtin::kSampleMask);
+                                    param->SetBuiltin(ir::FunctionParam::Builtin::kSampleMask);
                                     break;
                                 default:
                                     TINT_ICE(IR, diagnostics_)
@@ -740,7 +745,7 @@
 
         const auto* sem = program_->Sem().Get(stmt);
         for (const auto* c : sem->Cases()) {
-            utils::Vector<Switch::CaseSelector, 4> selectors;
+            utils::Vector<ir::Switch::CaseSelector, 4> selectors;
             for (const auto* selector : c->Selectors()) {
                 if (selector->IsDefault()) {
                     selectors.Push({nullptr});
@@ -759,7 +764,7 @@
     }
 
     void EmitReturn(const ast::ReturnStatement* stmt) {
-        Value* ret_value = nullptr;
+        ir::Value* ret_value = nullptr;
         if (stmt->value) {
             auto ret = EmitValueExpression(stmt->value);
             if (!ret) {
@@ -778,9 +783,9 @@
         auto* current_control = FindEnclosingControl(ControlFlags::kNone);
         TINT_ASSERT(IR, current_control);
 
-        if (auto* c = current_control->As<Loop>()) {
+        if (auto* c = current_control->As<ir::Loop>()) {
             SetTerminator(builder_.ExitLoop(c));
-        } else if (auto* s = current_control->As<Switch>()) {
+        } else if (auto* s = current_control->As<ir::Switch>()) {
             SetTerminator(builder_.ExitSwitch(s));
         } else {
             TINT_UNREACHABLE(IR, diagnostics_);
@@ -791,7 +796,7 @@
         auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch);
         TINT_ASSERT(IR, current_control);
 
-        if (auto* c = current_control->As<Loop>()) {
+        if (auto* c = current_control->As<ir::Loop>()) {
             SetTerminator(builder_.Continue(c));
         } else {
             TINT_UNREACHABLE(IR, diagnostics_);
@@ -871,9 +876,9 @@
                 return *val;
             }
 
-            Value* GetValue(const ast::Expression* expr) {
+            ir::Value* GetValue(const ast::Expression* expr) {
                 auto res = Get(expr);
-                if (auto** val = std::get_if<Value*>(&res)) {
+                if (auto** val = std::get_if<ir::Value*>(&res)) {
                     return *val;
                 }
                 TINT_ICE(IR, impl.diagnostics_) << "expression did not resolve to a value";
@@ -887,7 +892,7 @@
 
             void PopBlock() { impl.current_block_ = blocks.Pop(); }
 
-            Value* EmitConstant(const ast::Expression* expr) {
+            ir::Value* EmitConstant(const ast::Expression* expr) {
                 if (auto* sem = impl.program_->Sem().GetVal(expr)) {
                     if (auto* v = sem->ConstantValue()) {
                         if (auto* cv = v->Clone(impl.clone_ctx_)) {
@@ -961,8 +966,8 @@
                 // If the object is an unnamed value (a subexpression, not a let) and is the result
                 // of another access, then we can just append the index to that access.
                 if (!impl.mod.NameOf(obj).IsValid()) {
-                    if (auto* inst_res = obj->As<InstructionResult>()) {
-                        if (auto* access = inst_res->Source()->As<Access>()) {
+                    if (auto* inst_res = obj->As<ir::InstructionResult>()) {
+                        if (auto* access = inst_res->Source()->As<ir::Access>()) {
                             access->AddIndex(index);
                             access->Result()->SetType(ty);
                             bindings_.Remove(expr->object);
@@ -994,7 +999,7 @@
                 if (!rhs) {
                     return;
                 }
-                Binary* inst = impl.BinaryOp(ty, lhs, rhs, b->op);
+                ir::Binary* inst = impl.BinaryOp(ty, lhs, rhs, b->op);
                 if (!inst) {
                     return;
                 }
@@ -1009,7 +1014,7 @@
                 }
                 auto* sem = impl.program_->Sem().Get(expr);
                 auto* ty = sem->Type()->Clone(impl.clone_ctx_.type_ctx);
-                Instruction* inst = nullptr;
+                ir::Instruction* inst = nullptr;
                 switch (expr->op) {
                     case ast::UnaryOp::kAddressOf:
                     case ast::UnaryOp::kIndirection:
@@ -1057,7 +1062,7 @@
                         return;
                     }
                 }
-                utils::Vector<Value*, 8> args;
+                utils::Vector<ir::Value*, 8> args;
                 args.Reserve(expr->args.Length());
                 // Emit the arguments
                 for (const auto* arg : expr->args) {
@@ -1075,7 +1080,7 @@
                     return;
                 }
                 auto* ty = sem->Target()->ReturnType()->Clone(impl.clone_ctx_.type_ctx);
-                Instruction* inst = nullptr;
+                ir::Instruction* inst = nullptr;
                 // If this is a builtin function, emit the specific builtin value
                 if (auto* b = sem->Target()->As<sem::Builtin>()) {
                     inst = impl.builder_.Call(ty, b->Type(), args);
@@ -1193,7 +1198,7 @@
 
             void EndShortCircuit(const ast::BinaryExpression* b) {
                 auto res = GetValue(b);
-                auto* src = res->As<InstructionResult>()->Source();
+                auto* src = res->As<ir::InstructionResult>()->Source();
                 auto* if_ = src->As<ir::If>();
                 TINT_ASSERT_OR_RETURN(IR, if_);
                 auto rhs = GetValue(b->rhs);
@@ -1261,9 +1266,9 @@
         return Emitter(*this).Emit(root);
     }
 
-    Value* EmitValueExpression(const ast::Expression* root) {
+    ir::Value* EmitValueExpression(const ast::Expression* root) {
         auto res = EmitExpression(root);
-        if (auto** val = std::get_if<Value*>(&res)) {
+        if (auto** val = std::get_if<ir::Value*>(&res)) {
             return *val;
         }
         TINT_ICE(IR, diagnostics_) << "expression did not resolve to a value";
@@ -1396,7 +1401,7 @@
 
 }  // namespace
 
-utils::Result<Module, std::string> FromProgram(const Program* program) {
+utils::Result<ir::Module, std::string> ProgramToIR(const Program* program) {
     if (!program->IsValid()) {
         return std::string("input program is not valid");
     }
@@ -1410,4 +1415,4 @@
     return r.Move();
 }
 
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program.h b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h
similarity index 77%
rename from src/tint/lang/core/ir/from_program.h
rename to src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h
index 2fbcadd..dc86b8f 100644
--- a/src/tint/lang/core/ir/from_program.h
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.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_FROM_PROGRAM_H_
-#define SRC_TINT_LANG_CORE_IR_FROM_PROGRAM_H_
+#ifndef SRC_TINT_LANG_WGSL_READER_PROGRAM_TO_IR_PROGRAM_TO_IR_H_
+#define SRC_TINT_LANG_WGSL_READER_PROGRAM_TO_IR_PROGRAM_TO_IR_H_
 
 #include <string>
 
@@ -25,7 +25,7 @@
 class Program;
 }  // namespace tint
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 
 /// Builds an ir::Module from the given Program
 /// @param program the Program to use.
@@ -35,8 +35,8 @@
 /// @note this assumes the `program.IsValid()`, and has had const-eval done so
 /// any abstract values have been calculated and converted into the relevant
 /// concrete types.
-utils::Result<Module, std::string> FromProgram(const Program* program);
+utils::Result<ir::Module, std::string> ProgramToIR(const Program* program);
 
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
 
-#endif  // SRC_TINT_LANG_CORE_IR_FROM_PROGRAM_H_
+#endif  // SRC_TINT_LANG_WGSL_READER_PROGRAM_TO_IR_PROGRAM_TO_IR_H_
diff --git a/src/tint/lang/core/ir/from_program_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc
similarity index 97%
rename from src/tint/lang/core/ir/from_program_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc
index 3492bdd..d83002f 100644
--- a/src/tint/lang/core/ir/from_program_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir_test.cc
@@ -23,7 +23,7 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 /// Looks for the instruction with the given type T.
@@ -31,7 +31,7 @@
 /// If multiple instructions are found with the type T, then an error is raised and the first is
 /// returned.
 template <typename T>
-T* FindSingleInstruction(Module& mod) {
+T* FindSingleInstruction(ir::Module& mod) {
     T* found = nullptr;
     size_t count = 0;
     for (auto* node : mod.instructions.Objects()) {
@@ -51,7 +51,7 @@
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramTest = ProgramTestHelper;
+using IR_FromProgramTest = ir::ProgramTestHelper;
 
 TEST_F(IR_FromProgramTest, Func) {
     Func("f", utils::Empty, ty.void_(), utils::Empty);
@@ -64,7 +64,7 @@
     auto* f = m->functions[0];
     ASSERT_NE(f->Block(), nullptr);
 
-    EXPECT_EQ(m->functions[0]->Stage(), Function::PipelineStage::kUndefined);
+    EXPECT_EQ(m->functions[0]->Stage(), ir::Function::PipelineStage::kUndefined);
 
     EXPECT_EQ(Disassemble(m.Get()), R"(%f = func():void -> %b1 {
   %b1 = block {
@@ -85,7 +85,7 @@
     auto* f = m->functions[0];
     ASSERT_NE(f->Block(), nullptr);
 
-    EXPECT_EQ(m->functions[0]->Stage(), Function::PipelineStage::kUndefined);
+    EXPECT_EQ(m->functions[0]->Stage(), ir::Function::PipelineStage::kUndefined);
 
     EXPECT_EQ(Disassemble(m.Get()), R"(%f = func(%a:u32):u32 -> %b1 {
   %b1 = block {
@@ -107,7 +107,7 @@
     auto* f = m->functions[0];
     ASSERT_NE(f->Block(), nullptr);
 
-    EXPECT_EQ(m->functions[0]->Stage(), Function::PipelineStage::kUndefined);
+    EXPECT_EQ(m->functions[0]->Stage(), ir::Function::PipelineStage::kUndefined);
 
     EXPECT_EQ(Disassemble(m.Get()), R"(%f = func(%a:u32, %b:i32, %c:bool):void -> %b1 {
   %b1 = block {
@@ -124,7 +124,7 @@
     auto m = Build();
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
-    EXPECT_EQ(m->functions[0]->Stage(), Function::PipelineStage::kFragment);
+    EXPECT_EQ(m->functions[0]->Stage(), ir::Function::PipelineStage::kFragment);
 }
 
 TEST_F(IR_FromProgramTest, IfStatement) {
@@ -1134,4 +1134,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_shadowing_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/shadowing_test.cc
similarity index 91%
rename from src/tint/lang/core/ir/from_program_shadowing_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/shadowing_test.cc
index c58d2e6..66f9963 100644
--- a/src/tint/lang/core/ir/from_program_shadowing_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/shadowing_test.cc
@@ -27,12 +27,12 @@
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using IR_FromProgramShadowingTest = ProgramTestHelper;
+using ProgramToIRShadowingTest = ProgramTestHelper;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Shadowing tests
 ////////////////////////////////////////////////////////////////////////////////
-TEST_F(IR_FromProgramShadowingTest, Shadow_Struct_With_FnVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_Struct_With_FnVar) {
     auto m = Build(R"(
 struct S {
   i : i32,
@@ -62,7 +62,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_Struct_With_Param) {
+TEST_F(ProgramToIRShadowingTest, Shadow_Struct_With_Param) {
     auto m = Build(R"(
 struct S {
   i : i32,
@@ -89,7 +89,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_ModVar_With_FnVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_ModVar_With_FnVar) {
     auto m = Build(R"(
 var<private> i : i32 = 1i;
 
@@ -122,7 +122,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_ModVar_With_FnLet) {
+TEST_F(ProgramToIRShadowingTest, Shadow_ModVar_With_FnLet) {
     auto m = Build(R"(
 var<private> i : i32 = 1i;
 
@@ -153,7 +153,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_IfVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_IfVar) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -193,7 +193,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_IfLet) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_IfLet) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -229,7 +229,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_WhileVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_WhileVar) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -276,7 +276,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_WhileLet) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_WhileLet) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -321,7 +321,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_ForInitVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_ForInitVar) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -365,7 +365,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_ForInitLet) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_ForInitLet) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -408,7 +408,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_ForBodyVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_ForBodyVar) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -456,7 +456,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_ForBodyLet) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_ForBodyLet) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -502,7 +502,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_LoopBodyVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_LoopBodyVar) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -557,7 +557,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_LoopBodyLet) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_LoopBodyLet) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -610,7 +610,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_LoopContinuingVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_LoopContinuingVar) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -661,7 +661,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_LoopContinuingLet) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_LoopContinuingLet) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -710,7 +710,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_SwitchCaseVar) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_SwitchCaseVar) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
@@ -759,7 +759,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramShadowingTest, Shadow_FnVar_With_SwitchCaseLet) {
+TEST_F(ProgramToIRShadowingTest, Shadow_FnVar_With_SwitchCaseLet) {
     auto m = Build(R"(
 fn f() -> i32 {
   var i : i32;
diff --git a/src/tint/lang/core/ir/from_program_store_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/store_test.cc
similarity index 88%
rename from src/tint/lang/core/ir/from_program_store_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/store_test.cc
index d9ff9bf..d0a10b5 100644
--- a/src/tint/lang/core/ir/from_program_store_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/store_test.cc
@@ -18,14 +18,14 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramStoreTest = ProgramTestHelper;
+using ProgramToIRStoreTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramStoreTest, EmitStatement_Assign) {
+TEST_F(ProgramToIRStoreTest, EmitStatement_Assign) {
     GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate);
 
     auto* expr = Assign("a", 4_u);
@@ -48,4 +48,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_unary_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/unary_test.cc
similarity index 88%
rename from src/tint/lang/core/ir/from_program_unary_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/unary_test.cc
index 6c70b92..2ff5f01 100644
--- a/src/tint/lang/core/ir/from_program_unary_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/unary_test.cc
@@ -18,14 +18,14 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_FromProgramUnaryTest = ProgramTestHelper;
+using ProgramToIRUnaryTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramUnaryTest, EmitExpression_Unary_Not) {
+TEST_F(ProgramToIRUnaryTest, EmitExpression_Unary_Not) {
     Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(false)});
     auto* expr = Not(Call("my_func"));
     WrapInFunction(expr);
@@ -48,7 +48,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramUnaryTest, EmitExpression_Unary_Not_Vector) {
+TEST_F(ProgramToIRUnaryTest, EmitExpression_Unary_Not_Vector) {
     Func("my_func", utils::Empty, ty.vec4<bool>(),
          utils::Vector{Return(vec(ty.bool_(), 4, false))});
     auto* expr = Not(Call("my_func"));
@@ -72,7 +72,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramUnaryTest, EmitExpression_Unary_Complement) {
+TEST_F(ProgramToIRUnaryTest, EmitExpression_Unary_Complement) {
     Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(1_u)});
     auto* expr = Complement(Call("my_func"));
     WrapInFunction(expr);
@@ -95,7 +95,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramUnaryTest, EmitExpression_Unary_Negation) {
+TEST_F(ProgramToIRUnaryTest, EmitExpression_Unary_Negation) {
     Func("my_func", utils::Empty, ty.i32(), utils::Vector{Return(1_i)});
     auto* expr = Negation(Call("my_func"));
     WrapInFunction(expr);
@@ -118,7 +118,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramUnaryTest, EmitExpression_Unary_AddressOf) {
+TEST_F(ProgramToIRUnaryTest, EmitExpression_Unary_AddressOf) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.i32());
 
     auto* expr = Decl(Let("v2", AddressOf("v1")));
@@ -140,7 +140,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramUnaryTest, EmitExpression_Unary_Indirection) {
+TEST_F(ProgramToIRUnaryTest, EmitExpression_Unary_Indirection) {
     GlobalVar("v1", builtin::AddressSpace::kPrivate, ty.i32());
     utils::Vector stmts = {
         Decl(Let("v3", AddressOf("v1"))),
@@ -166,4 +166,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader
diff --git a/src/tint/lang/core/ir/from_program_var_test.cc b/src/tint/lang/wgsl/reader/program_to_ir/var_test.cc
similarity index 92%
rename from src/tint/lang/core/ir/from_program_var_test.cc
rename to src/tint/lang/wgsl/reader/program_to_ir/var_test.cc
index 0dcf16c..2ee91ad 100644
--- a/src/tint/lang/core/ir/from_program_var_test.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/var_test.cc
@@ -18,15 +18,15 @@
 #include "src/tint/lang/wgsl/ast/case_selector.h"
 #include "src/tint/lang/wgsl/ast/int_literal_expression.h"
 
-namespace tint::ir {
+namespace tint::wgsl::reader {
 namespace {
 
 using namespace tint::builtin::fluent_types;  // NOLINT
 using namespace tint::number_suffixes;        // NOLINT
 
-using IR_FromProgramVarTest = ProgramTestHelper;
+using ProgramToIRVarTest = ir::ProgramTestHelper;
 
-TEST_F(IR_FromProgramVarTest, Emit_GlobalVar_NoInit) {
+TEST_F(ProgramToIRVarTest, Emit_GlobalVar_NoInit) {
     GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate);
 
     auto m = Build();
@@ -39,7 +39,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_GlobalVar_Init) {
+TEST_F(ProgramToIRVarTest, Emit_GlobalVar_Init) {
     auto* expr = Expr(2_u);
     GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, expr);
 
@@ -53,7 +53,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_GlobalVar_GroupBinding) {
+TEST_F(ProgramToIRVarTest, Emit_GlobalVar_GroupBinding) {
     GlobalVar("a", ty.u32(), builtin::AddressSpace::kStorage,
               utils::Vector{Group(2_u), Binding(3_u)});
 
@@ -67,7 +67,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_NoInit) {
+TEST_F(ProgramToIRVarTest, Emit_Var_NoInit) {
     auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction);
     WrapInFunction(a);
 
@@ -84,7 +84,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_Init_Constant) {
+TEST_F(ProgramToIRVarTest, Emit_Var_Init_Constant) {
     auto* expr = Expr(2_u);
     auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction, expr);
     WrapInFunction(a);
@@ -102,7 +102,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_Init_NonConstant) {
+TEST_F(ProgramToIRVarTest, Emit_Var_Init_NonConstant) {
     auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction);
     auto* b = Var("b", ty.u32(), builtin::AddressSpace::kFunction, Add("a", 2_u));
     WrapInFunction(a, b);
@@ -123,7 +123,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_Assign_42i) {
+TEST_F(ProgramToIRVarTest, Emit_Var_Assign_42i) {
     WrapInFunction(Var("a", ty.i32(), builtin::AddressSpace::kFunction),  //
                    Assign("a", 42_i));
 
@@ -141,7 +141,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_Assign_ArrayOfArray_EvalOrder) {
+TEST_F(ProgramToIRVarTest, Emit_Var_Assign_ArrayOfArray_EvalOrder) {
     Func("f", utils::Vector{Param("p", ty.i32())}, ty.i32(), utils::Vector{Return("p")});
 
     auto* lhs =                                 //
@@ -192,7 +192,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_Assign_ArrayOfVec_EvalOrder) {
+TEST_F(ProgramToIRVarTest, Emit_Var_Assign_ArrayOfVec_EvalOrder) {
     Func("f", utils::Vector{Param("p", ty.i32())}, ty.i32(), utils::Vector{Return("p")});
 
     auto* lhs =                             //
@@ -236,7 +236,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_Assign_ArrayOfMatrix_EvalOrder) {
+TEST_F(ProgramToIRVarTest, Emit_Var_Assign_ArrayOfMatrix_EvalOrder) {
     Func("f", utils::Vector{Param("p", ty.i32())}, ty.i32(), utils::Vector{Return("p")});
 
     auto* lhs =                                 //
@@ -286,7 +286,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_CompoundAssign_42i) {
+TEST_F(ProgramToIRVarTest, Emit_Var_CompoundAssign_42i) {
     WrapInFunction(Var("a", ty.i32(), builtin::AddressSpace::kFunction),  //
                    CompoundAssign("a", 42_i, ast::BinaryOp::kAdd));
 
@@ -306,7 +306,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_CompoundAssign_ArrayOfArray_EvalOrder) {
+TEST_F(ProgramToIRVarTest, Emit_Var_CompoundAssign_ArrayOfArray_EvalOrder) {
     Func("f", utils::Vector{Param("p", ty.i32())}, ty.i32(), utils::Vector{Return("p")});
 
     auto* lhs =                                 //
@@ -359,7 +359,7 @@
 )");
 }
 
-TEST_F(IR_FromProgramVarTest, Emit_Var_CompoundAssign_ArrayOfMatrix_EvalOrder) {
+TEST_F(ProgramToIRVarTest, Emit_Var_CompoundAssign_ArrayOfMatrix_EvalOrder) {
     Func("f", utils::Vector{Param("p", ty.i32())}, ty.i32(), utils::Vector{Return("p")});
 
     auto* lhs =                                 //
@@ -412,4 +412,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::wgsl::reader