[ir] Move ir to `tint::core:ir` namespace

Update the `tint::ir` namespace to the new `tint::core::ir` location.

Bug: tint:1718
Change-Id: Id64e070328732302b64f75e7c73449a12528e824
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/147020
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 870b885..2520816 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -1080,7 +1080,7 @@
         } else {
             auto mod = result.Move();
             if (options.dump_ir) {
-                tint::ir::Disassembler d(mod);
+                tint::core::ir::Disassembler d(mod);
                 std::cout << d.Disassemble() << std::endl;
             }
         }
diff --git a/src/tint/lang/core/ir/access.cc b/src/tint/lang/core/ir/access.cc
index 15e567e..34051ac 100644
--- a/src/tint/lang/core/ir/access.cc
+++ b/src/tint/lang/core/ir/access.cc
@@ -16,9 +16,9 @@
 
 #include <utility>
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Access);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Access);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 //! @cond Doxygen_Suppress
 Access::Access(InstructionResult* result, Value* object, VectorRef<Value*> indices) {
@@ -30,4 +30,4 @@
 Access::~Access() = default;
 //! @endcond
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/access.h b/src/tint/lang/core/ir/access.h
index e8bf796..1afdceb 100644
--- a/src/tint/lang/core/ir/access.h
+++ b/src/tint/lang/core/ir/access.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// An access instruction in the IR.
 class Access : public Castable<Access, OperandInstruction<3, 1>> {
@@ -50,6 +50,6 @@
     std::string_view FriendlyName() override { return "access"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_ACCESS_H_
diff --git a/src/tint/lang/core/ir/access_test.cc b/src/tint/lang/core/ir/access_test.cc
index b29238d..8b3c310 100644
--- a/src/tint/lang/core/ir/access_test.cc
+++ b/src/tint/lang/core/ir/access_test.cc
@@ -20,7 +20,7 @@
 
 using namespace tint::core::fluent_types;  // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_AccessTest = IRTestHelper;
@@ -61,4 +61,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/binary.cc b/src/tint/lang/core/ir/binary.cc
index 521720a..1b1bdcf 100644
--- a/src/tint/lang/core/ir/binary.cc
+++ b/src/tint/lang/core/ir/binary.cc
@@ -14,9 +14,9 @@
 
 #include "src/tint/lang/core/ir/binary.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Binary);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Binary);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Binary::Binary(InstructionResult* result, enum Kind kind, Value* lhs, Value* rhs) : kind_(kind) {
     AddOperand(Binary::kLhsOperandOffset, lhs);
@@ -64,4 +64,4 @@
     return "<unknown>";
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/binary.h b/src/tint/lang/core/ir/binary.h
index fdda0e3..f70b1a4 100644
--- a/src/tint/lang/core/ir/binary.h
+++ b/src/tint/lang/core/ir/binary.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A binary instruction in the IR.
 class Binary : public Castable<Binary, OperandInstruction<2, 1>> {
@@ -86,6 +86,6 @@
     return out << ToString(kind);
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_BINARY_H_
diff --git a/src/tint/lang/core/ir/binary_test.cc b/src/tint/lang/core/ir/binary_test.cc
index 5fbe8fd..721bf45 100644
--- a/src/tint/lang/core/ir/binary_test.cc
+++ b/src/tint/lang/core/ir/binary_test.cc
@@ -22,7 +22,7 @@
 using namespace tint::core::number_suffixes;  // NOLINT
 using namespace tint::core::fluent_types;     // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_BinaryTest = IRTestHelper;
@@ -375,4 +375,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/bitcast.cc b/src/tint/lang/core/ir/bitcast.cc
index 6efa962..cdaf695 100644
--- a/src/tint/lang/core/ir/bitcast.cc
+++ b/src/tint/lang/core/ir/bitcast.cc
@@ -14,9 +14,9 @@
 
 #include "src/tint/lang/core/ir/bitcast.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Bitcast);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Bitcast);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Bitcast::Bitcast(InstructionResult* result, Value* val) {
     AddOperand(Bitcast::kValueOperandOffset, val);
@@ -25,4 +25,4 @@
 
 Bitcast::~Bitcast() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/bitcast.h b/src/tint/lang/core/ir/bitcast.h
index 4f49742..57355c7 100644
--- a/src/tint/lang/core/ir/bitcast.h
+++ b/src/tint/lang/core/ir/bitcast.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/call.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A bitcast instruction in the IR.
 class Bitcast : public Castable<Bitcast, Call> {
@@ -39,6 +39,6 @@
     std::string_view FriendlyName() override { return "bitcast"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_BITCAST_H_
diff --git a/src/tint/lang/core/ir/bitcast_test.cc b/src/tint/lang/core/ir/bitcast_test.cc
index e847ea4..02b190d 100644
--- a/src/tint/lang/core/ir/bitcast_test.cc
+++ b/src/tint/lang/core/ir/bitcast_test.cc
@@ -23,7 +23,7 @@
 using namespace tint::core::number_suffixes;  // NOLINT
 using namespace tint::core::fluent_types;     // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_BitcastTest = IRTestHelper;
@@ -71,4 +71,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/block.cc b/src/tint/lang/core/ir/block.cc
index a7bc38f..f49c9d0 100644
--- a/src/tint/lang/core/ir/block.cc
+++ b/src/tint/lang/core/ir/block.cc
@@ -15,9 +15,9 @@
 #include "src/tint/lang/core/ir/block.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Block);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Block);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Block::Block() : Base() {}
 
@@ -158,4 +158,4 @@
     inst->next = nullptr;
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/block.h b/src/tint/lang/core/ir/block.h
index 315582c..1badce2 100644
--- a/src/tint/lang/core/ir/block.h
+++ b/src/tint/lang/core/ir/block.h
@@ -22,11 +22,11 @@
 #include "src/tint/utils/containers/vector.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class ControlInstruction;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A block of statements. The instructions in the block are a linear list of instructions to
 /// execute. The block will terminate with a Terminator instruction at the end.
@@ -143,6 +143,6 @@
     ControlInstruction* parent_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_BLOCK_H_
diff --git a/src/tint/lang/core/ir/block_param.cc b/src/tint/lang/core/ir/block_param.cc
index 4f031c4..b2a992e 100644
--- a/src/tint/lang/core/ir/block_param.cc
+++ b/src/tint/lang/core/ir/block_param.cc
@@ -15,9 +15,9 @@
 #include "src/tint/lang/core/ir/block_param.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::BlockParam);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::BlockParam);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 BlockParam::BlockParam(const core::type::Type* ty) : type_(ty) {
     TINT_ASSERT(type_ != nullptr);
@@ -25,4 +25,4 @@
 
 BlockParam::~BlockParam() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/block_param.h b/src/tint/lang/core/ir/block_param.h
index 73e7853..315aba7 100644
--- a/src/tint/lang/core/ir/block_param.h
+++ b/src/tint/lang/core/ir/block_param.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/value.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// An instruction in the IR.
 class BlockParam : public Castable<BlockParam, Value> {
@@ -36,6 +36,6 @@
     const core::type::Type* type_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_BLOCK_PARAM_H_
diff --git a/src/tint/lang/core/ir/block_param_test.cc b/src/tint/lang/core/ir/block_param_test.cc
index 001e846..8677c83 100644
--- a/src/tint/lang/core/ir/block_param_test.cc
+++ b/src/tint/lang/core/ir/block_param_test.cc
@@ -16,7 +16,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -33,4 +33,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/block_test.cc b/src/tint/lang/core/ir/block_test.cc
index e7433e7..4c7c62e 100644
--- a/src/tint/lang/core/ir/block_test.cc
+++ b/src/tint/lang/core/ir/block_test.cc
@@ -16,7 +16,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -680,4 +680,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/break_if.cc b/src/tint/lang/core/ir/break_if.cc
index 5ca3b93..56ce784 100644
--- a/src/tint/lang/core/ir/break_if.cc
+++ b/src/tint/lang/core/ir/break_if.cc
@@ -21,9 +21,9 @@
 #include "src/tint/lang/core/ir/multi_in_block.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::BreakIf);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::BreakIf);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 BreakIf::BreakIf(Value* condition, ir::Loop* loop, VectorRef<Value*> args) : loop_(loop) {
     TINT_ASSERT(loop_);
@@ -38,4 +38,4 @@
 
 BreakIf::~BreakIf() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/break_if.h b/src/tint/lang/core/ir/break_if.h
index b1de2ca..341bc70 100644
--- a/src/tint/lang/core/ir/break_if.h
+++ b/src/tint/lang/core/ir/break_if.h
@@ -20,11 +20,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Loop;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A break-if iteration instruction.
 class BreakIf : public Castable<BreakIf, Terminator> {
@@ -60,6 +60,6 @@
     ir::Loop* loop_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_BREAK_IF_H_
diff --git a/src/tint/lang/core/ir/break_if_test.cc b/src/tint/lang/core/ir/break_if_test.cc
index 38f3f88..644e2dd7 100644
--- a/src/tint/lang/core/ir/break_if_test.cc
+++ b/src/tint/lang/core/ir/break_if_test.cc
@@ -18,7 +18,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -59,4 +59,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/builder.cc b/src/tint/lang/core/ir/builder.cc
index 0cfc9d1..71419f9 100644
--- a/src/tint/lang/core/ir/builder.cc
+++ b/src/tint/lang/core/ir/builder.cc
@@ -21,7 +21,7 @@
 #include "src/tint/lang/core/type/reference.h"
 #include "src/tint/utils/ice/ice.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Builder::Builder(Module& mod) : ir(mod) {}
 
@@ -125,4 +125,4 @@
     return ir.Types().i32();
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/builder.h b/src/tint/lang/core/ir/builder.h
index 7fea105..2cc934e 100644
--- a/src/tint/lang/core/ir/builder.h
+++ b/src/tint/lang/core/ir/builder.h
@@ -71,7 +71,7 @@
 #include "src/tint/utils/macros/scoped_assignment.h"
 #include "src/tint/utils/rtti/switch.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// Builds an ir::Module
 class Builder {
@@ -953,6 +953,6 @@
     const core::type::Type* VectorPtrElementType(const core::type::Type* type);
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_BUILDER_H_
diff --git a/src/tint/lang/core/ir/builtin_call.cc b/src/tint/lang/core/ir/builtin_call.cc
index da086cb..367ddae 100644
--- a/src/tint/lang/core/ir/builtin_call.cc
+++ b/src/tint/lang/core/ir/builtin_call.cc
@@ -16,9 +16,9 @@
 
 #include <utility>
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::BuiltinCall);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::BuiltinCall);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 BuiltinCall::BuiltinCall(InstructionResult* result, VectorRef<Value*> arguments) {
     AddOperands(BuiltinCall::kArgsOperandOffset, std::move(arguments));
@@ -27,4 +27,4 @@
 
 BuiltinCall::~BuiltinCall() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/builtin_call.h b/src/tint/lang/core/ir/builtin_call.h
index 1cf0f8e..bc9d17d 100644
--- a/src/tint/lang/core/ir/builtin_call.h
+++ b/src/tint/lang/core/ir/builtin_call.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/call.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A builtin call instruction in the IR.
 class BuiltinCall : public Castable<BuiltinCall, Call> {
@@ -33,6 +33,6 @@
     ~BuiltinCall() override;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_BUILTIN_CALL_H_
diff --git a/src/tint/lang/core/ir/call.cc b/src/tint/lang/core/ir/call.cc
index f470903..d79ac69 100644
--- a/src/tint/lang/core/ir/call.cc
+++ b/src/tint/lang/core/ir/call.cc
@@ -16,9 +16,9 @@
 
 #include <utility>
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Call);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Call);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Call::Call() {
     flags_.Add(Flag::kSequenced);
@@ -26,4 +26,4 @@
 
 Call::~Call() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/call.h b/src/tint/lang/core/ir/call.h
index 3069c85..9e59ca3 100644
--- a/src/tint/lang/core/ir/call.h
+++ b/src/tint/lang/core/ir/call.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A Call instruction in the IR.
 class Call : public Castable<Call, OperandInstruction<4, 1>> {
@@ -37,6 +37,6 @@
     Call();
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_CALL_H_
diff --git a/src/tint/lang/core/ir/constant.cc b/src/tint/lang/core/ir/constant.cc
index 16159ca..2510a39 100644
--- a/src/tint/lang/core/ir/constant.cc
+++ b/src/tint/lang/core/ir/constant.cc
@@ -15,9 +15,9 @@
 #include "src/tint/lang/core/ir/constant.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Constant);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Constant);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Constant::Constant(const core::constant::Value* val) : value_(val) {
     TINT_ASSERT(value_);
@@ -25,4 +25,4 @@
 
 Constant::~Constant() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/constant.h b/src/tint/lang/core/ir/constant.h
index 6a75e91..a316e24 100644
--- a/src/tint/lang/core/ir/constant.h
+++ b/src/tint/lang/core/ir/constant.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/constant/value.h"
 #include "src/tint/lang/core/ir/value.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// Constant in the IR.
 class Constant : public Castable<Constant, Value> {
@@ -38,6 +38,6 @@
     const core::constant::Value* const value_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_CONSTANT_H_
diff --git a/src/tint/lang/core/ir/constant_test.cc b/src/tint/lang/core/ir/constant_test.cc
index 6eb57aa..73b4282 100644
--- a/src/tint/lang/core/ir/constant_test.cc
+++ b/src/tint/lang/core/ir/constant_test.cc
@@ -21,7 +21,7 @@
 using namespace tint::core::number_suffixes;  // NOLINT
 using namespace tint::core::fluent_types;     // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_ConstantTest = IRTestHelper;
@@ -114,4 +114,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/construct.cc b/src/tint/lang/core/ir/construct.cc
index bbbff97..bbdb1db 100644
--- a/src/tint/lang/core/ir/construct.cc
+++ b/src/tint/lang/core/ir/construct.cc
@@ -16,9 +16,9 @@
 
 #include <utility>
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Construct);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Construct);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Construct::Construct(InstructionResult* result, VectorRef<Value*> arguments) {
     AddOperands(Construct::kArgsOperandOffset, std::move(arguments));
@@ -27,4 +27,4 @@
 
 Construct::~Construct() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/construct.h b/src/tint/lang/core/ir/construct.h
index ce7268f..e56fd48 100644
--- a/src/tint/lang/core/ir/construct.h
+++ b/src/tint/lang/core/ir/construct.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/call.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A constructor instruction in the IR.
 class Construct : public Castable<Construct, Call> {
@@ -36,6 +36,6 @@
     std::string_view FriendlyName() override { return "construct"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_CONSTRUCT_H_
diff --git a/src/tint/lang/core/ir/construct_test.cc b/src/tint/lang/core/ir/construct_test.cc
index 8d7a277..044fb87 100644
--- a/src/tint/lang/core/ir/construct_test.cc
+++ b/src/tint/lang/core/ir/construct_test.cc
@@ -18,7 +18,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -55,4 +55,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/continue.cc b/src/tint/lang/core/ir/continue.cc
index 206b045..6fb585b 100644
--- a/src/tint/lang/core/ir/continue.cc
+++ b/src/tint/lang/core/ir/continue.cc
@@ -21,9 +21,9 @@
 #include "src/tint/lang/core/ir/multi_in_block.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Continue);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Continue);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Continue::Continue(ir::Loop* loop, VectorRef<Value*> args) : loop_(loop) {
     TINT_ASSERT(loop_);
@@ -37,4 +37,4 @@
 
 Continue::~Continue() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/continue.h b/src/tint/lang/core/ir/continue.h
index fe7a466..0c8f8b1 100644
--- a/src/tint/lang/core/ir/continue.h
+++ b/src/tint/lang/core/ir/continue.h
@@ -19,11 +19,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Loop;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A continue instruction.
 class Continue : public Castable<Continue, Terminator> {
@@ -47,6 +47,6 @@
     ir::Loop* loop_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_CONTINUE_H_
diff --git a/src/tint/lang/core/ir/continue_test.cc b/src/tint/lang/core/ir/continue_test.cc
index 7acb484..0dfe024 100644
--- a/src/tint/lang/core/ir/continue_test.cc
+++ b/src/tint/lang/core/ir/continue_test.cc
@@ -18,7 +18,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -57,4 +57,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/control_instruction.cc b/src/tint/lang/core/ir/control_instruction.cc
index a51d0de..af0670a 100644
--- a/src/tint/lang/core/ir/control_instruction.cc
+++ b/src/tint/lang/core/ir/control_instruction.cc
@@ -14,9 +14,9 @@
 
 #include "src/tint/lang/core/ir/control_instruction.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::ControlInstruction);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ControlInstruction);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 ControlInstruction::ControlInstruction() {
     flags_.Add(Flag::kSequenced);
@@ -32,4 +32,4 @@
     exits_.Remove(exit);
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/control_instruction.h b/src/tint/lang/core/ir/control_instruction.h
index 6f989c4..fe8f6ce 100644
--- a/src/tint/lang/core/ir/control_instruction.h
+++ b/src/tint/lang/core/ir/control_instruction.h
@@ -20,12 +20,12 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Block;
 class Exit;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// Base class of instructions that perform control flow to two or more blocks, owned by the
 /// ControlInstruction.
@@ -82,6 +82,6 @@
     Hashset<Exit*, 2> exits_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_CONTROL_INSTRUCTION_H_
diff --git a/src/tint/lang/core/ir/convert.cc b/src/tint/lang/core/ir/convert.cc
index ac55ec5..3f3a70b 100644
--- a/src/tint/lang/core/ir/convert.cc
+++ b/src/tint/lang/core/ir/convert.cc
@@ -16,9 +16,9 @@
 
 #include <utility>
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Convert);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Convert);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Convert::Convert(InstructionResult* result, Value* value) {
     AddOperand(Convert::kValueOperandOffset, value);
@@ -27,4 +27,4 @@
 
 Convert::~Convert() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/convert.h b/src/tint/lang/core/ir/convert.h
index aaf5849..e9bfa44 100644
--- a/src/tint/lang/core/ir/convert.h
+++ b/src/tint/lang/core/ir/convert.h
@@ -19,7 +19,7 @@
 #include "src/tint/lang/core/type/type.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A value conversion instruction in the IR.
 class Convert : public Castable<Convert, Call> {
@@ -37,6 +37,6 @@
     std::string_view FriendlyName() override { return "convert"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_CONVERT_H_
diff --git a/src/tint/lang/core/ir/convert_test.cc b/src/tint/lang/core/ir/convert_test.cc
index 40cbf2d..d239dcc 100644
--- a/src/tint/lang/core/ir/convert_test.cc
+++ b/src/tint/lang/core/ir/convert_test.cc
@@ -16,7 +16,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -42,4 +42,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/core_builtin_call.cc b/src/tint/lang/core/ir/core_builtin_call.cc
index 7bda9da..68a49c8 100644
--- a/src/tint/lang/core/ir/core_builtin_call.cc
+++ b/src/tint/lang/core/ir/core_builtin_call.cc
@@ -18,9 +18,9 @@
 
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::CoreBuiltinCall);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::CoreBuiltinCall);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 CoreBuiltinCall::CoreBuiltinCall(InstructionResult* result,
                                  core::Function func,
@@ -32,4 +32,4 @@
 
 CoreBuiltinCall::~CoreBuiltinCall() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/core_builtin_call.h b/src/tint/lang/core/ir/core_builtin_call.h
index 54dce6d..b9e1f4b 100644
--- a/src/tint/lang/core/ir/core_builtin_call.h
+++ b/src/tint/lang/core/ir/core_builtin_call.h
@@ -19,7 +19,7 @@
 #include "src/tint/lang/core/ir/builtin_call.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A core builtin call instruction in the IR.
 class CoreBuiltinCall : public Castable<CoreBuiltinCall, BuiltinCall> {
@@ -43,6 +43,6 @@
     core::Function func_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_CORE_BUILTIN_CALL_H_
diff --git a/src/tint/lang/core/ir/core_builtin_call_test.cc b/src/tint/lang/core/ir/core_builtin_call_test.cc
index b24f5a5..1a201e4 100644
--- a/src/tint/lang/core/ir/core_builtin_call_test.cc
+++ b/src/tint/lang/core/ir/core_builtin_call_test.cc
@@ -17,7 +17,7 @@
 #include "src/tint/lang/core/ir/block_param.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -74,4 +74,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/disassembler.cc b/src/tint/lang/core/ir/disassembler.cc
index 1ed9997..9ec2d35 100644
--- a/src/tint/lang/core/ir/disassembler.cc
+++ b/src/tint/lang/core/ir/disassembler.cc
@@ -60,7 +60,7 @@
 
 using namespace tint::core::fluent_types;  // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 class ScopedIndent {
@@ -931,4 +931,4 @@
     EmitLine();
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/disassembler.h b/src/tint/lang/core/ir/disassembler.h
index 39ca61d..e29a857 100644
--- a/src/tint/lang/core/ir/disassembler.h
+++ b/src/tint/lang/core/ir/disassembler.h
@@ -34,7 +34,7 @@
 class Struct;
 }
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// Helper class to disassemble the IR
 class Disassembler {
@@ -166,6 +166,6 @@
     Hashmap<Switch*, std::string, 8> switch_names_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_DISASSEMBLER_H_
diff --git a/src/tint/lang/core/ir/discard.cc b/src/tint/lang/core/ir/discard.cc
index 27b1a1e..a4aaa19 100644
--- a/src/tint/lang/core/ir/discard.cc
+++ b/src/tint/lang/core/ir/discard.cc
@@ -15,12 +15,12 @@
 #include "src/tint/lang/core/ir/discard.h"
 #include "src/tint/lang/core/type/void.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Discard);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Discard);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Discard::Discard() = default;
 
 Discard::~Discard() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/discard.h b/src/tint/lang/core/ir/discard.h
index 9ae20d8..2fb03e0 100644
--- a/src/tint/lang/core/ir/discard.h
+++ b/src/tint/lang/core/ir/discard.h
@@ -19,7 +19,7 @@
 
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A discard instruction in the IR.
 class Discard : public Castable<Discard, Call> {
@@ -32,6 +32,6 @@
     std::string_view FriendlyName() override { return "discard"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_DISCARD_H_
diff --git a/src/tint/lang/core/ir/discard_test.cc b/src/tint/lang/core/ir/discard_test.cc
index 6ad2615..2ebb80b 100644
--- a/src/tint/lang/core/ir/discard_test.cc
+++ b/src/tint/lang/core/ir/discard_test.cc
@@ -17,7 +17,7 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_DiscardTest = IRTestHelper;
@@ -35,4 +35,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/exit.cc b/src/tint/lang/core/ir/exit.cc
index 91934d1..7d5c21c 100644
--- a/src/tint/lang/core/ir/exit.cc
+++ b/src/tint/lang/core/ir/exit.cc
@@ -16,9 +16,9 @@
 
 #include "src/tint/lang/core/ir/control_instruction.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Exit);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Exit);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Exit::~Exit() = default;
 
@@ -40,4 +40,4 @@
     }
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/exit.h b/src/tint/lang/core/ir/exit.h
index 5511a38..8eb6d69 100644
--- a/src/tint/lang/core/ir/exit.h
+++ b/src/tint/lang/core/ir/exit.h
@@ -18,11 +18,11 @@
 #include "src/tint/lang/core/ir/terminator.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class ControlInstruction;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// The base class for all exit terminators.
 class Exit : public Castable<Exit, Terminator> {
@@ -44,6 +44,6 @@
     ir::ControlInstruction* ctrl_inst_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_EXIT_H_
diff --git a/src/tint/lang/core/ir/exit_if.cc b/src/tint/lang/core/ir/exit_if.cc
index a2c6415..641df8c 100644
--- a/src/tint/lang/core/ir/exit_if.cc
+++ b/src/tint/lang/core/ir/exit_if.cc
@@ -19,9 +19,9 @@
 #include "src/tint/lang/core/ir/if.h"
 #include "src/tint/lang/core/ir/multi_in_block.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::ExitIf);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ExitIf);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 ExitIf::ExitIf(ir::If* i, VectorRef<Value*> args) {
     SetIf(i);
@@ -38,4 +38,4 @@
     return static_cast<ir::If*>(ControlInstruction());
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/exit_if.h b/src/tint/lang/core/ir/exit_if.h
index f1f0346..24f97b3 100644
--- a/src/tint/lang/core/ir/exit_if.h
+++ b/src/tint/lang/core/ir/exit_if.h
@@ -19,11 +19,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class If;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A exit if instruction.
 class ExitIf : public Castable<ExitIf, Exit> {
@@ -48,6 +48,6 @@
     std::string_view FriendlyName() override { return "exit-if"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_EXIT_IF_H_
diff --git a/src/tint/lang/core/ir/exit_if_test.cc b/src/tint/lang/core/ir/exit_if_test.cc
index aff09f4..a74ae52 100644
--- a/src/tint/lang/core/ir/exit_if_test.cc
+++ b/src/tint/lang/core/ir/exit_if_test.cc
@@ -17,7 +17,7 @@
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -54,4 +54,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/exit_loop.cc b/src/tint/lang/core/ir/exit_loop.cc
index 3c19c05f..674ce88 100644
--- a/src/tint/lang/core/ir/exit_loop.cc
+++ b/src/tint/lang/core/ir/exit_loop.cc
@@ -20,9 +20,9 @@
 #include "src/tint/lang/core/ir/loop.h"
 #include "src/tint/lang/core/ir/multi_in_block.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::ExitLoop);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ExitLoop);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 ExitLoop::ExitLoop(ir::Loop* loop, VectorRef<Value*> args /* = tint::Empty */) {
     SetLoop(loop);
@@ -39,4 +39,4 @@
     return static_cast<ir::Loop*>(ControlInstruction());
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/exit_loop.h b/src/tint/lang/core/ir/exit_loop.h
index d01b8cc..5212262 100644
--- a/src/tint/lang/core/ir/exit_loop.h
+++ b/src/tint/lang/core/ir/exit_loop.h
@@ -19,11 +19,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Loop;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A exit loop instruction.
 class ExitLoop : public Castable<ExitLoop, Exit> {
@@ -48,6 +48,6 @@
     std::string_view FriendlyName() override { return "exit-loop"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_EXIT_LOOP_H_
diff --git a/src/tint/lang/core/ir/exit_loop_test.cc b/src/tint/lang/core/ir/exit_loop_test.cc
index a7b7396..0853d6b1 100644
--- a/src/tint/lang/core/ir/exit_loop_test.cc
+++ b/src/tint/lang/core/ir/exit_loop_test.cc
@@ -17,7 +17,7 @@
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -44,4 +44,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/exit_switch.cc b/src/tint/lang/core/ir/exit_switch.cc
index 6f7040f..7a70073 100644
--- a/src/tint/lang/core/ir/exit_switch.cc
+++ b/src/tint/lang/core/ir/exit_switch.cc
@@ -19,9 +19,9 @@
 #include "src/tint/lang/core/ir/multi_in_block.h"
 #include "src/tint/lang/core/ir/switch.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::ExitSwitch);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::ExitSwitch);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 ExitSwitch::ExitSwitch(ir::Switch* sw, VectorRef<Value*> args /* = tint::Empty */) {
     SetSwitch(sw);
@@ -38,4 +38,4 @@
     return static_cast<ir::Switch*>(ControlInstruction());
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/exit_switch.h b/src/tint/lang/core/ir/exit_switch.h
index df1861b..80e2a54 100644
--- a/src/tint/lang/core/ir/exit_switch.h
+++ b/src/tint/lang/core/ir/exit_switch.h
@@ -19,11 +19,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Switch;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A exit switch instruction.
 class ExitSwitch : public Castable<ExitSwitch, Exit> {
@@ -48,6 +48,6 @@
     std::string_view FriendlyName() override { return "exit-switch"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_EXIT_SWITCH_H_
diff --git a/src/tint/lang/core/ir/exit_switch_test.cc b/src/tint/lang/core/ir/exit_switch_test.cc
index f7eaaea..d476cda 100644
--- a/src/tint/lang/core/ir/exit_switch_test.cc
+++ b/src/tint/lang/core/ir/exit_switch_test.cc
@@ -17,7 +17,7 @@
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -54,4 +54,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/function.cc b/src/tint/lang/core/ir/function.cc
index b5bf71b..28a23f2 100644
--- a/src/tint/lang/core/ir/function.cc
+++ b/src/tint/lang/core/ir/function.cc
@@ -17,9 +17,9 @@
 #include "src/tint/utils/containers/predicates.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Function);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Function);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Function::Function(const core::type::Type* rt,
                    PipelineStage stage,
@@ -68,4 +68,4 @@
     return "<unknown>";
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/function.h b/src/tint/lang/core/ir/function.h
index 135abea..c24db41 100644
--- a/src/tint/lang/core/ir/function.h
+++ b/src/tint/lang/core/ir/function.h
@@ -26,12 +26,12 @@
 #include "src/tint/utils/ice/ice.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Block;
 class FunctionTerminator;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// An IR representation of a function
 class Function : public Castable<Function, Value> {
@@ -176,6 +176,6 @@
     return out << ToString(value);
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_FUNCTION_H_
diff --git a/src/tint/lang/core/ir/function_param.cc b/src/tint/lang/core/ir/function_param.cc
index a016342..1b76ff6 100644
--- a/src/tint/lang/core/ir/function_param.cc
+++ b/src/tint/lang/core/ir/function_param.cc
@@ -16,9 +16,9 @@
 
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::FunctionParam);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::FunctionParam);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 FunctionParam::FunctionParam(const core::type::Type* ty) : type_(ty) {
     TINT_ASSERT(ty != nullptr);
@@ -54,4 +54,4 @@
     return "<unknown>";
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/function_param.h b/src/tint/lang/core/ir/function_param.h
index 7848deb..b1e5145 100644
--- a/src/tint/lang/core/ir/function_param.h
+++ b/src/tint/lang/core/ir/function_param.h
@@ -24,7 +24,7 @@
 #include "src/tint/utils/rtti/castable.h"
 #include "tint/binding_point.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A function parameter in the IR.
 class FunctionParam : public Castable<FunctionParam, Value> {
@@ -118,6 +118,6 @@
     return out << ToString(value);
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_FUNCTION_PARAM_H_
diff --git a/src/tint/lang/core/ir/function_param_test.cc b/src/tint/lang/core/ir/function_param_test.cc
index 03fbd08..1ca35d7 100644
--- a/src/tint/lang/core/ir/function_param_test.cc
+++ b/src/tint/lang/core/ir/function_param_test.cc
@@ -16,7 +16,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -45,4 +45,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/function_test.cc b/src/tint/lang/core/ir/function_test.cc
index 18ac34c..862c9ab 100644
--- a/src/tint/lang/core/ir/function_test.cc
+++ b/src/tint/lang/core/ir/function_test.cc
@@ -16,7 +16,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -67,4 +67,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/if.cc b/src/tint/lang/core/ir/if.cc
index 372039f..a57adf5 100644
--- a/src/tint/lang/core/ir/if.cc
+++ b/src/tint/lang/core/ir/if.cc
@@ -14,12 +14,12 @@
 
 #include "src/tint/lang/core/ir/if.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::If);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::If);
 
 #include "src/tint/lang/core/ir/multi_in_block.h"
 #include "src/tint/utils/ice/ice.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 If::If(Value* cond, ir::Block* t, ir::Block* f) : true_(t), false_(f) {
     TINT_ASSERT(true_);
@@ -46,4 +46,4 @@
     }
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/if.h b/src/tint/lang/core/ir/if.h
index 6b93df9..1c852df 100644
--- a/src/tint/lang/core/ir/if.h
+++ b/src/tint/lang/core/ir/if.h
@@ -18,11 +18,11 @@
 #include "src/tint/lang/core/ir/control_instruction.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class MultiInBlock;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// If instruction.
 ///
@@ -72,6 +72,6 @@
     ir::Block* false_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_IF_H_
diff --git a/src/tint/lang/core/ir/if_test.cc b/src/tint/lang/core/ir/if_test.cc
index 2e889a5..8ecb742 100644
--- a/src/tint/lang/core/ir/if_test.cc
+++ b/src/tint/lang/core/ir/if_test.cc
@@ -17,7 +17,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -64,4 +64,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/instruction.cc b/src/tint/lang/core/ir/instruction.cc
index feb7a58..738e55f 100644
--- a/src/tint/lang/core/ir/instruction.cc
+++ b/src/tint/lang/core/ir/instruction.cc
@@ -17,9 +17,9 @@
 #include "src/tint/lang/core/ir/block.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Instruction);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Instruction);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Instruction::Instruction() = default;
 
@@ -60,4 +60,4 @@
     Block()->Remove(this);
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/instruction.h b/src/tint/lang/core/ir/instruction.h
index 5e1cf71..192b4d7 100644
--- a/src/tint/lang/core/ir/instruction.h
+++ b/src/tint/lang/core/ir/instruction.h
@@ -21,11 +21,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Block;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// An instruction in the IR.
 class Instruction : public Castable<Instruction> {
@@ -118,6 +118,6 @@
     tint::EnumSet<Flag> flags_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_INSTRUCTION_H_
diff --git a/src/tint/lang/core/ir/instruction_result.cc b/src/tint/lang/core/ir/instruction_result.cc
index 531f716..cc78b33 100644
--- a/src/tint/lang/core/ir/instruction_result.cc
+++ b/src/tint/lang/core/ir/instruction_result.cc
@@ -18,9 +18,9 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::InstructionResult);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::InstructionResult);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 InstructionResult::InstructionResult(const core::type::Type* type) : type_(type) {
     TINT_ASSERT(type_ != nullptr);
@@ -33,4 +33,4 @@
     Base::Destroy();
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/instruction_result.h b/src/tint/lang/core/ir/instruction_result.h
index 1b7d21a..d139a3c 100644
--- a/src/tint/lang/core/ir/instruction_result.h
+++ b/src/tint/lang/core/ir/instruction_result.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/value.h"
 #include "src/tint/utils/text/string_stream.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// An instruction result in the IR.
 class InstructionResult : public Castable<InstructionResult, Value> {
@@ -52,6 +52,6 @@
     const core::type::Type* type_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_INSTRUCTION_RESULT_H_
diff --git a/src/tint/lang/core/ir/instruction_result_test.cc b/src/tint/lang/core/ir/instruction_result_test.cc
index dbf3b67..68951b7 100644
--- a/src/tint/lang/core/ir/instruction_result_test.cc
+++ b/src/tint/lang/core/ir/instruction_result_test.cc
@@ -19,7 +19,7 @@
 using namespace tint::core::number_suffixes;  // NOLINT
 using namespace tint::core::fluent_types;     // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_InstructionResultTest = IRTestHelper;
@@ -36,4 +36,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/instruction_test.cc b/src/tint/lang/core/ir/instruction_test.cc
index 8b6ca77..4054e94 100644
--- a/src/tint/lang/core/ir/instruction_test.cc
+++ b/src/tint/lang/core/ir/instruction_test.cc
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 #include "src/tint/lang/core/ir/module.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_InstructionTest = IRTestHelper;
@@ -155,4 +155,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/intrinsic_call.cc b/src/tint/lang/core/ir/intrinsic_call.cc
index 091076a..c95227e 100644
--- a/src/tint/lang/core/ir/intrinsic_call.cc
+++ b/src/tint/lang/core/ir/intrinsic_call.cc
@@ -16,9 +16,9 @@
 
 #include <utility>
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::IntrinsicCall);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::IntrinsicCall);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 IntrinsicCall::IntrinsicCall(InstructionResult* result, enum Kind kind, VectorRef<Value*> arguments)
     : kind_(kind) {
@@ -98,4 +98,4 @@
     return "<unknown>";
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/intrinsic_call.h b/src/tint/lang/core/ir/intrinsic_call.h
index a04b3ef..3c9b0a9 100644
--- a/src/tint/lang/core/ir/intrinsic_call.h
+++ b/src/tint/lang/core/ir/intrinsic_call.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/call.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A backend intrinsic call instruction in the IR.
 class IntrinsicCall : public Castable<IntrinsicCall, Call> {
@@ -90,6 +90,6 @@
     return out << ToString(kind);
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_INTRINSIC_CALL_H_
diff --git a/src/tint/lang/core/ir/intrinsic_call_test.cc b/src/tint/lang/core/ir/intrinsic_call_test.cc
index 651b29c..9753b2f 100644
--- a/src/tint/lang/core/ir/intrinsic_call_test.cc
+++ b/src/tint/lang/core/ir/intrinsic_call_test.cc
@@ -16,7 +16,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -55,4 +55,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/ir_helper_test.h b/src/tint/lang/core/ir/ir_helper_test.h
index bdb2b6c..9e13af9 100644
--- a/src/tint/lang/core/ir/ir_helper_test.h
+++ b/src/tint/lang/core/ir/ir_helper_test.h
@@ -19,7 +19,7 @@
 #include "src/tint/lang/core/ir/builder.h"
 #include "src/tint/lang/core/ir/module.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// Helper class for testing
 template <typename BASE>
@@ -41,6 +41,6 @@
 template <typename T>
 using IRTestParamHelper = IRTestHelperBase<testing::TestWithParam<T>>;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_IR_HELPER_TEST_H_
diff --git a/src/tint/lang/core/ir/let.cc b/src/tint/lang/core/ir/let.cc
index 7309786..4e7236a 100644
--- a/src/tint/lang/core/ir/let.cc
+++ b/src/tint/lang/core/ir/let.cc
@@ -15,9 +15,9 @@
 #include "src/tint/lang/core/ir/let.h"
 #include "src/tint/lang/core/ir/store.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Let);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Let);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Let::Let(InstructionResult* result, ir::Value* value) {
     AddOperand(Let::kValueOperandOffset, value);
@@ -26,4 +26,4 @@
 
 Let::~Let() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/let.h b/src/tint/lang/core/ir/let.h
index 2aca260..51fd71b 100644
--- a/src/tint/lang/core/ir/let.h
+++ b/src/tint/lang/core/ir/let.h
@@ -17,7 +17,7 @@
 
 #include "src/tint/lang/core/ir/operand_instruction.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A no-op instruction in the IR, used to position and name a value
 class Let : public Castable<Let, OperandInstruction<1, 1>> {
@@ -38,6 +38,6 @@
     std::string_view FriendlyName() override { return "let"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_LET_H_
diff --git a/src/tint/lang/core/ir/let_test.cc b/src/tint/lang/core/ir/let_test.cc
index 4625e2c..b0f716c 100644
--- a/src/tint/lang/core/ir/let_test.cc
+++ b/src/tint/lang/core/ir/let_test.cc
@@ -20,7 +20,7 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -50,4 +50,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/load.cc b/src/tint/lang/core/ir/load.cc
index b4cbd78..d60e151 100644
--- a/src/tint/lang/core/ir/load.cc
+++ b/src/tint/lang/core/ir/load.cc
@@ -17,9 +17,9 @@
 #include "src/tint/lang/core/type/pointer.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Load);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Load);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Load::Load(InstructionResult* result, Value* from) {
     flags_.Add(Flag::kSequenced);
@@ -33,4 +33,4 @@
 
 Load::~Load() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/load.h b/src/tint/lang/core/ir/load.h
index cdfa295..ec969d1 100644
--- a/src/tint/lang/core/ir/load.h
+++ b/src/tint/lang/core/ir/load.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A load instruction in the IR.
 class Load : public Castable<Load, OperandInstruction<1, 1>> {
@@ -40,6 +40,6 @@
     std::string_view FriendlyName() override { return "load"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_LOAD_H_
diff --git a/src/tint/lang/core/ir/load_test.cc b/src/tint/lang/core/ir/load_test.cc
index 4679e26..fe4c6fe 100644
--- a/src/tint/lang/core/ir/load_test.cc
+++ b/src/tint/lang/core/ir/load_test.cc
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -70,4 +70,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/load_vector_element.cc b/src/tint/lang/core/ir/load_vector_element.cc
index eb1669e..e0969b9 100644
--- a/src/tint/lang/core/ir/load_vector_element.cc
+++ b/src/tint/lang/core/ir/load_vector_element.cc
@@ -14,9 +14,9 @@
 
 #include "src/tint/lang/core/ir/load_vector_element.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::LoadVectorElement);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::LoadVectorElement);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 LoadVectorElement::LoadVectorElement(InstructionResult* result, ir::Value* from, ir::Value* index) {
     flags_.Add(Flag::kSequenced);
@@ -28,4 +28,4 @@
 
 LoadVectorElement::~LoadVectorElement() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/load_vector_element.h b/src/tint/lang/core/ir/load_vector_element.h
index 021ae6f..f66018e 100644
--- a/src/tint/lang/core/ir/load_vector_element.h
+++ b/src/tint/lang/core/ir/load_vector_element.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A load instruction for a single vector element in the IR.
 class LoadVectorElement : public Castable<LoadVectorElement, OperandInstruction<3, 0>> {
@@ -46,6 +46,6 @@
     std::string_view FriendlyName() override { return "load-vector-element"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_LOAD_VECTOR_ELEMENT_H_
diff --git a/src/tint/lang/core/ir/load_vector_element_test.cc b/src/tint/lang/core/ir/load_vector_element_test.cc
index a3b2f2f..35a755d 100644
--- a/src/tint/lang/core/ir/load_vector_element_test.cc
+++ b/src/tint/lang/core/ir/load_vector_element_test.cc
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -59,4 +59,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/location.h b/src/tint/lang/core/ir/location.h
index 299f6bb..ce1aeb6 100644
--- a/src/tint/lang/core/ir/location.h
+++ b/src/tint/lang/core/ir/location.h
@@ -19,7 +19,7 @@
 
 #include "src/tint/lang/core/interpolation.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A function parameter in the IR.
 struct Location {
@@ -29,6 +29,6 @@
     std::optional<core::Interpolation> interpolation;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_LOCATION_H_
diff --git a/src/tint/lang/core/ir/loop.cc b/src/tint/lang/core/ir/loop.cc
index 001a270..5112718 100644
--- a/src/tint/lang/core/ir/loop.cc
+++ b/src/tint/lang/core/ir/loop.cc
@@ -19,9 +19,9 @@
 #include "src/tint/lang/core/ir/multi_in_block.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Loop);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Loop);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Loop::Loop(ir::Block* i, ir::MultiInBlock* b, ir::MultiInBlock* c)
     : initializer_(i), body_(b), continuing_(c) {
@@ -58,4 +58,4 @@
     return initializer_->HasTerminator();
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/loop.h b/src/tint/lang/core/ir/loop.h
index b2ede16..79547b6 100644
--- a/src/tint/lang/core/ir/loop.h
+++ b/src/tint/lang/core/ir/loop.h
@@ -18,11 +18,11 @@
 #include "src/tint/lang/core/ir/control_instruction.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class MultiInBlock;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// Loop instruction.
 ///
@@ -88,6 +88,6 @@
     ir::MultiInBlock* continuing_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_LOOP_H_
diff --git a/src/tint/lang/core/ir/loop_test.cc b/src/tint/lang/core/ir/loop_test.cc
index b83ec2f..1a4beb5 100644
--- a/src/tint/lang/core/ir/loop_test.cc
+++ b/src/tint/lang/core/ir/loop_test.cc
@@ -16,7 +16,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -66,4 +66,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/module.cc b/src/tint/lang/core/ir/module.cc
index c7bc576..dd96309 100644
--- a/src/tint/lang/core/ir/module.cc
+++ b/src/tint/lang/core/ir/module.cc
@@ -18,7 +18,7 @@
 
 #include "src/tint/utils/ice/ice.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Module::Module() = default;
 
@@ -52,4 +52,4 @@
     value_to_name_.Replace(value, name);
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/module.h b/src/tint/lang/core/ir/module.h
index f5b638d..386784f 100644
--- a/src/tint/lang/core/ir/module.h
+++ b/src/tint/lang/core/ir/module.h
@@ -32,7 +32,7 @@
 #include "src/tint/utils/result/result.h"
 #include "src/tint/utils/symbol/symbol_table.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// Main module class for the IR.
 class Module {
@@ -109,6 +109,6 @@
     std::unique_ptr<Source::File> disassembly_file;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_MODULE_H_
diff --git a/src/tint/lang/core/ir/module_test.cc b/src/tint/lang/core/ir/module_test.cc
index c0310f7..d267003 100644
--- a/src/tint/lang/core/ir/module_test.cc
+++ b/src/tint/lang/core/ir/module_test.cc
@@ -16,7 +16,7 @@
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 #include "src/tint/lang/core/ir/var.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -43,4 +43,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/multi_in_block.cc b/src/tint/lang/core/ir/multi_in_block.cc
index 3753feb..6916512 100644
--- a/src/tint/lang/core/ir/multi_in_block.cc
+++ b/src/tint/lang/core/ir/multi_in_block.cc
@@ -17,9 +17,9 @@
 #include "src/tint/utils/containers/predicates.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::MultiInBlock);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::MultiInBlock);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 MultiInBlock::MultiInBlock() : Base() {}
 
@@ -41,4 +41,4 @@
     }
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/multi_in_block.h b/src/tint/lang/core/ir/multi_in_block.h
index d25cc26..1fecb6d 100644
--- a/src/tint/lang/core/ir/multi_in_block.h
+++ b/src/tint/lang/core/ir/multi_in_block.h
@@ -20,11 +20,11 @@
 #include "src/tint/lang/core/ir/block.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class BlockParam;
 }
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A block that can be the target of multiple branches.
 /// MultiInBlocks maintain a list of inbound branches and a number of BlockParam parameters, used to
@@ -58,6 +58,6 @@
     Vector<ir::Terminator*, 2> inbound_sibling_branches_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_MULTI_IN_BLOCK_H_
diff --git a/src/tint/lang/core/ir/multi_in_block_test.cc b/src/tint/lang/core/ir/multi_in_block_test.cc
index 810aac2..f2145af 100644
--- a/src/tint/lang/core/ir/multi_in_block_test.cc
+++ b/src/tint/lang/core/ir/multi_in_block_test.cc
@@ -17,7 +17,7 @@
 #include "src/tint/lang/core/ir/block_param.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -36,4 +36,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/next_iteration.cc b/src/tint/lang/core/ir/next_iteration.cc
index a7d9faf..1aeb9f4 100644
--- a/src/tint/lang/core/ir/next_iteration.cc
+++ b/src/tint/lang/core/ir/next_iteration.cc
@@ -20,9 +20,9 @@
 #include "src/tint/lang/core/ir/multi_in_block.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::NextIteration);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::NextIteration);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 NextIteration::NextIteration(ir::Loop* loop, VectorRef<Value*> args /* = tint::Empty */)
     : loop_(loop) {
@@ -37,4 +37,4 @@
 
 NextIteration::~NextIteration() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/next_iteration.h b/src/tint/lang/core/ir/next_iteration.h
index b1c8bf2..2489232 100644
--- a/src/tint/lang/core/ir/next_iteration.h
+++ b/src/tint/lang/core/ir/next_iteration.h
@@ -19,11 +19,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Loop;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A next iteration instruction.
 class NextIteration : public Castable<NextIteration, Terminator> {
@@ -47,6 +47,6 @@
     ir::Loop* loop_ = nullptr;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_NEXT_ITERATION_H_
diff --git a/src/tint/lang/core/ir/next_iteration_test.cc b/src/tint/lang/core/ir/next_iteration_test.cc
index 3a9562d..3d81331 100644
--- a/src/tint/lang/core/ir/next_iteration_test.cc
+++ b/src/tint/lang/core/ir/next_iteration_test.cc
@@ -16,7 +16,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -40,4 +40,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/operand_instruction.cc b/src/tint/lang/core/ir/operand_instruction.cc
index 702e78b..afe0f17 100644
--- a/src/tint/lang/core/ir/operand_instruction.cc
+++ b/src/tint/lang/core/ir/operand_instruction.cc
@@ -14,13 +14,13 @@
 
 #include "src/tint/lang/core/ir/operand_instruction.h"
 
-using Op10 = tint::ir::OperandInstruction<1, 0>;
-using Op11 = tint::ir::OperandInstruction<1, 1>;
-using Op20 = tint::ir::OperandInstruction<2, 0>;
-using Op30 = tint::ir::OperandInstruction<3, 0>;
-using Op21 = tint::ir::OperandInstruction<2, 1>;
-using Op31 = tint::ir::OperandInstruction<3, 1>;
-using Op41 = tint::ir::OperandInstruction<4, 1>;
+using Op10 = tint::core::ir::OperandInstruction<1, 0>;
+using Op11 = tint::core::ir::OperandInstruction<1, 1>;
+using Op20 = tint::core::ir::OperandInstruction<2, 0>;
+using Op30 = tint::core::ir::OperandInstruction<3, 0>;
+using Op21 = tint::core::ir::OperandInstruction<2, 1>;
+using Op31 = tint::core::ir::OperandInstruction<3, 1>;
+using Op41 = tint::core::ir::OperandInstruction<4, 1>;
 
 TINT_INSTANTIATE_TYPEINFO(Op10);
 TINT_INSTANTIATE_TYPEINFO(Op11);
@@ -30,4 +30,4 @@
 TINT_INSTANTIATE_TYPEINFO(Op31);
 TINT_INSTANTIATE_TYPEINFO(Op41);
 
-namespace tint::ir {}  // namespace tint::ir
+namespace tint::core::ir {}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/operand_instruction.h b/src/tint/lang/core/ir/operand_instruction.h
index abc81e3..49c2c85 100644
--- a/src/tint/lang/core/ir/operand_instruction.h
+++ b/src/tint/lang/core/ir/operand_instruction.h
@@ -21,7 +21,7 @@
 #include "src/tint/lang/core/ir/instruction_result.h"
 #include "src/tint/utils/ice/ice.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// An instruction in the IR that expects one or more operands.
 /// @tparam N the number of operands before spilling to the heap
@@ -32,7 +32,7 @@
     /// Destructor
     ~OperandInstruction() override = default;
 
-    /// @copydoc tint::ir::Value::Destroy
+    /// @copydoc tint::core::ir::Value::Destroy
     void Destroy() override {
         ClearOperands();
         Instruction::Destroy();
@@ -136,6 +136,6 @@
     Vector<ir::InstructionResult*, R> results_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_OPERAND_INSTRUCTION_H_
diff --git a/src/tint/lang/core/ir/operand_instruction_test.cc b/src/tint/lang/core/ir/operand_instruction_test.cc
index 1a9a926..8653b4e 100644
--- a/src/tint/lang/core/ir/operand_instruction_test.cc
+++ b/src/tint/lang/core/ir/operand_instruction_test.cc
@@ -15,7 +15,7 @@
 #include "gmock/gmock.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -62,4 +62,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/return.cc b/src/tint/lang/core/ir/return.cc
index 4280fe2..aac03dc 100644
--- a/src/tint/lang/core/ir/return.cc
+++ b/src/tint/lang/core/ir/return.cc
@@ -18,9 +18,9 @@
 
 #include "src/tint/lang/core/ir/function.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Return);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Return);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Return::Return(Function* func) {
     AddOperand(Return::kFunctionOperandOffset, func);
@@ -33,4 +33,4 @@
 
 Return::~Return() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/return.h b/src/tint/lang/core/ir/return.h
index d7d7b75..883f427 100644
--- a/src/tint/lang/core/ir/return.h
+++ b/src/tint/lang/core/ir/return.h
@@ -19,11 +19,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Function;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A return instruction.
 class Return : public Castable<Return, Terminator> {
@@ -66,6 +66,6 @@
     std::string_view FriendlyName() override { return "return"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_RETURN_H_
diff --git a/src/tint/lang/core/ir/return_test.cc b/src/tint/lang/core/ir/return_test.cc
index 31c33cd..f08c4b5 100644
--- a/src/tint/lang/core/ir/return_test.cc
+++ b/src/tint/lang/core/ir/return_test.cc
@@ -18,7 +18,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -63,4 +63,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/store.cc b/src/tint/lang/core/ir/store.cc
index 648e9f2..c333ede 100644
--- a/src/tint/lang/core/ir/store.cc
+++ b/src/tint/lang/core/ir/store.cc
@@ -14,9 +14,9 @@
 
 #include "src/tint/lang/core/ir/store.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Store);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Store);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Store::Store(Value* to, Value* from) {
     flags_.Add(Flag::kSequenced);
@@ -27,4 +27,4 @@
 
 Store::~Store() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/store.h b/src/tint/lang/core/ir/store.h
index d47a1ed..7da1d7e 100644
--- a/src/tint/lang/core/ir/store.h
+++ b/src/tint/lang/core/ir/store.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A store instruction in the IR.
 class Store : public Castable<Store, OperandInstruction<2, 0>> {
@@ -45,6 +45,6 @@
     std::string_view FriendlyName() override { return "store"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_STORE_H_
diff --git a/src/tint/lang/core/ir/store_test.cc b/src/tint/lang/core/ir/store_test.cc
index 3c93be2..f13049b 100644
--- a/src/tint/lang/core/ir/store_test.cc
+++ b/src/tint/lang/core/ir/store_test.cc
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -59,4 +59,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/store_vector_element.cc b/src/tint/lang/core/ir/store_vector_element.cc
index 219ded3..c133211 100644
--- a/src/tint/lang/core/ir/store_vector_element.cc
+++ b/src/tint/lang/core/ir/store_vector_element.cc
@@ -14,9 +14,9 @@
 
 #include "src/tint/lang/core/ir/store_vector_element.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::StoreVectorElement);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::StoreVectorElement);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 StoreVectorElement::StoreVectorElement(ir::Value* to, ir::Value* index, ir::Value* value) {
     flags_.Add(Flag::kSequenced);
@@ -28,4 +28,4 @@
 
 StoreVectorElement::~StoreVectorElement() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/store_vector_element.h b/src/tint/lang/core/ir/store_vector_element.h
index 0e081e8..7e8f4fc 100644
--- a/src/tint/lang/core/ir/store_vector_element.h
+++ b/src/tint/lang/core/ir/store_vector_element.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A store instruction for a single vector element in the IR.
 class StoreVectorElement : public Castable<StoreVectorElement, OperandInstruction<3, 0>> {
@@ -52,6 +52,6 @@
     std::string_view FriendlyName() override { return "store-vector-element"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_STORE_VECTOR_ELEMENT_H_
diff --git a/src/tint/lang/core/ir/store_vector_element_test.cc b/src/tint/lang/core/ir/store_vector_element_test.cc
index 5d21210..03e147e 100644
--- a/src/tint/lang/core/ir/store_vector_element_test.cc
+++ b/src/tint/lang/core/ir/store_vector_element_test.cc
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -67,4 +67,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/switch.cc b/src/tint/lang/core/ir/switch.cc
index bda068f..df353ab 100644
--- a/src/tint/lang/core/ir/switch.cc
+++ b/src/tint/lang/core/ir/switch.cc
@@ -16,9 +16,9 @@
 
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Switch);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Switch);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Switch::Switch(Value* cond) {
     TINT_ASSERT(cond);
@@ -34,4 +34,4 @@
     }
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/switch.h b/src/tint/lang/core/ir/switch.h
index 500281f..120c860 100644
--- a/src/tint/lang/core/ir/switch.h
+++ b/src/tint/lang/core/ir/switch.h
@@ -18,12 +18,12 @@
 #include "src/tint/lang/core/ir/control_instruction.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Constant;
 class MultiInBlock;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 /// Switch instruction.
 ///
 /// ```
@@ -87,6 +87,6 @@
     Vector<Case, 4> cases_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_SWITCH_H_
diff --git a/src/tint/lang/core/ir/switch_test.cc b/src/tint/lang/core/ir/switch_test.cc
index 2ffee15..5d1442c 100644
--- a/src/tint/lang/core/ir/switch_test.cc
+++ b/src/tint/lang/core/ir/switch_test.cc
@@ -18,7 +18,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -44,4 +44,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/swizzle.cc b/src/tint/lang/core/ir/swizzle.cc
index 83361a5..3789021 100644
--- a/src/tint/lang/core/ir/swizzle.cc
+++ b/src/tint/lang/core/ir/swizzle.cc
@@ -18,9 +18,9 @@
 
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Swizzle);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Swizzle);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Swizzle::Swizzle(InstructionResult* result, Value* object, VectorRef<uint32_t> indices)
     : indices_(std::move(indices)) {
@@ -37,4 +37,4 @@
 
 Swizzle::~Swizzle() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/swizzle.h b/src/tint/lang/core/ir/swizzle.h
index 927ab8e..6632515 100644
--- a/src/tint/lang/core/ir/swizzle.h
+++ b/src/tint/lang/core/ir/swizzle.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A swizzle instruction in the IR.
 class Swizzle : public Castable<Swizzle, OperandInstruction<1, 1>> {
@@ -46,6 +46,6 @@
     Vector<uint32_t, 4> indices_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_SWIZZLE_H_
diff --git a/src/tint/lang/core/ir/swizzle_test.cc b/src/tint/lang/core/ir/swizzle_test.cc
index 671b423..3f435ef 100644
--- a/src/tint/lang/core/ir/swizzle_test.cc
+++ b/src/tint/lang/core/ir/swizzle_test.cc
@@ -20,7 +20,7 @@
 
 using namespace tint::core::fluent_types;  // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_SwizzleTest = IRTestHelper;
@@ -87,4 +87,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/terminate_invocation.cc b/src/tint/lang/core/ir/terminate_invocation.cc
index 0f0bb3b..a7ab28e 100644
--- a/src/tint/lang/core/ir/terminate_invocation.cc
+++ b/src/tint/lang/core/ir/terminate_invocation.cc
@@ -14,10 +14,10 @@
 
 #include "src/tint/lang/core/ir/terminate_invocation.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::TerminateInvocation);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::TerminateInvocation);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 TerminateInvocation::~TerminateInvocation() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/terminate_invocation.h b/src/tint/lang/core/ir/terminate_invocation.h
index 6e98eb3..60fa964 100644
--- a/src/tint/lang/core/ir/terminate_invocation.h
+++ b/src/tint/lang/core/ir/terminate_invocation.h
@@ -17,7 +17,7 @@
 
 #include "src/tint/lang/core/ir/terminator.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// An terminate invocation instruction in the IR.
 class TerminateInvocation : public Castable<TerminateInvocation, Terminator> {
@@ -28,6 +28,6 @@
     std::string_view FriendlyName() override { return "terminate-invocation"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_TERMINATE_INVOCATION_H_
diff --git a/src/tint/lang/core/ir/terminator.cc b/src/tint/lang/core/ir/terminator.cc
index 97600bf..002f387 100644
--- a/src/tint/lang/core/ir/terminator.cc
+++ b/src/tint/lang/core/ir/terminator.cc
@@ -16,10 +16,10 @@
 
 #include <utility>
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Terminator);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Terminator);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Terminator::~Terminator() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/terminator.h b/src/tint/lang/core/ir/terminator.h
index 13ec744..5d534cd 100644
--- a/src/tint/lang/core/ir/terminator.h
+++ b/src/tint/lang/core/ir/terminator.h
@@ -20,11 +20,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Block;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// The base class of all instructions that terminate a block.
 class Terminator : public Castable<Terminator, OperandInstruction<1, 0>> {
@@ -35,6 +35,6 @@
     virtual tint::Slice<Value* const> Args() { return operands_.Slice(); }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_TERMINATOR_H_
diff --git a/src/tint/lang/core/ir/transform/add_empty_entry_point.cc b/src/tint/lang/core/ir/transform/add_empty_entry_point.cc
index cd37a50..aef5ff8 100644
--- a/src/tint/lang/core/ir/transform/add_empty_entry_point.cc
+++ b/src/tint/lang/core/ir/transform/add_empty_entry_point.cc
@@ -20,7 +20,7 @@
 #include "src/tint/lang/core/ir/module.h"
 #include "src/tint/lang/core/ir/validator.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -50,4 +50,4 @@
     return Success;
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/add_empty_entry_point.h b/src/tint/lang/core/ir/transform/add_empty_entry_point.h
index 2152834..2473d93 100644
--- a/src/tint/lang/core/ir/transform/add_empty_entry_point.h
+++ b/src/tint/lang/core/ir/transform/add_empty_entry_point.h
@@ -20,17 +20,17 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// Add an empty entry point to the module, if no other entry points exist.
 /// @param module the module to transform
 /// @returns an error string on failure
 Result<SuccessType, std::string> AddEmptyEntryPoint(Module* module);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_ADD_EMPTY_ENTRY_POINT_H_
diff --git a/src/tint/lang/core/ir/transform/add_empty_entry_point_test.cc b/src/tint/lang/core/ir/transform/add_empty_entry_point_test.cc
index d09d833..14a2b80 100644
--- a/src/tint/lang/core/ir/transform/add_empty_entry_point_test.cc
+++ b/src/tint/lang/core/ir/transform/add_empty_entry_point_test.cc
@@ -18,7 +18,7 @@
 
 #include "src/tint/lang/core/ir/transform/helper_test.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 namespace {
 
 using IR_AddEmptyEntryPointTest = TransformTest;
@@ -55,4 +55,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.cc b/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.cc
index 673b1ad..1c414d7 100644
--- a/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.cc
+++ b/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.cc
@@ -25,7 +25,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -176,4 +176,4 @@
     return Success;
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h b/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h
index 90f9fb5..46c788f 100644
--- a/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h
+++ b/src/tint/lang/core/ir/transform/bgra8unorm_polyfill.h
@@ -20,11 +20,11 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// Bgra8UnormPolyfill is a transform that changes the texel format of storage textures from
 /// bgra8unorm to rgba8unorm, inserting swizzles before and after texture accesses as necessary.
@@ -32,6 +32,6 @@
 /// @returns an error string on failure
 Result<SuccessType, std::string> Bgra8UnormPolyfill(Module* module);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_BGRA8UNORM_POLYFILL_H_
diff --git a/src/tint/lang/core/ir/transform/bgra8unorm_polyfill_test.cc b/src/tint/lang/core/ir/transform/bgra8unorm_polyfill_test.cc
index ed0f658..a7974d9 100644
--- a/src/tint/lang/core/ir/transform/bgra8unorm_polyfill_test.cc
+++ b/src/tint/lang/core/ir/transform/bgra8unorm_polyfill_test.cc
@@ -19,7 +19,7 @@
 #include "src/tint/lang/core/ir/transform/helper_test.h"
 #include "src/tint/lang/core/type/storage_texture.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -605,4 +605,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/binding_remapper.cc b/src/tint/lang/core/ir/transform/binding_remapper.cc
index dc91cc4..cbb023d 100644
--- a/src/tint/lang/core/ir/transform/binding_remapper.cc
+++ b/src/tint/lang/core/ir/transform/binding_remapper.cc
@@ -24,7 +24,7 @@
 
 using namespace tint::core::number_suffixes;  // NOLINT
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -73,4 +73,4 @@
     return Run(ir, options);
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/binding_remapper.h b/src/tint/lang/core/ir/transform/binding_remapper.h
index 2c1fbe6..535a856 100644
--- a/src/tint/lang/core/ir/transform/binding_remapper.h
+++ b/src/tint/lang/core/ir/transform/binding_remapper.h
@@ -21,11 +21,11 @@
 #include "tint/binding_remapper_options.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// BindingRemapper is a transform that remaps binding point indices and access controls.
 /// @param module the module to transform
@@ -34,6 +34,6 @@
 Result<SuccessType, std::string> BindingRemapper(Module* module,
                                                  const BindingRemapperOptions& options);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_BINDING_REMAPPER_H_
diff --git a/src/tint/lang/core/ir/transform/binding_remapper_test.cc b/src/tint/lang/core/ir/transform/binding_remapper_test.cc
index 5ce486e..26b2af9 100644
--- a/src/tint/lang/core/ir/transform/binding_remapper_test.cc
+++ b/src/tint/lang/core/ir/transform/binding_remapper_test.cc
@@ -18,7 +18,7 @@
 
 #include "src/tint/lang/core/ir/transform/helper_test.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -238,4 +238,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/block_decorated_structs.cc b/src/tint/lang/core/ir/transform/block_decorated_structs.cc
index 732a5d5..3fe380f 100644
--- a/src/tint/lang/core/ir/transform/block_decorated_structs.cc
+++ b/src/tint/lang/core/ir/transform/block_decorated_structs.cc
@@ -24,7 +24,7 @@
 
 using namespace tint::core::number_suffixes;  // NOLINT
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -122,4 +122,4 @@
     return Success;
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/block_decorated_structs.h b/src/tint/lang/core/ir/transform/block_decorated_structs.h
index 39f991b..ae5e065 100644
--- a/src/tint/lang/core/ir/transform/block_decorated_structs.h
+++ b/src/tint/lang/core/ir/transform/block_decorated_structs.h
@@ -20,11 +20,11 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// BlockDecoratedStructs is a transform that changes the store type of a buffer to be a special
 /// structure that is recognized as needing a block decoration in SPIR-V, potentially wrapping the
@@ -33,6 +33,6 @@
 /// @returns an error string on failure
 Result<SuccessType, std::string> BlockDecoratedStructs(Module* module);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_BLOCK_DECORATED_STRUCTS_H_
diff --git a/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc b/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
index 4d96454..4ef9c26 100644
--- a/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
+++ b/src/tint/lang/core/ir/transform/block_decorated_structs_test.cc
@@ -21,7 +21,7 @@
 #include "src/tint/lang/core/type/pointer.h"
 #include "src/tint/lang/core/type/struct.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -338,4 +338,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/builtin_polyfill.cc b/src/tint/lang/core/ir/transform/builtin_polyfill.cc
index 38c24b6..d8dc094 100644
--- a/src/tint/lang/core/ir/transform/builtin_polyfill.cc
+++ b/src/tint/lang/core/ir/transform/builtin_polyfill.cc
@@ -24,7 +24,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -468,4 +468,4 @@
     return Success;
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/builtin_polyfill.h b/src/tint/lang/core/ir/transform/builtin_polyfill.h
index 0f86380..df537aa 100644
--- a/src/tint/lang/core/ir/transform/builtin_polyfill.h
+++ b/src/tint/lang/core/ir/transform/builtin_polyfill.h
@@ -20,11 +20,11 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// The set of polyfills that should be applied.
 struct BuiltinPolyfillConfig {
@@ -50,6 +50,6 @@
 Result<SuccessType, std::string> BuiltinPolyfill(Module* module,
                                                  const BuiltinPolyfillConfig& config);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_BUILTIN_POLYFILL_H_
diff --git a/src/tint/lang/core/ir/transform/builtin_polyfill_test.cc b/src/tint/lang/core/ir/transform/builtin_polyfill_test.cc
index 8ff1d0e..a89ed53 100644
--- a/src/tint/lang/core/ir/transform/builtin_polyfill_test.cc
+++ b/src/tint/lang/core/ir/transform/builtin_polyfill_test.cc
@@ -19,7 +19,7 @@
 #include "src/tint/lang/core/ir/transform/helper_test.h"
 #include "src/tint/lang/core/type/sampled_texture.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -1117,4 +1117,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/demote_to_helper.cc b/src/tint/lang/core/ir/transform/demote_to_helper.cc
index c235adf..e96acd6 100644
--- a/src/tint/lang/core/ir/transform/demote_to_helper.cc
+++ b/src/tint/lang/core/ir/transform/demote_to_helper.cc
@@ -24,7 +24,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -214,4 +214,4 @@
     return Success;
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/demote_to_helper.h b/src/tint/lang/core/ir/transform/demote_to_helper.h
index ec19ea4..b80ce75 100644
--- a/src/tint/lang/core/ir/transform/demote_to_helper.h
+++ b/src/tint/lang/core/ir/transform/demote_to_helper.h
@@ -20,11 +20,11 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// DemoteToHelper is a transform that emulates demote-to-helper semantics for discard instructions.
 ///
@@ -36,6 +36,6 @@
 /// @returns an error string on failure
 Result<SuccessType, std::string> DemoteToHelper(Module* module);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_DEMOTE_TO_HELPER_H_
diff --git a/src/tint/lang/core/ir/transform/demote_to_helper_test.cc b/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
index fd36056..d7ebbb2 100644
--- a/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
+++ b/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
@@ -21,7 +21,7 @@
 #include "src/tint/lang/core/type/f32.h"
 #include "src/tint/lang/core/type/storage_texture.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -858,4 +858,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/helper_test.h b/src/tint/lang/core/ir/transform/helper_test.h
index 10552c5..71b2c22 100644
--- a/src/tint/lang/core/ir/transform/helper_test.h
+++ b/src/tint/lang/core/ir/transform/helper_test.h
@@ -25,7 +25,7 @@
 #include "src/tint/lang/core/ir/disassembler.h"
 #include "src/tint/lang/core/ir/validator.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// Helper class for testing IR transforms.
 template <typename BASE>
@@ -68,6 +68,6 @@
 template <typename T>
 using TransformTestWithParam = TransformTestBase<testing::TestWithParam<T>>;
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_HELPER_TEST_H_
diff --git a/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc b/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
index 38717c1..06eb634 100644
--- a/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
+++ b/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
@@ -25,7 +25,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -580,4 +580,4 @@
     return Success;
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/multiplanar_external_texture.h b/src/tint/lang/core/ir/transform/multiplanar_external_texture.h
index 1eaed4f..31df37a 100644
--- a/src/tint/lang/core/ir/transform/multiplanar_external_texture.h
+++ b/src/tint/lang/core/ir/transform/multiplanar_external_texture.h
@@ -21,11 +21,11 @@
 #include "tint/external_texture_options.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// MultiplanarExternalTexture is a transform that... TODO
 /// @param module the module to transform
@@ -34,6 +34,6 @@
 Result<SuccessType, std::string> MultiplanarExternalTexture(Module* module,
                                                             const ExternalTextureOptions& options);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_MULTIPLANAR_EXTERNAL_TEXTURE_H_
diff --git a/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc b/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
index 077bae3..25cba9b 100644
--- a/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
+++ b/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
@@ -19,7 +19,7 @@
 #include "src/tint/lang/core/ir/transform/helper_test.h"
 #include "src/tint/lang/core/type/external_texture.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -1277,4 +1277,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/shader_io.cc b/src/tint/lang/core/ir/transform/shader_io.cc
index 5f9e068..f279b86 100644
--- a/src/tint/lang/core/ir/transform/shader_io.cc
+++ b/src/tint/lang/core/ir/transform/shader_io.cc
@@ -24,7 +24,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -259,4 +259,4 @@
 
 ShaderIOBackendState::~ShaderIOBackendState() = default;
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/shader_io.h b/src/tint/lang/core/ir/transform/shader_io.h
index 23c20b5..e3e7194 100644
--- a/src/tint/lang/core/ir/transform/shader_io.h
+++ b/src/tint/lang/core/ir/transform/shader_io.h
@@ -21,7 +21,7 @@
 #include "src/tint/lang/core/ir/builder.h"
 #include "src/tint/lang/core/type/manager.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// Abstract base class for the state needed to handle IO for a particular backend target.
 struct ShaderIOBackendState {
@@ -100,6 +100,6 @@
 /// @param make_backend_state a function that creates a backend state object
 void RunShaderIOBase(Module* module, std::function<MakeBackendStateFunc> make_backend_state);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_SHADER_IO_H_
diff --git a/src/tint/lang/core/ir/transform/std140.cc b/src/tint/lang/core/ir/transform/std140.cc
index 8a3c165..ed73e70 100644
--- a/src/tint/lang/core/ir/transform/std140.cc
+++ b/src/tint/lang/core/ir/transform/std140.cc
@@ -26,7 +26,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 namespace {
 
@@ -340,4 +340,4 @@
     return Success;
 }
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/std140.h b/src/tint/lang/core/ir/transform/std140.h
index 0eca023..42f12c7 100644
--- a/src/tint/lang/core/ir/transform/std140.h
+++ b/src/tint/lang/core/ir/transform/std140.h
@@ -20,11 +20,11 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 
 /// Std140 is a transform that rewrites matrix types in the uniform address space to conform to
 /// GLSL's std140 layout rules.
@@ -32,6 +32,6 @@
 /// @returns an error string on failure
 Result<SuccessType, std::string> Std140(Module* module);
 
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
 
 #endif  // SRC_TINT_LANG_CORE_IR_TRANSFORM_STD140_H_
diff --git a/src/tint/lang/core/ir/transform/std140_test.cc b/src/tint/lang/core/ir/transform/std140_test.cc
index 7cbe306..4fca697 100644
--- a/src/tint/lang/core/ir/transform/std140_test.cc
+++ b/src/tint/lang/core/ir/transform/std140_test.cc
@@ -22,7 +22,7 @@
 #include "src/tint/lang/core/type/pointer.h"
 #include "src/tint/lang/core/type/struct.h"
 
-namespace tint::ir::transform {
+namespace tint::core::ir::transform {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -1589,4 +1589,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir::transform
+}  // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/unary.cc b/src/tint/lang/core/ir/unary.cc
index 5f83962..d6ce129 100644
--- a/src/tint/lang/core/ir/unary.cc
+++ b/src/tint/lang/core/ir/unary.cc
@@ -14,9 +14,9 @@
 
 #include "src/tint/lang/core/ir/unary.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Unary);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Unary);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Unary::Unary(InstructionResult* result, enum Kind k, Value* val) : kind_(k) {
     AddOperand(Unary::kValueOperandOffset, val);
@@ -25,4 +25,4 @@
 
 Unary::~Unary() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/unary.h b/src/tint/lang/core/ir/unary.h
index 14dfd72..4013c47 100644
--- a/src/tint/lang/core/ir/unary.h
+++ b/src/tint/lang/core/ir/unary.h
@@ -18,7 +18,7 @@
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A unary instruction in the IR.
 class Unary : public Castable<Unary, OperandInstruction<1, 1>> {
@@ -52,6 +52,6 @@
     enum Kind kind_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_UNARY_H_
diff --git a/src/tint/lang/core/ir/unary_test.cc b/src/tint/lang/core/ir/unary_test.cc
index af4289d..95d30cf 100644
--- a/src/tint/lang/core/ir/unary_test.cc
+++ b/src/tint/lang/core/ir/unary_test.cc
@@ -22,7 +22,7 @@
 using namespace tint::core::number_suffixes;  // NOLINT
 using namespace tint::core::fluent_types;     // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_UnaryTest = IRTestHelper;
@@ -79,4 +79,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/unreachable.cc b/src/tint/lang/core/ir/unreachable.cc
index 158d77f..0011530 100644
--- a/src/tint/lang/core/ir/unreachable.cc
+++ b/src/tint/lang/core/ir/unreachable.cc
@@ -14,10 +14,10 @@
 
 #include "src/tint/lang/core/ir/unreachable.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Unreachable);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Unreachable);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Unreachable::~Unreachable() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/unreachable.h b/src/tint/lang/core/ir/unreachable.h
index 2d417ae..97d052e 100644
--- a/src/tint/lang/core/ir/unreachable.h
+++ b/src/tint/lang/core/ir/unreachable.h
@@ -17,7 +17,7 @@
 
 #include "src/tint/lang/core/ir/terminator.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// An unreachable instruction in the IR.
 class Unreachable : public Castable<Unreachable, Terminator> {
@@ -28,6 +28,6 @@
     std::string_view FriendlyName() override { return "unreachable"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_UNREACHABLE_H_
diff --git a/src/tint/lang/core/ir/user_call.cc b/src/tint/lang/core/ir/user_call.cc
index 11f791a..1a41472 100644
--- a/src/tint/lang/core/ir/user_call.cc
+++ b/src/tint/lang/core/ir/user_call.cc
@@ -16,9 +16,9 @@
 
 #include <utility>
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::UserCall);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::UserCall);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 UserCall::UserCall(InstructionResult* result, Function* func, VectorRef<Value*> arguments) {
     AddOperand(UserCall::kFunctionOperandOffset, func);
@@ -28,4 +28,4 @@
 
 UserCall::~UserCall() = default;
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/user_call.h b/src/tint/lang/core/ir/user_call.h
index eb0c4f3..ed0f9eb 100644
--- a/src/tint/lang/core/ir/user_call.h
+++ b/src/tint/lang/core/ir/user_call.h
@@ -19,7 +19,7 @@
 #include "src/tint/lang/core/ir/function.h"
 #include "src/tint/utils/rtti/castable.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A user call instruction in the IR.
 class UserCall : public Castable<UserCall, Call> {
@@ -47,6 +47,6 @@
     std::string_view FriendlyName() override { return "user-call"; }
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_USER_CALL_H_
diff --git a/src/tint/lang/core/ir/user_call_test.cc b/src/tint/lang/core/ir/user_call_test.cc
index a1043c4..51f99eb 100644
--- a/src/tint/lang/core/ir/user_call_test.cc
+++ b/src/tint/lang/core/ir/user_call_test.cc
@@ -18,7 +18,7 @@
 #include "gtest/gtest-spi.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::number_suffixes;  // NOLINT
@@ -57,4 +57,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index b6818d3..e5f4c72 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -67,7 +67,7 @@
 
 using namespace tint::core::fluent_types;  // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Validator::Validator(Module& mod) : mod_(mod) {}
 
@@ -658,4 +658,4 @@
     return Success;
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/validator.h b/src/tint/lang/core/ir/validator.h
index 9448c7b..1723d65 100644
--- a/src/tint/lang/core/ir/validator.h
+++ b/src/tint/lang/core/ir/validator.h
@@ -23,7 +23,7 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Access;
 class ExitIf;
 class ExitLoop;
@@ -33,9 +33,9 @@
 class Return;
 class StoreVectorElement;
 class Var;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// Validates that a given IR module is correctly formed
 /// @param mod the module to validate
@@ -242,6 +242,6 @@
     void DisassembleIfNeeded();
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_VALIDATOR_H_
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index aa8a29c..7d09e7b 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -25,7 +25,7 @@
 #include "src/tint/lang/core/type/struct.h"
 #include "src/tint/utils/text/string.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -49,7 +49,8 @@
 
     auto res = ir::Validate(mod);
     ASSERT_FALSE(res);
-    EXPECT_EQ(res.Failure().str(), R"(:2:3 error: root block: invalid instruction: tint::ir::Loop
+    EXPECT_EQ(res.Failure().str(),
+              R"(:2:3 error: root block: invalid instruction: tint::core::ir::Loop
   loop [b: %b2] {  # loop_1
   ^^^^^^^^^^^^^
 
@@ -957,8 +958,8 @@
     auto arrows = std::string(addr.length(), '^');
 
     std::string expected = R"(:3:5 error: var: destroyed instruction found in instruction list
-    <destroyed tint::ir::Var $ADDRESS>
-    ^^^^^^^^^^^^^^^^^^^^^^^^^$ARROWS^
+    <destroyed tint::core::ir::Var $ADDRESS>
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^$ARROWS^
 
 :2:3 note: In block
   %b1 = block {
@@ -967,7 +968,7 @@
 note: # Disassembly
 %my_func = func():void -> %b1 {
   %b1 = block {
-    <destroyed tint::ir::Var $ADDRESS>
+    <destroyed tint::core::ir::Var $ADDRESS>
     ret
   }
 }
@@ -2926,4 +2927,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/value.cc b/src/tint/lang/core/ir/value.cc
index 5c3c37e..ab886da 100644
--- a/src/tint/lang/core/ir/value.cc
+++ b/src/tint/lang/core/ir/value.cc
@@ -18,9 +18,9 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Value);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Value);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Value::Value() = default;
 
@@ -54,4 +54,4 @@
     }
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/value.h b/src/tint/lang/core/ir/value.h
index 556f695..6393bc9 100644
--- a/src/tint/lang/core/ir/value.h
+++ b/src/tint/lang/core/ir/value.h
@@ -20,11 +20,11 @@
 #include "src/tint/utils/rtti/castable.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Instruction;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A specific usage of a Value in the IR.
 struct Usage {
@@ -106,6 +106,6 @@
     /// Bitset of value flags
     tint::EnumSet<Flag> flags_;
 };
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_VALUE_H_
diff --git a/src/tint/lang/core/ir/value_test.cc b/src/tint/lang/core/ir/value_test.cc
index 3ba12a8..36fb415 100644
--- a/src/tint/lang/core/ir/value_test.cc
+++ b/src/tint/lang/core/ir/value_test.cc
@@ -19,7 +19,7 @@
 using namespace tint::core::number_suffixes;  // NOLINT
 using namespace tint::core::fluent_types;     // NOLINT
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using IR_ValueTest = IRTestHelper;
@@ -77,4 +77,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/var.cc b/src/tint/lang/core/ir/var.cc
index cacf610..1042786 100644
--- a/src/tint/lang/core/ir/var.cc
+++ b/src/tint/lang/core/ir/var.cc
@@ -17,9 +17,9 @@
 #include "src/tint/lang/core/ir/store.h"
 #include "src/tint/utils/ice/ice.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::ir::Var);
+TINT_INSTANTIATE_TYPEINFO(tint::core::ir::Var);
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 Var::Var(InstructionResult* result) {
     if (result && result->Type()) {
@@ -48,4 +48,4 @@
     }
 }
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/var.h b/src/tint/lang/core/ir/var.h
index 3229d31..96d3b62 100644
--- a/src/tint/lang/core/ir/var.h
+++ b/src/tint/lang/core/ir/var.h
@@ -23,7 +23,7 @@
 #include "src/tint/utils/rtti/castable.h"
 #include "tint/binding_point.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 
 /// A var instruction in the IR.
 class Var : public Castable<Var, OperandInstruction<1, 1>> {
@@ -59,6 +59,6 @@
     std::optional<struct BindingPoint> binding_point_;
 };
 
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_VAR_H_
diff --git a/src/tint/lang/core/ir/var_test.cc b/src/tint/lang/core/ir/var_test.cc
index 5368dab..24fb70e 100644
--- a/src/tint/lang/core/ir/var_test.cc
+++ b/src/tint/lang/core/ir/var_test.cc
@@ -20,7 +20,7 @@
 #include "src/tint/lang/core/ir/instruction.h"
 #include "src/tint/lang/core/ir/ir_helper_test.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 namespace {
 
 using namespace tint::core::fluent_types;     // NOLINT
@@ -59,4 +59,4 @@
 }
 
 }  // namespace
-}  // namespace tint::ir
+}  // namespace tint::core::ir
diff --git a/src/tint/lang/msl/writer/printer/binary_test.cc b/src/tint/lang/msl/writer/printer/binary_test.cc
index 8a94cc2..8be9c80 100644
--- a/src/tint/lang/msl/writer/printer/binary_test.cc
+++ b/src/tint/lang/msl/writer/printer/binary_test.cc
@@ -25,7 +25,7 @@
 
 struct BinaryData {
     const char* result;
-    enum ir::Binary::Kind op;
+    enum core::ir::Binary::Kind op;
 };
 inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
     StringStream str;
@@ -60,16 +60,16 @@
 INSTANTIATE_TEST_SUITE_P(
     MslPrinterTest,
     MslPrinterBinaryTest,
-    testing::Values(BinaryData{"(left + right)", ir::Binary::Kind::kAdd},
-                    BinaryData{"(left - right)", ir::Binary::Kind::kSubtract},
-                    BinaryData{"(left * right)", ir::Binary::Kind::kMultiply},
-                    BinaryData{"(left / right)", ir::Binary::Kind::kDivide},
-                    BinaryData{"(left % right)", ir::Binary::Kind::kModulo},
-                    BinaryData{"(left & right)", ir::Binary::Kind::kAnd},
-                    BinaryData{"(left | right)", ir::Binary::Kind::kOr},
-                    BinaryData{"(left ^ right)", ir::Binary::Kind::kXor},
-                    BinaryData{"(left << right)", ir::Binary::Kind::kShiftLeft},
-                    BinaryData{"(left >> right)", ir::Binary::Kind::kShiftRight}));
+    testing::Values(BinaryData{"(left + right)", core::ir::Binary::Kind::kAdd},
+                    BinaryData{"(left - right)", core::ir::Binary::Kind::kSubtract},
+                    BinaryData{"(left * right)", core::ir::Binary::Kind::kMultiply},
+                    BinaryData{"(left / right)", core::ir::Binary::Kind::kDivide},
+                    BinaryData{"(left % right)", core::ir::Binary::Kind::kModulo},
+                    BinaryData{"(left & right)", core::ir::Binary::Kind::kAnd},
+                    BinaryData{"(left | right)", core::ir::Binary::Kind::kOr},
+                    BinaryData{"(left ^ right)", core::ir::Binary::Kind::kXor},
+                    BinaryData{"(left << right)", core::ir::Binary::Kind::kShiftLeft},
+                    BinaryData{"(left >> right)", core::ir::Binary::Kind::kShiftRight}));
 
 using MslPrinterBinaryBoolTest = MslPrinterTestWithParam<BinaryData>;
 TEST_P(MslPrinterBinaryBoolTest, Emit) {
@@ -97,12 +97,12 @@
 INSTANTIATE_TEST_SUITE_P(
     MslPrinterTest,
     MslPrinterBinaryBoolTest,
-    testing::Values(BinaryData{"(left == right)", ir::Binary::Kind::kEqual},
-                    BinaryData{"(left != right)", ir::Binary::Kind::kNotEqual},
-                    BinaryData{"(left < right)", ir::Binary::Kind::kLessThan},
-                    BinaryData{"(left > right)", ir::Binary::Kind::kGreaterThan},
-                    BinaryData{"(left <= right)", ir::Binary::Kind::kLessThanEqual},
-                    BinaryData{"(left >= right)", ir::Binary::Kind::kGreaterThanEqual}));
+    testing::Values(BinaryData{"(left == right)", core::ir::Binary::Kind::kEqual},
+                    BinaryData{"(left != right)", core::ir::Binary::Kind::kNotEqual},
+                    BinaryData{"(left < right)", core::ir::Binary::Kind::kLessThan},
+                    BinaryData{"(left > right)", core::ir::Binary::Kind::kGreaterThan},
+                    BinaryData{"(left <= right)", core::ir::Binary::Kind::kLessThanEqual},
+                    BinaryData{"(left >= right)", core::ir::Binary::Kind::kGreaterThanEqual}));
 
 // TODO(dsinclair): Needs transform
 // TODO(dsinclair): Requires `bitcast` support
@@ -132,9 +132,11 @@
 }
 
 constexpr BinaryData signed_overflow_defined_behaviour_cases[] = {
-    {"as_type<int>((as_type<uint>(left) + as_type<uint>(right)))", ir::Binary::Kind::kAdd},
-    {"as_type<int>((as_type<uint>(left) - as_type<uint>(right)))", ir::Binary::Kind::kSubtract},
-    {"as_type<int>((as_type<uint>(left) * as_type<uint>(right)))", ir::Binary::Kind::kMultiply}};
+    {"as_type<int>((as_type<uint>(left) + as_type<uint>(right)))", core::ir::Binary::Kind::kAdd},
+    {"as_type<int>((as_type<uint>(left) - as_type<uint>(right)))",
+     core::ir::Binary::Kind::kSubtract},
+    {"as_type<int>((as_type<uint>(left) * as_type<uint>(right)))",
+     core::ir::Binary::Kind::kMultiply}};
 INSTANTIATE_TEST_SUITE_P(MslPrinterTest,
                          MslPrinterBinaryTest_SignedOverflowDefinedBehaviour,
                          testing::ValuesIn(signed_overflow_defined_behaviour_cases));
@@ -167,8 +169,8 @@
 }
 
 constexpr BinaryData shift_signed_overflow_defined_behaviour_cases[] = {
-    {"as_type<int>((as_type<uint>(left) << right))", ir::Binary::Kind::kShiftLeft},
-    {"(left >> right)", ir::Binary::Kind::kShiftRight}};
+    {"as_type<int>((as_type<uint>(left) << right))", core::ir::Binary::Kind::kShiftLeft},
+    {"(left >> right)", core::ir::Binary::Kind::kShiftRight}};
 INSTANTIATE_TEST_SUITE_P(MslPrinterTest,
                          MslPrinterBinaryTest_ShiftSignedOverflowDefinedBehaviour,
                          testing::ValuesIn(shift_signed_overflow_defined_behaviour_cases));
@@ -203,13 +205,13 @@
 constexpr BinaryData signed_overflow_defined_behaviour_chained_cases[] = {
     {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(left) + as_type<uint>(right)))) +
     as_type<uint>(right))))",
-     ir::Binary::Kind::kAdd},
+     core::ir::Binary::Kind::kAdd},
     {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(left) - as_type<uint>(right)))) -
     as_type<uint>(right))))",
-     ir::Binary::Kind::kSubtract},
+     core::ir::Binary::Kind::kSubtract},
     {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(left) * as_type<uint>(right)))) *
     as_type<uint>(right))))",
-     ir::Binary::Kind::kMultiply}};
+     core::ir::Binary::Kind::kMultiply}};
 INSTANTIATE_TEST_SUITE_P(MslPrinterTest,
                          MslPrinterBinaryTest_SignedOverflowDefinedBehaviour_Chained,
                          testing::ValuesIn(signed_overflow_defined_behaviour_chained_cases));
@@ -243,8 +245,8 @@
 }
 constexpr BinaryData shift_signed_overflow_defined_behaviour_chained_cases[] = {
     {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(left) << right))) << right)))",
-     ir::Binary::Kind::kShiftLeft},
-    {R"(((left >> right) >> right))", ir::Binary::Kind::kShiftRight},
+     core::ir::Binary::Kind::kShiftLeft},
+    {R"(((left >> right) >> right))", core::ir::Binary::Kind::kShiftRight},
 };
 INSTANTIATE_TEST_SUITE_P(MslPrinterTest,
                          MslPrinterBinaryTest_ShiftSignedOverflowDefinedBehaviour_Chained,
@@ -257,7 +259,7 @@
         auto* left = b.Var("left", ty.ptr<core::AddressSpace::kFunction, f32>());
         auto* right = b.Var("right", ty.ptr<core::AddressSpace::kFunction, f32>());
 
-        auto* expr1 = b.Binary(ir::Binary::Kind::kModulo, ty.f32(), left, right);
+        auto* expr1 = b.Binary(core::ir::Binary::Kind::kModulo, ty.f32(), left, right);
 
         b.Let("val", expr1);
     });
@@ -280,7 +282,7 @@
         auto* left = b.Var("left", ty.ptr<core::AddressSpace::kFunction, f16>());
         auto* right = b.Var("right", ty.ptr<core::AddressSpace::kFunction, f16>());
 
-        auto* expr1 = b.Binary(ir::Binary::Kind::kModulo, ty.f16(), left, right);
+        auto* expr1 = b.Binary(core::ir::Binary::Kind::kModulo, ty.f16(), left, right);
 
         b.Let("val", expr1);
     });
@@ -301,7 +303,7 @@
         auto* left = b.Var("left", ty.ptr(core::AddressSpace::kFunction, ty.vec3<f32>()));
         auto* right = b.Var("right", ty.ptr(core::AddressSpace::kFunction, ty.vec3<f32>()));
 
-        auto* expr1 = b.Binary(ir::Binary::Kind::kModulo, ty.vec3<f32>(), left, right);
+        auto* expr1 = b.Binary(core::ir::Binary::Kind::kModulo, ty.vec3<f32>(), left, right);
 
         b.Let("val", expr1);
     });
@@ -324,7 +326,7 @@
         auto* left = b.Var("left", ty.ptr(core::AddressSpace::kFunction, ty.vec3<f16>()));
         auto* right = b.Var("right", ty.ptr(core::AddressSpace::kFunction, ty.vec3<f16>()));
 
-        auto* expr1 = b.Binary(ir::Binary::Kind::kModulo, ty.vec3<f16>(), left, right);
+        auto* expr1 = b.Binary(core::ir::Binary::Kind::kModulo, ty.vec3<f16>(), left, right);
 
         b.Let("val", expr1);
     });
@@ -345,7 +347,7 @@
         auto* left = b.Var("left", ty.ptr(core::AddressSpace::kFunction, ty.bool_()));
         auto* right = b.Var("right", ty.ptr(core::AddressSpace::kFunction, ty.bool_()));
 
-        auto* expr1 = b.Binary(ir::Binary::Kind::kAdd, ty.bool_(), left, right);
+        auto* expr1 = b.Binary(core::ir::Binary::Kind::kAdd, ty.bool_(), left, right);
 
         b.Let("val", expr1);
     });
@@ -366,7 +368,7 @@
         auto* left = b.Var("left", ty.ptr(core::AddressSpace::kFunction, ty.bool_()));
         auto* right = b.Var("right", ty.ptr(core::AddressSpace::kFunction, ty.bool_()));
 
-        auto* expr1 = b.Binary(ir::Binary::Kind::kOr, ty.bool_(), left, right);
+        auto* expr1 = b.Binary(core::ir::Binary::Kind::kOr, ty.bool_(), left, right);
 
         b.Let("val", expr1);
     });
diff --git a/src/tint/lang/msl/writer/printer/helper_test.h b/src/tint/lang/msl/writer/printer/helper_test.h
index 49c1535..00d1d85 100644
--- a/src/tint/lang/msl/writer/printer/helper_test.h
+++ b/src/tint/lang/msl/writer/printer/helper_test.h
@@ -51,9 +51,9 @@
     MslPrinterTestHelperBase() : writer_(&mod) {}
 
     /// The test module.
-    ir::Module mod;
+    core::ir::Module mod;
     /// The test builder.
-    ir::Builder b{mod};
+    core::ir::Builder b{mod};
     /// The type manager.
     core::type::Manager& ty{mod.Types()};
 
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index 99a25ce..77f12e3 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -63,12 +63,12 @@
     TINT_UNIMPLEMENTED() << "unhandled case in Switch(): " \
                          << (object_ptr ? object_ptr->TypeInfo().name : "<null>")
 
-Printer::Printer(ir::Module* module) : ir_(module) {}
+Printer::Printer(core::ir::Module* module) : ir_(module) {}
 
 Printer::~Printer() = default;
 
 tint::Result<SuccessType, std::string> Printer::Generate() {
-    auto valid = ir::ValidateAndDumpIfNeeded(*ir_, "MSL writer");
+    auto valid = core::ir::ValidateAndDumpIfNeeded(*ir_, "MSL writer");
     if (!valid) {
         return std::move(valid.Failure());
     }
@@ -125,7 +125,7 @@
     return array_template_name_;
 }
 
-void Printer::EmitFunction(ir::Function* func) {
+void Printer::EmitFunction(core::ir::Function* func) {
     TINT_SCOPED_ASSIGNMENT(current_function_, func);
 
     {
@@ -147,33 +147,33 @@
     Line() << "}";
 }
 
-void Printer::EmitBlock(ir::Block* block) {
+void Printer::EmitBlock(core::ir::Block* block) {
     MarkInlinable(block);
 
     EmitBlockInstructions(block);
 }
 
-void Printer::EmitBlockInstructions(ir::Block* block) {
+void Printer::EmitBlockInstructions(core::ir::Block* block) {
     TINT_SCOPED_ASSIGNMENT(current_block_, block);
 
     for (auto* inst : *block) {
         Switch(
-            inst,                                          //
-            [&](ir::Binary* b) { EmitBinary(b); },         //
-            [&](ir::ExitIf* e) { EmitExitIf(e); },         //
-            [&](ir::If* if_) { EmitIf(if_); },             //
-            [&](ir::Let* l) { EmitLet(l); },               //
-            [&](ir::Load* l) { EmitLoad(l); },             //
-            [&](ir::Return* r) { EmitReturn(r); },         //
-            [&](ir::Unreachable*) { EmitUnreachable(); },  //
-            [&](ir::Var* v) { EmitVar(v); },               //
+            inst,                                                //
+            [&](core::ir::Binary* b) { EmitBinary(b); },         //
+            [&](core::ir::ExitIf* e) { EmitExitIf(e); },         //
+            [&](core::ir::If* if_) { EmitIf(if_); },             //
+            [&](core::ir::Let* l) { EmitLet(l); },               //
+            [&](core::ir::Load* l) { EmitLoad(l); },             //
+            [&](core::ir::Return* r) { EmitReturn(r); },         //
+            [&](core::ir::Unreachable*) { EmitUnreachable(); },  //
+            [&](core::ir::Var* v) { EmitVar(v); },               //
             [&](Default) { TINT_ICE() << "unimplemented instruction: " << inst->TypeInfo().name; });
     }
 }
 
-void Printer::EmitBinary(ir::Binary* b) {
-    if (b->Kind() == ir::Binary::Kind::kEqual) {
-        auto* rhs = b->RHS()->As<ir::Constant>();
+void Printer::EmitBinary(core::ir::Binary* b) {
+    if (b->Kind() == core::ir::Binary::Kind::kEqual) {
+        auto* rhs = b->RHS()->As<core::ir::Constant>();
         if (rhs && rhs->Type()->Is<core::type::Bool>() && rhs->Value()->ValueAs<bool>() == false) {
             // expr == false
             Bind(b->Result(), "!(" + Expr(b->LHS()) + ")");
@@ -183,37 +183,37 @@
 
     auto kind = [&] {
         switch (b->Kind()) {
-            case ir::Binary::Kind::kAdd:
+            case core::ir::Binary::Kind::kAdd:
                 return "+";
-            case ir::Binary::Kind::kSubtract:
+            case core::ir::Binary::Kind::kSubtract:
                 return "-";
-            case ir::Binary::Kind::kMultiply:
+            case core::ir::Binary::Kind::kMultiply:
                 return "*";
-            case ir::Binary::Kind::kDivide:
+            case core::ir::Binary::Kind::kDivide:
                 return "/";
-            case ir::Binary::Kind::kModulo:
+            case core::ir::Binary::Kind::kModulo:
                 return "%";
-            case ir::Binary::Kind::kAnd:
+            case core::ir::Binary::Kind::kAnd:
                 return "&";
-            case ir::Binary::Kind::kOr:
+            case core::ir::Binary::Kind::kOr:
                 return "|";
-            case ir::Binary::Kind::kXor:
+            case core::ir::Binary::Kind::kXor:
                 return "^";
-            case ir::Binary::Kind::kEqual:
+            case core::ir::Binary::Kind::kEqual:
                 return "==";
-            case ir::Binary::Kind::kNotEqual:
+            case core::ir::Binary::Kind::kNotEqual:
                 return "!=";
-            case ir::Binary::Kind::kLessThan:
+            case core::ir::Binary::Kind::kLessThan:
                 return "<";
-            case ir::Binary::Kind::kGreaterThan:
+            case core::ir::Binary::Kind::kGreaterThan:
                 return ">";
-            case ir::Binary::Kind::kLessThanEqual:
+            case core::ir::Binary::Kind::kLessThanEqual:
                 return "<=";
-            case ir::Binary::Kind::kGreaterThanEqual:
+            case core::ir::Binary::Kind::kGreaterThanEqual:
                 return ">=";
-            case ir::Binary::Kind::kShiftLeft:
+            case core::ir::Binary::Kind::kShiftLeft:
                 return "<<";
-            case ir::Binary::Kind::kShiftRight:
+            case core::ir::Binary::Kind::kShiftRight:
                 return ">>";
         }
         return "<error>";
@@ -225,12 +225,12 @@
     Bind(b->Result(), str.str());
 }
 
-void Printer::EmitLoad(ir::Load* l) {
+void Printer::EmitLoad(core::ir::Load* l) {
     // Force loads to be bound as inlines
     bindings_.Add(l->Result(), InlinedValue{Expr(l->From()), PtrKind::kRef});
 }
 
-void Printer::EmitVar(ir::Var* v) {
+void Printer::EmitVar(core::ir::Var* v) {
     auto out = Line();
 
     auto* ptr = v->Result()->Type()->As<core::type::Pointer>();
@@ -269,11 +269,11 @@
     Bind(v->Result(), name, PtrKind::kRef);
 }
 
-void Printer::EmitLet(ir::Let* l) {
+void Printer::EmitLet(core::ir::Let* l) {
     Bind(l->Result(), Expr(l->Value(), PtrKind::kPtr), PtrKind::kPtr);
 }
 
-void Printer::EmitIf(ir::If* if_) {
+void Printer::EmitIf(core::ir::If* if_) {
     // Emit any nodes that need to be used as PHI nodes
     for (auto* phi : if_->Results()) {
         if (!ir_->NameOf(phi).IsValid()) {
@@ -306,7 +306,7 @@
     Line() << "}";
 }
 
-void Printer::EmitExitIf(ir::ExitIf* e) {
+void Printer::EmitExitIf(core::ir::ExitIf* e) {
     auto results = e->If()->Results();
     auto args = e->Args();
     for (size_t i = 0; i < e->Args().Length(); ++i) {
@@ -317,7 +317,7 @@
     }
 }
 
-void Printer::EmitReturn(ir::Return* r) {
+void Printer::EmitReturn(core::ir::Return* r) {
     // If this return has no arguments and the current block is for the function which is
     // being returned, skip the return.
     if (current_block_ == current_function_->Block() && r->Args().IsEmpty()) {
@@ -641,7 +641,7 @@
     preamble_buffer_.Append(str_buf);
 }
 
-void Printer::EmitConstant(StringStream& out, ir::Constant* c) {
+void Printer::EmitConstant(StringStream& out, core::ir::Constant* c) {
     EmitConstant(out, c->Value());
 }
 
@@ -748,12 +748,12 @@
 
 TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);
 
-std::string Printer::Expr(ir::Value* value, PtrKind want_ptr_kind) {
+std::string Printer::Expr(core::ir::Value* value, PtrKind want_ptr_kind) {
     using ExprAndPtrKind = std::pair<std::string, PtrKind>;
 
     auto [expr, got_ptr_kind] = tint::Switch(
         value,
-        [&](ir::Constant* c) -> ExprAndPtrKind {
+        [&](core::ir::Constant* c) -> ExprAndPtrKind {
             StringStream str;
             EmitConstant(str, c);
             return {str.str(), PtrKind::kRef};
@@ -816,7 +816,7 @@
     return in;
 }
 
-void Printer::Bind(ir::Value* value, const std::string& expr, PtrKind ptr_kind) {
+void Printer::Bind(core::ir::Value* value, const std::string& expr, PtrKind ptr_kind) {
     TINT_ASSERT(value);
 
     if (can_inline_.Remove(value)) {
@@ -851,7 +851,7 @@
     TINT_ICE() << "Bind(" << value->TypeInfo().name << ") called twice for same value";
 }
 
-void Printer::Bind(ir::Value* value, Symbol name, PtrKind ptr_kind) {
+void Printer::Bind(core::ir::Value* value, Symbol name, PtrKind ptr_kind) {
     TINT_ASSERT(value);
 
     bool added = bindings_.Add(value, VariableValue{name, ptr_kind});
@@ -860,10 +860,10 @@
     }
 }
 
-void Printer::MarkInlinable(ir::Block* block) {
+void Printer::MarkInlinable(core::ir::Block* block) {
     // An ordered list of possibly-inlinable values returned by sequenced instructions that have
     // not yet been marked-for or ruled-out-for inlining.
-    UniqueVector<ir::Value*, 32> pending_resolution;
+    UniqueVector<core::ir::Value*, 32> pending_resolution;
 
     // Walk the instructions of the block starting with the first.
     for (auto* inst : *block) {
diff --git a/src/tint/lang/msl/writer/printer/printer.h b/src/tint/lang/msl/writer/printer/printer.h
index 9a49a84..6b395cf 100644
--- a/src/tint/lang/msl/writer/printer/printer.h
+++ b/src/tint/lang/msl/writer/printer/printer.h
@@ -26,7 +26,7 @@
 #include "src/tint/utils/text/string_stream.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Binary;
 class ExitIf;
 class If;
@@ -35,7 +35,7 @@
 class Return;
 class Unreachable;
 class Var;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 namespace tint::msl::writer {
 
@@ -44,7 +44,7 @@
   public:
     /// Constructor
     /// @param module the Tint IR module to generate
-    explicit Printer(ir::Module* module);
+    explicit Printer(core::ir::Module* module);
     ~Printer() override;
 
     /// @returns true on successful generation; false otherwise
@@ -56,41 +56,41 @@
   private:
     /// Emit the function
     /// @param func the function to emit
-    void EmitFunction(ir::Function* func);
+    void EmitFunction(core::ir::Function* func);
 
     /// Emit a block
     /// @param block the block to emit
-    void EmitBlock(ir::Block* block);
+    void EmitBlock(core::ir::Block* block);
     /// Emit the instructions in a block
     /// @param block the block with the instructions to emit
-    void EmitBlockInstructions(ir::Block* block);
+    void EmitBlockInstructions(core::ir::Block* block);
 
     /// Emit an if instruction
     /// @param if_ the if instruction
-    void EmitIf(ir::If* if_);
+    void EmitIf(core::ir::If* if_);
     /// Emit an exit-if instruction
     /// @param e the exit-if instruction
-    void EmitExitIf(ir::ExitIf* e);
+    void EmitExitIf(core::ir::ExitIf* e);
 
     /// Emit a let instruction
     /// @param l the let instruction
-    void EmitLet(ir::Let* l);
+    void EmitLet(core::ir::Let* l);
     /// Emit a var instruction
     /// @param v the var instruction
-    void EmitVar(ir::Var* v);
+    void EmitVar(core::ir::Var* v);
     /// Emit a load instruction
     /// @param l the load instruction
-    void EmitLoad(ir::Load* l);
+    void EmitLoad(core::ir::Load* l);
 
     /// Emit a return instruction
     /// @param r the return instruction
-    void EmitReturn(ir::Return* r);
+    void EmitReturn(core::ir::Return* r);
     /// Emit an unreachable instruction
     void EmitUnreachable();
 
     /// Emit a binary instruction
     /// @param b the binary instruction
-    void EmitBinary(ir::Binary* b);
+    void EmitBinary(core::ir::Binary* b);
 
     /// Emit a type
     /// @param out the stream to emit too
@@ -131,10 +131,10 @@
     /// @param sc the address space to generate
     void EmitAddressSpace(StringStream& out, core::AddressSpace sc);
 
-    /// Handles ir::Constant values
+    /// Handles core::ir::Constant values
     /// @param out the stream to write the constant too
     /// @param c the constant to emit
-    void EmitConstant(StringStream& out, ir::Constant* c);
+    void EmitConstant(StringStream& out, core::ir::Constant* c);
     /// Handles core::constant::Value values
     /// @param out the stream to write the constant too
     /// @param c the constant to emit
@@ -162,7 +162,7 @@
     /// Map of builtin structure to unique generated name
     std::unordered_map<const core::type::Struct*, std::string> builtin_struct_names_;
 
-    ir::Module* const ir_;
+    core::ir::Module* const ir_;
 
     /// The buffer holding preamble text
     TextBuffer preamble_buffer_;
@@ -174,9 +174,9 @@
     std::unordered_set<const core::type::Struct*> emitted_structs_;
 
     /// The current function being emitted
-    ir::Function* current_function_ = nullptr;
+    core::ir::Function* current_function_ = nullptr;
     /// The current block being emitted
-    ir::Block* current_block_ = nullptr;
+    core::ir::Block* current_block_ = nullptr;
 
     /// Unique name of the tint_array<T, N> template.
     /// Non-empty only if the template has been generated.
@@ -208,16 +208,16 @@
     using ValueBinding = std::variant<VariableValue, InlinedValue, ConsumedValue>;
 
     /// IR values to their representation
-    Hashmap<ir::Value*, ValueBinding, 32> bindings_;
+    Hashmap<core::ir::Value*, ValueBinding, 32> bindings_;
 
     /// Values that can be inlined.
-    Hashset<ir::Value*, 64> can_inline_;
+    Hashset<core::ir::Value*, 64> can_inline_;
 
     /// Returns the expression for the given value
     /// @param value the value to lookup
     /// @param want_ptr_kind the pointer information for the return
     /// @returns the string expression
-    std::string Expr(ir::Value* value, PtrKind want_ptr_kind = PtrKind::kRef);
+    std::string Expr(core::ir::Value* value, PtrKind want_ptr_kind = PtrKind::kRef);
 
     /// Returns the given expression converted to the given pointer kind
     /// @param in the input expression
@@ -229,17 +229,17 @@
     /// @param value the IR value
     /// @param expr the result expression
     /// @param ptr_kind defines how pointer values are represented by the expression
-    void Bind(ir::Value* value, const std::string& expr, PtrKind ptr_kind = PtrKind::kRef);
+    void Bind(core::ir::Value* value, const std::string& expr, PtrKind ptr_kind = PtrKind::kRef);
 
     /// Associates an IR value the 'var', 'let' or parameter of the given name
     /// @param value the IR value
     /// @param name the name for the value
     /// @param ptr_kind defines how pointer values are represented by @p expr.
-    void Bind(ir::Value* value, Symbol name, PtrKind ptr_kind = PtrKind::kRef);
+    void Bind(core::ir::Value* value, Symbol name, PtrKind ptr_kind = PtrKind::kRef);
 
     /// Marks instructions in a block for inlineability
     /// @param block the block
-    void MarkInlinable(ir::Block* block);
+    void MarkInlinable(core::ir::Block* block);
 };
 
 }  // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/printer/type_test.cc b/src/tint/lang/msl/writer/printer/type_test.cc
index ccbdf5d..5200b33 100644
--- a/src/tint/lang/msl/writer/printer/type_test.cc
+++ b/src/tint/lang/msl/writer/printer/type_test.cc
@@ -411,7 +411,7 @@
     uint32_t size = 0;
     uint32_t align = 0;
 };
-core::type::Struct* MkStruct(ir::Module& mod,
+core::type::Struct* MkStruct(core::ir::Module& mod,
                              core::type::Manager& ty,
                              std::string_view name,
                              VectorRef<MemberData> data) {
diff --git a/src/tint/lang/msl/writer/printer/var_test.cc b/src/tint/lang/msl/writer/printer/var_test.cc
index 09a1a58..ce8b498 100644
--- a/src/tint/lang/msl/writer/printer/var_test.cc
+++ b/src/tint/lang/msl/writer/printer/var_test.cc
@@ -236,7 +236,7 @@
 
 // TODO(dsinclair): Requires ModuleScopeVarToEntryPointParam transform
 TEST_F(MslPrinterTest, DISABLED_VarGlobalPrivate) {
-    ir::Var* v = nullptr;
+    core::ir::Var* v = nullptr;
     b.Append(b.RootBlock(), [&] { v = b.Var("v", ty.ptr<core::AddressSpace::kPrivate, f32>()); });
 
     auto* func = b.Function("foo", ty.void_());
@@ -262,7 +262,7 @@
 }
 
 TEST_F(MslPrinterTest, VarGlobalWorkgroup) {
-    ir::Var* v = nullptr;
+    core::ir::Var* v = nullptr;
     b.Append(b.RootBlock(), [&] { v = b.Var("v", ty.ptr<core::AddressSpace::kWorkgroup, f32>()); });
 
     auto* func = b.Function("foo", ty.void_());
diff --git a/src/tint/lang/msl/writer/raise/raise.cc b/src/tint/lang/msl/writer/raise/raise.cc
index 646322b..efd03324 100644
--- a/src/tint/lang/msl/writer/raise/raise.cc
+++ b/src/tint/lang/msl/writer/raise/raise.cc
@@ -18,10 +18,10 @@
 
 namespace tint::msl::raise {
 
-Result<SuccessType, std::string> Raise(ir::Module*) {
+Result<SuccessType, std::string> Raise(core::ir::Module*) {
     // #define RUN_TRANSFORM(name)
     //     do {
-    //         auto result = ir::transform::name(module);
+    //         auto result = core::ir::transform::name(module);
     //         if (!result) {
     //             return result;
     //         }
diff --git a/src/tint/lang/msl/writer/raise/raise.h b/src/tint/lang/msl/writer/raise/raise.h
index b460675..bb668e7 100644
--- a/src/tint/lang/msl/writer/raise/raise.h
+++ b/src/tint/lang/msl/writer/raise/raise.h
@@ -20,16 +20,16 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 namespace tint::msl::raise {
 
 /// Raise a core IR module to the MSL dialect of the IR.
 /// @param mod the core IR module to raise to MSL dialect
 /// @returns success or an error string
-Result<SuccessType, std::string> Raise(ir::Module* mod);
+Result<SuccessType, std::string> Raise(core::ir::Module* mod);
 
 }  // namespace tint::msl::raise
 
diff --git a/src/tint/lang/spirv/writer/binary_test.cc b/src/tint/lang/spirv/writer/binary_test.cc
index b9fdc92..d15d9bc 100644
--- a/src/tint/lang/spirv/writer/binary_test.cc
+++ b/src/tint/lang/spirv/writer/binary_test.cc
@@ -30,7 +30,7 @@
     /// The element type to test.
     TestElementType type;
     /// The binary operation.
-    enum ir::Binary::Kind kind;
+    enum core::ir::Binary::Kind kind;
     /// The expected SPIR-V instruction.
     std::string spirv_inst;
     /// The expected SPIR-V result type name.
@@ -71,52 +71,53 @@
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Binary_I32,
     Arithmetic_Bitwise,
-    testing::Values(BinaryTestCase{kI32, ir::Binary::Kind::kAdd, "OpIAdd", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kSubtract, "OpISub", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kMultiply, "OpIMul", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kDivide, "OpSDiv", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kModulo, "OpSRem", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kAnd, "OpBitwiseAnd", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kOr, "OpBitwiseOr", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kXor, "OpBitwiseXor", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kShiftLeft, "OpShiftLeftLogical", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kShiftRight, "OpShiftRightArithmetic",
-                                   "int"}));
+    testing::Values(BinaryTestCase{kI32, core::ir::Binary::Kind::kAdd, "OpIAdd", "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kSubtract, "OpISub", "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kMultiply, "OpIMul", "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kDivide, "OpSDiv", "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kModulo, "OpSRem", "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kAnd, "OpBitwiseAnd", "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kOr, "OpBitwiseOr", "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kXor, "OpBitwiseXor", "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kShiftLeft, "OpShiftLeftLogical",
+                                   "int"},
+                    BinaryTestCase{kI32, core::ir::Binary::Kind::kShiftRight,
+                                   "OpShiftRightArithmetic", "int"}));
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Binary_U32,
     Arithmetic_Bitwise,
     testing::Values(
-        BinaryTestCase{kU32, ir::Binary::Kind::kAdd, "OpIAdd", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kSubtract, "OpISub", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kMultiply, "OpIMul", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kDivide, "OpUDiv", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kModulo, "OpUMod", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kAnd, "OpBitwiseAnd", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kOr, "OpBitwiseOr", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kXor, "OpBitwiseXor", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kShiftLeft, "OpShiftLeftLogical", "uint"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kShiftRight, "OpShiftRightLogical", "uint"}));
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kAdd, "OpIAdd", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kSubtract, "OpISub", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kMultiply, "OpIMul", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kDivide, "OpUDiv", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kModulo, "OpUMod", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kAnd, "OpBitwiseAnd", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kOr, "OpBitwiseOr", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kXor, "OpBitwiseXor", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kShiftLeft, "OpShiftLeftLogical", "uint"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kShiftRight, "OpShiftRightLogical", "uint"}));
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Binary_F32,
     Arithmetic_Bitwise,
-    testing::Values(BinaryTestCase{kF32, ir::Binary::Kind::kAdd, "OpFAdd", "float"},
-                    BinaryTestCase{kF32, ir::Binary::Kind::kSubtract, "OpFSub", "float"},
-                    BinaryTestCase{kF32, ir::Binary::Kind::kMultiply, "OpFMul", "float"},
-                    BinaryTestCase{kF32, ir::Binary::Kind::kDivide, "OpFDiv", "float"},
-                    BinaryTestCase{kF32, ir::Binary::Kind::kModulo, "OpFRem", "float"}));
+    testing::Values(BinaryTestCase{kF32, core::ir::Binary::Kind::kAdd, "OpFAdd", "float"},
+                    BinaryTestCase{kF32, core::ir::Binary::Kind::kSubtract, "OpFSub", "float"},
+                    BinaryTestCase{kF32, core::ir::Binary::Kind::kMultiply, "OpFMul", "float"},
+                    BinaryTestCase{kF32, core::ir::Binary::Kind::kDivide, "OpFDiv", "float"},
+                    BinaryTestCase{kF32, core::ir::Binary::Kind::kModulo, "OpFRem", "float"}));
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Binary_F16,
     Arithmetic_Bitwise,
-    testing::Values(BinaryTestCase{kF16, ir::Binary::Kind::kAdd, "OpFAdd", "half"},
-                    BinaryTestCase{kF16, ir::Binary::Kind::kSubtract, "OpFSub", "half"},
-                    BinaryTestCase{kF16, ir::Binary::Kind::kMultiply, "OpFMul", "half"},
-                    BinaryTestCase{kF16, ir::Binary::Kind::kDivide, "OpFDiv", "half"},
-                    BinaryTestCase{kF16, ir::Binary::Kind::kModulo, "OpFRem", "half"}));
+    testing::Values(BinaryTestCase{kF16, core::ir::Binary::Kind::kAdd, "OpFAdd", "half"},
+                    BinaryTestCase{kF16, core::ir::Binary::Kind::kSubtract, "OpFSub", "half"},
+                    BinaryTestCase{kF16, core::ir::Binary::Kind::kMultiply, "OpFMul", "half"},
+                    BinaryTestCase{kF16, core::ir::Binary::Kind::kDivide, "OpFDiv", "half"},
+                    BinaryTestCase{kF16, core::ir::Binary::Kind::kModulo, "OpFRem", "half"}));
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Binary_Bool,
     Arithmetic_Bitwise,
-    testing::Values(BinaryTestCase{kBool, ir::Binary::Kind::kAnd, "OpLogicalAnd", "bool"},
-                    BinaryTestCase{kBool, ir::Binary::Kind::kOr, "OpLogicalOr", "bool"}));
+    testing::Values(BinaryTestCase{kBool, core::ir::Binary::Kind::kAnd, "OpLogicalAnd", "bool"},
+                    BinaryTestCase{kBool, core::ir::Binary::Kind::kOr, "OpLogicalOr", "bool"}));
 
 TEST_F(SpirvWriterTest, Binary_ScalarTimesVector_F32) {
     auto* scalar = b.FunctionParam("scalar", ty.f32());
@@ -259,47 +260,53 @@
     SpirvWriterTest_Binary_I32,
     Comparison,
     testing::Values(
-        BinaryTestCase{kI32, ir::Binary::Kind::kEqual, "OpIEqual", "bool"},
-        BinaryTestCase{kI32, ir::Binary::Kind::kNotEqual, "OpINotEqual", "bool"},
-        BinaryTestCase{kI32, ir::Binary::Kind::kGreaterThan, "OpSGreaterThan", "bool"},
-        BinaryTestCase{kI32, ir::Binary::Kind::kGreaterThanEqual, "OpSGreaterThanEqual", "bool"},
-        BinaryTestCase{kI32, ir::Binary::Kind::kLessThan, "OpSLessThan", "bool"},
-        BinaryTestCase{kI32, ir::Binary::Kind::kLessThanEqual, "OpSLessThanEqual", "bool"}));
+        BinaryTestCase{kI32, core::ir::Binary::Kind::kEqual, "OpIEqual", "bool"},
+        BinaryTestCase{kI32, core::ir::Binary::Kind::kNotEqual, "OpINotEqual", "bool"},
+        BinaryTestCase{kI32, core::ir::Binary::Kind::kGreaterThan, "OpSGreaterThan", "bool"},
+        BinaryTestCase{kI32, core::ir::Binary::Kind::kGreaterThanEqual, "OpSGreaterThanEqual",
+                       "bool"},
+        BinaryTestCase{kI32, core::ir::Binary::Kind::kLessThan, "OpSLessThan", "bool"},
+        BinaryTestCase{kI32, core::ir::Binary::Kind::kLessThanEqual, "OpSLessThanEqual", "bool"}));
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Binary_U32,
     Comparison,
     testing::Values(
-        BinaryTestCase{kU32, ir::Binary::Kind::kEqual, "OpIEqual", "bool"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kNotEqual, "OpINotEqual", "bool"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kGreaterThan, "OpUGreaterThan", "bool"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kGreaterThanEqual, "OpUGreaterThanEqual", "bool"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kLessThan, "OpULessThan", "bool"},
-        BinaryTestCase{kU32, ir::Binary::Kind::kLessThanEqual, "OpULessThanEqual", "bool"}));
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kEqual, "OpIEqual", "bool"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kNotEqual, "OpINotEqual", "bool"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kGreaterThan, "OpUGreaterThan", "bool"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kGreaterThanEqual, "OpUGreaterThanEqual",
+                       "bool"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kLessThan, "OpULessThan", "bool"},
+        BinaryTestCase{kU32, core::ir::Binary::Kind::kLessThanEqual, "OpULessThanEqual", "bool"}));
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Binary_F32,
     Comparison,
     testing::Values(
-        BinaryTestCase{kF32, ir::Binary::Kind::kEqual, "OpFOrdEqual", "bool"},
-        BinaryTestCase{kF32, ir::Binary::Kind::kNotEqual, "OpFOrdNotEqual", "bool"},
-        BinaryTestCase{kF32, ir::Binary::Kind::kGreaterThan, "OpFOrdGreaterThan", "bool"},
-        BinaryTestCase{kF32, ir::Binary::Kind::kGreaterThanEqual, "OpFOrdGreaterThanEqual", "bool"},
-        BinaryTestCase{kF32, ir::Binary::Kind::kLessThan, "OpFOrdLessThan", "bool"},
-        BinaryTestCase{kF32, ir::Binary::Kind::kLessThanEqual, "OpFOrdLessThanEqual", "bool"}));
+        BinaryTestCase{kF32, core::ir::Binary::Kind::kEqual, "OpFOrdEqual", "bool"},
+        BinaryTestCase{kF32, core::ir::Binary::Kind::kNotEqual, "OpFOrdNotEqual", "bool"},
+        BinaryTestCase{kF32, core::ir::Binary::Kind::kGreaterThan, "OpFOrdGreaterThan", "bool"},
+        BinaryTestCase{kF32, core::ir::Binary::Kind::kGreaterThanEqual, "OpFOrdGreaterThanEqual",
+                       "bool"},
+        BinaryTestCase{kF32, core::ir::Binary::Kind::kLessThan, "OpFOrdLessThan", "bool"},
+        BinaryTestCase{kF32, core::ir::Binary::Kind::kLessThanEqual, "OpFOrdLessThanEqual",
+                       "bool"}));
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Binary_F16,
     Comparison,
     testing::Values(
-        BinaryTestCase{kF16, ir::Binary::Kind::kEqual, "OpFOrdEqual", "bool"},
-        BinaryTestCase{kF16, ir::Binary::Kind::kNotEqual, "OpFOrdNotEqual", "bool"},
-        BinaryTestCase{kF16, ir::Binary::Kind::kGreaterThan, "OpFOrdGreaterThan", "bool"},
-        BinaryTestCase{kF16, ir::Binary::Kind::kGreaterThanEqual, "OpFOrdGreaterThanEqual", "bool"},
-        BinaryTestCase{kF16, ir::Binary::Kind::kLessThan, "OpFOrdLessThan", "bool"},
-        BinaryTestCase{kF16, ir::Binary::Kind::kLessThanEqual, "OpFOrdLessThanEqual", "bool"}));
+        BinaryTestCase{kF16, core::ir::Binary::Kind::kEqual, "OpFOrdEqual", "bool"},
+        BinaryTestCase{kF16, core::ir::Binary::Kind::kNotEqual, "OpFOrdNotEqual", "bool"},
+        BinaryTestCase{kF16, core::ir::Binary::Kind::kGreaterThan, "OpFOrdGreaterThan", "bool"},
+        BinaryTestCase{kF16, core::ir::Binary::Kind::kGreaterThanEqual, "OpFOrdGreaterThanEqual",
+                       "bool"},
+        BinaryTestCase{kF16, core::ir::Binary::Kind::kLessThan, "OpFOrdLessThan", "bool"},
+        BinaryTestCase{kF16, core::ir::Binary::Kind::kLessThanEqual, "OpFOrdLessThanEqual",
+                       "bool"}));
 INSTANTIATE_TEST_SUITE_P(SpirvWriterTest_Binary_Bool,
                          Comparison,
-                         testing::Values(BinaryTestCase{kBool, ir::Binary::Kind::kEqual,
+                         testing::Values(BinaryTestCase{kBool, core::ir::Binary::Kind::kEqual,
                                                         "OpLogicalEqual", "bool"},
-                                         BinaryTestCase{kBool, ir::Binary::Kind::kNotEqual,
+                                         BinaryTestCase{kBool, core::ir::Binary::Kind::kNotEqual,
                                                         "OpLogicalNotEqual", "bool"}));
 
 TEST_F(SpirvWriterTest, Binary_Chain) {
diff --git a/src/tint/lang/spirv/writer/common/helper_test.h b/src/tint/lang/spirv/writer/common/helper_test.h
index 62e811c..e534c6a 100644
--- a/src/tint/lang/spirv/writer/common/helper_test.h
+++ b/src/tint/lang/spirv/writer/common/helper_test.h
@@ -81,9 +81,9 @@
     SpirvWriterTestHelperBase() : writer_(&mod, false) {}
 
     /// The test module.
-    ir::Module mod;
+    core::ir::Module mod;
     /// The test builder.
-    ir::Builder b{mod};
+    core::ir::Builder b{mod};
     /// The type manager.
     core::type::Manager& ty{mod.Types()};
 
@@ -199,7 +199,7 @@
     /// @param type the element type
     /// @param value the optional value to use
     /// @returns the scalar value
-    ir::Constant* MakeScalarValue(TestElementType type, uint32_t value = 1) {
+    core::ir::Constant* MakeScalarValue(TestElementType type, uint32_t value = 1) {
         switch (type) {
             case kBool:
                 return b.Constant(true);
@@ -218,7 +218,7 @@
     /// Helper to make a vector value with an element type of `type`.
     /// @param type the element type
     /// @returns the vector value
-    ir::Constant* MakeVectorValue(TestElementType type) {
+    core::ir::Constant* MakeVectorValue(TestElementType type) {
         switch (type) {
             case kBool:
                 return b.Composite(MakeVectorType(type), true, false);
diff --git a/src/tint/lang/spirv/writer/discard_test.cc b/src/tint/lang/spirv/writer/discard_test.cc
index ea3281a..74d383d 100644
--- a/src/tint/lang/spirv/writer/discard_test.cc
+++ b/src/tint/lang/spirv/writer/discard_test.cc
@@ -28,8 +28,8 @@
     b.RootBlock()->Append(buffer);
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(ir::FunctionParam::Builtin::kFrontFacing);
-    auto* ep = b.Function("ep", ty.f32(), ir::Function::PipelineStage::kFragment);
+    front_facing->SetBuiltin(core::ir::FunctionParam::Builtin::kFrontFacing);
+    auto* ep = b.Function("ep", ty.f32(), core::ir::Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
 
diff --git a/src/tint/lang/spirv/writer/function_test.cc b/src/tint/lang/spirv/writer/function_test.cc
index 971cc30..6ab2c34 100644
--- a/src/tint/lang/spirv/writer/function_test.cc
+++ b/src/tint/lang/spirv/writer/function_test.cc
@@ -80,7 +80,7 @@
 
 TEST_F(SpirvWriterTest, Function_EntryPoint_Compute) {
     auto* func =
-        b.Function("main", ty.void_(), ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
+        b.Function("main", ty.void_(), core::ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
     b.Append(func->Block(), [&] {  //
         b.Return(func);
     });
@@ -106,7 +106,7 @@
 }
 
 TEST_F(SpirvWriterTest, Function_EntryPoint_Fragment) {
-    auto* func = b.Function("main", ty.void_(), ir::Function::PipelineStage::kFragment);
+    auto* func = b.Function("main", ty.void_(), core::ir::Function::PipelineStage::kFragment);
     b.Append(func->Block(), [&] {  //
         b.Return(func);
     });
@@ -132,7 +132,7 @@
 }
 
 TEST_F(SpirvWriterTest, Function_EntryPoint_Vertex) {
-    auto* func = b.Function("main", ty.void_(), ir::Function::PipelineStage::kVertex);
+    auto* func = b.Function("main", ty.void_(), core::ir::Function::PipelineStage::kVertex);
     b.Append(func->Block(), [&] {  //
         b.Return(func);
     });
@@ -157,17 +157,19 @@
 }
 
 TEST_F(SpirvWriterTest, Function_EntryPoint_Multiple) {
-    auto* f1 = b.Function("main1", ty.void_(), ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
+    auto* f1 =
+        b.Function("main1", ty.void_(), core::ir::Function::PipelineStage::kCompute, {{32, 4, 1}});
     b.Append(f1->Block(), [&] {  //
         b.Return(f1);
     });
 
-    auto* f2 = b.Function("main2", ty.void_(), ir::Function::PipelineStage::kCompute, {{8, 2, 16}});
+    auto* f2 =
+        b.Function("main2", ty.void_(), core::ir::Function::PipelineStage::kCompute, {{8, 2, 16}});
     b.Append(f2->Block(), [&] {  //
         b.Return(f2);
     });
 
-    auto* f3 = b.Function("main3", ty.void_(), ir::Function::PipelineStage::kFragment);
+    auto* f3 = b.Function("main3", ty.void_(), core::ir::Function::PipelineStage::kFragment);
     b.Append(f3->Block(), [&] {  //
         b.Return(f3);
     });
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index 827ee1e..ca7e390 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -150,11 +150,11 @@
 
 }  // namespace
 
-Printer::Printer(ir::Module* module, bool zero_init_workgroup_mem)
+Printer::Printer(core::ir::Module* module, bool zero_init_workgroup_mem)
     : ir_(module), b_(*module), zero_init_workgroup_memory_(zero_init_workgroup_mem) {}
 
 Result<std::vector<uint32_t>, std::string> Printer::Generate() {
-    auto valid = ir::ValidateAndDumpIfNeeded(*ir_, "SPIR-V writer");
+    auto valid = core::ir::ValidateAndDumpIfNeeded(*ir_, "SPIR-V writer");
     if (!valid) {
         return std::move(valid.Failure());
     }
@@ -231,7 +231,7 @@
     return SpvBuiltInMax;
 }
 
-uint32_t Printer::Constant(ir::Constant* constant) {
+uint32_t Printer::Constant(core::ir::Constant* constant) {
     // If it is a literal operand, just return the value.
     if (auto* literal = constant->As<raise::LiteralOperand>()) {
         return literal->Value()->ValueAs<uint32_t>();
@@ -383,18 +383,20 @@
     });
 }
 
-uint32_t Printer::Value(ir::Instruction* inst) {
+uint32_t Printer::Value(core::ir::Instruction* inst) {
     return Value(inst->Result());
 }
 
-uint32_t Printer::Value(ir::Value* value) {
+uint32_t Printer::Value(core::ir::Value* value) {
     return Switch(
         value,  //
-        [&](ir::Constant* constant) { return Constant(constant); },
-        [&](ir::Value*) { return values_.GetOrCreate(value, [&] { return module_.NextId(); }); });
+        [&](core::ir::Constant* constant) { return Constant(constant); },
+        [&](core::ir::Value*) {
+            return values_.GetOrCreate(value, [&] { return module_.NextId(); });
+        });
 }
 
-uint32_t Printer::Label(ir::Block* block) {
+uint32_t Printer::Label(core::ir::Block* block) {
     return block_labels_.GetOrCreate(block, [&] { return module_.NextId(); });
 }
 
@@ -573,14 +575,14 @@
                      {id, sampled_type, dim, depth, array, ms, sampled, format});
 }
 
-void Printer::EmitFunction(ir::Function* func) {
+void Printer::EmitFunction(core::ir::Function* func) {
     auto id = Value(func);
 
     // Emit the function name.
     module_.PushDebug(spv::Op::OpName, {id, Operand(ir_->NameOf(func).Name())});
 
     // Emit OpEntryPoint and OpExecutionMode declarations if needed.
-    if (func->Stage() != ir::Function::PipelineStage::kUndefined) {
+    if (func->Stage() != core::ir::Function::PipelineStage::kUndefined) {
         EmitEntryPoint(func, id);
     }
 
@@ -628,10 +630,10 @@
     module_.PushFunction(current_function_);
 }
 
-void Printer::EmitEntryPoint(ir::Function* func, uint32_t id) {
+void Printer::EmitEntryPoint(core::ir::Function* func, uint32_t id) {
     SpvExecutionModel stage = SpvExecutionModelMax;
     switch (func->Stage()) {
-        case ir::Function::PipelineStage::kCompute: {
+        case core::ir::Function::PipelineStage::kCompute: {
             stage = SpvExecutionModelGLCompute;
             module_.PushExecutionMode(
                 spv::Op::OpExecutionMode,
@@ -639,17 +641,17 @@
                  func->WorkgroupSize()->at(1), func->WorkgroupSize()->at(2)});
             break;
         }
-        case ir::Function::PipelineStage::kFragment: {
+        case core::ir::Function::PipelineStage::kFragment: {
             stage = SpvExecutionModelFragment;
             module_.PushExecutionMode(spv::Op::OpExecutionMode,
                                       {id, U32Operand(SpvExecutionModeOriginUpperLeft)});
             break;
         }
-        case ir::Function::PipelineStage::kVertex: {
+        case core::ir::Function::PipelineStage::kVertex: {
             stage = SpvExecutionModelVertex;
             break;
         }
-        case ir::Function::PipelineStage::kUndefined:
+        case core::ir::Function::PipelineStage::kUndefined:
             TINT_ICE() << "undefined pipeline stage for entry point";
             return;
     }
@@ -659,7 +661,7 @@
     // Add the list of all referenced shader IO variables.
     if (ir_->root_block) {
         for (auto* global : *ir_->root_block) {
-            auto* var = global->As<ir::Var>();
+            auto* var = global->As<core::ir::Var>();
             if (!var) {
                 continue;
             }
@@ -702,18 +704,18 @@
     module_.PushEntryPoint(spv::Op::OpEntryPoint, operands);
 }
 
-void Printer::EmitRootBlock(ir::Block* root_block) {
+void Printer::EmitRootBlock(core::ir::Block* root_block) {
     for (auto* inst : *root_block) {
         Switch(
             inst,  //
-            [&](ir::Var* v) { return EmitVar(v); },
+            [&](core::ir::Var* v) { return EmitVar(v); },
             [&](Default) {
                 TINT_ICE() << "unimplemented root block instruction: " << inst->TypeInfo().name;
             });
     }
 }
 
-void Printer::EmitBlock(ir::Block* block) {
+void Printer::EmitBlock(core::ir::Block* block) {
     // Emit the label.
     // Skip if this is the function's entry block, as it will be emitted by the function object.
     if (!current_function_.instructions().empty()) {
@@ -727,7 +729,7 @@
         return;
     }
 
-    if (auto* mib = block->As<ir::MultiInBlock>()) {
+    if (auto* mib = block->As<core::ir::MultiInBlock>()) {
         // Emit all OpPhi nodes for incoming branches to block.
         EmitIncomingPhis(mib);
     }
@@ -736,7 +738,7 @@
     EmitBlockInstructions(block);
 }
 
-void Printer::EmitIncomingPhis(ir::MultiInBlock* block) {
+void Printer::EmitIncomingPhis(core::ir::MultiInBlock* block) {
     // Emit Phi nodes for all the incoming block parameters
     for (size_t param_idx = 0; param_idx < block->Params().Length(); param_idx++) {
         auto* param = block->Params()[param_idx];
@@ -752,34 +754,34 @@
     }
 }
 
-void Printer::EmitBlockInstructions(ir::Block* block) {
+void Printer::EmitBlockInstructions(core::ir::Block* block) {
     for (auto* inst : *block) {
         Switch(
-            inst,                                                           //
-            [&](ir::Access* a) { EmitAccess(a); },                          //
-            [&](ir::Binary* b) { EmitBinary(b); },                          //
-            [&](ir::Bitcast* b) { EmitBitcast(b); },                        //
-            [&](ir::CoreBuiltinCall* b) { EmitCoreBuiltinCall(b); },        //
-            [&](ir::Construct* c) { EmitConstruct(c); },                    //
-            [&](ir::Convert* c) { EmitConvert(c); },                        //
-            [&](ir::IntrinsicCall* i) { EmitIntrinsicCall(i); },            //
-            [&](ir::Load* l) { EmitLoad(l); },                              //
-            [&](ir::LoadVectorElement* l) { EmitLoadVectorElement(l); },    //
-            [&](ir::Loop* l) { EmitLoop(l); },                              //
-            [&](ir::Switch* sw) { EmitSwitch(sw); },                        //
-            [&](ir::Swizzle* s) { EmitSwizzle(s); },                        //
-            [&](ir::Store* s) { EmitStore(s); },                            //
-            [&](ir::StoreVectorElement* s) { EmitStoreVectorElement(s); },  //
-            [&](ir::UserCall* c) { EmitUserCall(c); },                      //
-            [&](ir::Unary* u) { EmitUnary(u); },                            //
-            [&](ir::Var* v) { EmitVar(v); },                                //
-            [&](ir::Let* l) { EmitLet(l); },                                //
-            [&](ir::If* i) { EmitIf(i); },                                  //
-            [&](ir::Terminator* t) { EmitTerminator(t); },                  //
+            inst,                                                                 //
+            [&](core::ir::Access* a) { EmitAccess(a); },                          //
+            [&](core::ir::Binary* b) { EmitBinary(b); },                          //
+            [&](core::ir::Bitcast* b) { EmitBitcast(b); },                        //
+            [&](core::ir::CoreBuiltinCall* b) { EmitCoreBuiltinCall(b); },        //
+            [&](core::ir::Construct* c) { EmitConstruct(c); },                    //
+            [&](core::ir::Convert* c) { EmitConvert(c); },                        //
+            [&](core::ir::IntrinsicCall* i) { EmitIntrinsicCall(i); },            //
+            [&](core::ir::Load* l) { EmitLoad(l); },                              //
+            [&](core::ir::LoadVectorElement* l) { EmitLoadVectorElement(l); },    //
+            [&](core::ir::Loop* l) { EmitLoop(l); },                              //
+            [&](core::ir::Switch* sw) { EmitSwitch(sw); },                        //
+            [&](core::ir::Swizzle* s) { EmitSwizzle(s); },                        //
+            [&](core::ir::Store* s) { EmitStore(s); },                            //
+            [&](core::ir::StoreVectorElement* s) { EmitStoreVectorElement(s); },  //
+            [&](core::ir::UserCall* c) { EmitUserCall(c); },                      //
+            [&](core::ir::Unary* u) { EmitUnary(u); },                            //
+            [&](core::ir::Var* v) { EmitVar(v); },                                //
+            [&](core::ir::Let* l) { EmitLet(l); },                                //
+            [&](core::ir::If* i) { EmitIf(i); },                                  //
+            [&](core::ir::Terminator* t) { EmitTerminator(t); },                  //
             [&](Default) { TINT_ICE() << "unimplemented instruction: " << inst->TypeInfo().name; });
 
         // Set the name for the SPIR-V result ID if provided in the module.
-        if (inst->Result() && !inst->Is<ir::Var>()) {
+        if (inst->Result() && !inst->Is<core::ir::Var>()) {
             if (auto name = ir_->NameOf(inst)) {
                 module_.PushDebug(spv::Op::OpName, {Value(inst), Operand(name.Name())});
             }
@@ -792,10 +794,10 @@
     }
 }
 
-void Printer::EmitTerminator(ir::Terminator* t) {
+void Printer::EmitTerminator(core::ir::Terminator* t) {
     tint::Switch(  //
         t,         //
-        [&](ir::Return*) {
+        [&](core::ir::Return*) {
             if (!t->Args().IsEmpty()) {
                 TINT_ASSERT(t->Args().Length() == 1u);
                 OperandList operands;
@@ -806,7 +808,7 @@
             }
             return;
         },
-        [&](ir::BreakIf* breakif) {
+        [&](core::ir::BreakIf* breakif) {
             current_function_.push_inst(spv::Op::OpBranchConditional,
                                         {
                                             Value(breakif->Condition()),
@@ -814,24 +816,28 @@
                                             loop_header_label_,
                                         });
         },
-        [&](ir::Continue* cont) {
+        [&](core::ir::Continue* cont) {
             current_function_.push_inst(spv::Op::OpBranch, {Label(cont->Loop()->Continuing())});
         },
-        [&](ir::ExitIf*) { current_function_.push_inst(spv::Op::OpBranch, {if_merge_label_}); },
-        [&](ir::ExitLoop*) { current_function_.push_inst(spv::Op::OpBranch, {loop_merge_label_}); },
-        [&](ir::ExitSwitch*) {
+        [&](core::ir::ExitIf*) {
+            current_function_.push_inst(spv::Op::OpBranch, {if_merge_label_});
+        },
+        [&](core::ir::ExitLoop*) {
+            current_function_.push_inst(spv::Op::OpBranch, {loop_merge_label_});
+        },
+        [&](core::ir::ExitSwitch*) {
             current_function_.push_inst(spv::Op::OpBranch, {switch_merge_label_});
         },
-        [&](ir::NextIteration*) {
+        [&](core::ir::NextIteration*) {
             current_function_.push_inst(spv::Op::OpBranch, {loop_header_label_});
         },
-        [&](ir::TerminateInvocation*) { current_function_.push_inst(spv::Op::OpKill, {}); },
-        [&](ir::Unreachable*) { current_function_.push_inst(spv::Op::OpUnreachable, {}); },
+        [&](core::ir::TerminateInvocation*) { current_function_.push_inst(spv::Op::OpKill, {}); },
+        [&](core::ir::Unreachable*) { current_function_.push_inst(spv::Op::OpUnreachable, {}); },
 
         [&](Default) { TINT_ICE() << "unimplemented branch: " << t->TypeInfo().name; });
 }
 
-void Printer::EmitIf(ir::If* i) {
+void Printer::EmitIf(core::ir::If* i) {
     auto* true_block = i->True();
     auto* false_block = i->False();
 
@@ -846,11 +852,11 @@
     uint32_t true_label = merge_label;
     uint32_t false_label = merge_label;
     if (true_block->Length() > 1 || i->HasResults() ||
-        (true_block->HasTerminator() && !true_block->Terminator()->Is<ir::ExitIf>())) {
+        (true_block->HasTerminator() && !true_block->Terminator()->Is<core::ir::ExitIf>())) {
         true_label = Label(true_block);
     }
     if (false_block->Length() > 1 || i->HasResults() ||
-        (false_block->HasTerminator() && !false_block->Terminator()->Is<ir::ExitIf>())) {
+        (false_block->HasTerminator() && !false_block->Terminator()->Is<core::ir::ExitIf>())) {
         false_label = Label(false_block);
     }
 
@@ -874,7 +880,7 @@
     EmitExitPhis(i);
 }
 
-void Printer::EmitAccess(ir::Access* access) {
+void Printer::EmitAccess(core::ir::Access* access) {
     auto* ty = access->Result()->Type();
 
     auto id = Value(access);
@@ -893,7 +899,7 @@
     // If we hit a non-constant index into a vector type, use OpVectorExtractDynamic for it.
     auto* source_ty = access->Object()->Type();
     for (auto* idx : access->Indices()) {
-        if (auto* constant = idx->As<ir::Constant>()) {
+        if (auto* constant = idx->As<core::ir::Constant>()) {
             // Push the index to the chain and update the current type.
             auto i = constant->Value()->ValueAs<u32>();
             operands.push_back(i);
@@ -922,7 +928,7 @@
     current_function_.push_inst(spv::Op::OpCompositeExtract, std::move(operands));
 }
 
-void Printer::EmitBinary(ir::Binary* binary) {
+void Printer::EmitBinary(core::ir::Binary* binary) {
     auto id = Value(binary);
     auto lhs = Value(binary->LHS());
     auto rhs = Value(binary->RHS());
@@ -932,11 +938,11 @@
     // Determine the opcode.
     spv::Op op = spv::Op::Max;
     switch (binary->Kind()) {
-        case ir::Binary::Kind::kAdd: {
+        case core::ir::Binary::Kind::kAdd: {
             op = ty->is_integer_scalar_or_vector() ? spv::Op::OpIAdd : spv::Op::OpFAdd;
             break;
         }
-        case ir::Binary::Kind::kDivide: {
+        case core::ir::Binary::Kind::kDivide: {
             if (ty->is_signed_integer_scalar_or_vector()) {
                 op = spv::Op::OpSDiv;
             } else if (ty->is_unsigned_integer_scalar_or_vector()) {
@@ -946,7 +952,7 @@
             }
             break;
         }
-        case ir::Binary::Kind::kMultiply: {
+        case core::ir::Binary::Kind::kMultiply: {
             if (ty->is_integer_scalar_or_vector()) {
                 op = spv::Op::OpIMul;
             } else if (ty->is_float_scalar_or_vector()) {
@@ -954,11 +960,11 @@
             }
             break;
         }
-        case ir::Binary::Kind::kSubtract: {
+        case core::ir::Binary::Kind::kSubtract: {
             op = ty->is_integer_scalar_or_vector() ? spv::Op::OpISub : spv::Op::OpFSub;
             break;
         }
-        case ir::Binary::Kind::kModulo: {
+        case core::ir::Binary::Kind::kModulo: {
             if (ty->is_signed_integer_scalar_or_vector()) {
                 op = spv::Op::OpSRem;
             } else if (ty->is_unsigned_integer_scalar_or_vector()) {
@@ -969,7 +975,7 @@
             break;
         }
 
-        case ir::Binary::Kind::kAnd: {
+        case core::ir::Binary::Kind::kAnd: {
             if (ty->is_integer_scalar_or_vector()) {
                 op = spv::Op::OpBitwiseAnd;
             } else if (ty->is_bool_scalar_or_vector()) {
@@ -977,7 +983,7 @@
             }
             break;
         }
-        case ir::Binary::Kind::kOr: {
+        case core::ir::Binary::Kind::kOr: {
             if (ty->is_integer_scalar_or_vector()) {
                 op = spv::Op::OpBitwiseOr;
             } else if (ty->is_bool_scalar_or_vector()) {
@@ -985,16 +991,16 @@
             }
             break;
         }
-        case ir::Binary::Kind::kXor: {
+        case core::ir::Binary::Kind::kXor: {
             op = spv::Op::OpBitwiseXor;
             break;
         }
 
-        case ir::Binary::Kind::kShiftLeft: {
+        case core::ir::Binary::Kind::kShiftLeft: {
             op = spv::Op::OpShiftLeftLogical;
             break;
         }
-        case ir::Binary::Kind::kShiftRight: {
+        case core::ir::Binary::Kind::kShiftRight: {
             if (ty->is_signed_integer_scalar_or_vector()) {
                 op = spv::Op::OpShiftRightArithmetic;
             } else if (ty->is_unsigned_integer_scalar_or_vector()) {
@@ -1003,7 +1009,7 @@
             break;
         }
 
-        case ir::Binary::Kind::kEqual: {
+        case core::ir::Binary::Kind::kEqual: {
             if (lhs_ty->is_bool_scalar_or_vector()) {
                 op = spv::Op::OpLogicalEqual;
             } else if (lhs_ty->is_float_scalar_or_vector()) {
@@ -1013,7 +1019,7 @@
             }
             break;
         }
-        case ir::Binary::Kind::kNotEqual: {
+        case core::ir::Binary::Kind::kNotEqual: {
             if (lhs_ty->is_bool_scalar_or_vector()) {
                 op = spv::Op::OpLogicalNotEqual;
             } else if (lhs_ty->is_float_scalar_or_vector()) {
@@ -1023,7 +1029,7 @@
             }
             break;
         }
-        case ir::Binary::Kind::kGreaterThan: {
+        case core::ir::Binary::Kind::kGreaterThan: {
             if (lhs_ty->is_float_scalar_or_vector()) {
                 op = spv::Op::OpFOrdGreaterThan;
             } else if (lhs_ty->is_signed_integer_scalar_or_vector()) {
@@ -1033,7 +1039,7 @@
             }
             break;
         }
-        case ir::Binary::Kind::kGreaterThanEqual: {
+        case core::ir::Binary::Kind::kGreaterThanEqual: {
             if (lhs_ty->is_float_scalar_or_vector()) {
                 op = spv::Op::OpFOrdGreaterThanEqual;
             } else if (lhs_ty->is_signed_integer_scalar_or_vector()) {
@@ -1043,7 +1049,7 @@
             }
             break;
         }
-        case ir::Binary::Kind::kLessThan: {
+        case core::ir::Binary::Kind::kLessThan: {
             if (lhs_ty->is_float_scalar_or_vector()) {
                 op = spv::Op::OpFOrdLessThan;
             } else if (lhs_ty->is_signed_integer_scalar_or_vector()) {
@@ -1053,7 +1059,7 @@
             }
             break;
         }
-        case ir::Binary::Kind::kLessThanEqual: {
+        case core::ir::Binary::Kind::kLessThanEqual: {
             if (lhs_ty->is_float_scalar_or_vector()) {
                 op = spv::Op::OpFOrdLessThanEqual;
             } else if (lhs_ty->is_signed_integer_scalar_or_vector()) {
@@ -1069,7 +1075,7 @@
     current_function_.push_inst(op, {Type(ty), id, lhs, rhs});
 }
 
-void Printer::EmitBitcast(ir::Bitcast* bitcast) {
+void Printer::EmitBitcast(core::ir::Bitcast* bitcast) {
     auto* ty = bitcast->Result()->Type();
     if (ty == bitcast->Val()->Type()) {
         values_.Add(bitcast->Result(), Value(bitcast->Val()));
@@ -1079,7 +1085,7 @@
                                 {Type(ty), Value(bitcast), Value(bitcast->Val())});
 }
 
-void Printer::EmitCoreBuiltinCall(ir::CoreBuiltinCall* builtin) {
+void Printer::EmitCoreBuiltinCall(core::ir::CoreBuiltinCall* builtin) {
     auto* result_ty = builtin->Result()->Type();
 
     if (builtin->Func() == core::Function::kAbs &&
@@ -1425,7 +1431,7 @@
     current_function_.push_inst(op, operands);
 }
 
-void Printer::EmitConstruct(ir::Construct* construct) {
+void Printer::EmitConstruct(core::ir::Construct* construct) {
     // If there is just a single argument with the same type as the result, this is an identity
     // constructor and we can just pass through the ID of the argument.
     if (construct->Args().Length() == 1 &&
@@ -1441,7 +1447,7 @@
     current_function_.push_inst(spv::Op::OpCompositeConstruct, std::move(operands));
 }
 
-void Printer::EmitConvert(ir::Convert* convert) {
+void Printer::EmitConvert(core::ir::Convert* convert) {
     auto* res_ty = convert->Result()->Type();
     auto* arg_ty = convert->Args()[0]->Type();
 
@@ -1485,8 +1491,8 @@
         operands.push_back(ConstantNull(arg_ty));
     } else if (arg_ty->is_bool_scalar_or_vector()) {
         // Select between constant one and zero, splatting them to vectors if necessary.
-        ir::Constant* one = nullptr;
-        ir::Constant* zero = nullptr;
+        core::ir::Constant* one = nullptr;
+        core::ir::Constant* zero = nullptr;
         Switch(
             res_ty->DeepestElement(),  //
             [&](const core::type::F32*) {
@@ -1523,107 +1529,107 @@
     current_function_.push_inst(op, std::move(operands));
 }
 
-void Printer::EmitIntrinsicCall(ir::IntrinsicCall* call) {
+void Printer::EmitIntrinsicCall(core::ir::IntrinsicCall* call) {
     auto id = Value(call);
 
     spv::Op op = spv::Op::Max;
     switch (call->Kind()) {
-        case ir::IntrinsicCall::Kind::kSpirvArrayLength:
+        case core::ir::IntrinsicCall::Kind::kSpirvArrayLength:
             op = spv::Op::OpArrayLength;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicIAdd:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicIAdd:
             op = spv::Op::OpAtomicIAdd;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicISub:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicISub:
             op = spv::Op::OpAtomicISub;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicAnd:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicAnd:
             op = spv::Op::OpAtomicAnd;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicCompareExchange:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicCompareExchange:
             op = spv::Op::OpAtomicCompareExchange;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicExchange:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicExchange:
             op = spv::Op::OpAtomicExchange;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicLoad:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicLoad:
             op = spv::Op::OpAtomicLoad;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicOr:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicOr:
             op = spv::Op::OpAtomicOr;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicSMax:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicSMax:
             op = spv::Op::OpAtomicSMax;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicSMin:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicSMin:
             op = spv::Op::OpAtomicSMin;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicStore:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicStore:
             op = spv::Op::OpAtomicStore;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicUMax:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicUMax:
             op = spv::Op::OpAtomicUMax;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicUMin:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicUMin:
             op = spv::Op::OpAtomicUMin;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvAtomicXor:
+        case core::ir::IntrinsicCall::Kind::kSpirvAtomicXor:
             op = spv::Op::OpAtomicXor;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvDot:
+        case core::ir::IntrinsicCall::Kind::kSpirvDot:
             op = spv::Op::OpDot;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageFetch:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageFetch:
             op = spv::Op::OpImageFetch;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageGather:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageGather:
             op = spv::Op::OpImageGather;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageDrefGather:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageDrefGather:
             op = spv::Op::OpImageDrefGather;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageQuerySize:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageQuerySize:
             module_.PushCapability(SpvCapabilityImageQuery);
             op = spv::Op::OpImageQuerySize;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageQuerySizeLod:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageQuerySizeLod:
             module_.PushCapability(SpvCapabilityImageQuery);
             op = spv::Op::OpImageQuerySizeLod;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageSampleImplicitLod:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageSampleImplicitLod:
             op = spv::Op::OpImageSampleImplicitLod;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageSampleExplicitLod:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageSampleExplicitLod:
             op = spv::Op::OpImageSampleExplicitLod;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageSampleDrefImplicitLod:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageSampleDrefImplicitLod:
             op = spv::Op::OpImageSampleDrefImplicitLod;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageSampleDrefExplicitLod:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageSampleDrefExplicitLod:
             op = spv::Op::OpImageSampleDrefExplicitLod;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvImageWrite:
+        case core::ir::IntrinsicCall::Kind::kSpirvImageWrite:
             op = spv::Op::OpImageWrite;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvMatrixTimesMatrix:
+        case core::ir::IntrinsicCall::Kind::kSpirvMatrixTimesMatrix:
             op = spv::Op::OpMatrixTimesMatrix;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvMatrixTimesScalar:
+        case core::ir::IntrinsicCall::Kind::kSpirvMatrixTimesScalar:
             op = spv::Op::OpMatrixTimesScalar;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvMatrixTimesVector:
+        case core::ir::IntrinsicCall::Kind::kSpirvMatrixTimesVector:
             op = spv::Op::OpMatrixTimesVector;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvSampledImage:
+        case core::ir::IntrinsicCall::Kind::kSpirvSampledImage:
             op = spv::Op::OpSampledImage;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvSelect:
+        case core::ir::IntrinsicCall::Kind::kSpirvSelect:
             op = spv::Op::OpSelect;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvVectorTimesMatrix:
+        case core::ir::IntrinsicCall::Kind::kSpirvVectorTimesMatrix:
             op = spv::Op::OpVectorTimesMatrix;
             break;
-        case ir::IntrinsicCall::Kind::kSpirvVectorTimesScalar:
+        case core::ir::IntrinsicCall::Kind::kSpirvVectorTimesScalar:
             op = spv::Op::OpVectorTimesScalar;
             break;
     }
@@ -1638,12 +1644,12 @@
     current_function_.push_inst(op, operands);
 }
 
-void Printer::EmitLoad(ir::Load* load) {
+void Printer::EmitLoad(core::ir::Load* load) {
     current_function_.push_inst(spv::Op::OpLoad,
                                 {Type(load->Result()->Type()), Value(load), Value(load->From())});
 }
 
-void Printer::EmitLoadVectorElement(ir::LoadVectorElement* load) {
+void Printer::EmitLoadVectorElement(core::ir::LoadVectorElement* load) {
     auto* vec_ptr_ty = load->From()->Type()->As<core::type::Pointer>();
     auto* el_ty = load->Result()->Type();
     auto* el_ptr_ty = ir_->Types().ptr(vec_ptr_ty->AddressSpace(), el_ty, vec_ptr_ty->Access());
@@ -1655,7 +1661,7 @@
                                 {Type(load->Result()->Type()), Value(load), el_ptr_id});
 }
 
-void Printer::EmitLoop(ir::Loop* loop) {
+void Printer::EmitLoop(core::ir::Loop* loop) {
     auto init_label = loop->HasInitializer() ? Label(loop->Initializer()) : 0;
     auto body_label = Label(loop->Body());
     auto continuing_label = Label(loop->Continuing());
@@ -1703,7 +1709,7 @@
     EmitExitPhis(loop);
 }
 
-void Printer::EmitSwitch(ir::Switch* swtch) {
+void Printer::EmitSwitch(core::ir::Switch* swtch) {
     // Find the default selector. There must be exactly one.
     uint32_t default_label = 0u;
     for (auto& c : swtch->Cases()) {
@@ -1748,7 +1754,7 @@
     EmitExitPhis(swtch);
 }
 
-void Printer::EmitSwizzle(ir::Swizzle* swizzle) {
+void Printer::EmitSwizzle(core::ir::Swizzle* swizzle) {
     auto id = Value(swizzle);
     auto obj = Value(swizzle->Object());
     OperandList operands = {Type(swizzle->Result()->Type()), id, obj, obj};
@@ -1758,11 +1764,11 @@
     current_function_.push_inst(spv::Op::OpVectorShuffle, operands);
 }
 
-void Printer::EmitStore(ir::Store* store) {
+void Printer::EmitStore(core::ir::Store* store) {
     current_function_.push_inst(spv::Op::OpStore, {Value(store->To()), Value(store->From())});
 }
 
-void Printer::EmitStoreVectorElement(ir::StoreVectorElement* store) {
+void Printer::EmitStoreVectorElement(core::ir::StoreVectorElement* store) {
     auto* vec_ptr_ty = store->To()->Type()->As<core::type::Pointer>();
     auto* el_ty = store->Value()->Type();
     auto* el_ptr_ty = ir_->Types().ptr(vec_ptr_ty->AddressSpace(), el_ty, vec_ptr_ty->Access());
@@ -1773,15 +1779,15 @@
     current_function_.push_inst(spv::Op::OpStore, {el_ptr_id, Value(store->Value())});
 }
 
-void Printer::EmitUnary(ir::Unary* unary) {
+void Printer::EmitUnary(core::ir::Unary* unary) {
     auto id = Value(unary);
     auto* ty = unary->Result()->Type();
     spv::Op op = spv::Op::Max;
     switch (unary->Kind()) {
-        case ir::Unary::Kind::kComplement:
+        case core::ir::Unary::Kind::kComplement:
             op = spv::Op::OpNot;
             break;
-        case ir::Unary::Kind::kNegation:
+        case core::ir::Unary::Kind::kNegation:
             if (ty->is_float_scalar_or_vector()) {
                 op = spv::Op::OpFNegate;
             } else if (ty->is_signed_integer_scalar_or_vector()) {
@@ -1792,7 +1798,7 @@
     current_function_.push_inst(op, {Type(ty), id, Value(unary->Val())});
 }
 
-void Printer::EmitUserCall(ir::UserCall* call) {
+void Printer::EmitUserCall(core::ir::UserCall* call) {
     auto id = Value(call);
     OperandList operands = {Type(call->Result()->Type()), id, Value(call->Func())};
     for (auto* arg : call->Args()) {
@@ -1801,7 +1807,7 @@
     current_function_.push_inst(spv::Op::OpFunctionCall, operands);
 }
 
-void Printer::EmitVar(ir::Var* var) {
+void Printer::EmitVar(core::ir::Var* var) {
     auto id = Value(var);
     auto* ptr = var->Result()->Type()->As<core::type::Pointer>();
     auto ty = Type(ptr);
@@ -1824,7 +1830,7 @@
             TINT_ASSERT(!current_function_);
             OperandList operands = {ty, id, U32Operand(SpvStorageClassPrivate)};
             if (var->Initializer()) {
-                TINT_ASSERT(var->Initializer()->Is<ir::Constant>());
+                TINT_ASSERT(var->Initializer()->Is<core::ir::Constant>());
                 operands.push_back(Value(var->Initializer()));
             }
             module_.PushType(spv::Op::OpVariable, operands);
@@ -1876,15 +1882,15 @@
     }
 }
 
-void Printer::EmitLet(ir::Let* let) {
+void Printer::EmitLet(core::ir::Let* let) {
     auto id = Value(let->Value());
     values_.Add(let->Result(), id);
 }
 
-void Printer::EmitExitPhis(ir::ControlInstruction* inst) {
+void Printer::EmitExitPhis(core::ir::ControlInstruction* inst) {
     struct Branch {
         uint32_t label = 0;
-        ir::Value* value = nullptr;
+        core::ir::Value* value = nullptr;
         bool operator<(const Branch& other) const { return label < other.label; }
     };
 
diff --git a/src/tint/lang/spirv/writer/printer/printer.h b/src/tint/lang/spirv/writer/printer/printer.h
index dceafb0..4218ade 100644
--- a/src/tint/lang/spirv/writer/printer/printer.h
+++ b/src/tint/lang/spirv/writer/printer/printer.h
@@ -34,7 +34,7 @@
 #include "src/tint/utils/symbol/symbol.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Access;
 class Binary;
 class Bitcast;
@@ -65,7 +65,7 @@
 class UserCall;
 class Value;
 class Var;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 namespace tint::core::type {
 class Struct;
 class Texture;
@@ -81,7 +81,7 @@
     /// @param module the Tint IR module to generate
     /// @param zero_init_workgroup_memory `true` to initialize all the variables in the Workgroup
     ///                                   storage class with OpConstantNull
-    Printer(ir::Module* module, bool zero_init_workgroup_memory);
+    Printer(core::ir::Module* module, bool zero_init_workgroup_memory);
 
     /// @returns the generated SPIR-V binary on success, or an error string on failure
     tint::Result<std::vector<uint32_t>, std::string> Generate();
@@ -92,7 +92,7 @@
     /// Get the result ID of the constant `constant`, emitting its instruction if necessary.
     /// @param constant the constant to get the ID for
     /// @returns the result ID of the constant
-    uint32_t Constant(ir::Constant* constant);
+    uint32_t Constant(core::ir::Constant* constant);
 
     /// Get the result ID of the type `ty`, emitting a type declaration instruction if necessary.
     /// @param ty the type to get the ID for
@@ -127,17 +127,17 @@
     /// Get the ID of the label for `block`.
     /// @param block the block to get the label ID for
     /// @returns the ID of the block's label
-    uint32_t Label(ir::Block* block);
+    uint32_t Label(core::ir::Block* block);
 
     /// Get the result ID of the value `value`, emitting its instruction if necessary.
     /// @param value the value to get the ID for
     /// @returns the result ID of the value
-    uint32_t Value(ir::Value* value);
+    uint32_t Value(core::ir::Value* value);
 
     /// Get the result ID of the instruction result `value`, emitting its instruction if necessary.
     /// @param inst the instruction to get the ID for
     /// @returns the result ID of the instruction
-    uint32_t Value(ir::Instruction* inst);
+    uint32_t Value(core::ir::Instruction* inst);
 
     /// Get the result ID of the OpUndef instruction with type `ty`, emitting it if necessary.
     /// @param ty the type of the undef value
@@ -159,115 +159,115 @@
 
     /// Emit a function.
     /// @param func the function to emit
-    void EmitFunction(ir::Function* func);
+    void EmitFunction(core::ir::Function* func);
 
     /// Emit entry point declarations for a function.
     /// @param func the function to emit entry point declarations for
     /// @param id the result ID of the function declaration
-    void EmitEntryPoint(ir::Function* func, uint32_t id);
+    void EmitEntryPoint(core::ir::Function* func, uint32_t id);
 
     /// Emit a block, including the initial OpLabel, OpPhis and instructions.
     /// @param block the block to emit
-    void EmitBlock(ir::Block* block);
+    void EmitBlock(core::ir::Block* block);
 
     /// Emit all OpPhi nodes for incoming branches to @p block.
     /// @param block the block to emit the OpPhis for
-    void EmitIncomingPhis(ir::MultiInBlock* block);
+    void EmitIncomingPhis(core::ir::MultiInBlock* block);
 
     /// Emit all instructions of @p block.
     /// @param block the block's instructions to emit
-    void EmitBlockInstructions(ir::Block* block);
+    void EmitBlockInstructions(core::ir::Block* block);
 
     /// Emit the root block.
     /// @param root_block the root block to emit
-    void EmitRootBlock(ir::Block* root_block);
+    void EmitRootBlock(core::ir::Block* root_block);
 
     /// Emit an `if` flow node.
     /// @param i the if node to emit
-    void EmitIf(ir::If* i);
+    void EmitIf(core::ir::If* i);
 
     /// Emit an access instruction
     /// @param access the access instruction to emit
-    void EmitAccess(ir::Access* access);
+    void EmitAccess(core::ir::Access* access);
 
     /// Emit a binary instruction.
     /// @param binary the binary instruction to emit
-    void EmitBinary(ir::Binary* binary);
+    void EmitBinary(core::ir::Binary* binary);
 
     /// Emit a bitcast instruction.
     /// @param bitcast the bitcast instruction to emit
-    void EmitBitcast(ir::Bitcast* bitcast);
+    void EmitBitcast(core::ir::Bitcast* bitcast);
 
     /// Emit a builtin function call instruction.
     /// @param call the builtin call instruction to emit
-    void EmitCoreBuiltinCall(ir::CoreBuiltinCall* call);
+    void EmitCoreBuiltinCall(core::ir::CoreBuiltinCall* call);
 
     /// Emit a construct instruction.
     /// @param construct the construct instruction to emit
-    void EmitConstruct(ir::Construct* construct);
+    void EmitConstruct(core::ir::Construct* construct);
 
     /// Emit a convert instruction.
     /// @param convert the convert instruction to emit
-    void EmitConvert(ir::Convert* convert);
+    void EmitConvert(core::ir::Convert* convert);
 
     /// Emit an intrinsic call instruction.
     /// @param call the intrinsic call instruction to emit
-    void EmitIntrinsicCall(ir::IntrinsicCall* call);
+    void EmitIntrinsicCall(core::ir::IntrinsicCall* call);
 
     /// Emit a load instruction.
     /// @param load the load instruction to emit
-    void EmitLoad(ir::Load* load);
+    void EmitLoad(core::ir::Load* load);
 
     /// Emit a load vector element instruction.
     /// @param load the load vector element instruction to emit
-    void EmitLoadVectorElement(ir::LoadVectorElement* load);
+    void EmitLoadVectorElement(core::ir::LoadVectorElement* load);
 
     /// Emit a loop instruction.
     /// @param loop the loop instruction to emit
-    void EmitLoop(ir::Loop* loop);
+    void EmitLoop(core::ir::Loop* loop);
 
     /// Emit a store instruction.
     /// @param store the store instruction to emit
-    void EmitStore(ir::Store* store);
+    void EmitStore(core::ir::Store* store);
 
     /// Emit a store vector element instruction.
     /// @param store the store vector element instruction to emit
-    void EmitStoreVectorElement(ir::StoreVectorElement* store);
+    void EmitStoreVectorElement(core::ir::StoreVectorElement* store);
 
     /// Emit a switch instruction.
     /// @param swtch the switch instruction to emit
-    void EmitSwitch(ir::Switch* swtch);
+    void EmitSwitch(core::ir::Switch* swtch);
 
     /// Emit a swizzle instruction.
     /// @param swizzle the swizzle instruction to emit
-    void EmitSwizzle(ir::Swizzle* swizzle);
+    void EmitSwizzle(core::ir::Swizzle* swizzle);
 
     /// Emit a unary instruction.
     /// @param unary the unary instruction to emit
-    void EmitUnary(ir::Unary* unary);
+    void EmitUnary(core::ir::Unary* unary);
 
     /// Emit a user call instruction.
     /// @param call the user call instruction to emit
-    void EmitUserCall(ir::UserCall* call);
+    void EmitUserCall(core::ir::UserCall* call);
 
     /// Emit a var instruction.
     /// @param var the var instruction to emit
-    void EmitVar(ir::Var* var);
+    void EmitVar(core::ir::Var* var);
 
     /// Emit a let instruction.
     /// @param let the let instruction to emit
-    void EmitLet(ir::Let* let);
+    void EmitLet(core::ir::Let* let);
 
     /// Emit a terminator instruction.
     /// @param term the terminator instruction to emit
-    void EmitTerminator(ir::Terminator* term);
+    void EmitTerminator(core::ir::Terminator* term);
 
     /// Emit the OpPhis for the given flow control instruction.
     /// @param inst the flow control instruction
-    void EmitExitPhis(ir::ControlInstruction* inst);
+    void EmitExitPhis(core::ir::ControlInstruction* inst);
 
-    ir::Module* ir_;
-    ir::Builder b_;
+    core::ir::Module* ir_;
+    core::ir::Builder b_;
     writer::Module module_;
     BinaryWriter writer_;
 
@@ -312,10 +312,10 @@
     Hashmap<const core::type::Type*, uint32_t, 4> undef_values_;
 
     /// The map of non-constant values to their result IDs.
-    Hashmap<ir::Value*, uint32_t, 8> values_;
+    Hashmap<core::ir::Value*, uint32_t, 8> values_;
 
     /// The map of blocks to the IDs of their label instructions.
-    Hashmap<ir::Block*, uint32_t, 8> block_labels_;
+    Hashmap<core::ir::Block*, uint32_t, 8> block_labels_;
 
     /// The map of extended instruction set names to their result IDs.
     Hashmap<std::string_view, uint32_t, 2> imports_;
diff --git a/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc b/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
index 65289a3..bd73280 100644
--- a/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/spirv/writer/raise/builtin_polyfill.cc
@@ -43,10 +43,10 @@
 /// PIMPL state for the transform.
 struct State {
     /// The IR module.
-    ir::Module* ir = nullptr;
+    core::ir::Module* ir = nullptr;
 
     /// The IR builder.
-    ir::Builder b{*ir};
+    core::ir::Builder b{*ir};
 
     /// The type manager.
     core::type::Manager& ty{ir->Types()};
@@ -54,12 +54,12 @@
     /// Process the module.
     void Process() {
         // Find the builtins that need replacing.
-        Vector<ir::CoreBuiltinCall*, 4> worklist;
+        Vector<core::ir::CoreBuiltinCall*, 4> worklist;
         for (auto* inst : ir->instructions.Objects()) {
             if (!inst->Alive()) {
                 continue;
             }
-            if (auto* builtin = inst->As<ir::CoreBuiltinCall>()) {
+            if (auto* builtin = inst->As<core::ir::CoreBuiltinCall>()) {
                 switch (builtin->Func()) {
                     case core::Function::kArrayLength:
                     case core::Function::kAtomicAdd:
@@ -97,7 +97,7 @@
 
         // Replace the builtins that we found.
         for (auto* builtin : worklist) {
-            ir::Value* replacement = nullptr;
+            core::ir::Value* replacement = nullptr;
             switch (builtin->Func()) {
                 case core::Function::kArrayLength:
                     replacement = ArrayLength(builtin);
@@ -169,24 +169,24 @@
     /// Handle an `arrayLength()` builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* ArrayLength(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* ArrayLength(core::ir::CoreBuiltinCall* builtin) {
         // Strip away any let instructions to get to the original struct member access instruction.
-        auto* ptr = builtin->Args()[0]->As<ir::InstructionResult>();
-        while (auto* let = tint::As<ir::Let>(ptr->Source())) {
-            ptr = let->Value()->As<ir::InstructionResult>();
+        auto* ptr = builtin->Args()[0]->As<core::ir::InstructionResult>();
+        while (auto* let = tint::As<core::ir::Let>(ptr->Source())) {
+            ptr = let->Value()->As<core::ir::InstructionResult>();
         }
         TINT_ASSERT_OR_RETURN_VALUE(ptr, nullptr);
 
-        auto* access = ptr->Source()->As<ir::Access>();
+        auto* access = ptr->Source()->As<core::ir::Access>();
         TINT_ASSERT_OR_RETURN_VALUE(access, nullptr);
         TINT_ASSERT_OR_RETURN_VALUE(access->Indices().Length() == 1u, nullptr);
         TINT_ASSERT_OR_RETURN_VALUE(access->Object()->Type()->UnwrapPtr()->Is<core::type::Struct>(),
                                     nullptr);
-        auto* const_idx = access->Indices()[0]->As<ir::Constant>();
+        auto* const_idx = access->Indices()[0]->As<core::ir::Constant>();
 
         // Replace the builtin call with a call to the spirv.array_length intrinsic.
         auto* call =
-            b.Call(builtin->Result()->Type(), ir::IntrinsicCall::Kind::kSpirvArrayLength,
+            b.Call(builtin->Result()->Type(), core::ir::IntrinsicCall::Kind::kSpirvArrayLength,
                    Vector{access->Object(), Literal(u32(const_idx->Value()->ValueAs<uint32_t>()))});
         call->InsertBefore(builtin);
         return call->Result();
@@ -195,11 +195,11 @@
     /// Handle an atomic*() builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* Atomic(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* Atomic(core::ir::CoreBuiltinCall* builtin) {
         auto* result_ty = builtin->Result()->Type();
 
         auto* pointer = builtin->Args()[0];
-        auto* memory = [&]() -> ir::Value* {
+        auto* memory = [&]() -> core::ir::Value* {
             switch (pointer->Type()->As<core::type::Pointer>()->AddressSpace()) {
                 case core::AddressSpace::kWorkgroup:
                     return b.Constant(u32(SpvScopeWorkgroup));
@@ -213,26 +213,27 @@
         auto* memory_semantics = b.Constant(u32(SpvMemorySemanticsMaskNone));
 
         // Helper to build the intrinsic call with the common operands.
-        auto build = [&](const core::type::Type* type, enum ir::IntrinsicCall::Kind intrinsic) {
+        auto build = [&](const core::type::Type* type,
+                         enum core::ir::IntrinsicCall::Kind intrinsic) {
             return b.Call(type, intrinsic, pointer, memory, memory_semantics);
         };
 
         // Create the replacement call instruction.
-        ir::Call* call = nullptr;
+        core::ir::Call* call = nullptr;
         switch (builtin->Func()) {
             case core::Function::kAtomicAdd:
-                call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicIAdd);
+                call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicIAdd);
                 call->AppendArg(builtin->Args()[1]);
                 break;
             case core::Function::kAtomicAnd:
-                call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicAnd);
+                call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicAnd);
                 call->AppendArg(builtin->Args()[1]);
                 break;
             case core::Function::kAtomicCompareExchangeWeak: {
                 auto* cmp = builtin->Args()[1];
                 auto* value = builtin->Args()[2];
                 auto* int_ty = value->Type();
-                call = build(int_ty, ir::IntrinsicCall::Kind::kSpirvAtomicCompareExchange);
+                call = build(int_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicCompareExchange);
                 call->AppendArg(memory_semantics);
                 call->AppendArg(value);
                 call->AppendArg(cmp);
@@ -250,42 +251,42 @@
                 break;
             }
             case core::Function::kAtomicExchange:
-                call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicExchange);
+                call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicExchange);
                 call->AppendArg(builtin->Args()[1]);
                 break;
             case core::Function::kAtomicLoad:
-                call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicLoad);
+                call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicLoad);
                 break;
             case core::Function::kAtomicOr:
-                call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicOr);
+                call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicOr);
                 call->AppendArg(builtin->Args()[1]);
                 break;
             case core::Function::kAtomicMax:
                 if (result_ty->is_signed_integer_scalar()) {
-                    call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicSMax);
+                    call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicSMax);
                 } else {
-                    call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicUMax);
+                    call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicUMax);
                 }
                 call->AppendArg(builtin->Args()[1]);
                 break;
             case core::Function::kAtomicMin:
                 if (result_ty->is_signed_integer_scalar()) {
-                    call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicSMin);
+                    call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicSMin);
                 } else {
-                    call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicUMin);
+                    call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicUMin);
                 }
                 call->AppendArg(builtin->Args()[1]);
                 break;
             case core::Function::kAtomicStore:
-                call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicStore);
+                call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicStore);
                 call->AppendArg(builtin->Args()[1]);
                 break;
             case core::Function::kAtomicSub:
-                call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicISub);
+                call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicISub);
                 call->AppendArg(builtin->Args()[1]);
                 break;
             case core::Function::kAtomicXor:
-                call = build(result_ty, ir::IntrinsicCall::Kind::kSpirvAtomicXor);
+                call = build(result_ty, core::ir::IntrinsicCall::Kind::kSpirvAtomicXor);
                 call->AppendArg(builtin->Args()[1]);
                 break;
             default:
@@ -299,11 +300,11 @@
     /// Handle a `dot()` builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* Dot(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* Dot(core::ir::CoreBuiltinCall* builtin) {
         // OpDot only supports floating point operands, so we need to polyfill the integer case.
         // TODO(crbug.com/tint/1267): If SPV_KHR_integer_dot_product is supported, use that instead.
         if (builtin->Result()->Type()->is_integer_scalar()) {
-            ir::Instruction* sum = nullptr;
+            core::ir::Instruction* sum = nullptr;
 
             auto* v1 = builtin->Args()[0];
             auto* v2 = builtin->Args()[1];
@@ -325,9 +326,9 @@
         }
 
         // Replace the builtin call with a call to the spirv.dot intrinsic.
-        auto args = Vector<ir::Value*, 4>(builtin->Args());
-        auto* call =
-            b.Call(builtin->Result()->Type(), ir::IntrinsicCall::Kind::kSpirvDot, std::move(args));
+        auto args = Vector<core::ir::Value*, 4>(builtin->Args());
+        auto* call = b.Call(builtin->Result()->Type(), core::ir::IntrinsicCall::Kind::kSpirvDot,
+                            std::move(args));
         call->InsertBefore(builtin);
         return call->Result();
     }
@@ -335,9 +336,9 @@
     /// Handle a `select()` builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* Select(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* Select(core::ir::CoreBuiltinCall* builtin) {
         // Argument order is different in SPIR-V: (condition, true_operand, false_operand).
-        Vector<ir::Value*, 4> args = {
+        Vector<core::ir::Value*, 4> args = {
             builtin->Args()[2],
             builtin->Args()[1],
             builtin->Args()[0],
@@ -348,7 +349,7 @@
         // TODO(jrprice): We don't need to do this if we're targeting SPIR-V 1.4 or newer.
         auto* vec = builtin->Result()->Type()->As<core::type::Vector>();
         if (vec && args[0]->Type()->Is<core::type::Scalar>()) {
-            Vector<ir::Value*, 4> elements;
+            Vector<core::ir::Value*, 4> elements;
             elements.Resize(vec->Width(), args[0]);
 
             auto* construct = b.Construct(ty.vec(ty.bool_(), vec->Width()), std::move(elements));
@@ -357,7 +358,7 @@
         }
 
         // Replace the builtin call with a call to the spirv.select intrinsic.
-        auto* call = b.Call(builtin->Result()->Type(), ir::IntrinsicCall::Kind::kSpirvSelect,
+        auto* call = b.Call(builtin->Result()->Type(), core::ir::IntrinsicCall::Kind::kSpirvSelect,
                             std::move(args));
         call->InsertBefore(builtin);
         return call->Result();
@@ -366,17 +367,17 @@
     /// ImageOperands represents the optional image operands for an image instruction.
     struct ImageOperands {
         /// Bias
-        ir::Value* bias = nullptr;
+        core::ir::Value* bias = nullptr;
         /// Lod
-        ir::Value* lod = nullptr;
+        core::ir::Value* lod = nullptr;
         /// Grad (dx)
-        ir::Value* ddx = nullptr;
+        core::ir::Value* ddx = nullptr;
         /// Grad (dy)
-        ir::Value* ddy = nullptr;
+        core::ir::Value* ddy = nullptr;
         /// ConstOffset
-        ir::Value* offset = nullptr;
+        core::ir::Value* offset = nullptr;
         /// Sample
-        ir::Value* sample = nullptr;
+        core::ir::Value* sample = nullptr;
     };
 
     /// Append optional image operands to an image intrinsic argument list.
@@ -385,8 +386,8 @@
     /// @param insertion_point the insertion point for new instructions
     /// @param requires_float_lod true if the lod needs to be a floating point value
     void AppendImageOperands(ImageOperands& operands,
-                             Vector<ir::Value*, 8>& args,
-                             ir::Instruction* insertion_point,
+                             Vector<core::ir::Value*, 8>& args,
+                             core::ir::Instruction* insertion_point,
                              bool requires_float_lod) {
         // Add a placeholder argument for the image operand mask, which we will fill in when we have
         // processed the image operands.
@@ -431,9 +432,9 @@
     /// @param array_idx the array index
     /// @param insertion_point the insertion point for new instructions
     /// @returns the modified coordinate vector
-    ir::Value* AppendArrayIndex(ir::Value* coords,
-                                ir::Value* array_idx,
-                                ir::Instruction* insertion_point) {
+    core::ir::Value* AppendArrayIndex(core::ir::Value* coords,
+                                      core::ir::Value* array_idx,
+                                      core::ir::Instruction* insertion_point) {
         auto* vec = coords->Type()->As<core::type::Vector>();
         auto* element_ty = vec->type();
 
@@ -455,7 +456,7 @@
     /// Handle a textureSample*() builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* TextureSample(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* TextureSample(core::ir::CoreBuiltinCall* builtin) {
         // Helper to get the next argument from the call, or nullptr if there are no more arguments.
         uint32_t arg_idx = 0;
         auto next_arg = [&]() {
@@ -469,8 +470,8 @@
 
         // Use OpSampledImage to create an OpTypeSampledImage object.
         auto* sampled_image =
-            b.Call(ty.Get<SampledImage>(texture_ty), ir::IntrinsicCall::Kind::kSpirvSampledImage,
-                   Vector{texture, sampler});
+            b.Call(ty.Get<SampledImage>(texture_ty),
+                   core::ir::IntrinsicCall::Kind::kSpirvSampledImage, Vector{texture, sampler});
         sampled_image->InsertBefore(builtin);
 
         // Append the array index to the coordinates if provided.
@@ -480,38 +481,38 @@
         }
 
         // Determine which SPIR-V intrinsic to use and which optional image operands are needed.
-        enum ir::IntrinsicCall::Kind intrinsic;
-        ir::Value* depth = nullptr;
+        enum core::ir::IntrinsicCall::Kind intrinsic;
+        core::ir::Value* depth = nullptr;
         ImageOperands operands;
         switch (builtin->Func()) {
             case core::Function::kTextureSample:
-                intrinsic = ir::IntrinsicCall::Kind::kSpirvImageSampleImplicitLod;
+                intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageSampleImplicitLod;
                 operands.offset = next_arg();
                 break;
             case core::Function::kTextureSampleBias:
-                intrinsic = ir::IntrinsicCall::Kind::kSpirvImageSampleImplicitLod;
+                intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageSampleImplicitLod;
                 operands.bias = next_arg();
                 operands.offset = next_arg();
                 break;
             case core::Function::kTextureSampleCompare:
-                intrinsic = ir::IntrinsicCall::Kind::kSpirvImageSampleDrefImplicitLod;
+                intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageSampleDrefImplicitLod;
                 depth = next_arg();
                 operands.offset = next_arg();
                 break;
             case core::Function::kTextureSampleCompareLevel:
-                intrinsic = ir::IntrinsicCall::Kind::kSpirvImageSampleDrefExplicitLod;
+                intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageSampleDrefExplicitLod;
                 depth = next_arg();
                 operands.lod = b.Constant(0_f);
                 operands.offset = next_arg();
                 break;
             case core::Function::kTextureSampleGrad:
-                intrinsic = ir::IntrinsicCall::Kind::kSpirvImageSampleExplicitLod;
+                intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageSampleExplicitLod;
                 operands.ddx = next_arg();
                 operands.ddy = next_arg();
                 operands.offset = next_arg();
                 break;
             case core::Function::kTextureSampleLevel:
-                intrinsic = ir::IntrinsicCall::Kind::kSpirvImageSampleExplicitLod;
+                intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageSampleExplicitLod;
                 operands.lod = next_arg();
                 operands.offset = next_arg();
                 break;
@@ -522,7 +523,7 @@
         // Start building the argument list for the intrinsic.
         // The first two operands are always the sampled image and then the coordinates, followed by
         // the depth reference if used.
-        Vector<ir::Value*, 8> intrinsic_args;
+        Vector<core::ir::Value*, 8> intrinsic_args;
         intrinsic_args.Push(sampled_image->Result());
         intrinsic_args.Push(coords);
         if (depth) {
@@ -555,7 +556,7 @@
     /// Handle a textureGather*() builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* TextureGather(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* TextureGather(core::ir::CoreBuiltinCall* builtin) {
         // Helper to get the next argument from the call, or nullptr if there are no more arguments.
         uint32_t arg_idx = 0;
         auto next_arg = [&]() {
@@ -576,8 +577,8 @@
 
         // Use OpSampledImage to create an OpTypeSampledImage object.
         auto* sampled_image =
-            b.Call(ty.Get<SampledImage>(texture_ty), ir::IntrinsicCall::Kind::kSpirvSampledImage,
-                   Vector{texture, sampler});
+            b.Call(ty.Get<SampledImage>(texture_ty),
+                   core::ir::IntrinsicCall::Kind::kSpirvSampledImage, Vector{texture, sampler});
         sampled_image->InsertBefore(builtin);
 
         // Append the array index to the coordinates if provided.
@@ -587,16 +588,16 @@
         }
 
         // Determine which SPIR-V intrinsic to use and which optional image operands are needed.
-        enum ir::IntrinsicCall::Kind intrinsic;
-        ir::Value* depth = nullptr;
+        enum core::ir::IntrinsicCall::Kind intrinsic;
+        core::ir::Value* depth = nullptr;
         ImageOperands operands;
         switch (builtin->Func()) {
             case core::Function::kTextureGather:
-                intrinsic = ir::IntrinsicCall::Kind::kSpirvImageGather;
+                intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageGather;
                 operands.offset = next_arg();
                 break;
             case core::Function::kTextureGatherCompare:
-                intrinsic = ir::IntrinsicCall::Kind::kSpirvImageDrefGather;
+                intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageDrefGather;
                 depth = next_arg();
                 operands.offset = next_arg();
                 break;
@@ -607,7 +608,7 @@
         // Start building the argument list for the intrinsic.
         // The first two operands are always the sampled image and then the coordinates, followed by
         // either the depth reference or the component.
-        Vector<ir::Value*, 8> intrinsic_args;
+        Vector<core::ir::Value*, 8> intrinsic_args;
         intrinsic_args.Push(sampled_image->Result());
         intrinsic_args.Push(coords);
         if (depth) {
@@ -629,7 +630,7 @@
     /// Handle a textureLoad() builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* TextureLoad(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* TextureLoad(core::ir::CoreBuiltinCall* builtin) {
         // Helper to get the next argument from the call, or nullptr if there are no more arguments.
         uint32_t arg_idx = 0;
         auto next_arg = [&]() {
@@ -648,7 +649,7 @@
 
         // Start building the argument list for the intrinsic.
         // The first two operands are always the texture and then the coordinates.
-        Vector<ir::Value*, 8> intrinsic_args;
+        Vector<core::ir::Value*, 8> intrinsic_args;
         intrinsic_args.Push(texture);
         intrinsic_args.Push(coords);
 
@@ -669,8 +670,8 @@
         if (expects_scalar_result) {
             result_ty = ty.vec4(result_ty);
         }
-        auto* texture_call =
-            b.Call(result_ty, ir::IntrinsicCall::Kind::kSpirvImageFetch, std::move(intrinsic_args));
+        auto* texture_call = b.Call(result_ty, core::ir::IntrinsicCall::Kind::kSpirvImageFetch,
+                                    std::move(intrinsic_args));
         texture_call->InsertBefore(builtin);
         auto* result = texture_call->Result();
 
@@ -687,7 +688,7 @@
     /// Handle a textureStore() builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* TextureStore(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* TextureStore(core::ir::CoreBuiltinCall* builtin) {
         // Helper to get the next argument from the call, or nullptr if there are no more arguments.
         uint32_t arg_idx = 0;
         auto next_arg = [&]() {
@@ -708,7 +709,7 @@
 
         // Start building the argument list for the intrinsic.
         // The first two operands are always the texture and then the coordinates.
-        Vector<ir::Value*, 8> intrinsic_args;
+        Vector<core::ir::Value*, 8> intrinsic_args;
         intrinsic_args.Push(texture);
         intrinsic_args.Push(coords);
         intrinsic_args.Push(texel);
@@ -717,7 +718,7 @@
         AppendImageOperands(operands, intrinsic_args, builtin, /* requires_float_lod */ false);
 
         // Call the intrinsic.
-        auto* texture_call = b.Call(ty.void_(), ir::IntrinsicCall::Kind::kSpirvImageWrite,
+        auto* texture_call = b.Call(ty.void_(), core::ir::IntrinsicCall::Kind::kSpirvImageWrite,
                                     std::move(intrinsic_args));
         texture_call->InsertBefore(builtin);
         return texture_call->Result();
@@ -726,7 +727,7 @@
     /// Handle a textureDimensions() builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* TextureDimensions(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* TextureDimensions(core::ir::CoreBuiltinCall* builtin) {
         // Helper to get the next argument from the call, or nullptr if there are no more arguments.
         uint32_t arg_idx = 0;
         auto next_arg = [&]() {
@@ -736,17 +737,17 @@
         auto* texture = next_arg();
         auto* texture_ty = texture->Type()->As<core::type::Texture>();
 
-        Vector<ir::Value*, 8> intrinsic_args;
+        Vector<core::ir::Value*, 8> intrinsic_args;
         intrinsic_args.Push(texture);
 
         // Determine which SPIR-V intrinsic to use, and add the Lod argument if needed.
-        enum ir::IntrinsicCall::Kind intrinsic;
+        enum core::ir::IntrinsicCall::Kind intrinsic;
         if (texture_ty
                 ->IsAnyOf<core::type::MultisampledTexture, core::type::DepthMultisampledTexture,
                           core::type::StorageTexture>()) {
-            intrinsic = ir::IntrinsicCall::Kind::kSpirvImageQuerySize;
+            intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageQuerySize;
         } else {
-            intrinsic = ir::IntrinsicCall::Kind::kSpirvImageQuerySizeLod;
+            intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageQuerySizeLod;
             if (auto* lod = next_arg()) {
                 intrinsic_args.Push(lod);
             } else {
@@ -781,21 +782,21 @@
     /// Handle a textureNumLayers() builtin.
     /// @param builtin the builtin call instruction
     /// @returns the replacement value
-    ir::Value* TextureNumLayers(ir::CoreBuiltinCall* builtin) {
+    core::ir::Value* TextureNumLayers(core::ir::CoreBuiltinCall* builtin) {
         auto* texture = builtin->Args()[0];
         auto* texture_ty = texture->Type()->As<core::type::Texture>();
 
-        Vector<ir::Value*, 2> intrinsic_args;
+        Vector<core::ir::Value*, 2> intrinsic_args;
         intrinsic_args.Push(texture);
 
         // Determine which SPIR-V intrinsic to use, and add the Lod argument if needed.
-        enum ir::IntrinsicCall::Kind intrinsic;
+        enum core::ir::IntrinsicCall::Kind intrinsic;
         if (texture_ty
                 ->IsAnyOf<core::type::MultisampledTexture, core::type::DepthMultisampledTexture,
                           core::type::StorageTexture>()) {
-            intrinsic = ir::IntrinsicCall::Kind::kSpirvImageQuerySize;
+            intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageQuerySize;
         } else {
-            intrinsic = ir::IntrinsicCall::Kind::kSpirvImageQuerySizeLod;
+            intrinsic = core::ir::IntrinsicCall::Kind::kSpirvImageQuerySizeLod;
             intrinsic_args.Push(b.Constant(0_u));
         }
 
@@ -812,7 +813,7 @@
 
 }  // namespace
 
-Result<SuccessType, std::string> BuiltinPolyfill(ir::Module* ir) {
+Result<SuccessType, std::string> BuiltinPolyfill(core::ir::Module* ir) {
     auto result = ValidateAndDumpIfNeeded(*ir, "BuiltinPolyfill transform");
     if (!result) {
         return result;
diff --git a/src/tint/lang/spirv/writer/raise/builtin_polyfill.h b/src/tint/lang/spirv/writer/raise/builtin_polyfill.h
index 343caf6..a99adb9 100644
--- a/src/tint/lang/spirv/writer/raise/builtin_polyfill.h
+++ b/src/tint/lang/spirv/writer/raise/builtin_polyfill.h
@@ -22,10 +22,10 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 class Texture;
-}  // namespace tint::ir
+}  // namespace tint::core::ir
 
 namespace tint::spirv::writer::raise {
 
@@ -33,12 +33,12 @@
 /// SPIR-V backend intrinsic functions.
 /// @param module the module to transform
 /// @returns an error string on failure
-Result<SuccessType, std::string> BuiltinPolyfill(ir::Module* module);
+Result<SuccessType, std::string> BuiltinPolyfill(core::ir::Module* module);
 
 /// LiteralOperand is a type of constant value that is intended to be emitted as a literal in
 /// the SPIR-V instruction stream.
 /// TODO(jrprice): Move this to lang/spirv.
-class LiteralOperand final : public Castable<LiteralOperand, ir::Constant> {
+class LiteralOperand final : public Castable<LiteralOperand, core::ir::Constant> {
   public:
     /// Constructor
     /// @param value the operand value
diff --git a/src/tint/lang/spirv/writer/raise/builtin_polyfill_test.cc b/src/tint/lang/spirv/writer/raise/builtin_polyfill_test.cc
index a19982a..586b90d 100644
--- a/src/tint/lang/spirv/writer/raise/builtin_polyfill_test.cc
+++ b/src/tint/lang/spirv/writer/raise/builtin_polyfill_test.cc
@@ -31,7 +31,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-using SpirvWriter_BuiltinPolyfillTest = ir::transform::TransformTest;
+using SpirvWriter_BuiltinPolyfillTest = core::ir::transform::TransformTest;
 
 TEST_F(SpirvWriter_BuiltinPolyfillTest, ArrayLength) {
     auto* arr = ty.runtime_array(ty.i32());
diff --git a/src/tint/lang/spirv/writer/raise/expand_implicit_splats.cc b/src/tint/lang/spirv/writer/raise/expand_implicit_splats.cc
index 19dc647..fbf1ee1 100644
--- a/src/tint/lang/spirv/writer/raise/expand_implicit_splats.cc
+++ b/src/tint/lang/spirv/writer/raise/expand_implicit_splats.cc
@@ -26,18 +26,18 @@
 
 namespace {
 
-void Run(ir::Module* ir) {
-    ir::Builder b(*ir);
+void Run(core::ir::Module* ir) {
+    core::ir::Builder b(*ir);
 
     // Find the instructions that use implicit splats and either modify them in place or record them
     // to be replaced in a second pass.
-    Vector<ir::Binary*, 4> binary_worklist;
-    Vector<ir::CoreBuiltinCall*, 4> builtin_worklist;
+    Vector<core::ir::Binary*, 4> binary_worklist;
+    Vector<core::ir::CoreBuiltinCall*, 4> builtin_worklist;
     for (auto* inst : ir->instructions.Objects()) {
         if (!inst->Alive()) {
             continue;
         }
-        if (auto* construct = inst->As<ir::Construct>()) {
+        if (auto* construct = inst->As<core::ir::Construct>()) {
             // A vector constructor with a single scalar argument needs to be modified to replicate
             // the argument N times.
             auto* vec = construct->Result()->Type()->As<core::type::Vector>();
@@ -48,7 +48,7 @@
                     construct->AppendArg(construct->Args()[0]);
                 }
             }
-        } else if (auto* binary = inst->As<ir::Binary>()) {
+        } else if (auto* binary = inst->As<core::ir::Binary>()) {
             // A binary instruction that mixes vector and scalar operands needs to have the scalar
             // operand replaced with an explicit vector constructor.
             if (binary->Result()->Type()->Is<core::type::Vector>()) {
@@ -57,7 +57,7 @@
                     binary_worklist.Push(binary);
                 }
             }
-        } else if (auto* builtin = inst->As<ir::CoreBuiltinCall>()) {
+        } else if (auto* builtin = inst->As<core::ir::CoreBuiltinCall>()) {
             // A mix builtin call that mixes vector and scalar operands needs to have the scalar
             // operand replaced with an explicit vector constructor.
             if (builtin->Func() == core::Function::kMix) {
@@ -72,10 +72,10 @@
 
     // Helper to expand a scalar operand of an instruction by replacing it with an explicitly
     // constructed vector that matches the result type.
-    auto expand_operand = [&](ir::Instruction* inst, size_t operand_idx) {
+    auto expand_operand = [&](core::ir::Instruction* inst, size_t operand_idx) {
         auto* vec = inst->Result()->Type()->As<core::type::Vector>();
 
-        Vector<ir::Value*, 4> args;
+        Vector<core::ir::Value*, 4> args;
         args.Resize(vec->Width(), inst->Operands()[operand_idx]);
 
         auto* construct = b.Construct(vec, std::move(args));
@@ -86,9 +86,9 @@
     // Replace scalar operands to binary instructions that produce vectors.
     for (auto* binary : binary_worklist) {
         auto* result_ty = binary->Result()->Type();
-        if (result_ty->is_float_vector() && binary->Kind() == ir::Binary::Kind::kMultiply) {
+        if (result_ty->is_float_vector() && binary->Kind() == core::ir::Binary::Kind::kMultiply) {
             // Use OpVectorTimesScalar for floating point multiply.
-            auto* vts = b.Call(result_ty, ir::IntrinsicCall::Kind::kSpirvVectorTimesScalar);
+            auto* vts = b.Call(result_ty, core::ir::IntrinsicCall::Kind::kSpirvVectorTimesScalar);
             if (binary->LHS()->Type()->Is<core::type::Scalar>()) {
                 vts->AppendArg(binary->RHS());
                 vts->AppendArg(binary->LHS());
@@ -105,9 +105,9 @@
         } else {
             // Expand the scalar argument into an explicitly constructed vector.
             if (binary->LHS()->Type()->Is<core::type::Scalar>()) {
-                expand_operand(binary, ir::Binary::kLhsOperandOffset);
+                expand_operand(binary, core::ir::Binary::kLhsOperandOffset);
             } else if (binary->RHS()->Type()->Is<core::type::Scalar>()) {
-                expand_operand(binary, ir::Binary::kRhsOperandOffset);
+                expand_operand(binary, core::ir::Binary::kRhsOperandOffset);
             }
         }
     }
@@ -117,7 +117,7 @@
         switch (builtin->Func()) {
             case core::Function::kMix:
                 // Expand the scalar argument into an explicitly constructed vector.
-                expand_operand(builtin, ir::CoreBuiltinCall::kArgsOperandOffset + 2);
+                expand_operand(builtin, core::ir::CoreBuiltinCall::kArgsOperandOffset + 2);
                 break;
             default:
                 TINT_UNREACHABLE() << "unhandled builtin call";
@@ -128,7 +128,7 @@
 
 }  // namespace
 
-Result<SuccessType, std::string> ExpandImplicitSplats(ir::Module* ir) {
+Result<SuccessType, std::string> ExpandImplicitSplats(core::ir::Module* ir) {
     auto result = ValidateAndDumpIfNeeded(*ir, "ExpandImplicitSplats transform");
     if (!result) {
         return result;
diff --git a/src/tint/lang/spirv/writer/raise/expand_implicit_splats.h b/src/tint/lang/spirv/writer/raise/expand_implicit_splats.h
index 9efef18..18bf1d8 100644
--- a/src/tint/lang/spirv/writer/raise/expand_implicit_splats.h
+++ b/src/tint/lang/spirv/writer/raise/expand_implicit_splats.h
@@ -20,7 +20,7 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
@@ -30,7 +30,7 @@
 /// instructions and binary instructions where not supported by SPIR-V.
 /// @param module the module to transform
 /// @returns an error string on failure
-Result<SuccessType, std::string> ExpandImplicitSplats(ir::Module* module);
+Result<SuccessType, std::string> ExpandImplicitSplats(core::ir::Module* module);
 
 }  // namespace tint::spirv::writer::raise
 
diff --git a/src/tint/lang/spirv/writer/raise/expand_implicit_splats_test.cc b/src/tint/lang/spirv/writer/raise/expand_implicit_splats_test.cc
index 0c1b919..9111271 100644
--- a/src/tint/lang/spirv/writer/raise/expand_implicit_splats_test.cc
+++ b/src/tint/lang/spirv/writer/raise/expand_implicit_splats_test.cc
@@ -24,7 +24,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-using SpirvWriter_ExpandImplicitSplatsTest = ir::transform::TransformTest;
+using SpirvWriter_ExpandImplicitSplatsTest = core::ir::transform::TransformTest;
 
 TEST_F(SpirvWriter_ExpandImplicitSplatsTest, NoModify_Construct_VectorIdentity) {
     auto* vector = b.FunctionParam("vector", ty.vec2<i32>());
diff --git a/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.cc b/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.cc
index fbcc95b..7c321a8 100644
--- a/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.cc
+++ b/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.cc
@@ -30,23 +30,23 @@
 
 namespace {
 
-void Run(ir::Module* ir) {
-    ir::Builder b(*ir);
+void Run(core::ir::Module* ir) {
+    core::ir::Builder b(*ir);
 
     // Find the instructions that need to be modified.
-    Vector<ir::Binary*, 4> binary_worklist;
-    Vector<ir::Convert*, 4> convert_worklist;
+    Vector<core::ir::Binary*, 4> binary_worklist;
+    Vector<core::ir::Convert*, 4> convert_worklist;
     for (auto* inst : ir->instructions.Objects()) {
         if (!inst->Alive()) {
             continue;
         }
-        if (auto* binary = inst->As<ir::Binary>()) {
+        if (auto* binary = inst->As<core::ir::Binary>()) {
             TINT_ASSERT(binary->Operands().Length() == 2);
             if (binary->LHS()->Type()->Is<core::type::Matrix>() ||
                 binary->RHS()->Type()->Is<core::type::Matrix>()) {
                 binary_worklist.Push(binary);
             }
-        } else if (auto* convert = inst->As<ir::Convert>()) {
+        } else if (auto* convert = inst->As<core::ir::Convert>()) {
             if (convert->Result()->Type()->Is<core::type::Matrix>()) {
                 convert_worklist.Push(convert);
             }
@@ -62,7 +62,7 @@
         auto* ty = binary->Result()->Type();
 
         // Helper to replace the instruction with a new one.
-        auto replace = [&](ir::Instruction* inst) {
+        auto replace = [&](core::ir::Instruction* inst) {
             if (auto name = ir->NameOf(binary)) {
                 ir->SetName(inst->Result(), name);
             }
@@ -72,9 +72,9 @@
         };
 
         // Helper to replace the instruction with a column-wise operation.
-        auto column_wise = [&](enum ir::Binary::Kind op) {
+        auto column_wise = [&](enum core::ir::Binary::Kind op) {
             auto* mat = ty->As<core::type::Matrix>();
-            Vector<ir::Value*, 4> args;
+            Vector<core::ir::Value*, 4> args;
             for (uint32_t col = 0; col < mat->columns(); col++) {
                 b.InsertBefore(binary, [&] {
                     auto* lhs_col = b.Access(mat->ColumnType(), lhs, u32(col));
@@ -87,32 +87,32 @@
         };
 
         switch (binary->Kind()) {
-            case ir::Binary::Kind::kAdd:
-                column_wise(ir::Binary::Kind::kAdd);
+            case core::ir::Binary::Kind::kAdd:
+                column_wise(core::ir::Binary::Kind::kAdd);
                 break;
-            case ir::Binary::Kind::kSubtract:
-                column_wise(ir::Binary::Kind::kSubtract);
+            case core::ir::Binary::Kind::kSubtract:
+                column_wise(core::ir::Binary::Kind::kSubtract);
                 break;
-            case ir::Binary::Kind::kMultiply:
+            case core::ir::Binary::Kind::kMultiply:
                 // Select the SPIR-V intrinsic that corresponds to the operation being performed.
                 if (lhs_ty->Is<core::type::Matrix>()) {
                     if (rhs_ty->Is<core::type::Scalar>()) {
-                        replace(
-                            b.Call(ty, ir::IntrinsicCall::Kind::kSpirvMatrixTimesScalar, lhs, rhs));
+                        replace(b.Call(ty, core::ir::IntrinsicCall::Kind::kSpirvMatrixTimesScalar,
+                                       lhs, rhs));
                     } else if (rhs_ty->Is<core::type::Vector>()) {
-                        replace(
-                            b.Call(ty, ir::IntrinsicCall::Kind::kSpirvMatrixTimesVector, lhs, rhs));
+                        replace(b.Call(ty, core::ir::IntrinsicCall::Kind::kSpirvMatrixTimesVector,
+                                       lhs, rhs));
                     } else if (rhs_ty->Is<core::type::Matrix>()) {
-                        replace(
-                            b.Call(ty, ir::IntrinsicCall::Kind::kSpirvMatrixTimesMatrix, lhs, rhs));
+                        replace(b.Call(ty, core::ir::IntrinsicCall::Kind::kSpirvMatrixTimesMatrix,
+                                       lhs, rhs));
                     }
                 } else {
                     if (lhs_ty->Is<core::type::Scalar>()) {
-                        replace(
-                            b.Call(ty, ir::IntrinsicCall::Kind::kSpirvMatrixTimesScalar, rhs, lhs));
+                        replace(b.Call(ty, core::ir::IntrinsicCall::Kind::kSpirvMatrixTimesScalar,
+                                       rhs, lhs));
                     } else if (lhs_ty->Is<core::type::Vector>()) {
-                        replace(
-                            b.Call(ty, ir::IntrinsicCall::Kind::kSpirvVectorTimesMatrix, lhs, rhs));
+                        replace(b.Call(ty, core::ir::IntrinsicCall::Kind::kSpirvVectorTimesMatrix,
+                                       lhs, rhs));
                     }
                 }
                 break;
@@ -125,12 +125,12 @@
 
     // Replace the matrix convert instructions that we found.
     for (auto* convert : convert_worklist) {
-        auto* arg = convert->Args()[ir::Convert::kValueOperandOffset];
+        auto* arg = convert->Args()[core::ir::Convert::kValueOperandOffset];
         auto* in_mat = arg->Type()->As<core::type::Matrix>();
         auto* out_mat = convert->Result()->Type()->As<core::type::Matrix>();
 
         // Extract and convert each column separately.
-        Vector<ir::Value*, 4> args;
+        Vector<core::ir::Value*, 4> args;
         for (uint32_t c = 0; c < out_mat->columns(); c++) {
             b.InsertBefore(convert, [&] {
                 auto* col = b.Access(in_mat->ColumnType(), arg, u32(c));
@@ -152,7 +152,7 @@
 
 }  // namespace
 
-Result<SuccessType, std::string> HandleMatrixArithmetic(ir::Module* ir) {
+Result<SuccessType, std::string> HandleMatrixArithmetic(core::ir::Module* ir) {
     auto result = ValidateAndDumpIfNeeded(*ir, "HandleMatrixArithmetic transform");
     if (!result) {
         return result;
diff --git a/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h b/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h
index 8590f37..41b4a72 100644
--- a/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h
+++ b/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h
@@ -20,7 +20,7 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
@@ -30,7 +30,7 @@
 /// SPIR-V intrinsics or polyfills.
 /// @param module the module to transform
 /// @returns an error string on failure
-Result<SuccessType, std::string> HandleMatrixArithmetic(ir::Module* module);
+Result<SuccessType, std::string> HandleMatrixArithmetic(core::ir::Module* module);
 
 }  // namespace tint::spirv::writer::raise
 
diff --git a/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic_test.cc b/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic_test.cc
index 264bd54..bd31efd 100644
--- a/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic_test.cc
+++ b/src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic_test.cc
@@ -25,7 +25,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-using SpirvWriter_HandleMatrixArithmeticTest = ir::transform::TransformTest;
+using SpirvWriter_HandleMatrixArithmeticTest = core::ir::transform::TransformTest;
 
 TEST_F(SpirvWriter_HandleMatrixArithmeticTest, Add_Mat2x3f) {
     auto* arg1 = b.FunctionParam("arg1", ty.mat2x3<f32>());
diff --git a/src/tint/lang/spirv/writer/raise/merge_return.cc b/src/tint/lang/spirv/writer/raise/merge_return.cc
index 6f657f2..c09fdc6 100644
--- a/src/tint/lang/spirv/writer/raise/merge_return.cc
+++ b/src/tint/lang/spirv/writer/raise/merge_return.cc
@@ -33,38 +33,38 @@
 /// PIMPL state for the transform, for a single function.
 struct State {
     /// The IR module.
-    ir::Module* ir = nullptr;
+    core::ir::Module* ir = nullptr;
 
     /// The IR builder.
-    ir::Builder b{*ir};
+    core::ir::Builder b{*ir};
 
     /// The type manager.
     core::type::Manager& ty{ir->Types()};
 
     /// The "has not returned" flag.
-    ir::Var* continue_execution = nullptr;
+    core::ir::Var* continue_execution = nullptr;
 
     /// The variable that holds the return value.
     /// Null when the function does not return a value.
-    ir::Var* return_val = nullptr;
+    core::ir::Var* return_val = nullptr;
 
     /// The final return at the end of the function block.
     /// May be null when the function returns in all blocks of a control instruction.
-    ir::Return* fn_return = nullptr;
+    core::ir::Return* fn_return = nullptr;
 
     /// A set of control instructions that transitively hold a return instruction
-    Hashset<ir::ControlInstruction*, 8> holds_return_;
+    Hashset<core::ir::ControlInstruction*, 8> holds_return_;
 
     /// Constructor
     /// @param mod the module
-    explicit State(ir::Module* mod) : ir(mod) {}
+    explicit State(core::ir::Module* mod) : ir(mod) {}
 
     /// Process the function.
     /// @param fn the function to process
-    void Process(ir::Function* fn) {
+    void Process(core::ir::Function* fn) {
         // Find all of the nested return instructions in the function.
         for (const auto& usage : fn->Usages()) {
-            if (auto* ret = usage.instruction->As<ir::Return>()) {
+            if (auto* ret = usage.instruction->As<core::ir::Return>()) {
                 TransitivelyMarkAsReturning(ret->Block()->Parent());
             }
         }
@@ -86,7 +86,7 @@
         }
 
         // Look to see if the function ends with a return
-        fn_return = tint::As<ir::Return>(fn->Block()->Terminator());
+        fn_return = tint::As<core::ir::Return>(fn->Block()->Terminator());
 
         // Process the function's block.
         // This will traverse into control instructions that hold returns, and apply the necessary
@@ -105,7 +105,7 @@
     /// Marks all the control instructions from ctrl to the function as holding a return.
     /// @param ctrl the control instruction to mark as returning, along with all ancestor control
     /// instructions.
-    void TransitivelyMarkAsReturning(ir::ControlInstruction* ctrl) {
+    void TransitivelyMarkAsReturning(core::ir::ControlInstruction* ctrl) {
         for (; ctrl; ctrl = ctrl->Block()->Parent()) {
             if (!holds_return_.Add(ctrl)) {
                 return;
@@ -118,21 +118,21 @@
     /// instructions following the control instruction will be wrapped in a 'if' that only executes
     /// if a return was not reached.
     /// @param block the block to process
-    void ProcessBlock(ir::Block* block) {
-        ir::If* inner_if = nullptr;
+    void ProcessBlock(core::ir::Block* block) {
+        core::ir::If* inner_if = nullptr;
         for (auto* inst = *block->begin(); inst;) {  // For each instruction in 'block'
             // As we're modifying the block that we're iterating over, grab the pointer to the next
             // instruction before (potentially) moving 'inst' to another block.
             auto* next = inst->next;
             TINT_DEFER(inst = next);
 
-            if (auto* ret = inst->As<ir::Return>()) {
+            if (auto* ret = inst->As<core::ir::Return>()) {
                 // Note: Return instructions are processed without being moved into the 'if' block.
                 ProcessReturn(ret, inner_if);
                 break;  // All instructions processed.
             }
 
-            if (inst->Is<ir::Unreachable>()) {
+            if (inst->Is<core::ir::Unreachable>()) {
                 // Unreachable can become reachable once returns are turned into exits.
                 // As this is the terminator for the block, simply stop processing the
                 // instructions. A appropriate terminator will be created for this block below.
@@ -150,12 +150,13 @@
             // Control instructions holding a return need to be processed, and then a new 'if' needs
             // to be created to hold the instructions that are between the control instruction and
             // the block's terminating instruction.
-            if (auto* ctrl = inst->As<ir::ControlInstruction>()) {
+            if (auto* ctrl = inst->As<core::ir::ControlInstruction>()) {
                 if (holds_return_.Contains(ctrl)) {
                     // Control instruction transitively holds a return.
-                    ctrl->ForeachBlock([&](ir::Block* ctrl_block) { ProcessBlock(ctrl_block); });
+                    ctrl->ForeachBlock(
+                        [&](core::ir::Block* ctrl_block) { ProcessBlock(ctrl_block); });
                     if (next && (next != fn_return || fn_return->Value()) &&
-                        !tint::IsAnyOf<ir::Exit, ir::Unreachable>(next)) {
+                        !tint::IsAnyOf<core::ir::Exit, core::ir::Unreachable>(next)) {
                         inner_if = CreateIfContinueExecution(ctrl);
                     }
                 }
@@ -164,10 +165,12 @@
 
         if (inner_if) {
             // new_value_with_type returns a new RuntimeValue with the same type as 'v'
-            auto new_value_with_type = [&](ir::Value* v) { return b.InstructionResult(v->Type()); };
+            auto new_value_with_type = [&](core::ir::Value* v) {
+                return b.InstructionResult(v->Type());
+            };
 
             if (inner_if->True()->HasTerminator()) {
-                if (auto* exit_if = inner_if->True()->Terminator()->As<ir::ExitIf>()) {
+                if (auto* exit_if = inner_if->True()->Terminator()->As<core::ir::ExitIf>()) {
                     // Ensure the associated 'if' is updated.
                     exit_if->SetIf(inner_if);
 
@@ -185,10 +188,10 @@
 
             // Loop over the 'if' instructions, starting with the inner-most, and add any missing
             // terminating instructions to the blocks holding the 'if'.
-            for (auto* i = inner_if; i; i = tint::As<ir::If>(i->Block()->Parent())) {
+            for (auto* i = inner_if; i; i = tint::As<core::ir::If>(i->Block()->Parent())) {
                 if (!i->Block()->HasTerminator()) {
                     // Append the exit instruction to the block holding the 'if'.
-                    Vector<ir::InstructionResult*, 8> exit_args = i->Results();
+                    Vector<core::ir::InstructionResult*, 8> exit_args = i->Results();
                     if (!i->HasResults()) {
                         i->SetResults(tint::Transform(exit_args, new_value_with_type));
                     }
@@ -204,7 +207,7 @@
     /// @param cond the possibly null 'if(continue_execution)' instruction for the current block.
     /// @note unlike other instructions, return instructions are not automatically moved into the
     /// 'if(continue_execution)' block.
-    void ProcessReturn(ir::Return* ret, ir::If* cond) {
+    void ProcessReturn(core::ir::Return* ret, core::ir::If* cond) {
         if (ret == fn_return) {
             // 'ret' is the final instruction for the function.
             ProcessFunctionBlockReturn(ret, cond);
@@ -217,7 +220,7 @@
     /// Transforms the return instruction that is the last instruction in the function's block.
     /// @param ret the return instruction
     /// @param cond the possibly null 'if(continue_execution)' instruction for the current block.
-    void ProcessFunctionBlockReturn(ir::Return* ret, ir::If* cond) {
+    void ProcessFunctionBlockReturn(core::ir::Return* ret, core::ir::If* cond) {
         if (!return_val) {
             return;  // No need to transform non-value, end-of-function returns
         }
@@ -238,7 +241,7 @@
     /// Transforms the return instruction that is found in a control instruction.
     /// @param ret the return instruction
     /// @param cond the possibly null 'if(continue_execution)' instruction for the current block.
-    void ProcessNestedReturn(ir::Return* ret, ir::If* cond) {
+    void ProcessNestedReturn(core::ir::Return* ret, core::ir::If* cond) {
         // If we have a 'if(continue_execution)' block, then insert instructions into that,
         // otherwise insert into the block holding the return.
         auto* block = cond ? cond->True() : ret->Block();
@@ -253,7 +256,7 @@
         // If the outermost control instruction is expecting exit values, then return them as
         // 'undef' values.
         auto* ctrl = block->Parent();
-        Vector<ir::Value*, 8> exit_args;
+        Vector<core::ir::Value*, 8> exit_args;
         exit_args.Resize(ctrl->Results().Length());
 
         // Replace the return instruction with an exit instruction.
@@ -264,7 +267,7 @@
     /// Builds instructions to create a 'if(continue_execution)' conditional.
     /// @param after new instructions will be inserted after this instruction
     /// @return the 'If' control instruction
-    ir::If* CreateIfContinueExecution(ir::Instruction* after) {
+    core::ir::If* CreateIfContinueExecution(core::ir::Instruction* after) {
         auto* load = b.Load(continue_execution);
         auto* cond = b.If(load);
         load->InsertAfter(after);
@@ -274,7 +277,7 @@
 
     /// Adds a final return instruction to the end of @p fn
     /// @param fn the function
-    void AppendFinalReturn(ir::Function* fn) {
+    void AppendFinalReturn(core::ir::Function* fn) {
         b.Append(fn->Block(), [&] {
             if (return_val) {
                 b.Return(fn, b.Load(return_val));
@@ -287,7 +290,7 @@
 
 }  // namespace
 
-Result<SuccessType, std::string> MergeReturn(ir::Module* ir) {
+Result<SuccessType, std::string> MergeReturn(core::ir::Module* ir) {
     auto result = ValidateAndDumpIfNeeded(*ir, "MergeReturn transform");
     if (!result) {
         return result;
diff --git a/src/tint/lang/spirv/writer/raise/merge_return.h b/src/tint/lang/spirv/writer/raise/merge_return.h
index 88ba2ce..1ad6d87 100644
--- a/src/tint/lang/spirv/writer/raise/merge_return.h
+++ b/src/tint/lang/spirv/writer/raise/merge_return.h
@@ -20,7 +20,7 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
@@ -30,7 +30,7 @@
 /// at the end of the function.
 /// @param module the module to transform
 /// @returns an error string on failure
-Result<SuccessType, std::string> MergeReturn(ir::Module* module);
+Result<SuccessType, std::string> MergeReturn(core::ir::Module* module);
 
 }  // namespace tint::spirv::writer::raise
 
diff --git a/src/tint/lang/spirv/writer/raise/merge_return_test.cc b/src/tint/lang/spirv/writer/raise/merge_return_test.cc
index f6554c7..a7a53a5 100644
--- a/src/tint/lang/spirv/writer/raise/merge_return_test.cc
+++ b/src/tint/lang/spirv/writer/raise/merge_return_test.cc
@@ -24,7 +24,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-using SpirvWriter_MergeReturnTest = ir::transform::TransformTest;
+using SpirvWriter_MergeReturnTest = core::ir::transform::TransformTest;
 
 TEST_F(SpirvWriter_MergeReturnTest, NoModify_SingleReturnInRootBlock) {
     auto* in = b.FunctionParam(ty.i32());
@@ -98,7 +98,7 @@
 
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(in);
-        b.Append(b.Case(swtch, {ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(swtch); });
+        b.Append(b.Case(swtch, {core::ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(swtch); });
 
         auto* l = b.Loop();
         b.Append(l->Body(), [&] { b.ExitLoop(l); });
@@ -1551,9 +1551,9 @@
 
     b.Append(func->Block(), [&] {
         auto* sw = b.Switch(cond);
-        b.Append(b.Case(sw, {ir::Switch::CaseSelector{b.Constant(1_i)}}),
+        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(1_i)}}),
                  [&] { b.Return(func, 42_i); });
-        b.Append(b.Case(sw, {ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw); });
+        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw); });
 
         b.Return(func, 0_i);
     });
@@ -1618,7 +1618,7 @@
 
     b.Append(func->Block(), [&] {
         auto* sw = b.Switch(cond);
-        b.Append(b.Case(sw, {ir::Switch::CaseSelector{b.Constant(1_i)}}), [&] {
+        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(1_i)}}), [&] {
             auto* ifcond = b.Equal(ty.bool_(), cond, 1_i);
             auto* ifelse = b.If(ifcond);
             b.Append(ifelse->True(), [&] { b.Return(func, 42_i); });
@@ -1628,7 +1628,7 @@
             b.ExitSwitch(sw);
         });
 
-        b.Append(b.Case(sw, {ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw); });
+        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw); });
 
         b.Return(func, 0_i);
     });
@@ -1725,13 +1725,13 @@
     b.Append(func->Block(), [&] {
         auto* sw = b.Switch(cond);
         sw->SetResults(b.InstructionResult(ty.i32()));  // NOLINT: false detection of std::tuple
-        b.Append(b.Case(sw, {ir::Switch::CaseSelector{b.Constant(1_i)}}),
+        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(1_i)}}),
                  [&] { b.Return(func, 42_i); });
-        b.Append(b.Case(sw, {ir::Switch::CaseSelector{b.Constant(2_i)}}),
+        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(2_i)}}),
                  [&] { b.Return(func, 99_i); });
-        b.Append(b.Case(sw, {ir::Switch::CaseSelector{b.Constant(3_i)}}),
+        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(3_i)}}),
                  [&] { b.ExitSwitch(sw, 1_i); });
-        b.Append(b.Case(sw, {ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw, 0_i); });
+        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw, 0_i); });
 
         b.Return(func, sw->Result(0));
     });
diff --git a/src/tint/lang/spirv/writer/raise/raise.cc b/src/tint/lang/spirv/writer/raise/raise.cc
index 842c799..2d510db 100644
--- a/src/tint/lang/spirv/writer/raise/raise.cc
+++ b/src/tint/lang/spirv/writer/raise/raise.cc
@@ -32,7 +32,7 @@
 
 namespace tint::spirv::writer::raise {
 
-Result<SuccessType, std::string> Raise(ir::Module* module, const Options& options) {
+Result<SuccessType, std::string> Raise(core::ir::Module* module, const Options& options) {
 #define RUN_TRANSFORM(name, ...)         \
     do {                                 \
         auto result = name(__VA_ARGS__); \
@@ -41,28 +41,28 @@
         }                                \
     } while (false)
 
-    ir::transform::BuiltinPolyfillConfig core_polyfills;
+    core::ir::transform::BuiltinPolyfillConfig core_polyfills;
     core_polyfills.count_leading_zeros = true;
     core_polyfills.count_trailing_zeros = true;
     core_polyfills.first_leading_bit = true;
     core_polyfills.first_trailing_bit = true;
     core_polyfills.saturate = true;
     core_polyfills.texture_sample_base_clamp_to_edge_2d_f32 = true;
-    RUN_TRANSFORM(ir::transform::BuiltinPolyfill, module, core_polyfills);
+    RUN_TRANSFORM(core::ir::transform::BuiltinPolyfill, module, core_polyfills);
 
-    RUN_TRANSFORM(ir::transform::MultiplanarExternalTexture, module,
+    RUN_TRANSFORM(core::ir::transform::MultiplanarExternalTexture, module,
                   options.external_texture_options);
 
-    RUN_TRANSFORM(ir::transform::AddEmptyEntryPoint, module);
-    RUN_TRANSFORM(ir::transform::Bgra8UnormPolyfill, module);
-    RUN_TRANSFORM(ir::transform::BlockDecoratedStructs, module);
+    RUN_TRANSFORM(core::ir::transform::AddEmptyEntryPoint, module);
+    RUN_TRANSFORM(core::ir::transform::Bgra8UnormPolyfill, module);
+    RUN_TRANSFORM(core::ir::transform::BlockDecoratedStructs, module);
     RUN_TRANSFORM(BuiltinPolyfill, module);
-    RUN_TRANSFORM(ir::transform::DemoteToHelper, module);
+    RUN_TRANSFORM(core::ir::transform::DemoteToHelper, module);
     RUN_TRANSFORM(ExpandImplicitSplats, module);
     RUN_TRANSFORM(HandleMatrixArithmetic, module);
     RUN_TRANSFORM(MergeReturn, module);
     RUN_TRANSFORM(ShaderIO, module, ShaderIOConfig{options.clamp_frag_depth});
-    RUN_TRANSFORM(ir::transform::Std140, module);
+    RUN_TRANSFORM(core::ir::transform::Std140, module);
     RUN_TRANSFORM(VarForDynamicIndex, module);
 
     return Success;
diff --git a/src/tint/lang/spirv/writer/raise/raise.h b/src/tint/lang/spirv/writer/raise/raise.h
index 50d47bd..adaae92 100644
--- a/src/tint/lang/spirv/writer/raise/raise.h
+++ b/src/tint/lang/spirv/writer/raise/raise.h
@@ -21,7 +21,7 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
@@ -31,7 +31,7 @@
 /// @param module the core IR module to raise to SPIR-V dialect
 /// @param options the SPIR-V writer options
 /// @returns success or an error string
-Result<SuccessType, std::string> Raise(ir::Module* module, const Options& options);
+Result<SuccessType, std::string> Raise(core::ir::Module* module, const Options& options);
 
 }  // namespace tint::spirv::writer::raise
 
diff --git a/src/tint/lang/spirv/writer/raise/shader_io.cc b/src/tint/lang/spirv/writer/raise/shader_io.cc
index ebdfc2a..2716b67 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io.cc
@@ -36,15 +36,15 @@
 /// output, and declare global variables for them. The wrapper entry point then loads from and
 /// stores to these variables.
 /// We also modify the type of the SampleMask builtin to be an array, as required by Vulkan.
-struct StateImpl : ir::transform::ShaderIOBackendState {
+struct StateImpl : core::ir::transform::ShaderIOBackendState {
     /// The global variable for input builtins.
-    ir::Var* builtin_input_var = nullptr;
+    core::ir::Var* builtin_input_var = nullptr;
     /// The global variable for input locations.
-    ir::Var* location_input_var = nullptr;
+    core::ir::Var* location_input_var = nullptr;
     /// The global variable for output builtins.
-    ir::Var* builtin_output_var = nullptr;
+    core::ir::Var* builtin_output_var = nullptr;
     /// The global variable for output locations.
-    ir::Var* location_output_var = nullptr;
+    core::ir::Var* location_output_var = nullptr;
     /// The member indices for inputs.
     Vector<uint32_t, 4> input_indices;
     /// The member indices for outputs.
@@ -54,10 +54,10 @@
     const ShaderIOConfig& config;
 
     /// The frag_depth clamp arguments.
-    ir::Value* frag_depth_clamp_args = nullptr;
+    core::ir::Value* frag_depth_clamp_args = nullptr;
 
     /// Constructor
-    StateImpl(ir::Module* mod, ir::Function* f, const ShaderIOConfig& cfg)
+    StateImpl(core::ir::Module* mod, core::ir::Function* f, const ShaderIOConfig& cfg)
         : ShaderIOBackendState(mod, f), config(cfg) {}
 
     /// Destructor
@@ -72,8 +72,8 @@
     /// @param addrspace the address to use for the global variables
     /// @param access the access mode to use for the global variables
     /// @param name_suffix the suffix to add to struct and variable names
-    void MakeStructs(ir::Var*& builtin_var,
-                     ir::Var*& location_var,
+    void MakeStructs(core::ir::Var*& builtin_var,
+                     core::ir::Var*& location_var,
                      Vector<uint32_t, 4>* indices,
                      Vector<core::type::Manager::StructMemberDesc, 4>& entries,
                      core::AddressSpace addrspace,
@@ -116,24 +116,24 @@
     }
 
     /// @copydoc ShaderIO::BackendState::FinalizeInputs
-    Vector<ir::FunctionParam*, 4> FinalizeInputs() override {
+    Vector<core::ir::FunctionParam*, 4> FinalizeInputs() override {
         MakeStructs(builtin_input_var, location_input_var, &input_indices, inputs,
                     core::AddressSpace::kIn, core::Access::kRead, "Inputs");
         return tint::Empty;
     }
 
     /// @copydoc ShaderIO::BackendState::FinalizeOutputs
-    ir::Value* FinalizeOutputs() override {
+    core::ir::Value* FinalizeOutputs() override {
         MakeStructs(builtin_output_var, location_output_var, &output_indices, outputs,
                     core::AddressSpace::kOut, core::Access::kWrite, "Outputs");
         return nullptr;
     }
 
     /// @copydoc ShaderIO::BackendState::GetInput
-    ir::Value* GetInput(ir::Builder& builder, uint32_t idx) override {
+    core::ir::Value* GetInput(core::ir::Builder& builder, uint32_t idx) override {
         // Load the input from the global variable declared earlier.
         auto* ptr = ty.ptr(core::AddressSpace::kIn, inputs[idx].type, core::Access::kRead);
-        ir::Access* from = nullptr;
+        core::ir::Access* from = nullptr;
         if (inputs[idx].attributes.builtin) {
             if (inputs[idx].attributes.builtin.value() == core::BuiltinValue::kSampleMask) {
                 // SampleMask becomes an array for SPIR-V, so load from the first element.
@@ -148,10 +148,10 @@
     }
 
     /// @copydoc ShaderIO::BackendState::SetOutput
-    void SetOutput(ir::Builder& builder, uint32_t idx, ir::Value* value) override {
+    void SetOutput(core::ir::Builder& builder, uint32_t idx, core::ir::Value* value) override {
         // Store the output to the global variable declared earlier.
         auto* ptr = ty.ptr(core::AddressSpace::kOut, outputs[idx].type, core::Access::kWrite);
-        ir::Access* to = nullptr;
+        core::ir::Access* to = nullptr;
         if (outputs[idx].attributes.builtin) {
             if (outputs[idx].attributes.builtin.value() == core::BuiltinValue::kSampleMask) {
                 // SampleMask becomes an array for SPIR-V, so store to the first element.
@@ -174,7 +174,7 @@
     /// @param builder the builder to use for new instructions
     /// @param frag_depth the incoming frag_depth value
     /// @returns the clamped value
-    ir::Value* ClampFragDepth(ir::Builder& builder, ir::Value* frag_depth) {
+    core::ir::Value* ClampFragDepth(core::ir::Builder& builder, core::ir::Value* frag_depth) {
         if (!config.clamp_frag_depth) {
             return frag_depth;
         }
@@ -183,7 +183,7 @@
         if (!frag_depth_clamp_args) {
             // Check that there are no push constants in the module already.
             for (auto* inst : *b.RootBlock()) {
-                if (auto* var = inst->As<ir::Var>()) {
+                if (auto* var = inst->As<core::ir::Var>()) {
                     auto* ptr = var->Result()->Type()->As<core::type::Pointer>();
                     if (ptr->AddressSpace() == core::AddressSpace::kPushConstant) {
                         TINT_ICE() << "cannot clamp frag_depth with pre-existing push constants";
@@ -216,13 +216,13 @@
 };
 }  // namespace
 
-Result<SuccessType, std::string> ShaderIO(ir::Module* ir, const ShaderIOConfig& config) {
+Result<SuccessType, std::string> ShaderIO(core::ir::Module* ir, const ShaderIOConfig& config) {
     auto result = ValidateAndDumpIfNeeded(*ir, "ShaderIO transform");
     if (!result) {
         return result;
     }
 
-    ir::transform::RunShaderIOBase(ir, [&](ir::Module* mod, ir::Function* func) {
+    core::ir::transform::RunShaderIOBase(ir, [&](core::ir::Module* mod, core::ir::Function* func) {
         return std::make_unique<StateImpl>(mod, func, config);
     });
 
diff --git a/src/tint/lang/spirv/writer/raise/shader_io.h b/src/tint/lang/spirv/writer/raise/shader_io.h
index 633339f..5924c12 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io.h
+++ b/src/tint/lang/spirv/writer/raise/shader_io.h
@@ -20,7 +20,7 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
@@ -37,7 +37,7 @@
 /// @param module the module to transform
 /// @param config the configuration
 /// @returns an error string on failure
-Result<SuccessType, std::string> ShaderIO(ir::Module* module, const ShaderIOConfig& config);
+Result<SuccessType, std::string> ShaderIO(core::ir::Module* module, const ShaderIOConfig& config);
 
 }  // namespace tint::spirv::writer::raise
 
diff --git a/src/tint/lang/spirv/writer/raise/shader_io_test.cc b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
index 63229e6..0638d50 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io_test.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
@@ -24,11 +24,11 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-using SpirvWriter_ShaderIOTest = ir::transform::TransformTest;
+using SpirvWriter_ShaderIOTest = core::ir::transform::TransformTest;
 
 TEST_F(SpirvWriter_ShaderIOTest, NoInputsOrOutputs) {
     auto* ep = b.Function("foo", ty.void_());
-    ep->SetStage(ir::Function::PipelineStage::kCompute);
+    ep->SetStage(core::ir::Function::PipelineStage::kCompute);
 
     b.Append(ep->Block(), [&] {  //
         b.Return(ep);
@@ -55,9 +55,9 @@
 TEST_F(SpirvWriter_ShaderIOTest, Parameters_NonStruct) {
     auto* ep = b.Function("foo", ty.void_());
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(ir::FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(core::ir::FunctionParam::Builtin::kFrontFacing);
     auto* position = b.FunctionParam("position", ty.vec4<f32>());
-    position->SetBuiltin(ir::FunctionParam::Builtin::kPosition);
+    position->SetBuiltin(core::ir::FunctionParam::Builtin::kPosition);
     position->SetInvariant(true);
     auto* color1 = b.FunctionParam("color1", ty.f32());
     color1->SetLocation(0, {});
@@ -66,7 +66,7 @@
                                                core::InterpolationSampling::kSample});
 
     ep->SetParams({front_facing, position, color1, color2});
-    ep->SetStage(ir::Function::PipelineStage::kFragment);
+    ep->SetStage(core::ir::Function::PipelineStage::kFragment);
 
     b.Append(ep->Block(), [&] {
         auto* ifelse = b.If(front_facing);
@@ -177,7 +177,7 @@
     auto* ep = b.Function("foo", ty.void_());
     auto* str_param = b.FunctionParam("inputs", str_ty);
     ep->SetParams({str_param});
-    ep->SetStage(ir::Function::PipelineStage::kFragment);
+    ep->SetStage(core::ir::Function::PipelineStage::kFragment);
 
     b.Append(ep->Block(), [&] {
         auto* ifelse = b.If(b.Access(ty.bool_(), str_param, 0_i));
@@ -298,14 +298,14 @@
 
     auto* ep = b.Function("foo", ty.void_());
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(ir::FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(core::ir::FunctionParam::Builtin::kFrontFacing);
     auto* str_param = b.FunctionParam("inputs", str_ty);
     auto* color2 = b.FunctionParam("color2", ty.f32());
     color2->SetLocation(1, core::Interpolation{core::InterpolationType::kLinear,
                                                core::InterpolationSampling::kSample});
 
     ep->SetParams({front_facing, str_param, color2});
-    ep->SetStage(ir::Function::PipelineStage::kFragment);
+    ep->SetStage(core::ir::Function::PipelineStage::kFragment);
 
     b.Append(ep->Block(), [&] {
         auto* ifelse = b.If(front_facing);
@@ -402,9 +402,9 @@
 
 TEST_F(SpirvWriter_ShaderIOTest, ReturnValue_NonStructBuiltin) {
     auto* ep = b.Function("foo", ty.vec4<f32>());
-    ep->SetReturnBuiltin(ir::Function::ReturnBuiltin::kPosition);
+    ep->SetReturnBuiltin(core::ir::Function::ReturnBuiltin::kPosition);
     ep->SetReturnInvariant(true);
-    ep->SetStage(ir::Function::PipelineStage::kVertex);
+    ep->SetStage(core::ir::Function::PipelineStage::kVertex);
 
     b.Append(ep->Block(), [&] {  //
         b.Return(ep, b.Construct(ty.vec4<f32>(), 0.5_f));
@@ -455,7 +455,7 @@
 TEST_F(SpirvWriter_ShaderIOTest, ReturnValue_NonStructLocation) {
     auto* ep = b.Function("foo", ty.vec4<f32>());
     ep->SetReturnLocation(1u, {});
-    ep->SetStage(ir::Function::PipelineStage::kFragment);
+    ep->SetStage(core::ir::Function::PipelineStage::kFragment);
 
     b.Append(ep->Block(), [&] {  //
         b.Return(ep, b.Construct(ty.vec4<f32>(), 0.5_f));
@@ -529,7 +529,7 @@
                              });
 
     auto* ep = b.Function("foo", str_ty);
-    ep->SetStage(ir::Function::PipelineStage::kVertex);
+    ep->SetStage(core::ir::Function::PipelineStage::kVertex);
 
     b.Append(ep->Block(), [&] {  //
         b.Return(ep, b.Construct(str_ty, b.Construct(ty.vec4<f32>(), 0_f), 0.25_f, 0.75_f));
@@ -623,7 +623,7 @@
     // Vertex shader.
     {
         auto* ep = b.Function("vert", str_ty);
-        ep->SetStage(ir::Function::PipelineStage::kVertex);
+        ep->SetStage(core::ir::Function::PipelineStage::kVertex);
 
         b.Append(ep->Block(), [&] {  //
             auto* position = b.Construct(vec4f, 0_f);
@@ -636,7 +636,7 @@
     {
         auto* ep = b.Function("frag", vec4f);
         auto* inputs = b.FunctionParam("inputs", str_ty);
-        ep->SetStage(ir::Function::PipelineStage::kFragment);
+        ep->SetStage(core::ir::Function::PipelineStage::kFragment);
         ep->SetParams({inputs});
 
         b.Append(ep->Block(), [&] {  //
@@ -774,7 +774,7 @@
     auto* buffer = b.RootBlock()->Append(b.Var(ty.ptr(storage, str_ty, read)));
 
     auto* ep = b.Function("vert", str_ty);
-    ep->SetStage(ir::Function::PipelineStage::kVertex);
+    ep->SetStage(core::ir::Function::PipelineStage::kVertex);
 
     b.Append(ep->Block(), [&] {  //
         b.Return(ep, b.Load(buffer));
@@ -863,10 +863,10 @@
                              });
 
     auto* mask_in = b.FunctionParam("mask_in", ty.u32());
-    mask_in->SetBuiltin(ir::FunctionParam::Builtin::kSampleMask);
+    mask_in->SetBuiltin(core::ir::FunctionParam::Builtin::kSampleMask);
 
     auto* ep = b.Function("foo", str_ty);
-    ep->SetStage(ir::Function::PipelineStage::kFragment);
+    ep->SetStage(core::ir::Function::PipelineStage::kFragment);
     ep->SetParams({mask_in});
 
     b.Append(ep->Block(), [&] {  //
@@ -957,7 +957,7 @@
                              });
 
     auto* ep = b.Function("foo", str_ty);
-    ep->SetStage(ir::Function::PipelineStage::kFragment);
+    ep->SetStage(core::ir::Function::PipelineStage::kFragment);
 
     b.Append(ep->Block(), [&] {  //
         b.Return(ep, b.Construct(str_ty, 0.5_f, 2_f));
diff --git a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc
index c66d8de7..e749a28 100644
--- a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc
+++ b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.cc
@@ -35,7 +35,7 @@
 // An access that needs replacing.
 struct AccessToReplace {
     // The access instruction.
-    ir::Access* access = nullptr;
+    core::ir::Access* access = nullptr;
     // The index of the first dynamic index.
     size_t first_dynamic_index = 0;
     // The object type that corresponds to the source of the first dynamic index.
@@ -48,9 +48,9 @@
 // dynamically indexed.
 struct PartialAccess {
     // The base object.
-    ir::Value* base = nullptr;
+    core::ir::Value* base = nullptr;
     // The list of constant indices to get from the base to the source object.
-    Vector<ir::Value*, 4> indices;
+    Vector<core::ir::Value*, 4> indices;
 
     // A specialization of Hasher for PartialAccess.
     struct Hasher {
@@ -68,26 +68,26 @@
 enum class Action { kStop, kContinue };
 
 template <typename CALLBACK>
-void WalkAccessChain(ir::Access* access, CALLBACK&& callback) {
+void WalkAccessChain(core::ir::Access* access, CALLBACK&& callback) {
     auto indices = access->Indices();
     auto* ty = access->Object()->Type();
     for (size_t i = 0; i < indices.Length(); i++) {
         if (callback(i, indices[i], ty) == Action::kStop) {
             break;
         }
-        auto* const_idx = indices[i]->As<ir::Constant>();
+        auto* const_idx = indices[i]->As<core::ir::Constant>();
         ty = const_idx ? ty->Element(const_idx->Value()->ValueAs<u32>()) : ty->Elements().type;
     }
 }
 
-std::optional<AccessToReplace> ShouldReplace(ir::Access* access) {
+std::optional<AccessToReplace> ShouldReplace(core::ir::Access* access) {
     if (access->Result()->Type()->Is<core::type::Pointer>()) {
         // No need to modify accesses into pointer types.
         return {};
     }
 
     std::optional<AccessToReplace> result;
-    WalkAccessChain(access, [&](size_t i, ir::Value* index, const core::type::Type* ty) {
+    WalkAccessChain(access, [&](size_t i, core::ir::Value* index, const core::type::Type* ty) {
         if (auto* vec = ty->As<core::type::Vector>()) {
             // If we haven't found a dynamic index before the vector, then the transform doesn't
             // need to hoist the access into a var as a vector value can be dynamically indexed.
@@ -101,7 +101,7 @@
         }
 
         // Check if this is the first dynamic index.
-        if (!result && !index->Is<ir::Constant>()) {
+        if (!result && !index->Is<core::ir::Constant>()) {
             result = AccessToReplace{access, i, ty};
         }
 
@@ -111,13 +111,13 @@
     return result;
 }
 
-void Run(ir::Module* ir) {
-    ir::Builder builder(*ir);
+void Run(core::ir::Module* ir) {
+    core::ir::Builder builder(*ir);
 
     // Find the access instructions that need replacing.
     Vector<AccessToReplace, 4> worklist;
     for (auto* inst : ir->instructions.Objects()) {
-        if (auto* access = inst->As<ir::Access>()) {
+        if (auto* access = inst->As<core::ir::Access>()) {
             if (auto to_replace = ShouldReplace(access)) {
                 worklist.Push(to_replace.value());
             }
@@ -125,8 +125,8 @@
     }
 
     // Replace each access instruction that we recorded.
-    Hashmap<ir::Value*, ir::Value*, 4> object_to_local;
-    Hashmap<PartialAccess, ir::Value*, 4, PartialAccess::Hasher> source_object_to_value;
+    Hashmap<core::ir::Value*, core::ir::Value*, 4> object_to_local;
+    Hashmap<PartialAccess, core::ir::Value*, 4, PartialAccess::Hasher> source_object_to_value;
     for (const auto& to_replace : worklist) {
         auto* access = to_replace.access;
         auto* source_object = access->Object();
@@ -154,9 +154,10 @@
         });
 
         // Create a new access instruction using the local variable as the source.
-        Vector<ir::Value*, 4> indices{access->Indices().Offset(to_replace.first_dynamic_index)};
+        Vector<core::ir::Value*, 4> indices{
+            access->Indices().Offset(to_replace.first_dynamic_index)};
         const core::type::Type* access_type = access->Result()->Type();
-        ir::Value* vector_index = nullptr;
+        core::ir::Value* vector_index = nullptr;
         if (to_replace.vector_access_type) {
             // The old access indexed the element of a vector.
             // Its not valid to obtain the address of an element of a vector, so we need to access
@@ -168,12 +169,12 @@
             vector_index = indices.Pop();
         }
 
-        ir::Instruction* new_access = builder.Access(
+        core::ir::Instruction* new_access = builder.Access(
             ir->Types().ptr(core::AddressSpace::kFunction, access_type, core::Access::kReadWrite),
             local, indices);
         new_access->InsertBefore(access);
 
-        ir::Instruction* load = nullptr;
+        core::ir::Instruction* load = nullptr;
         if (to_replace.vector_access_type) {
             load = builder.LoadVectorElement(new_access->Result(), vector_index);
         } else {
@@ -188,7 +189,7 @@
 
 }  // namespace
 
-Result<SuccessType, std::string> VarForDynamicIndex(ir::Module* ir) {
+Result<SuccessType, std::string> VarForDynamicIndex(core::ir::Module* ir) {
     auto result = ValidateAndDumpIfNeeded(*ir, "VarForDynamicIndex transform");
     if (!result) {
         return result;
diff --git a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h
index e8c1387..6878db4 100644
--- a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h
+++ b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index.h
@@ -20,7 +20,7 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
@@ -32,7 +32,7 @@
 /// composite.
 /// @param module the module to transform
 /// @returns an error string on failure
-Result<SuccessType, std::string> VarForDynamicIndex(ir::Module* module);
+Result<SuccessType, std::string> VarForDynamicIndex(core::ir::Module* module);
 
 }  // namespace tint::spirv::writer::raise
 
diff --git a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index_test.cc b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index_test.cc
index d71a10c..7daf9b2 100644
--- a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index_test.cc
+++ b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index_test.cc
@@ -27,7 +27,7 @@
 using namespace tint::core::fluent_types;     // NOLINT
 using namespace tint::core::number_suffixes;  // NOLINT
 
-using SpirvWriter_VarForDynamicIndexTest = ir::transform::TransformTest;
+using SpirvWriter_VarForDynamicIndexTest = core::ir::transform::TransformTest;
 
 TEST_F(SpirvWriter_VarForDynamicIndexTest, NoModify_ConstantIndex_ArrayValue) {
     auto* arr = b.FunctionParam(ty.array<i32, 4u>());
diff --git a/src/tint/lang/spirv/writer/switch_test.cc b/src/tint/lang/spirv/writer/switch_test.cc
index 7accfd2..da931bb 100644
--- a/src/tint/lang/spirv/writer/switch_test.cc
+++ b/src/tint/lang/spirv/writer/switch_test.cc
@@ -26,7 +26,7 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* def_case = b.Case(swtch, Vector{ir::Switch::CaseSelector()});
+        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector()});
         b.Append(def_case, [&] {  //
             b.ExitSwitch(swtch);
         });
@@ -52,17 +52,17 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* case_a = b.Case(swtch, Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
+        auto* case_a = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)}});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(swtch);
         });
 
-        auto* case_b = b.Case(swtch, Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(swtch);
         });
 
-        auto* def_case = b.Case(swtch, Vector{ir::Switch::CaseSelector()});
+        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector()});
         b.Append(def_case, [&] {  //
             b.ExitSwitch(swtch);
         });
@@ -92,20 +92,20 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* case_a = b.Case(swtch, Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
-                                            ir::Switch::CaseSelector{b.Constant(3_i)}});
+        auto* case_a = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                                            core::ir::Switch::CaseSelector{b.Constant(3_i)}});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(swtch);
         });
 
-        auto* case_b = b.Case(swtch, Vector{ir::Switch::CaseSelector{b.Constant(2_i)},
-                                            ir::Switch::CaseSelector{b.Constant(4_i)}});
+        auto* case_b = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)},
+                                            core::ir::Switch::CaseSelector{b.Constant(4_i)}});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(swtch);
         });
 
-        auto* def_case = b.Case(
-            swtch, Vector{ir::Switch::CaseSelector{b.Constant(5_i)}, ir::Switch::CaseSelector()});
+        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(5_i)},
+                                              core::ir::Switch::CaseSelector()});
         b.Append(def_case, [&] {  //
             b.ExitSwitch(swtch);
         });
@@ -135,17 +135,17 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* case_a = b.Case(swtch, Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
+        auto* case_a = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)}});
         b.Append(case_a, [&] {  //
             b.Return(func);
         });
 
-        auto* case_b = b.Case(swtch, Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
         b.Append(case_b, [&] {  //
             b.Return(func);
         });
 
-        auto* def_case = b.Case(swtch, Vector{ir::Switch::CaseSelector()});
+        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector()});
         b.Append(def_case, [&] {  //
             b.Return(func);
         });
@@ -175,7 +175,7 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* case_a = b.Case(swtch, Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
+        auto* case_a = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)}});
         b.Append(case_a, [&] {
             auto* cond_break = b.If(true);
             b.Append(cond_break->True(), [&] {  //
@@ -188,7 +188,7 @@
             b.Return(func);
         });
 
-        auto* def_case = b.Case(swtch, Vector{ir::Switch::CaseSelector()});
+        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector()});
         b.Append(def_case, [&] {  //
             b.ExitSwitch(swtch);
         });
@@ -221,13 +221,13 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(42_i);
         s->SetResults(b.InstructionResult(ty.i32()));
-        auto* case_a = b.Case(s, Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                                        core::ir::Switch::CaseSelector{nullptr}});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(s, 10_i);
         });
 
-        auto* case_b = b.Case(s, Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i);
         });
@@ -256,13 +256,13 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(42_i);
         s->SetResults(b.InstructionResult(ty.i32()));
-        auto* case_a = b.Case(s, Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                                        core::ir::Switch::CaseSelector{nullptr}});
         b.Append(case_a, [&] {  //
             b.Return(func, 10_i);
         });
 
-        auto* case_b = b.Case(s, Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i);
         });
@@ -304,13 +304,13 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(42_i);
         s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
-        auto* case_a = b.Case(s, Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                                        core::ir::Switch::CaseSelector{nullptr}});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(s, 10_i, true);
         });
 
-        auto* case_b = b.Case(s, Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i, false);
         });
@@ -340,13 +340,13 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(b.Constant(42_i));
         s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
-        auto* case_a = b.Case(s, Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                                        core::ir::Switch::CaseSelector{nullptr}});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(s, 10_i, true);
         });
 
-        auto* case_b = b.Case(s, Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i, false);
         });
diff --git a/src/tint/lang/spirv/writer/texture_builtin_test.cc b/src/tint/lang/spirv/writer/texture_builtin_test.cc
index 4b91601..baa3e04 100644
--- a/src/tint/lang/spirv/writer/texture_builtin_test.cc
+++ b/src/tint/lang/spirv/writer/texture_builtin_test.cc
@@ -143,12 +143,12 @@
             result_ty = ty.vec(result_ty, params.result.width);
         }
 
-        Vector<ir::FunctionParam*, 4> func_params;
+        Vector<core::ir::FunctionParam*, 4> func_params;
 
         auto* t = b.FunctionParam(
             "t", MakeTextureType(params.texture_type, params.dim, params.texel_type));
         func_params.Push(t);
-        ir::FunctionParam* s = nullptr;
+        core::ir::FunctionParam* s = nullptr;
         if (sampler == kSampler) {
             s = b.FunctionParam("s", ty.sampler());
             func_params.Push(s);
@@ -163,7 +163,7 @@
         b.Append(func->Block(), [&] {
             uint32_t arg_value = 1;
 
-            Vector<ir::Value*, 4> args;
+            Vector<core::ir::Value*, 4> args;
             if (function == core::Function::kTextureGather &&
                 params.texture_type != kDepthTexture) {
                 // Special case for textureGather, which has a component argument first.
@@ -1883,7 +1883,7 @@
     auto* texture_ty =
         ty.Get<core::type::SampledTexture>(core::type::TextureDimension::k2d, ty.f32());
 
-    Vector<ir::FunctionParam*, 4> args;
+    Vector<core::ir::FunctionParam*, 4> args;
     args.Push(b.FunctionParam("texture", texture_ty));
     args.Push(b.FunctionParam("sampler", ty.sampler()));
     args.Push(b.FunctionParam("coords", ty.vec2<f32>()));
diff --git a/src/tint/lang/spirv/writer/unary_test.cc b/src/tint/lang/spirv/writer/unary_test.cc
index 0384b39..b991a61 100644
--- a/src/tint/lang/spirv/writer/unary_test.cc
+++ b/src/tint/lang/spirv/writer/unary_test.cc
@@ -28,7 +28,7 @@
     /// The element type to test.
     TestElementType type;
     /// The unary operation.
-    enum ir::Unary::Kind kind;
+    enum core::ir::Unary::Kind kind;
     /// The expected SPIR-V instruction.
     std::string spirv_inst;
     /// The expected SPIR-V result type name.
@@ -69,11 +69,11 @@
 INSTANTIATE_TEST_SUITE_P(
     SpirvWriterTest_Unary,
     Arithmetic,
-    testing::Values(UnaryTestCase{kI32, ir::Unary::Kind::kComplement, "OpNot", "int"},
-                    UnaryTestCase{kU32, ir::Unary::Kind::kComplement, "OpNot", "uint"},
-                    UnaryTestCase{kI32, ir::Unary::Kind::kNegation, "OpSNegate", "int"},
-                    UnaryTestCase{kF32, ir::Unary::Kind::kNegation, "OpFNegate", "float"},
-                    UnaryTestCase{kF16, ir::Unary::Kind::kNegation, "OpFNegate", "half"}));
+    testing::Values(UnaryTestCase{kI32, core::ir::Unary::Kind::kComplement, "OpNot", "int"},
+                    UnaryTestCase{kU32, core::ir::Unary::Kind::kComplement, "OpNot", "uint"},
+                    UnaryTestCase{kI32, core::ir::Unary::Kind::kNegation, "OpSNegate", "int"},
+                    UnaryTestCase{kF32, core::ir::Unary::Kind::kNegation, "OpFNegate", "float"},
+                    UnaryTestCase{kF16, core::ir::Unary::Kind::kNegation, "OpFNegate", "half"}));
 
 }  // namespace
 }  // namespace tint::spirv::writer
diff --git a/src/tint/lang/spirv/writer/var_test.cc b/src/tint/lang/spirv/writer/var_test.cc
index ffe1437..6581e3d 100644
--- a/src/tint/lang/spirv/writer/var_test.cc
+++ b/src/tint/lang/spirv/writer/var_test.cc
@@ -124,7 +124,7 @@
     v->SetInitializer(b.Constant(42_i));
     b.RootBlock()->Append(v);
 
-    auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kFragment);
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
     b.Append(func->Block(), [&] {
         auto* load = b.Load(v);
         auto* add = b.Add(ty.i32(), load, 1_i);
@@ -150,7 +150,7 @@
 TEST_F(SpirvWriterTest, WorkgroupVar_LoadAndStore) {
     auto* v = b.RootBlock()->Append(b.Var("v", ty.ptr<workgroup, i32>()));
 
-    auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kCompute,
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute,
                             std::array{1u, 1u, 1u});
     b.Append(func->Block(), [&] {
         auto* load = b.Load(v);
@@ -200,7 +200,7 @@
     v->SetBindingPoint(0, 0);
     b.RootBlock()->Append(v);
 
-    auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kCompute,
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute,
                             std::array{1u, 1u, 1u});
     b.Append(func->Block(), [&] {
         auto* load = b.Load(v);
@@ -244,7 +244,7 @@
     v->SetBindingPoint(0, 0);
     b.RootBlock()->Append(v);
 
-    auto* func = b.Function("foo", ty.void_(), ir::Function::PipelineStage::kCompute,
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute,
                             std::array{1u, 1u, 1u});
     b.Append(func->Block(), [&] {
         auto* load = b.Load(v);
diff --git a/src/tint/lang/spirv/writer/writer.cc b/src/tint/lang/spirv/writer/writer.cc
index 02443c2..42fe4c2 100644
--- a/src/tint/lang/spirv/writer/writer.cc
+++ b/src/tint/lang/spirv/writer/writer.cc
@@ -55,7 +55,7 @@
         auto ir = converted.Move();
 
         // Apply transforms as required by writer options.
-        auto remapper = ir::transform::BindingRemapper(&ir, options.binding_remapper_options);
+        auto remapper = core::ir::transform::BindingRemapper(&ir, options.binding_remapper_options);
         if (!remapper) {
             return remapper.Failure();
         }
diff --git a/src/tint/lang/wgsl/helpers/ir_program_test.h b/src/tint/lang/wgsl/helpers/ir_program_test.h
index cd4807d..1f148e4 100644
--- a/src/tint/lang/wgsl/helpers/ir_program_test.h
+++ b/src/tint/lang/wgsl/helpers/ir_program_test.h
@@ -40,7 +40,7 @@
 
     /// Build the module, cleaning up the program before returning.
     /// @returns the generated module
-    tint::Result<ir::Module, std::string> Build() {
+    tint::Result<core::ir::Module, std::string> Build() {
         Program program{resolver::Resolve(*this)};
         if (!program.IsValid()) {
             return program.Diagnostics().str();
@@ -48,7 +48,7 @@
 
         auto result = wgsl::reader::ProgramToIR(&program);
         if (result) {
-            auto validated = ir::Validate(result.Get());
+            auto validated = core::ir::Validate(result.Get());
             if (!validated) {
                 return validated.Failure().str();
             }
@@ -59,7 +59,7 @@
     /// Build the module from the given WGSL.
     /// @param wgsl the WGSL to convert to IR
     /// @returns the generated module
-    tint::Result<ir::Module, std::string> Build(std::string wgsl) {
+    tint::Result<core::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);
@@ -69,7 +69,7 @@
 
         auto result = wgsl::reader::ProgramToIR(&program);
         if (result) {
-            auto validated = ir::Validate(result.Get());
+            auto validated = core::ir::Validate(result.Get());
             if (!validated) {
                 return validated.Failure().str();
             }
@@ -82,8 +82,8 @@
 
     /// @param mod the module
     /// @returns the disassembly string of the module
-    std::string Disassemble(ir::Module& mod) {
-        ir::Disassembler d(mod);
+    std::string Disassemble(core::ir::Module& mod) {
+        core::ir::Disassembler d(mod);
         return d.Disassemble();
     }
 };
diff --git a/src/tint/lang/wgsl/ir_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
index ef4207a..c4bda0a 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -37,7 +37,7 @@
         auto ir_module = wgsl::reader::ProgramToIR(&input_program);
         ASSERT_TRUE(ir_module) << (ir_module ? "" : ir_module.Failure());
 
-        tint::ir::Disassembler d{ir_module.Get()};
+        tint::core::ir::Disassembler d{ir_module.Get()};
         auto disassembly = d.Disassemble();
 
         auto output_program = wgsl::writer::IRToProgram(ir_module.Get());
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 23612b5..688399c 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
@@ -27,14 +27,14 @@
 namespace tint::wgsl::reader {
 namespace {
 
-ir::Value* GlobalVarInitializer(ir::Module& m) {
+core::ir::Value* GlobalVarInitializer(core::ir::Module& m) {
     if (m.root_block->Length() == 0u) {
         ADD_FAILURE() << "m.root_block has no instruction";
         return nullptr;
     }
 
     auto instr = m.root_block->Instructions();
-    auto* var = instr->As<ir::Var>();
+    auto* var = instr->As<core::ir::Var>();
     if (!var) {
         ADD_FAILURE() << "m.root_block.instructions[0] was not a var";
         return nullptr;
@@ -54,8 +54,8 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<ir::Constant>(init));
-    auto* val = init->As<ir::Constant>()->Value();
+    ASSERT_TRUE(Is<core::ir::Constant>(init));
+    auto* val = init->As<core::ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<core::constant::Scalar<bool>>());
     EXPECT_TRUE(val->As<core::constant::Scalar<bool>>()->ValueAs<bool>());
 }
@@ -68,8 +68,8 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<ir::Constant>(init));
-    auto* val = init->As<ir::Constant>()->Value();
+    ASSERT_TRUE(Is<core::ir::Constant>(init));
+    auto* val = init->As<core::ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<core::constant::Scalar<bool>>());
     EXPECT_FALSE(val->As<core::constant::Scalar<bool>>()->ValueAs<bool>());
 }
@@ -84,19 +84,19 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto itr = m.Get().root_block->begin();
-    auto* var_a = (*itr)->As<ir::Var>();
+    auto* var_a = (*itr)->As<core::ir::Var>();
     ++itr;
 
     ASSERT_NE(var_a, nullptr);
-    auto* var_b = (*itr)->As<ir::Var>();
+    auto* var_b = (*itr)->As<core::ir::Var>();
     ++itr;
 
     ASSERT_NE(var_b, nullptr);
-    auto* var_c = (*itr)->As<ir::Var>();
+    auto* var_c = (*itr)->As<core::ir::Var>();
     ++itr;
 
     ASSERT_NE(var_c, nullptr);
-    auto* var_d = (*itr)->As<ir::Var>();
+    auto* var_d = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_d, nullptr);
 
     ASSERT_EQ(var_a->Initializer(), var_c->Initializer());
@@ -112,8 +112,8 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<ir::Constant>(init));
-    auto* val = init->As<ir::Constant>()->Value();
+    ASSERT_TRUE(Is<core::ir::Constant>(init));
+    auto* val = init->As<core::ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<core::constant::Scalar<f32>>());
     EXPECT_EQ(1.2_f, val->As<core::constant::Scalar<f32>>()->ValueAs<f32>());
 }
@@ -127,15 +127,15 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto itr = m.Get().root_block->begin();
-    auto* var_a = (*itr)->As<ir::Var>();
+    auto* var_a = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_a, nullptr);
     ++itr;
 
-    auto* var_b = (*itr)->As<ir::Var>();
+    auto* var_b = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_b, nullptr);
     ++itr;
 
-    auto* var_c = (*itr)->As<ir::Var>();
+    auto* var_c = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_c, nullptr);
 
     ASSERT_EQ(var_a->Initializer(), var_c->Initializer());
@@ -151,8 +151,8 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<ir::Constant>(init));
-    auto* val = init->As<ir::Constant>()->Value();
+    ASSERT_TRUE(Is<core::ir::Constant>(init));
+    auto* val = init->As<core::ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<core::constant::Scalar<f16>>());
     EXPECT_EQ(1.2_h, val->As<core::constant::Scalar<f16>>()->ValueAs<f32>());
 }
@@ -167,15 +167,15 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto itr = m.Get().root_block->begin();
-    auto* var_a = (*itr)->As<ir::Var>();
+    auto* var_a = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_a, nullptr);
     ++itr;
 
-    auto* var_b = (*itr)->As<ir::Var>();
+    auto* var_b = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_b, nullptr);
     ++itr;
 
-    auto* var_c = (*itr)->As<ir::Var>();
+    auto* var_c = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_c, nullptr);
 
     ASSERT_EQ(var_a->Initializer(), var_c->Initializer());
@@ -190,8 +190,8 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<ir::Constant>(init));
-    auto* val = init->As<ir::Constant>()->Value();
+    ASSERT_TRUE(Is<core::ir::Constant>(init));
+    auto* val = init->As<core::ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<core::constant::Scalar<i32>>());
     EXPECT_EQ(-2_i, val->As<core::constant::Scalar<i32>>()->ValueAs<f32>());
 }
@@ -205,15 +205,15 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto itr = m.Get().root_block->begin();
-    auto* var_a = (*itr)->As<ir::Var>();
+    auto* var_a = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_a, nullptr);
     ++itr;
 
-    auto* var_b = (*itr)->As<ir::Var>();
+    auto* var_b = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_b, nullptr);
     ++itr;
 
-    auto* var_c = (*itr)->As<ir::Var>();
+    auto* var_c = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_c, nullptr);
 
     ASSERT_EQ(var_a->Initializer(), var_c->Initializer());
@@ -228,8 +228,8 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto* init = GlobalVarInitializer(m.Get());
-    ASSERT_TRUE(Is<ir::Constant>(init));
-    auto* val = init->As<ir::Constant>()->Value();
+    ASSERT_TRUE(Is<core::ir::Constant>(init));
+    auto* val = init->As<core::ir::Constant>()->Value();
     EXPECT_TRUE(val->Is<core::constant::Scalar<u32>>());
     EXPECT_EQ(2_u, val->As<core::constant::Scalar<u32>>()->ValueAs<f32>());
 }
@@ -243,15 +243,15 @@
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
     auto itr = m.Get().root_block->begin();
-    auto* var_a = (*itr)->As<ir::Var>();
+    auto* var_a = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_a, nullptr);
     ++itr;
 
-    auto* var_b = (*itr)->As<ir::Var>();
+    auto* var_b = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_b, nullptr);
     ++itr;
 
-    auto* var_c = (*itr)->As<ir::Var>();
+    auto* var_c = (*itr)->As<core::ir::Var>();
     ASSERT_NE(var_c, nullptr);
 
     ASSERT_EQ(var_a->Initializer(), var_c->Initializer());
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
index 503ab91..1464464 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
@@ -111,7 +111,7 @@
 namespace tint::wgsl::reader {
 namespace {
 
-using ResultType = tint::Result<ir::Module, diag::List>;
+using ResultType = tint::Result<core::ir::Module, diag::List>;
 
 /// Impl is the private-implementation of FromProgram().
 class Impl {
@@ -131,10 +131,10 @@
     const Program* program_ = nullptr;
 
     /// The IR module being built
-    ir::Module mod;
+    core::ir::Module mod;
 
     /// The IR builder being used by the impl.
-    ir::Builder builder_{mod};
+    core::ir::Builder builder_{mod};
 
     // The clone context used to clone data from #program_
     core::constant::CloneContext clone_ctx_{
@@ -146,23 +146,23 @@
     };
 
     /// The stack of flow control instructions.
-    Vector<ir::ControlInstruction*, 8> control_stack_;
+    Vector<core::ir::ControlInstruction*, 8> control_stack_;
 
     struct VectorRefElementAccess {
-        ir::Value* vector = nullptr;
-        ir::Value* index = nullptr;
+        core::ir::Value* vector = nullptr;
+        core::ir::Value* index = nullptr;
     };
 
-    using ValueOrVecElAccess = std::variant<ir::Value*, VectorRefElementAccess>;
+    using ValueOrVecElAccess = std::variant<core::ir::Value*, VectorRefElementAccess>;
 
     /// The current block for expressions.
-    ir::Block* current_block_ = nullptr;
+    core::ir::Block* current_block_ = nullptr;
 
     /// The current function being processed.
-    ir::Function* current_function_ = nullptr;
+    core::ir::Function* current_function_ = nullptr;
 
     /// The current stack of scopes being processed.
-    ScopeStack<Symbol, ir::Value*> scopes_;
+    ScopeStack<Symbol, core::ir::Value*> scopes_;
 
     /// The diagnostic that have been raised.
     diag::List diagnostics_;
@@ -179,7 +179,7 @@
 
     class ControlStackScope : public StackScope {
       public:
-        ControlStackScope(Impl* impl, ir::ControlInstruction* b) : StackScope(impl) {
+        ControlStackScope(Impl* impl, core::ir::ControlInstruction* b) : StackScope(impl) {
             impl_->control_stack_.Push(b);
         }
 
@@ -192,7 +192,7 @@
 
     bool NeedTerminator() { return current_block_ && !current_block_->HasTerminator(); }
 
-    void SetTerminator(ir::Terminator* terminator) {
+    void SetTerminator(core::ir::Terminator* terminator) {
         TINT_ASSERT(current_block_);
         TINT_ASSERT(!current_block_->HasTerminator());
 
@@ -200,15 +200,15 @@
         current_block_ = nullptr;
     }
 
-    ir::Instruction* FindEnclosingControl(ControlFlags flags) {
+    core::ir::Instruction* FindEnclosingControl(ControlFlags flags) {
         for (auto it = control_stack_.rbegin(); it != control_stack_.rend(); ++it) {
-            if ((*it)->Is<ir::Loop>()) {
+            if ((*it)->Is<core::ir::Loop>()) {
                 return *it;
             }
             if (flags == ControlFlags::kExcludeSwitch) {
                 continue;
             }
-            if ((*it)->Is<ir::Switch>()) {
+            if ((*it)->Is<core::ir::Switch>()) {
                 return *it;
             }
         }
@@ -290,13 +290,13 @@
         if (ast_func->IsEntryPoint()) {
             switch (ast_func->PipelineStage()) {
                 case ast::PipelineStage::kVertex:
-                    ir_func->SetStage(ir::Function::PipelineStage::kVertex);
+                    ir_func->SetStage(core::ir::Function::PipelineStage::kVertex);
                     break;
                 case ast::PipelineStage::kFragment:
-                    ir_func->SetStage(ir::Function::PipelineStage::kFragment);
+                    ir_func->SetStage(core::ir::Function::PipelineStage::kFragment);
                     break;
                 case ast::PipelineStage::kCompute: {
-                    ir_func->SetStage(ir::Function::PipelineStage::kCompute);
+                    ir_func->SetStage(core::ir::Function::PipelineStage::kCompute);
 
                     auto wg_size = sem->WorkgroupSize();
                     ir_func->SetWorkgroupSize(wg_size[0].value(), wg_size[1].value_or(1),
@@ -327,15 +327,15 @@
                             switch (ident_sem->Value()) {
                                 case core::BuiltinValue::kPosition:
                                     ir_func->SetReturnBuiltin(
-                                        ir::Function::ReturnBuiltin::kPosition);
+                                        core::ir::Function::ReturnBuiltin::kPosition);
                                     break;
                                 case core::BuiltinValue::kFragDepth:
                                     ir_func->SetReturnBuiltin(
-                                        ir::Function::ReturnBuiltin::kFragDepth);
+                                        core::ir::Function::ReturnBuiltin::kFragDepth);
                                     break;
                                 case core::BuiltinValue::kSampleMask:
                                     ir_func->SetReturnBuiltin(
-                                        ir::Function::ReturnBuiltin::kSampleMask);
+                                        core::ir::Function::ReturnBuiltin::kSampleMask);
                                     break;
                                 default:
                                     TINT_ICE() << "Unknown builtin value in return attributes "
@@ -356,7 +356,7 @@
         scopes_.Push();
         TINT_DEFER(scopes_.Pop());
 
-        Vector<ir::FunctionParam*, 1> params;
+        Vector<core::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);
@@ -379,40 +379,47 @@
                                     ->As<sem::BuiltinEnumExpression<core::BuiltinValue>>()) {
                             switch (ident_sem->Value()) {
                                 case core::BuiltinValue::kVertexIndex:
-                                    param->SetBuiltin(ir::FunctionParam::Builtin::kVertexIndex);
+                                    param->SetBuiltin(
+                                        core::ir::FunctionParam::Builtin::kVertexIndex);
                                     break;
                                 case core::BuiltinValue::kInstanceIndex:
-                                    param->SetBuiltin(ir::FunctionParam::Builtin::kInstanceIndex);
+                                    param->SetBuiltin(
+                                        core::ir::FunctionParam::Builtin::kInstanceIndex);
                                     break;
                                 case core::BuiltinValue::kPosition:
-                                    param->SetBuiltin(ir::FunctionParam::Builtin::kPosition);
+                                    param->SetBuiltin(core::ir::FunctionParam::Builtin::kPosition);
                                     break;
                                 case core::BuiltinValue::kFrontFacing:
-                                    param->SetBuiltin(ir::FunctionParam::Builtin::kFrontFacing);
+                                    param->SetBuiltin(
+                                        core::ir::FunctionParam::Builtin::kFrontFacing);
                                     break;
                                 case core::BuiltinValue::kLocalInvocationId:
                                     param->SetBuiltin(
-                                        ir::FunctionParam::Builtin::kLocalInvocationId);
+                                        core::ir::FunctionParam::Builtin::kLocalInvocationId);
                                     break;
                                 case core::BuiltinValue::kLocalInvocationIndex:
                                     param->SetBuiltin(
-                                        ir::FunctionParam::Builtin::kLocalInvocationIndex);
+                                        core::ir::FunctionParam::Builtin::kLocalInvocationIndex);
                                     break;
                                 case core::BuiltinValue::kGlobalInvocationId:
                                     param->SetBuiltin(
-                                        ir::FunctionParam::Builtin::kGlobalInvocationId);
+                                        core::ir::FunctionParam::Builtin::kGlobalInvocationId);
                                     break;
                                 case core::BuiltinValue::kWorkgroupId:
-                                    param->SetBuiltin(ir::FunctionParam::Builtin::kWorkgroupId);
+                                    param->SetBuiltin(
+                                        core::ir::FunctionParam::Builtin::kWorkgroupId);
                                     break;
                                 case core::BuiltinValue::kNumWorkgroups:
-                                    param->SetBuiltin(ir::FunctionParam::Builtin::kNumWorkgroups);
+                                    param->SetBuiltin(
+                                        core::ir::FunctionParam::Builtin::kNumWorkgroups);
                                     break;
                                 case core::BuiltinValue::kSampleIndex:
-                                    param->SetBuiltin(ir::FunctionParam::Builtin::kSampleIndex);
+                                    param->SetBuiltin(
+                                        core::ir::FunctionParam::Builtin::kSampleIndex);
                                     break;
                                 case core::BuiltinValue::kSampleMask:
-                                    param->SetBuiltin(ir::FunctionParam::Builtin::kSampleMask);
+                                    param->SetBuiltin(
+                                        core::ir::FunctionParam::Builtin::kSampleMask);
                                     break;
                                 default:
                                     TINT_ICE() << "Unknown builtin value in parameter attributes "
@@ -514,7 +521,7 @@
         }
 
         auto b = builder_.Append(current_block_);
-        if (auto* v = std::get_if<ir::Value*>(&lhs)) {
+        if (auto* v = std::get_if<core::ir::Value*>(&lhs)) {
             b.Store(*v, rhs);
         } else if (auto ref = std::get_if<VectorRefElementAccess>(&lhs)) {
             b.StoreVectorElement(ref->vector, ref->index, rhs);
@@ -543,9 +550,9 @@
         EmitCompoundAssignment(lhs, rhs, stmt->op);
     }
 
-    void EmitCompoundAssignment(ValueOrVecElAccess lhs, ir::Value* rhs, core::BinaryOp op) {
+    void EmitCompoundAssignment(ValueOrVecElAccess lhs, core::ir::Value* rhs, core::BinaryOp op) {
         auto b = builder_.Append(current_block_);
-        if (auto* v = std::get_if<ir::Value*>(&lhs)) {
+        if (auto* v = std::get_if<core::ir::Value*>(&lhs)) {
             auto* load = b.Load(*v);
             auto* ty = load->Result()->Type();
             auto* inst = current_block_->Append(BinaryOp(ty, load->Result(), rhs, op));
@@ -744,7 +751,7 @@
 
         const auto* sem = program_->Sem().Get(stmt);
         for (const auto* c : sem->Cases()) {
-            Vector<ir::Switch::CaseSelector, 4> selectors;
+            Vector<core::ir::Switch::CaseSelector, 4> selectors;
             for (const auto* selector : c->Selectors()) {
                 if (selector->IsDefault()) {
                     selectors.Push({nullptr});
@@ -763,7 +770,7 @@
     }
 
     void EmitReturn(const ast::ReturnStatement* stmt) {
-        ir::Value* ret_value = nullptr;
+        core::ir::Value* ret_value = nullptr;
         if (stmt->value) {
             auto ret = EmitValueExpression(stmt->value);
             if (!ret) {
@@ -782,9 +789,9 @@
         auto* current_control = FindEnclosingControl(ControlFlags::kNone);
         TINT_ASSERT(current_control);
 
-        if (auto* c = current_control->As<ir::Loop>()) {
+        if (auto* c = current_control->As<core::ir::Loop>()) {
             SetTerminator(builder_.ExitLoop(c));
-        } else if (auto* s = current_control->As<ir::Switch>()) {
+        } else if (auto* s = current_control->As<core::ir::Switch>()) {
             SetTerminator(builder_.ExitSwitch(s));
         } else {
             TINT_UNREACHABLE();
@@ -795,7 +802,7 @@
         auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch);
         TINT_ASSERT(current_control);
 
-        if (auto* c = current_control->As<ir::Loop>()) {
+        if (auto* c = current_control->As<core::ir::Loop>()) {
             SetTerminator(builder_.Continue(c));
         } else {
             TINT_UNREACHABLE();
@@ -819,7 +826,7 @@
         if (!cond) {
             return;
         }
-        SetTerminator(builder_.BreakIf(current_control->As<ir::Loop>(), cond));
+        SetTerminator(builder_.BreakIf(current_control->As<core::ir::Loop>(), cond));
     }
 
     ValueOrVecElAccess EmitExpression(const ast::Expression* root) {
@@ -842,11 +849,11 @@
 
           private:
             Impl& impl;
-            Vector<ir::Block*, 8> blocks;
+            Vector<core::ir::Block*, 8> blocks;
             Vector<std::function<void()>, 64> tasks;
             Hashmap<const ast::Expression*, ValueOrVecElAccess, 64> bindings_;
 
-            void Bind(const ast::Expression* expr, ir::Value* value) {
+            void Bind(const ast::Expression* expr, core::ir::Value* value) {
                 // If this expression maps to sem::Load, insert a load instruction to get the result
                 if (impl.program_->Sem().Get<sem::Load>(expr)) {
                     auto* load = impl.builder_.Load(value);
@@ -875,23 +882,23 @@
                 return *val;
             }
 
-            ir::Value* GetValue(const ast::Expression* expr) {
+            core::ir::Value* GetValue(const ast::Expression* expr) {
                 auto res = Get(expr);
-                if (auto** val = std::get_if<ir::Value*>(&res)) {
+                if (auto** val = std::get_if<core::ir::Value*>(&res)) {
                     return *val;
                 }
                 TINT_ICE() << "expression did not resolve to a value";
                 return nullptr;
             }
 
-            void PushBlock(ir::Block* block) {
+            void PushBlock(core::ir::Block* block) {
                 blocks.Push(impl.current_block_);
                 impl.current_block_ = block;
             }
 
             void PopBlock() { impl.current_block_ = blocks.Pop(); }
 
-            ir::Value* EmitConstant(const ast::Expression* expr) {
+            core::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_)) {
@@ -929,7 +936,7 @@
 
                 auto index = tint::Switch(
                     sem,
-                    [&](const sem::IndexAccessorExpression* idx) -> ir::Value* {
+                    [&](const sem::IndexAccessorExpression* idx) -> core::ir::Value* {
                         if (auto* v = idx->Index()->ConstantValue()) {
                             if (auto* cv = v->Clone(impl.clone_ctx_)) {
                                 return impl.builder_.Constant(cv);
@@ -939,10 +946,10 @@
                         }
                         return GetValue(idx->Index()->Declaration());
                     },
-                    [&](const sem::StructMemberAccess* access) -> ir::Value* {
+                    [&](const sem::StructMemberAccess* access) -> core::ir::Value* {
                         return impl.builder_.Constant(u32((access->Member()->Index())));
                     },
-                    [&](const sem::Swizzle* swizzle) -> ir::Value* {
+                    [&](const sem::Swizzle* swizzle) -> core::ir::Value* {
                         auto& indices = swizzle->Indices();
 
                         // A single element swizzle is just treated as an accessor.
@@ -966,8 +973,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<ir::InstructionResult>()) {
-                        if (auto* access = inst_res->Source()->As<ir::Access>()) {
+                    if (auto* inst_res = obj->As<core::ir::InstructionResult>()) {
+                        if (auto* access = inst_res->Source()->As<core::ir::Access>()) {
                             access->AddIndex(index);
                             access->Result()->SetType(ty);
                             bindings_.Remove(expr->object);
@@ -999,7 +1006,7 @@
                 if (!rhs) {
                     return;
                 }
-                ir::Binary* inst = impl.BinaryOp(ty, lhs, rhs, b->op);
+                core::ir::Binary* inst = impl.BinaryOp(ty, lhs, rhs, b->op);
                 if (!inst) {
                     return;
                 }
@@ -1014,7 +1021,7 @@
                 }
                 auto* sem = impl.program_->Sem().Get(expr);
                 auto* ty = sem->Type()->Clone(impl.clone_ctx_.type_ctx);
-                ir::Instruction* inst = nullptr;
+                core::ir::Instruction* inst = nullptr;
                 switch (expr->op) {
                     case core::UnaryOp::kAddressOf:
                     case core::UnaryOp::kIndirection:
@@ -1062,7 +1069,7 @@
                         return;
                     }
                 }
-                Vector<ir::Value*, 8> args;
+                Vector<core::ir::Value*, 8> args;
                 args.Reserve(expr->args.Length());
                 // Emit the arguments
                 for (const auto* arg : expr->args) {
@@ -1080,7 +1087,7 @@
                     return;
                 }
                 auto* ty = sem->Target()->ReturnType()->Clone(impl.clone_ctx_.type_ctx);
-                ir::Instruction* inst = nullptr;
+                core::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);
@@ -1093,9 +1100,10 @@
                     return;
                 } else {
                     // Not a builtin and not a templated call, so this is a user function.
-                    inst = impl.builder_.Call(
-                        ty, impl.scopes_.Get(expr->target->identifier->symbol)->As<ir::Function>(),
-                        std::move(args));
+                    inst = impl.builder_.Call(ty,
+                                              impl.scopes_.Get(expr->target->identifier->symbol)
+                                                  ->As<core::ir::Function>(),
+                                              std::move(args));
                 }
                 if (inst == nullptr) {
                     return;
@@ -1198,8 +1206,8 @@
 
             void EndShortCircuit(const ast::BinaryExpression* b) {
                 auto res = GetValue(b);
-                auto* src = res->As<ir::InstructionResult>()->Source();
-                auto* if_ = src->As<ir::If>();
+                auto* src = res->As<core::ir::InstructionResult>()->Source();
+                auto* if_ = src->As<core::ir::If>();
                 TINT_ASSERT_OR_RETURN(if_);
                 auto rhs = GetValue(b->rhs);
                 if (!rhs) {
@@ -1266,9 +1274,9 @@
         return Emitter(*this).Emit(root);
     }
 
-    ir::Value* EmitValueExpression(const ast::Expression* root) {
+    core::ir::Value* EmitValueExpression(const ast::Expression* root) {
         auto res = EmitExpression(root);
-        if (auto** val = std::get_if<ir::Value*>(&res)) {
+        if (auto** val = std::get_if<core::ir::Value*>(&res)) {
             return *val;
         }
         TINT_ICE() << "expression did not resolve to a value";
@@ -1319,7 +1327,7 @@
                 auto* value = init;
                 if (current_block_->Back() == last_stmt) {
                     // Emitting the let's initializer didn't create an instruction.
-                    // Create an ir::Let to give the let an instruction. This gives the let a
+                    // Create an core::ir::Let to give the let an instruction. This gives the let a
                     // place of declaration and name, which preserves runtime semantics of the
                     // let, and can be used by consumers of the IR to produce a variable or
                     // debug info.
@@ -1352,10 +1360,10 @@
             });
     }
 
-    ir::Binary* BinaryOp(const core::type::Type* ty,
-                         ir::Value* lhs,
-                         ir::Value* rhs,
-                         core::BinaryOp op) {
+    core::ir::Binary* BinaryOp(const core::type::Type* ty,
+                               core::ir::Value* lhs,
+                               core::ir::Value* rhs,
+                               core::BinaryOp op) {
         switch (op) {
             case core::BinaryOp::kAnd:
                 return builder_.And(ty, lhs, rhs);
@@ -1401,7 +1409,7 @@
 
 }  // namespace
 
-tint::Result<ir::Module, std::string> ProgramToIR(const Program* program) {
+tint::Result<core::ir::Module, std::string> ProgramToIR(const Program* program) {
     if (!program->IsValid()) {
         return std::string("input program is not valid");
     }
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h
index 602d478..c09549b 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h
@@ -27,15 +27,15 @@
 
 namespace tint::wgsl::reader {
 
-/// Builds an ir::Module from the given Program
+/// Builds an core::ir::Module from the given Program
 /// @param program the Program to use.
-/// @returns the `utiils::Result` of generating the IR. The result will contain the `ir::Module` on
-/// success, otherwise the `std::string` error.
+/// @returns the `utiils::Result` of generating the IR. The result will contain the
+/// `core::ir::Module` on success, otherwise the `std::string` error.
 ///
 /// @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.
-tint::Result<ir::Module, std::string> ProgramToIR(const Program* program);
+tint::Result<core::ir::Module, std::string> ProgramToIR(const Program* program);
 
 }  // namespace tint::wgsl::reader
 
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 608f973..899bd38 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
@@ -34,7 +34,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(ir::Module& mod) {
+T* FindSingleInstruction(core::ir::Module& mod) {
     T* found = nullptr;
     size_t count = 0;
     for (auto* node : mod.instructions.Objects()) {
@@ -67,7 +67,7 @@
     auto* f = m->functions[0];
     ASSERT_NE(f->Block(), nullptr);
 
-    EXPECT_EQ(m->functions[0]->Stage(), ir::Function::PipelineStage::kUndefined);
+    EXPECT_EQ(m->functions[0]->Stage(), core::ir::Function::PipelineStage::kUndefined);
 
     EXPECT_EQ(Disassemble(m.Get()), R"(%f = func():void -> %b1 {
   %b1 = block {
@@ -88,7 +88,7 @@
     auto* f = m->functions[0];
     ASSERT_NE(f->Block(), nullptr);
 
-    EXPECT_EQ(m->functions[0]->Stage(), ir::Function::PipelineStage::kUndefined);
+    EXPECT_EQ(m->functions[0]->Stage(), core::ir::Function::PipelineStage::kUndefined);
 
     EXPECT_EQ(Disassemble(m.Get()), R"(%f = func(%a:u32):u32 -> %b1 {
   %b1 = block {
@@ -110,7 +110,7 @@
     auto* f = m->functions[0];
     ASSERT_NE(f->Block(), nullptr);
 
-    EXPECT_EQ(m->functions[0]->Stage(), ir::Function::PipelineStage::kUndefined);
+    EXPECT_EQ(m->functions[0]->Stage(), core::ir::Function::PipelineStage::kUndefined);
 
     EXPECT_EQ(Disassemble(m.Get()), R"(%f = func(%a:u32, %b:i32, %c:bool):void -> %b1 {
   %b1 = block {
@@ -126,7 +126,7 @@
     auto m = Build();
     ASSERT_TRUE(m) << (!m ? m.Failure() : "");
 
-    EXPECT_EQ(m->functions[0]->Stage(), ir::Function::PipelineStage::kFragment);
+    EXPECT_EQ(m->functions[0]->Stage(), core::ir::Function::PipelineStage::kFragment);
 }
 
 TEST_F(IR_FromProgramTest, IfStatement) {
@@ -278,7 +278,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -311,7 +311,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -349,7 +349,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -410,7 +410,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -447,7 +447,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -488,7 +488,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -526,7 +526,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -639,7 +639,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -679,7 +679,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -719,7 +719,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -768,7 +768,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -801,7 +801,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* loop = FindSingleInstruction<ir::Loop>(m);
+    auto* loop = FindSingleInstruction<core::ir::Loop>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -833,7 +833,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* swtch = FindSingleInstruction<ir::Switch>(m);
+    auto* swtch = FindSingleInstruction<core::ir::Switch>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -884,7 +884,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* swtch = FindSingleInstruction<ir::Switch>(m);
+    auto* swtch = FindSingleInstruction<core::ir::Switch>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -923,7 +923,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* swtch = FindSingleInstruction<ir::Switch>(m);
+    auto* swtch = FindSingleInstruction<core::ir::Switch>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -956,7 +956,7 @@
     ASSERT_TRUE(res) << (!res ? res.Failure() : "");
 
     auto m = res.Move();
-    auto* swtch = FindSingleInstruction<ir::Switch>(m);
+    auto* swtch = FindSingleInstruction<core::ir::Switch>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
@@ -1000,7 +1000,7 @@
 
     auto m = res.Move();
 
-    auto* swtch = FindSingleInstruction<ir::Switch>(m);
+    auto* swtch = FindSingleInstruction<core::ir::Switch>(m);
 
     ASSERT_EQ(1u, m.functions.Length());
 
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
index 07e27ea..69632ee 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
@@ -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_, {ir::Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {core::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_, {ir::Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {core::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_, {ir::Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {core::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_, {ir::Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {core::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_, {ir::Switch::CaseSelector{}});
+        auto* case_ = b.Case(switch_, {core::ir::Switch::CaseSelector{}});
         b.Append(case_, [&] {
             b.Store(var, 2_i);
             b.ExitSwitch(switch_);
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 188fd1a..b32e60e 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -93,7 +93,7 @@
 
 class State {
   public:
-    explicit State(ir::Module& m) : mod(m) {}
+    explicit State(core::ir::Module& m) : mod(m) {}
 
     Program Run() {
         // Run transforms need to sanitize for WGSL.
@@ -105,7 +105,7 @@
             }
         }
 
-        if (auto res = ir::Validate(mod); !res) {
+        if (auto res = core::ir::Validate(mod); !res) {
             // IR module failed validation.
             b.Diagnostics() = res.Failure();
             return Program{resolver::Resolve(b)};
@@ -129,7 +129,7 @@
     };
 
     /// The source IR module
-    ir::Module& mod;
+    core::ir::Module& mod;
 
     /// The target ProgramBuilder
     ProgramBuilder b;
@@ -154,10 +154,10 @@
     using ValueBinding = std::variant<VariableValue, InlinedValue, ConsumedValue>;
 
     /// IR values to their representation
-    Hashmap<ir::Value*, ValueBinding, 32> bindings_;
+    Hashmap<core::ir::Value*, ValueBinding, 32> bindings_;
 
     /// Names for values
-    Hashmap<ir::Value*, Symbol, 32> names_;
+    Hashmap<core::ir::Value*, Symbol, 32> names_;
 
     /// The nesting depth of the currently generated AST
     /// 0  is module scope
@@ -170,10 +170,10 @@
     StatementList* statements_ = nullptr;
 
     /// The current switch case block
-    ir::Block* current_switch_case_ = nullptr;
+    core::ir::Block* current_switch_case_ = nullptr;
 
     /// Values that can be inlined.
-    Hashset<ir::Value*, 64> can_inline_;
+    Hashset<core::ir::Value*, 64> can_inline_;
 
     /// Set of enable directives emitted.
     Hashset<core::Extension, 4> enables_;
@@ -184,20 +184,20 @@
     /// True if 'diagnostic(off, derivative_uniformity)' has been emitted
     bool disabled_derivative_uniformity_ = false;
 
-    void RootBlock(ir::Block* root) {
+    void RootBlock(core::ir::Block* root) {
         for (auto* inst : *root) {
             tint::Switch(
-                inst,                             //
-                [&](ir::Var* var) { Var(var); },  //
+                inst,                                   //
+                [&](core::ir::Var* var) { Var(var); },  //
                 [&](Default) { UNHANDLED_CASE(inst); });
         }
     }
-    const ast::Function* Fn(ir::Function* fn) {
+    const ast::Function* Fn(core::ir::Function* fn) {
         SCOPED_NESTING();
 
         // 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 = tint::Transform<N>(fn->Params(), [&](ir::FunctionParam* param) {
+        auto params = tint::Transform<N>(fn->Params(), [&](core::ir::FunctionParam* param) {
             auto ty = Type(param->Type());
             auto name = NameFor(param);
             Bind(param, name, PtrKind::kPtr);
@@ -213,12 +213,12 @@
                       std::move(ret_attrs));
     }
 
-    const ast::BlockStatement* Block(ir::Block* block) {
+    const ast::BlockStatement* Block(core::ir::Block* block) {
         // TODO(crbug.com/tint/1902): Handle block arguments.
         return b.Block(Statements(block));
     }
 
-    StatementList Statements(ir::Block* block) {
+    StatementList Statements(core::ir::Block* block) {
         StatementList stmts;
         if (block) {
             MarkInlinable(block);
@@ -230,10 +230,10 @@
         return stmts;
     }
 
-    void MarkInlinable(ir::Block* block) {
+    void MarkInlinable(core::ir::Block* block) {
         // An ordered list of possibly-inlinable values returned by sequenced instructions that have
         // not yet been marked-for or ruled-out-for inlining.
-        UniqueVector<ir::Value*, 32> pending_resolution;
+        UniqueVector<core::ir::Value*, 32> pending_resolution;
 
         // Walk the instructions of the block starting with the first.
         for (auto* inst : *block) {
@@ -299,35 +299,35 @@
 
     void Append(const ast::Statement* inst) { statements_->Push(inst); }
 
-    void Instruction(ir::Instruction* inst) {
+    void Instruction(core::ir::Instruction* inst) {
         tint::Switch(
-            inst,                                                       //
-            [&](ir::Access* i) { Access(i); },                          //
-            [&](ir::Binary* i) { Binary(i); },                          //
-            [&](ir::BreakIf* i) { BreakIf(i); },                        //
-            [&](ir::Call* i) { Call(i); },                              //
-            [&](ir::Continue*) {},                                      //
-            [&](ir::ExitIf*) {},                                        //
-            [&](ir::ExitLoop* i) { ExitLoop(i); },                      //
-            [&](ir::ExitSwitch* i) { ExitSwitch(i); },                  //
-            [&](ir::If* i) { If(i); },                                  //
-            [&](ir::Let* i) { Let(i); },                                //
-            [&](ir::Load* l) { Load(l); },                              //
-            [&](ir::LoadVectorElement* i) { LoadVectorElement(i); },    //
-            [&](ir::Loop* l) { Loop(l); },                              //
-            [&](ir::NextIteration*) {},                                 //
-            [&](ir::Return* i) { Return(i); },                          //
-            [&](ir::Store* i) { Store(i); },                            //
-            [&](ir::StoreVectorElement* i) { StoreVectorElement(i); },  //
-            [&](ir::Switch* i) { Switch(i); },                          //
-            [&](ir::Swizzle* i) { Swizzle(i); },                        //
-            [&](ir::Unary* i) { Unary(i); },                            //
-            [&](ir::Unreachable*) {},                                   //
-            [&](ir::Var* i) { Var(i); },                                //
+            inst,                                                             //
+            [&](core::ir::Access* i) { Access(i); },                          //
+            [&](core::ir::Binary* i) { Binary(i); },                          //
+            [&](core::ir::BreakIf* i) { BreakIf(i); },                        //
+            [&](core::ir::Call* i) { Call(i); },                              //
+            [&](core::ir::Continue*) {},                                      //
+            [&](core::ir::ExitIf*) {},                                        //
+            [&](core::ir::ExitLoop* i) { ExitLoop(i); },                      //
+            [&](core::ir::ExitSwitch* i) { ExitSwitch(i); },                  //
+            [&](core::ir::If* i) { If(i); },                                  //
+            [&](core::ir::Let* i) { Let(i); },                                //
+            [&](core::ir::Load* l) { Load(l); },                              //
+            [&](core::ir::LoadVectorElement* i) { LoadVectorElement(i); },    //
+            [&](core::ir::Loop* l) { Loop(l); },                              //
+            [&](core::ir::NextIteration*) {},                                 //
+            [&](core::ir::Return* i) { Return(i); },                          //
+            [&](core::ir::Store* i) { Store(i); },                            //
+            [&](core::ir::StoreVectorElement* i) { StoreVectorElement(i); },  //
+            [&](core::ir::Switch* i) { Switch(i); },                          //
+            [&](core::ir::Swizzle* i) { Swizzle(i); },                        //
+            [&](core::ir::Unary* i) { Unary(i); },                            //
+            [&](core::ir::Unreachable*) {},                                   //
+            [&](core::ir::Var* i) { Var(i); },                                //
             [&](Default) { UNHANDLED_CASE(inst); });
     }
 
-    void If(ir::If* if_) {
+    void If(core::ir::If* if_) {
         SCOPED_NESTING();
 
         auto true_stmts = Statements(if_->True());
@@ -355,7 +355,7 @@
         Append(b.If(cond, true_block, b.Else(false_block)));
     }
 
-    void Loop(ir::Loop* l) {
+    void Loop(core::ir::Loop* l) {
         SCOPED_NESTING();
 
         // Build all the initializer statements
@@ -385,12 +385,12 @@
             TINT_SCOPED_ASSIGNMENT(statements_, &body_stmts);
             for (auto* inst : *l->Body()) {
                 if (body_stmts.IsEmpty()) {
-                    if (auto* if_ = inst->As<ir::If>()) {
-                        if (!if_->HasResults() &&                          //
-                            if_->True()->Length() == 1 &&                  //
-                            if_->False()->Length() == 1 &&                 //
-                            tint::Is<ir::ExitIf>(if_->True()->Front()) &&  //
-                            tint::Is<ir::ExitLoop>(if_->False()->Front())) {
+                    if (auto* if_ = inst->As<core::ir::If>()) {
+                        if (!if_->HasResults() &&                                //
+                            if_->True()->Length() == 1 &&                        //
+                            if_->False()->Length() == 1 &&                       //
+                            tint::Is<core::ir::ExitIf>(if_->True()->Front()) &&  //
+                            tint::Is<core::ir::ExitLoop>(if_->False()->Front())) {
                             // Matched the loop condition.
                             cond = Expr(if_->Condition());
                             continue;  // Don't emit this as an instruction in the body.
@@ -452,14 +452,14 @@
         statements_->Push(loop);
     }
 
-    void Switch(ir::Switch* s) {
+    void Switch(core::ir::Switch* s) {
         SCOPED_NESTING();
 
         auto* cond = Expr(s->Condition());
 
         auto cases = tint::Transform(
             s->Cases(),  //
-            [&](ir::Switch::Case c) -> const tint::ast::CaseStatement* {
+            [&](core::ir::Switch::Case c) -> const tint::ast::CaseStatement* {
                 SCOPED_NESTING();
 
                 const ast::BlockStatement* body = nullptr;
@@ -469,7 +469,7 @@
                 }
 
                 auto selectors = tint::Transform(c.selectors,  //
-                                                 [&](ir::Switch::CaseSelector cs) {
+                                                 [&](core::ir::Switch::CaseSelector cs) {
                                                      return cs.IsDefault()
                                                                 ? b.DefaultCaseSelector()
                                                                 : b.CaseSelector(Expr(cs.val));
@@ -480,18 +480,18 @@
         Append(b.Switch(cond, std::move(cases)));
     }
 
-    void ExitSwitch(const ir::ExitSwitch* e) {
+    void ExitSwitch(const core::ir::ExitSwitch* e) {
         if (current_switch_case_ && current_switch_case_->Terminator() == e) {
             return;  // No need to emit
         }
         Append(b.Break());
     }
 
-    void ExitLoop(const ir::ExitLoop*) { Append(b.Break()); }
+    void ExitLoop(const core::ir::ExitLoop*) { Append(b.Break()); }
 
-    void BreakIf(ir::BreakIf* i) { Append(b.BreakIf(Expr(i->Condition()))); }
+    void BreakIf(core::ir::BreakIf* i) { Append(b.BreakIf(Expr(i->Condition()))); }
 
-    void Return(ir::Return* ret) {
+    void Return(core::ir::Return* ret) {
         if (ret->Args().IsEmpty()) {
             // Return has no arguments.
             // If this block is nested withing some control flow, then we must
@@ -512,7 +512,7 @@
         Append(b.Return(Expr(ret->Args().Front())));
     }
 
-    void Var(ir::Var* var) {
+    void Var(core::ir::Var* var) {
         auto* val = var->Result();
         auto* ptr = As<core::type::Pointer>(val->Type());
         auto ty = Type(ptr->StoreType());
@@ -545,32 +545,32 @@
         }
     }
 
-    void Let(ir::Let* let) {
+    void Let(core::ir::Let* let) {
         Symbol name = NameFor(let->Result());
         Append(b.Decl(b.Let(name, Expr(let->Value(), PtrKind::kPtr))));
         Bind(let->Result(), name, PtrKind::kPtr);
     }
 
-    void Store(ir::Store* store) {
+    void Store(core::ir::Store* store) {
         auto* dst = Expr(store->To());
         auto* src = Expr(store->From());
         Append(b.Assign(dst, src));
     }
 
-    void StoreVectorElement(ir::StoreVectorElement* store) {
+    void StoreVectorElement(core::ir::StoreVectorElement* store) {
         auto* ptr = Expr(store->To());
         auto* val = Expr(store->Value());
         Append(b.Assign(VectorMemberAccess(ptr, store->Index()), val));
     }
 
-    void Call(ir::Call* call) {
-        auto args = tint::Transform<4>(call->Args(), [&](ir::Value* arg) {
+    void Call(core::ir::Call* call) {
+        auto args = tint::Transform<4>(call->Args(), [&](core::ir::Value* arg) {
             // Pointer-like arguments are passed by pointer, never reference.
             return Expr(arg, PtrKind::kPtr);
         });
         tint::Switch(
             call,  //
-            [&](ir::UserCall* c) {
+            [&](core::ir::UserCall* c) {
                 auto* expr = b.Call(NameFor(c->Func()), std::move(args));
                 if (!call->HasResults() || call->Result()->Usages().IsEmpty()) {
                     Append(b.CallStmt(expr));
@@ -578,7 +578,7 @@
                 }
                 Bind(c->Result(), expr, PtrKind::kPtr);
             },
-            [&](ir::CoreBuiltinCall* c) {
+            [&](core::ir::CoreBuiltinCall* c) {
                 if (!disabled_derivative_uniformity_ && RequiresDerivativeUniformity(c->Func())) {
                     // TODO(crbug.com/tint/1985): Be smarter about disabling derivative uniformity.
                     b.DiagnosticDirective(core::DiagnosticSeverity::kOff,
@@ -593,43 +593,43 @@
                 }
                 Bind(c->Result(), expr, PtrKind::kPtr);
             },
-            [&](ir::Construct* c) {
+            [&](core::ir::Construct* c) {
                 auto ty = Type(c->Result()->Type());
                 Bind(c->Result(), b.Call(ty, std::move(args)), PtrKind::kPtr);
             },
-            [&](ir::Convert* c) {
+            [&](core::ir::Convert* c) {
                 auto ty = Type(c->Result()->Type());
                 Bind(c->Result(), b.Call(ty, std::move(args)), PtrKind::kPtr);
             },
-            [&](ir::Bitcast* c) {
+            [&](core::ir::Bitcast* c) {
                 auto ty = Type(c->Result()->Type());
                 Bind(c->Result(), b.Bitcast(ty, args[0]), PtrKind::kPtr);
             },
-            [&](ir::Discard*) { Append(b.Discard()); },  //
+            [&](core::ir::Discard*) { Append(b.Discard()); },  //
             [&](Default) { UNHANDLED_CASE(call); });
     }
 
-    void Load(ir::Load* l) { Bind(l->Result(), Expr(l->From())); }
+    void Load(core::ir::Load* l) { Bind(l->Result(), Expr(l->From())); }
 
-    void LoadVectorElement(ir::LoadVectorElement* load) {
+    void LoadVectorElement(core::ir::LoadVectorElement* load) {
         auto* ptr = Expr(load->From());
         Bind(load->Result(), VectorMemberAccess(ptr, load->Index()));
     }
 
-    void Unary(ir::Unary* u) {
+    void Unary(core::ir::Unary* u) {
         const ast::Expression* expr = nullptr;
         switch (u->Kind()) {
-            case ir::Unary::Kind::kComplement:
+            case core::ir::Unary::Kind::kComplement:
                 expr = b.Complement(Expr(u->Val()));
                 break;
-            case ir::Unary::Kind::kNegation:
+            case core::ir::Unary::Kind::kNegation:
                 expr = b.Negation(Expr(u->Val()));
                 break;
         }
         Bind(u->Result(), expr);
     }
 
-    void Access(ir::Access* a) {
+    void Access(core::ir::Access* a) {
         auto* expr = Expr(a->Object());
         auto* obj_ty = a->Object()->Type()->UnwrapPtr();
         for (auto* index : a->Indices()) {
@@ -648,7 +648,7 @@
                     expr = b.IndexAccessor(expr, Expr(index));
                 },
                 [&](const core::type::Struct* s) {
-                    if (auto* c = index->As<ir::Constant>()) {
+                    if (auto* c = index->As<core::ir::Constant>()) {
                         auto i = c->Value()->ValueAs<uint32_t>();
                         TINT_ASSERT_OR_RETURN(i < s->Members().Length());
                         auto* member = s->Members()[i];
@@ -663,7 +663,7 @@
         Bind(a->Result(), expr);
     }
 
-    void Swizzle(ir::Swizzle* s) {
+    void Swizzle(core::ir::Swizzle* s) {
         auto* vec = Expr(s->Object());
         Vector<char, 4> components;
         for (uint32_t i : s->Indices()) {
@@ -678,9 +678,9 @@
         Bind(s->Result(), swizzle);
     }
 
-    void Binary(ir::Binary* e) {
-        if (e->Kind() == ir::Binary::Kind::kEqual) {
-            auto* rhs = e->RHS()->As<ir::Constant>();
+    void Binary(core::ir::Binary* e) {
+        if (e->Kind() == core::ir::Binary::Kind::kEqual) {
+            auto* rhs = e->RHS()->As<core::ir::Constant>();
             if (rhs && rhs->Type()->Is<core::type::Bool>() &&
                 rhs->Value()->ValueAs<bool>() == false) {
                 // expr == false
@@ -692,52 +692,52 @@
         auto* rhs = Expr(e->RHS());
         const ast::Expression* expr = nullptr;
         switch (e->Kind()) {
-            case ir::Binary::Kind::kAdd:
+            case core::ir::Binary::Kind::kAdd:
                 expr = b.Add(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kSubtract:
+            case core::ir::Binary::Kind::kSubtract:
                 expr = b.Sub(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kMultiply:
+            case core::ir::Binary::Kind::kMultiply:
                 expr = b.Mul(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kDivide:
+            case core::ir::Binary::Kind::kDivide:
                 expr = b.Div(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kModulo:
+            case core::ir::Binary::Kind::kModulo:
                 expr = b.Mod(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kAnd:
+            case core::ir::Binary::Kind::kAnd:
                 expr = b.And(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kOr:
+            case core::ir::Binary::Kind::kOr:
                 expr = b.Or(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kXor:
+            case core::ir::Binary::Kind::kXor:
                 expr = b.Xor(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kEqual:
+            case core::ir::Binary::Kind::kEqual:
                 expr = b.Equal(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kNotEqual:
+            case core::ir::Binary::Kind::kNotEqual:
                 expr = b.NotEqual(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kLessThan:
+            case core::ir::Binary::Kind::kLessThan:
                 expr = b.LessThan(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kGreaterThan:
+            case core::ir::Binary::Kind::kGreaterThan:
                 expr = b.GreaterThan(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kLessThanEqual:
+            case core::ir::Binary::Kind::kLessThanEqual:
                 expr = b.LessThanEqual(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kGreaterThanEqual:
+            case core::ir::Binary::Kind::kGreaterThanEqual:
                 expr = b.GreaterThanEqual(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kShiftLeft:
+            case core::ir::Binary::Kind::kShiftLeft:
                 expr = b.Shl(lhs, rhs);
                 break;
-            case ir::Binary::Kind::kShiftRight:
+            case core::ir::Binary::Kind::kShiftRight:
                 expr = b.Shr(lhs, rhs);
                 break;
         }
@@ -746,12 +746,12 @@
 
     TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);
 
-    const ast::Expression* Expr(ir::Value* value, PtrKind want_ptr_kind = PtrKind::kRef) {
+    const ast::Expression* Expr(core::ir::Value* value, PtrKind want_ptr_kind = PtrKind::kRef) {
         using ExprAndPtrKind = std::pair<const ast::Expression*, PtrKind>;
 
         auto [expr, got_ptr_kind] = tint::Switch(
             value,
-            [&](ir::Constant* c) -> ExprAndPtrKind {
+            [&](core::ir::Constant* c) -> ExprAndPtrKind {
                 return {Constant(c), PtrKind::kRef};
             },
             [&](Default) -> ExprAndPtrKind {
@@ -802,7 +802,7 @@
 
     TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);
 
-    const ast::Expression* Constant(ir::Constant* c) { return Constant(c->Value()); }
+    const ast::Expression* Constant(core::ir::Constant* c) { return Constant(c->Value()); }
 
     const ast::Expression* Constant(const core::constant::Value* c) {
         auto composite = [&](bool can_splat) {
@@ -996,7 +996,7 @@
 
     /// @returns the AST name for the given value, creating and returning a new name on the first
     /// call.
-    Symbol NameFor(ir::Value* value, std::string_view suggested = {}) {
+    Symbol NameFor(core::ir::Value* value, std::string_view suggested = {}) {
         return names_.GetOrCreate(value, [&] {
             if (!suggested.empty()) {
                 return b.Symbols().Register(suggested);
@@ -1010,7 +1010,9 @@
 
     /// Associates the IR value @p value with the AST expression @p expr.
     /// @p ptr_kind defines how pointer values are represented by @p expr.
-    void Bind(ir::Value* value, const ast::Expression* expr, PtrKind ptr_kind = PtrKind::kRef) {
+    void Bind(core::ir::Value* value,
+              const ast::Expression* expr,
+              PtrKind ptr_kind = PtrKind::kRef) {
         TINT_ASSERT(value);
         if (can_inline_.Remove(value)) {
             // Value will be inlined at its place of usage.
@@ -1041,7 +1043,7 @@
     /// Associates the IR value @p value with the AST 'var', 'let' or parameter with the name @p
     /// name.
     /// @p ptr_kind defines how pointer values are represented by @p expr.
-    void Bind(ir::Value* value, Symbol name, PtrKind ptr_kind) {
+    void Bind(core::ir::Value* value, Symbol name, PtrKind ptr_kind) {
         TINT_ASSERT(value);
 
         bool added = bindings_.Add(value, VariableValue{name, ptr_kind});
@@ -1053,7 +1055,7 @@
     ////////////////////////////////////////////////////////////////////////////////////////////////
     // Helpers
     ////////////////////////////////////////////////////////////////////////////////////////////////
-    bool AsShortCircuit(ir::If* i,
+    bool AsShortCircuit(core::ir::If* i,
                         const StatementList& true_stmts,
                         const StatementList& false_stmts) {
         if (!i->HasResults()) {
@@ -1114,8 +1116,8 @@
         return false;
     }
 
-    bool IsConstant(ir::Value* val, bool value) {
-        if (auto* c = val->As<ir::Constant>()) {
+    bool IsConstant(core::ir::Value* val, bool value) {
+        if (auto* c = val->As<core::ir::Constant>()) {
             if (c->Type()->Is<core::type::Bool>()) {
                 return c->Value()->ValueAs<bool>() == value;
             }
@@ -1123,8 +1125,8 @@
         return false;
     }
 
-    const ast::Expression* VectorMemberAccess(const ast::Expression* expr, ir::Value* index) {
-        if (auto* c = index->As<ir::Constant>()) {
+    const ast::Expression* VectorMemberAccess(const ast::Expression* expr, core::ir::Value* index) {
+        if (auto* c = index->As<core::ir::Constant>()) {
             switch (c->Value()->ValueAs<int>()) {
                 case 0:
                     return b.MemberAccessor(expr, "x");
@@ -1162,7 +1164,7 @@
 
 }  // namespace
 
-Program IRToProgram(ir::Module& i) {
+Program IRToProgram(core::ir::Module& i) {
     return State{i}.Run();
 }
 
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
index e4186a4..71b5fe3 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h
@@ -17,17 +17,17 @@
 
 #include "src/tint/lang/wgsl/program/program.h"
 
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
 namespace tint::wgsl::writer {
 
-/// Builds a tint::Program from an ir::Module
+/// Builds a tint::Program from an core::ir::Module
 /// @param module the IR module
 /// @return the tint::Program.
 /// @note Check the returned Program::Diagnostics() for any errors.
-Program IRToProgram(ir::Module& module);
+Program IRToProgram(core::ir::Module& module);
 
 }  // namespace tint::wgsl::writer
 
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index 8053a73..a479310 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -29,7 +29,7 @@
 IRToProgramTest::Result IRToProgramTest::Run() {
     Result result;
 
-    tint::ir::Disassembler d{mod};
+    tint::core::ir::Disassembler d{mod};
     result.ir = d.Disassemble();
 
     auto output_program = IRToProgram(mod);
@@ -1819,7 +1819,7 @@
         v->SetInitializer(b.Constant(42_i));
 
         auto s = b.Switch(b.Load(v));
-        b.Append(b.Case(s, {ir::Switch::CaseSelector{}}), [&] {
+        b.Append(b.Case(s, {core::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, {ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] {
+        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] {
             b.Call(ty.void_(), fn_a);
             b.ExitSwitch(s);
         });
         b.Append(b.Case(s,
                         {
-                            ir::Switch::CaseSelector{b.Constant(1_i)},
-                            ir::Switch::CaseSelector{},
+                            core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                            core::ir::Switch::CaseSelector{},
                         }),
                  [&] {
                      b.Call(ty.void_(), fn_b);
                      b.ExitSwitch(s);
                  });
-        b.Append(b.Case(s, {ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] {
+        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] {
             b.Call(ty.void_(), fn_c);
             b.ExitSwitch(s);
         });
@@ -1918,14 +1918,16 @@
         v->SetInitializer(b.Constant(42_i));
 
         auto s = b.Switch(b.Load(v));
-        b.Append(b.Case(s, {ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] { b.Return(fn); });
+        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{b.Constant(0_i)}}),
+                 [&] { b.Return(fn); });
         b.Append(b.Case(s,
                         {
-                            ir::Switch::CaseSelector{b.Constant(1_i)},
-                            ir::Switch::CaseSelector{},
+                            core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                            core::ir::Switch::CaseSelector{},
                         }),
                  [&] { b.Return(fn); });
-        b.Append(b.Case(s, {ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] { b.Return(fn); });
+        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{b.Constant(2_i)}}),
+                 [&] { b.Return(fn); });
 
         b.Call(ty.void_(), fn_a);
         b.Return(fn);
@@ -1972,29 +1974,29 @@
         v2->SetInitializer(b.Constant(24_i));
 
         auto s1 = b.Switch(b.Load(v1));
-        b.Append(b.Case(s1, {ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] {
+        b.Append(b.Case(s1, {core::ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] {
             b.Call(ty.void_(), fn_a);
             b.ExitSwitch(s1);
         });
         b.Append(b.Case(s1,
                         {
-                            ir::Switch::CaseSelector{b.Constant(1_i)},
-                            ir::Switch::CaseSelector{},
+                            core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                            core::ir::Switch::CaseSelector{},
                         }),
                  [&] {
                      auto s2 = b.Switch(b.Load(v2));
-                     b.Append(b.Case(s2, {ir::Switch::CaseSelector{b.Constant(0_i)}}),
+                     b.Append(b.Case(s2, {core::ir::Switch::CaseSelector{b.Constant(0_i)}}),
                               [&] { b.ExitSwitch(s2); });
                      b.Append(b.Case(s2,
                                      {
-                                         ir::Switch::CaseSelector{b.Constant(1_i)},
-                                         ir::Switch::CaseSelector{},
+                                         core::ir::Switch::CaseSelector{b.Constant(1_i)},
+                                         core::ir::Switch::CaseSelector{},
                                      }),
                               [&] { b.Return(fn); });
 
                      b.ExitSwitch(s1);
                  });
-        b.Append(b.Case(s1, {ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] {
+        b.Append(b.Case(s1, {core::ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] {
             b.Call(ty.void_(), fn_c);
             b.ExitSwitch(s1);
         });
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h
index 1095d0f..6f4aadb 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.h
@@ -22,7 +22,7 @@
 namespace tint::wgsl::writer {
 
 /// Class used for IR to Program tests
-class IRToProgramTest : public ir::IRTestHelper {
+class IRToProgramTest : public core::ir::IRTestHelper {
   public:
     /// The result of Run()
     struct Result {
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.cc b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.cc
index cb57213..0d61b8a 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.cc
@@ -44,7 +44,7 @@
 struct State {
     /// Constructor
     /// @param i the IR module
-    explicit State(ir::Module* i) : ir(i) {}
+    explicit State(core::ir::Module* i) : ir(i) {}
 
     /// Processes the module, renaming all declarations that would prevent an identifier resolving
     /// to the correct declaration.
@@ -77,11 +77,11 @@
 
   private:
     /// Map of identifier to declaration.
-    /// The declarations may be one of an ir::Value or core::type::Struct.
+    /// The declarations may be one of an core::ir::Value or core::type::Struct.
     using Scope = Hashmap<std::string_view, CastableBase*, 8>;
 
     /// The IR module.
-    ir::Module* ir = nullptr;
+    core::ir::Module* ir = nullptr;
 
     /// Stack of scopes
     Vector<Scope, 8> scopes{};
@@ -119,7 +119,7 @@
     }
 
     /// Processes the instructions of the block
-    void Process(ir::Block* block) {
+    void Process(core::ir::Block* block) {
         for (auto* inst : *block) {
             Process(inst);
         }
@@ -127,7 +127,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(ir::Instruction* inst) {
+    void Process(core::ir::Instruction* inst) {
         // Check resolving of operands
         for (auto* operand : inst->Operands()) {
             if (operand) {
@@ -136,7 +136,7 @@
                     EnsureResolvesTo(symbol.NameView(), operand);
                 }
                 // If the operand is a constant, then ensure that type name can be resolved.
-                if (auto* c = operand->As<ir::Constant>()) {
+                if (auto* c = operand->As<core::ir::Constant>()) {
                     EnsureResolvable(c->Type());
                 }
             }
@@ -144,7 +144,7 @@
 
         Switch(
             inst,  //
-            [&](ir::Loop* loop) {
+            [&](core::ir::Loop* loop) {
                 // Initializer's scope encompasses the body and continuing
                 scopes.Push(Scope{});
                 TINT_DEFER(scopes.Pop());
@@ -161,23 +161,23 @@
                     }
                 }
             },
-            [&](ir::ControlInstruction* ctrl) {
+            [&](core::ir::ControlInstruction* ctrl) {
                 // Traverse into the control instruction's blocks
-                ctrl->ForeachBlock([&](ir::Block* block) {
+                ctrl->ForeachBlock([&](core::ir::Block* block) {
                     scopes.Push(Scope{});
                     TINT_DEFER(scopes.Pop());
                     Process(block);
                 });
             },
-            [&](ir::Var*) {
+            [&](core::ir::Var*) {
                 // Ensure the var's type is resolvable
                 EnsureResolvable(inst->Result()->Type());
             },
-            [&](ir::Construct*) {
+            [&](core::ir::Construct*) {
                 // Ensure the type of a type constructor is resolvable
                 EnsureResolvable(inst->Result()->Type());
             },
-            [&](ir::CoreBuiltinCall* call) {
+            [&](core::ir::CoreBuiltinCall* call) {
                 // Ensure builtin of a builtin call is resolvable
                 auto name = tint::ToString(call->Func());
                 EnsureResolvesTo(name, nullptr);
@@ -259,7 +259,7 @@
         Symbol new_name = ir->symbols.New(old_name);
         Switch(
             thing,  //
-            [&](ir::Value* value) { ir->SetName(value, new_name); },
+            [&](core::ir::Value* value) { ir->SetName(value, new_name); },
             [&](core::type::Struct* str) { str->SetName(new_name); },
             [&](Default) {
                 TINT_ICE() << "unhandled type for renaming: " << thing->TypeInfo().name;
@@ -275,7 +275,7 @@
 
 }  // namespace
 
-Result<SuccessType, std::string> RenameConflicts(ir::Module* ir) {
+Result<SuccessType, std::string> RenameConflicts(core::ir::Module* ir) {
     auto result = ValidateAndDumpIfNeeded(*ir, "RenameConflicts transform");
     if (!result) {
         return result;
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
index 9dc9620..b513409 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.h
+++ b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts.h
@@ -20,7 +20,7 @@
 #include "src/tint/utils/result/result.h"
 
 // Forward declarations.
-namespace tint::ir {
+namespace tint::core::ir {
 class Module;
 }
 
@@ -31,7 +31,7 @@
 /// scope.
 /// @param module the module to transform
 /// @returns an error string on failure
-Result<SuccessType, std::string> RenameConflicts(ir::Module* module);
+Result<SuccessType, std::string> RenameConflicts(core::ir::Module* module);
 
 }  // namespace tint::wgsl::writer
 
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc
index e9b03f9..57620ed 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/rename_conflicts_test.cc
@@ -34,7 +34,7 @@
     void Run() {
         // Validate the input IR.
         {
-            auto res = ir::Validate(mod);
+            auto res = core::ir::Validate(mod);
             EXPECT_TRUE(res) << res.Failure().str();
             if (!res) {
                 return;
@@ -46,21 +46,21 @@
         EXPECT_TRUE(result) << result.Failure();
 
         // Validate the output IR.
-        auto res = ir::Validate(mod);
+        auto res = core::ir::Validate(mod);
         EXPECT_TRUE(res) << res.Failure().str();
     }
 
     /// @returns the transformed module as a disassembled string
     std::string str() {
-        ir::Disassembler dis(mod);
+        core::ir::Disassembler dis(mod);
         return "\n" + dis.Disassemble();
     }
 
   protected:
     /// The test IR module.
-    ir::Module mod;
+    core::ir::Module mod;
     /// The test IR builder.
-    ir::Builder b{mod};
+    core::ir::Builder b{mod};
     /// The type manager.
     core::type::Manager& ty{mod.Types()};
 };